<% /* Draws an SVG diagram to display an interface's inheritance chain $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 - http://localhost:3000/en-US/docs/Web/API/SVGTSpanElement */ 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 xpos = 0; let ypos = 0; let left = 0; let right = 0; let inheritanceChain = [mainInterfaceName]; let inh = data[mainInterfaceName] != undefined ? data[mainInterfaceName].inh : ''; function getInheritance(inh) { if (inh !== '') { inheritanceChain.unshift(inh); if (data[inh]) { inh = data[inh].inh; getInheritance(inh); } } } getInheritance(inh); function rectWithText(x, y, fill, interfaceName, reverse) { const rectWidth = calculateRectWidth(interfaceName); if (reverse) x -= rectWidth; return ` ${interfaceName} `; } function lineWithTriangle(x, y, reverse) { const length = reverse ? -30 : 30; return ` ${triangle(x, y, reverse)}`; } function connectingLineWithTriangle(x, y, reverse) { const width = reverse ? -17 : 17; return ` ${triangle(x, y, reverse)}`; } function triangle(x, y, reverse) { const width = reverse ? -10 : 10; return ``; } function calculateRectWidth(text) { return text.length * 8 < 75 ? 75 : text.length * 8; } function moveBy(number, delta, reverse) { return number + (reverse ? -delta : delta); } function includeInRange(number, start, end) { return [ Math.min(start, number), Math.max(end, number) ]; } function drawDiagram(inheritanceChain) { let str = ''; let reverse = false; for (let i = 0; i < inheritanceChain.length; i++) { const fill = (inheritanceChain[i] == mainInterfaceName) ? '#F4F7F8': '#fff'; const rectWidth = calculateRectWidth(inheritanceChain[i]); // Minumum space required to continue the current row let reqSpace = rectWidth; if (i > 0) reqSpace += 30; // If the rect from the next iteration won't fit in the row, we need to be // sure that at least the connectingLineWithTriangle will fit if (i < inheritanceChain.length - 1) reqSpace += 17; const reqBounds = includeInRange( moveBy(xpos, reqSpace, reverse), left, right ); // Will the current drawing items fit inside the viewbox? Subtract the // stroke width from the viewbox width to prevent stroke cut off. const canContinueRow = reqBounds[1] - reqBounds[0] <= 650 - 2; if (i > 0) { if (canContinueRow) { str += lineWithTriangle(xpos, ypos + 14, reverse); xpos = moveBy(xpos, 30, reverse); } else { str += connectingLineWithTriangle(xpos, ypos + 14, reverse); [left, right] = includeInRange(moveBy(xpos, 17, reverse), left, right); ypos += 46; height += 46; reverse = !reverse; } } str += rectWithText(xpos, ypos, fill, inheritanceChain[i], reverse); xpos = moveBy(xpos, rectWidth, reverse); [left, right] = includeInRange(xpos, left, right); } return str; } let output = ''; if (inheritanceChain.length > 1) { let diagram = drawDiagram(inheritanceChain); // needs to run first to calculate left and height output = ``; output += diagram; output +=''; } %> <%-output%>