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');
}