Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InheritanceDiagram: cleanup code; avoid iframe hack; use single parameter #5056

Merged
merged 4 commits into from
Jan 13, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 94 additions & 97 deletions kumascript/macros/InheritanceDiagram.ejs
Original file line number Diff line number Diff line change
@@ -1,132 +1,129 @@
<%
/*
Draws an responsive SVG diagram for the inheritance chain (inverted in rtl)
Draws an SVG diagram to display an interface's inheritance chain

$0 - width - defaults to 600
$1 - height - defaults to 70
$2 - offset - defaults to 50
$3 - Interface name
$0 - Interface name (defaults to the interface page the macro is called on)

Test pages

- http://localhost:3000/en-US/docs/Web/API/SVGTextPositioningElement
- http://localhost:3000/en-US/docs/Web/API/WheelEvent
- http://localhost:3000/en-US/docs/Web/API/USB/connect_event
*/

var data = web.getJSONData("InterfaceData");
var slug = env.slug;
var result = "";
// slug is not available in preview mode.
if (slug) {
var locale = env.locale;
var href = 'https://developer.mozilla.org/' + locale + '/docs/Web/API/';
var mainIF = $3 || slug.replace('Web/API/','').split('/')[0];
var rtlLocales = ['ar', 'he', 'fa'];
var inheritanceChain = [mainIF];
var inh = data[0][mainIF] != undefined ? data[0][mainIF].inh : '';
var width = $0 || 600;
var height = $1 || 70;
var offset = $2 || 50;
var rtl = false;
if (rtlLocales.indexOf(locale) != -1) {
rtl = true;
}
const data = web.getJSONData("InterfaceData")[0];
const href = `/${env.locale}/docs/Web/API/`;
const mainInterfaceName = $0 || env.slug.replace('Web/API/','').split('/')[0];

let height = 40;
let offset = 0;
let xpos = 1;
let ypos = 1;

let inheritanceChain = [mainInterfaceName];
let inh = data[mainInterfaceName] != undefined ? data[mainInterfaceName].inh : '';

function getInheritance(inh) {
if (inh.length > 0) {
if (inh !== '') {
inheritanceChain.unshift(inh);
if (Object.prototype.hasOwnProperty.call(data[0], inh)) {
var inh = data[0][inh].inh;
if (data[inh]) {
inh = data[inh].inh;
getInheritance(inh);
}
}
}
getInheritance(inh);

var l = 0;

function rectWithText(x, y, fill, interface, reverse) {
var flip = rtl ? 'transform="scale(-1 1)"' : '';
var inv = rtl ? '-' : '';
l = interface.length * 10 < 75 ? 75 : interface.length * 10;
function rectWithText(x, y, fill, interfaceName, reverse) {
const rectWidth = interfaceName.length * 8 < 75 ? 75 : interfaceName.length * 8;
if (reverse) {
xpos -= l;
xpos -= rectWidth;
x = xpos;
} else {
xpos += rectWidth;
}
if (!reverse) {
xpos += l;
}
return '<a xlink:href="' + href + interface + '" target="_top">' +
'<rect x="'+x+'" y="'+y+'" width="'+l+'" height="50" fill="'+fill+'" stroke="#D4DDE4" stroke-width="2px" />' +
'<text '+flip+' x="'+inv+(x+l/2)+'" y="'+(y+29)+'" font-size="12px" font-family="Consolas,Monaco,Andale Mono,monospace"' +
' fill="#4D4E53" text-anchor="middle" alignment-baseline="middle">'+interface+'</text>' +
'</a>';
return `
<a style="text-decoration: none;" xlink:href="${href+interfaceName}">
<rect x="${x}" y="${y}" width="${rectWidth}" height="25" fill="${fill}" stroke="#D4DDE4" stroke-width="2px" />
<text x="${x+rectWidth/2}" y="${y+16}" font-size="10px" fill="#4D4E53" text-anchor="middle">
${interfaceName}
</text>
</a>`;
}

function lineWithTriangle(x, y, reverse) {
var str = '';
let str = '';
let polylinePoints = `${x},${y+14} ${x+10},${y+9} ${x+10},${y+19} ${x},${y+14}`;
let linePoints = `x1="${x+10}" y1="${y+14}" x2="${x+30}" y2="${y+14}"`;

if (reverse) {
str += '<polyline points="'+x+','+(y+24)+' '+(x-10)+','+(y+19)+' '+(x-10)+','+(y+29)+' '+x+','+(y+24)+'" stroke="#D4DDE4" fill="none"/>';
x -= 10;
str += '<line x1="'+x+'" y1="'+(y+24)+'" x2="'+(x-30)+'" y2="'+(y+24)+'" stroke="#D4DDE4"/>';
} else {
str += '<polyline points="'+x+','+(y+24)+' '+(x+10)+','+(y+19)+' '+(x+10)+','+(y+29)+' '+x+','+(y+24)+'" stroke="#D4DDE4" fill="none"/>';
x += 10;
str += '<line x1="'+x+'" y1="'+(y+24)+'" x2="'+(x+30)+'" y2="'+(y+24)+'" stroke="#D4DDE4"/>';
polylinePoints = `${x},${y+14} ${x-10},${y+9} ${x-10},${y+19} ${x},${y+14}`;
linePoints = `x1="${x-10}" y1="${y+14}" x2="${x-30}" y2="${y+14}"`;
}

str += `<polyline points="${polylinePoints}" stroke="#D4DDE4" fill="none"/>`;
x -= 10;
str += `<line ${linePoints} stroke="#D4DDE4"/>`;

return str;
}

var padding = (height / width) * 100;
var xpos = 1;
var ypos = 1;
var viewbox = 'viewbox="-'+ offset + ' 0 '+ width + ' ' + height +'"';
function connectingLineWithTriangle() {
let str = '';

if (rtl) {
viewbox = 'viewbox="510 0 '+ width + ' ' + height +'" transform="scale(-1 1)"';
str += `<polyline points="${xpos},${ypos+14} ${xpos+10},${ypos+9} ${xpos+10},${ypos+19} ${xpos},${ypos+14}" stroke="#D4DDE4" fill="none"/>`;
xpos += 10;
str += `<line x1="${xpos}" y1="${ypos+14}" x2="${xpos+8}" y2="${ypos+14}" stroke="#D4DDE4"/>`;
xpos += 8;
str += `<line x1="${xpos}" y1="${ypos+14}" x2="${xpos}" y2="${ypos+59}" stroke="#D4DDE4"/>`;
ypos = 60;
str += `<line x1="${xpos}" y1="${ypos}" x2="${xpos-17}" y2="${ypos}" stroke="#D4DDE4"/>`;

return str;
}
result = '<div id="interfaceDiagram" style="display: inline-block; position: relative; width: 100%; padding-bottom: '+ padding +'%; vertical-align: middle; overflow: hidden;">' +
'<svg style="display: inline-block; position: absolute; top: 0; left: 0;" '+ viewbox +' preserveAspectRatio="xMinYMin meet">';

for (var i = 0; i < inheritanceChain.length; i++) {
var fill = (inheritanceChain[i] == mainIF) ? '#F4F7F8': '#fff';
// we are going to the second row with a special line
if (i == 4) {
result += '<polyline points="'+xpos+','+(ypos+24)+' '+(xpos+10)+','+(ypos+19)+' '+(xpos+10)+','+(ypos+29)+' '+xpos+','+(ypos+24)+'" stroke="#D4DDE4" fill="none"/>'
xpos += 10;
result += '<line x1="'+xpos+'" y1="'+(ypos+24)+'" x2="'+(xpos+8)+'" y2="'+(ypos+24)+'" stroke="#D4DDE4"/>';
xpos += 8;
result += '<line x1="'+xpos+'" y1="'+(ypos+24)+'" x2="'+xpos+'" y2="'+(ypos+89)+'" stroke="#D4DDE4"/>';
ypos = 90;
result += '<line x1="'+xpos+'" y1="'+ypos+'" x2="'+(xpos-17)+'" y2="'+ypos+'" stroke="#D4DDE4"/>';
xpos -= 18;
ypos = 65;
}
// first row
if (i < 4) {
result += rectWithText(xpos, ypos, fill, inheritanceChain[i]);
if (i != inheritanceChain.length - 1 && i != 3) {
result += lineWithTriangle(xpos, ypos);
xpos += 40;

function drawDiagram(inheritanceChain) {
let str = '';
for (let i = 0; i < inheritanceChain.length; i++) {
const fill = (inheritanceChain[i] == mainInterfaceName) ? '#F4F7F8': '#fff';
// we are going to the second row with a connecting line
if (i === 4) {
str += connectingLineWithTriangle();
xpos -= 18;
ypos = 47;
}
} else {
// first row
if (i < 4) {
str += rectWithText(xpos, ypos, fill, inheritanceChain[i]);
if (i != inheritanceChain.length - 1 && i != 3) {
str += lineWithTriangle(xpos, ypos);
xpos += 30;
}
// second row
result += rectWithText(xpos, ypos, fill, inheritanceChain[i], true);
if (i != inheritanceChain.length - 1 && i != 3) {
result += lineWithTriangle(xpos, ypos, true);
xpos -= 40;
} else {
height = 80; // need more space
str += rectWithText(xpos, ypos, fill, inheritanceChain[i], true);
if (i != inheritanceChain.length - 1) {
str += lineWithTriangle(xpos, ypos, true);
xpos -= 30;
}
if (xpos < 0) {
// prevent cut off in case of a really long chain (see e.g. SVGTextPositioningElement)
offset = 1 + Math.abs(xpos);
}
}
}
return str;
}

result +='</svg></div>';
}
%>
<div class="hidden" id="inheritance_diagram">

<pre class="brush: html">
<%=result%>
</pre>
let output = '';

<pre class="brush: css">
a:hover text { fill: #0095DD; pointer-events: all;}
</pre>

</div>
if (inheritanceChain.length > 1) {
let diagram = drawDiagram(inheritanceChain); // needs to run first to calculate offset and height
output = `<svg viewbox="-${offset} 0 650 ${height}" preserveAspectRatio="xMinYMin meet">`;
output += diagram;
output +='</svg>';
}

<%-await template("EmbedLiveSample", ["inheritance_diagram", width, height, '', '', 'inheritance-diagram-frame'])%>
%>
<%-output%>