diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index af35ce910..601ea1729 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -25,28 +25,156 @@ +
+pie title Pets adopted by volunteers + "Dogs" : 386 + "Cats" : 85 + "Rats" : 15 +
-classDiagram - Animal "1" <|-- Duck - Animal <|-- Fish - Animal <--o Zebra - Animal : +int age - Animal : +String gender - Animal: +isMammal() - Animal: +mate() - class Duck{ - +String beakColor - +swim() - +quack() - } - class Fish{ - -int sizeInFeet - -canEat() - } - class Zebra{ - +bool is_wild - +run() - } +gantt + dateFormat :YYYY-MM-DD + title Adding GANTT diagram functionality to mermaid + excludes :excludes the named dates/days from being included in a charted task.. + section A section + Completed task :done, des1, 2014-01-06,2014-01-08 + Active task :active, des2, 2014-01-09, 3d + Future task : des3, after des2, 5d + Future task2 : des4, after des3, 5d + + section Critical tasks + Completed task in the critical line :crit, done, 2014-01-06,24h + Implement parser and jison :crit, done, after des1, 2d + Create tests for parser :crit, active, 3d + Future task in critical line :crit, 5d + Create tests for renderer :2d + Add to mermaid :1d + + section Documentation + Describe gantt syntax :active, a1, after des1, 3d + Add gantt diagram to demo page :after a1 , 20h + Add another diagram to demo page :doc1, after a1 , 48h + + section Last section + Describe gantt syntax :after doc1, 3d + Add gantt diagram to demo page :20h + Add another diagram to demo page :48h +
+
+info +
+
+gitGraph: +options +{ + "nodeSpacing": 150, + "nodeRadius": 10 +} +end +commit +branch newbranch +checkout newbranch +commit +commit +checkout master +commit +commit +merge newbranch +
+
+journey + title My working day + section Go to work + Make tea: 5: Me + Go upstairs: 3: Me + Do work: 1: Me, Cat + section Go home + Go downstairs: 5: Me + Sit down: 5: Me +
+
+requirementDiagram + + requirement test_req { + id: 1 + text: the test text. + risk: high + verifymethod: test + } + + functionalRequirement test_req2 { + id: 1.1 + text: the second test text. + risk: low + verifymethod: inspection + } + + performanceRequirement test_req3 { + id: 1.2 + text: the third test text. + risk: medium + verifymethod: demonstration + } + + element test_entity { + type: simulation + } + + element test_entity2 { + type: word doc + docRef: reqs/test_entity + } + + + test_entity - satisfies -> test_req2 + test_req - traces -> test_req2 + test_req - contains -> test_req3 + test_req <- copies - test_entity2 +
+
+ erDiagram + CUSTOMER }|..|{ DELIVERY-ADDRESS : has + CUSTOMER ||--o{ ORDER : places + CUSTOMER ||--o{ INVOICE : "liable for" + DELIVERY-ADDRESS ||--o{ ORDER : receives + INVOICE ||--|{ ORDER : covers + ORDER ||--|{ ORDER-ITEM : includes + PRODUCT-CATEGORY ||--|{ PRODUCT : contains + PRODUCT ||--o{ ORDER-ITEM : "ordered in" +
+
+ graph TB + subgraph One + a1-->a2-->a3 + end +
+
+ stateDiagram + [*] --> S1 + state "Some long name" as S1 +
+
+ classDiagram + Animal "1" <|-- Duck + Animal <|-- Fish + Animal <--o Zebra + Animal : +int age + Animal : +String gender + Animal: +isMammal() + Animal: +mate() + class Duck{ + +String beakColor + +swim() + +quack() + } + class Fish{ + -int sizeInFeet + -canEat() + } + class Zebra{ + +bool is_wild + +run() + }
@@ -57,9 +185,17 @@ classDiagram mermaid.initialize({ // theme: 'dark', theme: 'forest', - arrowMarkerAbsolute: true, + // arrowMarkerAbsolute: true, // themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}', - flowchart: { nodeSpacing: 10, curve: 'cardinal', htmlLabels: false }, + flowchart: { + nodeSpacing: 10, + curve: 'cardinal', + htmlLabels: true, + defaultRenderer: 'dagre-d3', + }, + class: { + defaultRenderer: 'dagre-d3', + }, // gantt: { axisFormat: '%m/%d/%Y' }, sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false }, // sequenceDiagram: { actorMargin: 300 } // deprecated @@ -68,12 +204,12 @@ classDiagram state: { nodeSpacing: 50, rankSpacing: 50, - defaultRenderer: 'dagre-wrapper', + defaultRenderer: 'dagre-d3', }, logLevel: 0, fontSize: 18, curve: 'cardinal', - securityLevel: 'sandbox', + // securityLevel: 'sandbox', // themeVariables: {relationLabelColor: 'red'} }); function callback() { diff --git a/cypress/screenshots/other/rerender.spec.js/Rerendering -- should be able to render after an error has occured (failed).png b/cypress/screenshots/other/rerender.spec.js/Rerendering -- should be able to render after an error has occured (failed).png new file mode 100644 index 000000000..d08f7d092 Binary files /dev/null and b/cypress/screenshots/other/rerender.spec.js/Rerendering -- should be able to render after an error has occured (failed).png differ diff --git a/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is false (failed).png b/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is false (failed).png new file mode 100644 index 000000000..30c03ba68 Binary files /dev/null and b/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is false (failed).png differ diff --git a/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is true (default) (failed).png b/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is true (default) (failed).png new file mode 100644 index 000000000..6065ea1b7 Binary files /dev/null and b/cypress/screenshots/rendering/sequencediagram.spec.js/Sequence diagram -- svg size -- should render a sequence diagram when useMaxWidth is true (default) (failed).png differ diff --git a/src/diagrams/class/classRenderer-v2.js b/src/diagrams/class/classRenderer-v2.js index 3cd30105e..eda96e5a9 100644 --- a/src/diagrams/class/classRenderer-v2.js +++ b/src/diagrams/class/classRenderer-v2.js @@ -269,99 +269,6 @@ export const setConf = function (cnf) { * @param {string} text * @param {string} id */ -export const drawOld = function (text, id) { - idCache = {}; - parser.yy.clear(); - parser.parse(text); - - log.info('Rendering diagram ' + text); - - // Fetch the default direction, use TD if none was found - const diagram = select(`[id='${id}']`); - // insertMarkers(diagram); - - // Layout graph, Create a new directed graph - const g = new graphlib.Graph({ - multigraph: true, - }); - - // Set an object for the graph label - g.setGraph({ - isMultiGraph: true, - }); - - // Default to assigning a new object as a label for each new edge. - g.setDefaultEdgeLabel(function () { - return {}; - }); - - const classes = classDb.getClasses(); - log.info('classes:'); - log.info(classes); - const keys = Object.keys(classes); - for (let i = 0; i < keys.length; i++) { - const classDef = classes[keys[i]]; - const node = svgDraw.drawClass(diagram, classDef, conf); - idCache[node.id] = node; - - // Add nodes to the graph. The first argument is the node id. The second is - // metadata about the node. In this case we're going to add labels to each of - // our nodes. - g.setNode(node.id, node); - - log.info('Org height: ' + node.height); - } - - const relations = classDb.getRelations(); - log.info('relations:', relations); - relations.forEach(function (relation) { - log.info( - 'tjoho' + getGraphId(relation.id1) + getGraphId(relation.id2) + JSON.stringify(relation) - ); - g.setEdge( - getGraphId(relation.id1), - getGraphId(relation.id2), - { - relation: relation, - }, - relation.title || 'DEFAULT' - ); - }); - - dagre.layout(g); - g.nodes().forEach(function (v) { - if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') { - log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v))); - select('#' + lookUpDomId(v)).attr( - 'transform', - 'translate(' + - (g.node(v).x - g.node(v).width / 2) + - ',' + - (g.node(v).y - g.node(v).height / 2) + - ' )' - ); - } - }); - - g.edges().forEach(function (e) { - if (typeof e !== 'undefined' && typeof g.edge(e) !== 'undefined') { - log.debug('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(g.edge(e))); - svgDraw.drawEdge(diagram, g.edge(e), g.edge(e).relation, conf); - } - }); - - const svgBounds = diagram.node().getBBox(); - const width = svgBounds.width + padding * 2; - const height = svgBounds.height + padding * 2; - - configureSvgSize(diagram, height, width, conf.useMaxWidth); - - // Ensure the viewBox includes the whole svgBounds area with extra space for padding - const vBox = `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`; - log.debug(`viewBox ${vBox}`); - diagram.attr('viewBox', vBox); -}; - export const draw = function (text, id) { log.info('Drawing class - ', id); classDb.clear(); diff --git a/src/diagrams/class/classRenderer.js b/src/diagrams/class/classRenderer.js index ca3fd1d94..b2a57d032 100644 --- a/src/diagrams/class/classRenderer.js +++ b/src/diagrams/class/classRenderer.js @@ -6,6 +6,7 @@ import classDb, { lookUpDomId } from './classDb'; import { parser } from './parser/classDiagram'; import svgDraw from './svgDraw'; import { configureSvgSize } from '../../utils'; +import { getConfig } from '../../config'; parser.yy = classDb; @@ -165,8 +166,20 @@ export const draw = function (text, id) { log.info('Rendering diagram ' + text); + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + // Fetch the default direction, use TD if none was found - const diagram = select(`[id='${id}']`); + const diagram = root.select(`[id='${id}']`); diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink'); insertMarkers(diagram); @@ -220,14 +233,16 @@ export const draw = function (text, id) { g.nodes().forEach(function (v) { if (typeof v !== 'undefined' && typeof g.node(v) !== 'undefined') { log.debug('Node ' + v + ': ' + JSON.stringify(g.node(v))); - select('#' + lookUpDomId(v)).attr( - 'transform', - 'translate(' + - (g.node(v).x - g.node(v).width / 2) + - ',' + - (g.node(v).y - g.node(v).height / 2) + - ' )' - ); + root + .select('#' + lookUpDomId(v)) + .attr( + 'transform', + 'translate(' + + (g.node(v).x - g.node(v).width / 2) + + ',' + + (g.node(v).y - g.node(v).height / 2) + + ' )' + ); } }); diff --git a/src/diagrams/er/erRenderer.js b/src/diagrams/er/erRenderer.js index a1e027ccc..d2e2cc0d9 100644 --- a/src/diagrams/er/erRenderer.js +++ b/src/diagrams/er/erRenderer.js @@ -545,6 +545,17 @@ export const draw = function (text, id) { erDb.clear(); const parser = erParser.parser; parser.yy = erDb; + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; // Parse the text to populate erDb try { @@ -554,7 +565,7 @@ export const draw = function (text, id) { } // Get a reference to the svg node that contains the text - const svg = select(`[id='${id}']`); + const svg = root.select(`[id='${id}']`); // Add cardinality marker definitions to the svg erMarkers.insertMarkers(svg, conf); diff --git a/src/diagrams/flowchart/flowRenderer-v2.js b/src/diagrams/flowchart/flowRenderer-v2.js index b046d9c67..545107c0d 100644 --- a/src/diagrams/flowchart/flowRenderer-v2.js +++ b/src/diagrams/flowchart/flowRenderer-v2.js @@ -25,9 +25,11 @@ export const setConf = function (cnf) { * @param vert Object containing the vertices. * @param g The graph that is to be drawn. * @param svgId + * @param root + * @param doc */ -export const addVertices = function (vert, g, svgId) { - const svg = select(`[id="${svgId}"]`); +export const addVertices = function (vert, g, svgId, root, doc) { + const svg = root.select(`[id="${svgId}"]`); const keys = Object.keys(vert); // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition @@ -62,13 +64,13 @@ export const addVertices = function (vert, g, svgId) { vertexNode = addHtmlLabel(svg, node).node(); vertexNode.parentNode.removeChild(vertexNode); } else { - const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); + const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); const rows = vertexText.split(common.lineBreakRegex); for (let j = 0; j < rows.length; j++) { - const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); tspan.setAttribute('dy', '1em'); tspan.setAttribute('x', '1'); @@ -374,6 +376,18 @@ export const draw = function (text, id) { const nodeSpacing = conf.nodeSpacing || 50; const rankSpacing = conf.rankSpacing || 50; + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + // Create the input mermaid.graph const g = new graphlib.Graph({ multigraph: true, @@ -417,18 +431,18 @@ export const draw = function (text, id) { g.setParent(subG.nodes[j], subG.id); } } - addVertices(vert, g, id); + addVertices(vert, g, id, root, doc); addEdges(edges, g); // Add custom shapes // flowChartShapes.addToRenderV2(addShape); // Set up an SVG group so that we can translate the final graph. - const svg = select(`[id="${id}"]`); + const svg = root.select(`[id="${id}"]`); svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink'); // Run the renderer. This is what draws the final graph. - const element = select('#' + id + ' g'); + const element = root.select('#' + id + ' g'); render(element, g, ['point', 'circle', 'cross'], 'flowchart', id); const padding = conf.diagramPadding; @@ -452,14 +466,14 @@ export const draw = function (text, id) { // Add label rects for non html labels if (!conf.htmlLabels) { - const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); + const labels = doc.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); for (let k = 0; k < labels.length; k++) { const label = labels[k]; // Get dimensions of label const dim = label.getBBox(); - const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect'); rect.setAttribute('rx', 0); rect.setAttribute('ry', 0); rect.setAttribute('width', dim.width); @@ -478,7 +492,7 @@ export const draw = function (text, id) { if (vertex.link) { const node = select('#' + id + ' [id="' + key + '"]'); if (node) { - const link = document.createElementNS('http://www.w3.org/2000/svg', 'a'); + const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a'); link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' ')); link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link); link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener'); diff --git a/src/diagrams/flowchart/flowRenderer.js b/src/diagrams/flowchart/flowRenderer.js index c65f4397a..72f4a9085 100644 --- a/src/diagrams/flowchart/flowRenderer.js +++ b/src/diagrams/flowchart/flowRenderer.js @@ -26,9 +26,12 @@ export const setConf = function (cnf) { * @param vert Object containing the vertices. * @param g The graph that is to be drawn. * @param svgId + * @param root + * @param doc */ -export const addVertices = function (vert, g, svgId) { - const svg = select(`[id="${svgId}"]`); +export const addVertices = function (vert, g, svgId, root, doc) { + const securityLevel = getConfig().securityLevel; + const svg = root.select(`[id="${svgId}"]`); const keys = Object.keys(vert); // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition @@ -63,13 +66,13 @@ export const addVertices = function (vert, g, svgId) { vertexNode = addHtmlLabel(svg, node).node(); vertexNode.parentNode.removeChild(vertexNode); } else { - const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); + const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); const rows = vertexText.split(common.lineBreakRegex); for (let j = 0; j < rows.length; j++) { - const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); tspan.setAttribute('dy', '1em'); tspan.setAttribute('x', '1'); @@ -293,6 +296,17 @@ export const draw = function (text, id) { const parser = flow.parser; parser.yy = flowDb; + const securityLevel = getConfig().securityLevel; + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + // Parse the graph definition // try { parser.parse(text); @@ -355,7 +369,7 @@ export const draw = function (text, id) { g.setParent(flowDb.lookUpDomId(subG.nodes[j]), flowDb.lookUpDomId(subG.id)); } } - addVertices(vert, g, id); + addVertices(vert, g, id, root, doc); addEdges(edges, g); // Create the renderer @@ -404,13 +418,13 @@ export const draw = function (text, id) { }; // Set up an SVG group so that we can translate the final graph. - const svg = select(`[id="${id}"]`); + const svg = root.select(`[id="${id}"]`); svg.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink'); log.warn(g); // Run the renderer. This is what draws the final graph. - const element = select('#' + id + ' g'); + const element = root.select('#' + id + ' g'); render(element, g); element.selectAll('g.node').attr('title', function () { @@ -436,10 +450,10 @@ export const draw = function (text, id) { for (i = 0; i < subGraphs.length; i++) { subG = subGraphs[i]; if (subG.title !== 'undefined') { - const clusterRects = document.querySelectorAll( + const clusterRects = doc.querySelectorAll( '#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"] rect' ); - const clusterEl = document.querySelectorAll( + const clusterEl = doc.querySelectorAll( '#' + id + ' [id="' + flowDb.lookUpDomId(subG.id) + '"]' ); @@ -459,14 +473,14 @@ export const draw = function (text, id) { // Add label rects for non html labels if (!evaluate(conf.htmlLabels) || true) { // eslint-disable-line - const labels = document.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); + const labels = doc.querySelectorAll('[id="' + id + '"] .edgeLabel .label'); for (let k = 0; k < labels.length; k++) { const label = labels[k]; // Get dimensions of label const dim = label.getBBox(); - const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect'); + const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect'); rect.setAttribute('rx', 0); rect.setAttribute('ry', 0); rect.setAttribute('width', dim.width); @@ -483,9 +497,9 @@ export const draw = function (text, id) { const vertex = vert[key]; if (vertex.link) { - const node = select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]'); + const node = root.select('#' + id + ' [id="' + flowDb.lookUpDomId(key) + '"]'); if (node) { - const link = document.createElementNS('http://www.w3.org/2000/svg', 'a'); + const link = doc.createElementNS('http://www.w3.org/2000/svg', 'a'); link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' ')); link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link); link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener'); diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index c535a7285..00b991f57 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -29,7 +29,19 @@ export const draw = function (text, id) { parser.yy.clear(); parser.parse(text); - const elem = document.getElementById(id); + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + + const elem = doc.getElementById(id); w = elem.parentElement.offsetWidth; if (typeof w === 'undefined') { @@ -47,7 +59,7 @@ export const draw = function (text, id) { // Set viewBox elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h); - const svg = select(`[id="${id}"]`); + const svg = root.select(`[id="${id}"]`); // Set timescale const timeScale = scaleTime() @@ -505,11 +517,11 @@ export const draw = function (text, id) { const rows = d[0].split(common.lineBreakRegex); const dy = -(rows.length - 1) / 2; - const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); + const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); svgLabel.setAttribute('dy', dy + 'em'); for (let j = 0; j < rows.length; j++) { - const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan'); + const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); tspan.setAttribute('alignment-baseline', 'central'); tspan.setAttribute('x', '10'); if (j > 0) tspan.setAttribute('dy', '1em'); diff --git a/src/diagrams/git/gitGraphRenderer.js b/src/diagrams/git/gitGraphRenderer.js index e9da5faa1..49d04b759 100644 --- a/src/diagrams/git/gitGraphRenderer.js +++ b/src/diagrams/git/gitGraphRenderer.js @@ -4,6 +4,7 @@ import db from './gitGraphAst'; import gitGraphParser from './parser/gitGraph'; import { log } from '../../logger'; import { interpolateToCurve } from '../../utils'; +import { getConfig } from '../../config'; let allCommitsDict = {}; let branchNum; @@ -338,6 +339,18 @@ export const draw = function (txt, id, ver) { parser.yy = db; parser.yy.clear(); + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + log.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver); // Parse the graph definition parser.parse(txt + '\n'); @@ -352,7 +365,7 @@ export const draw = function (txt, id, ver) { config.nodeLabel.width = '100%'; config.nodeLabel.y = -1 * 2 * config.nodeRadius; } - const svg = select(`[id="${id}"]`); + const svg = root.select(`[id="${id}"]`); svgCreateDefs(svg); branchNum = 1; for (let branch in branches) { diff --git a/src/diagrams/info/infoRenderer.js b/src/diagrams/info/infoRenderer.js index 12d3217ee..b01931a22 100644 --- a/src/diagrams/info/infoRenderer.js +++ b/src/diagrams/info/infoRenderer.js @@ -3,6 +3,7 @@ import { select } from 'd3'; import db from './infoDb'; import infoParser from './parser/info'; import { log } from '../../logger'; +import { getConfig } from '../../config'; const conf = {}; export const setConf = function (cnf) { @@ -25,11 +26,24 @@ export const draw = (text, id, version) => { const parser = infoParser.parser; parser.yy = db; log.debug('Renering info diagram\n' + text); + + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + // Parse the graph definition parser.parse(text); log.debug('Parsed info diagram'); // Fetch the default direction, use TD if none was found - const svg = select('#' + id); + const svg = root.select('#' + id); const g = svg.append('g'); diff --git a/src/diagrams/pie/pieRenderer.js b/src/diagrams/pie/pieRenderer.js index c405a5c6d..f8cf77380 100644 --- a/src/diagrams/pie/pieRenderer.js +++ b/src/diagrams/pie/pieRenderer.js @@ -22,11 +22,24 @@ export const draw = (txt, id) => { const parser = pieParser.parser; parser.yy = pieData; log.debug('Rendering info diagram\n' + txt); + + const securityLevel = configApi.getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + // Parse the Pie Chart definition parser.yy.clear(); parser.parse(txt); log.debug('Parsed info diagram'); - const elem = document.getElementById(id); + const elem = doc.getElementById(id); width = elem.parentElement.offsetWidth; if (typeof width === 'undefined') { @@ -40,7 +53,7 @@ export const draw = (txt, id) => { width = conf.pie.useWidth; } - const diagram = select('#' + id); + const diagram = root.select('#' + id); configureSvgSize(diagram, height, width, conf.pie.useMaxWidth); // Set viewBox diff --git a/src/diagrams/requirement/requirementRenderer.js b/src/diagrams/requirement/requirementRenderer.js index 5ba75d464..0814b0088 100644 --- a/src/diagrams/requirement/requirementRenderer.js +++ b/src/diagrams/requirement/requirementRenderer.js @@ -8,6 +8,7 @@ import common from '../common/common'; import { parser } from './parser/requirementDiagram'; import requirementDb from './requirementDb'; import markers from './requirementMarkers'; +import { getConfig } from '../../config'; const conf = {}; let relCnt = 0; @@ -321,7 +322,19 @@ export const draw = (text, id) => { parser.yy.clear(); parser.parse(text); - const svg = select(`[id='${id}']`); + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + + const svg = root.select(`[id='${id}']`); markers.insertLineEndings(svg, conf); const g = new graphlib.Graph({ diff --git a/src/diagrams/sequence/sequenceRenderer.js b/src/diagrams/sequence/sequenceRenderer.js index 5e7cc0c65..6bd75aa88 100644 --- a/src/diagrams/sequence/sequenceRenderer.js +++ b/src/diagrams/sequence/sequenceRenderer.js @@ -539,6 +539,18 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop */ export const draw = function (text, id) { conf = configApi.getConfig().sequence; + const securityLevel = configApi.getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + parser.yy.clear(); parser.yy.setWrap(conf.wrap); parser.parse(text + '\n'); diff --git a/src/diagrams/state/stateRenderer-v2.js b/src/diagrams/state/stateRenderer-v2.js index 9137d958e..6499d58a3 100644 --- a/src/diagrams/state/stateRenderer-v2.js +++ b/src/diagrams/state/stateRenderer-v2.js @@ -258,6 +258,8 @@ export const draw = function (text, id) { const nodeSpacing = conf.nodeSpacing || 50; const rankSpacing = conf.rankSpacing || 50; + const securityLevel = getConfig().securityLevel; + log.info(stateDb.getRootDocV2()); stateDb.extract(stateDb.getRootDocV2()); log.info(stateDb.getRootDocV2()); @@ -281,10 +283,20 @@ export const draw = function (text, id) { setupNode(g, undefined, stateDb.getRootDocV2(), true); // Set up an SVG group so that we can translate the final graph. - const svg = select(`[id="${id}"]`); + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + const svg = root.select(`[id="${id}"]`); // Run the renderer. This is what draws the final graph. - const element = select('#' + id + ' g'); + + const element = root.select('#' + id + ' g'); render(element, g, ['barb'], 'statediagram', id); const padding = 8; diff --git a/src/diagrams/state/stateRenderer.js b/src/diagrams/state/stateRenderer.js index 5a297aa05..e243987bc 100644 --- a/src/diagrams/state/stateRenderer.js +++ b/src/diagrams/state/stateRenderer.js @@ -46,12 +46,24 @@ const insertMarkers = function (elem) { */ export const draw = function (text, id) { conf = getConfig().state; + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + parser.yy.clear(); parser.parse(text); log.debug('Rendering diagram ' + text); // Fetch the default direction, use TD if none was found - const diagram = select(`[id='${id}']`); + const diagram = root.select(`[id='${id}']`); insertMarkers(diagram); // Layout graph, Create a new directed graph @@ -69,7 +81,7 @@ export const draw = function (text, id) { }); const rootDoc = stateDb.getRootDoc(); - renderDoc(rootDoc, diagram, undefined, false); + renderDoc(rootDoc, diagram, undefined, false, root, doc); const padding = conf.padding; const bounds = diagram.node().getBBox(); @@ -90,7 +102,7 @@ const getLabelWidth = (text) => { return text ? text.length * conf.fontSizeFactor : 1; }; -const renderDoc = (doc, diagram, parentId, altBkg) => { +const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument) => { // Layout graph, Create a new directed graph const graph = new graphlib.Graph({ compound: true, @@ -159,7 +171,7 @@ const renderDoc = (doc, diagram, parentId, altBkg) => { let node; if (stateDef.doc) { let sub = diagram.append('g').attr('id', stateDef.id).attr('class', 'stateGroup'); - node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg); + node = renderDoc(stateDef.doc, sub, stateDef.id, !altBkg, root, domDocument); if (first) { // first = false; @@ -234,21 +246,22 @@ const renderDoc = (doc, diagram, parentId, altBkg) => { graph.nodes().forEach(function (v) { if (typeof v !== 'undefined' && typeof graph.node(v) !== 'undefined') { log.warn('Node ' + v + ': ' + JSON.stringify(graph.node(v))); - select('#' + svgElem.id + ' #' + v).attr( - 'transform', - 'translate(' + - (graph.node(v).x - graph.node(v).width / 2) + - ',' + - (graph.node(v).y + - (transformationLog[v] ? transformationLog[v].y : 0) - - graph.node(v).height / 2) + - ' )' - ); - select('#' + svgElem.id + ' #' + v).attr( - 'data-x-shift', - graph.node(v).x - graph.node(v).width / 2 - ); - const dividers = document.querySelectorAll('#' + svgElem.id + ' #' + v + ' .divider'); + root + .select('#' + svgElem.id + ' #' + v) + .attr( + 'transform', + 'translate(' + + (graph.node(v).x - graph.node(v).width / 2) + + ',' + + (graph.node(v).y + + (transformationLog[v] ? transformationLog[v].y : 0) - + graph.node(v).height / 2) + + ' )' + ); + root + .select('#' + svgElem.id + ' #' + v) + .attr('data-x-shift', graph.node(v).x - graph.node(v).width / 2); + const dividers = domDocument.querySelectorAll('#' + svgElem.id + ' #' + v + ' .divider'); dividers.forEach((divider) => { const parent = divider.parentElement; let pWidth = 0; diff --git a/src/diagrams/user-journey/journeyRenderer.js b/src/diagrams/user-journey/journeyRenderer.js index 18ac05147..7ce2caa68 100644 --- a/src/diagrams/user-journey/journeyRenderer.js +++ b/src/diagrams/user-journey/journeyRenderer.js @@ -54,8 +54,20 @@ export const draw = function (text, id) { parser.yy.clear(); parser.parse(text + '\n'); + const securityLevel = getConfig().securityLevel; + // Handle root and ocument for when rendering in sanbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; + bounds.init(); - const diagram = select('#' + id); + const diagram = root.select('#' + id); diagram.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink'); svgDraw.initGraphics(diagram); diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js index bf064ba06..eb3a0182e 100755 --- a/src/mermaidAPI.js +++ b/src/mermaidAPI.js @@ -240,6 +240,7 @@ const render = function (id, _txt, cb, container) { const iframe = select('body') .append('iframe') .attr('id', 'i' + id) + .attr('style', 'width: 100%; height: 100%;') .attr('sandbox', ''); // const iframeBody = ; root = select(iframe.nodes()[0].contentDocument.body); @@ -258,6 +259,7 @@ const render = function (id, _txt, cb, container) { const iframe = select(container) .append('iframe') .attr('id', 'i' + id) + .attr('style', 'width: 100%; height: 100%;') .attr('sandbox', ''); // const iframeBody = ; root = select(iframe.nodes()[0].contentDocument.body); @@ -492,7 +494,10 @@ const render = function (id, _txt, cb, container) { // Fix for when the base tag is used let svgCode = root.select('#d' + id).node().innerHTML; log.debug('cnf.arrowMarkerAbsolute', cnf.arrowMarkerAbsolute); - if (!cnf.arrowMarkerAbsolute || cnf.arrowMarkerAbsolute === 'false') { + if ( + (!cnf.arrowMarkerAbsolute || cnf.arrowMarkerAbsolute === 'false') && + cnf.arrowMarkerAbsolute !== 'sandbox' + ) { svgCode = svgCode.replace(/marker-end="url\(.*?#/g, 'marker-end="url(#', 'g'); }