merge develop to current branch

This commit is contained in:
Ashish Jain
2022-02-24 19:24:42 +01:00
45 changed files with 1197 additions and 343 deletions

View File

@@ -143,6 +143,7 @@ export const addMember = function (className, member) {
if (memberString.startsWith('<<') && memberString.endsWith('>>')) {
// Remove leading and trailing brackets
// theClass.annotations.push(memberString.substring(2, memberString.length - 2));
theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2)));
} else if (memberString.indexOf(')') > 0) {
theClass.methods.push(sanitizeText(memberString));
@@ -212,8 +213,10 @@ export const setLink = function (ids, linkStr, target) {
if (_id[0].match(/\d/)) id = MERMAID_DOM_ID_PREFIX + id;
if (typeof classes[id] !== 'undefined') {
classes[id].link = utils.formatUrl(linkStr, config);
if (typeof target === 'string') {
classes[id].linkTarget = target;
if (config.securityLevel === 'sandbox') {
classes[id].linkTarget = '_top';
} else if (typeof target === 'string') {
classes[id].linkTarget = sanitizeText(target);
} else {
classes[id].linkTarget = '_blank';
}

View File

@@ -269,101 +269,8 @@ 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');
log.info('Drawing class - ', id);
classDb.clear();
// const parser = classDb.parser;
// parser.yy = classDb;
@@ -379,6 +286,7 @@ export const draw = function (text, id) {
//let dir = 'TD';
const conf = getConfig().flowchart;
const securityLevel = getConfig().securityLevel;
log.info('config:', conf);
const nodeSpacing = conf.nodeSpacing || 50;
const rankSpacing = conf.rankSpacing || 50;
@@ -430,11 +338,19 @@ export const draw = function (text, id) {
// flowChartShapes.addToRenderV2(addShape);
// 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 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, ['aggregation', 'extension', 'composition', 'dependency'], 'classDiagram', id);
// element.selectAll('g.node').attr('title', function() {
@@ -462,14 +378,15 @@ 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 doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
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);

View File

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

View File

@@ -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);

View File

@@ -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');
@@ -131,6 +133,9 @@ export const addVertices = function (vert, g, svgId) {
case 'group':
_shape = 'rect';
break;
case 'doublecircle':
_shape = 'doublecircle';
break;
default:
_shape = 'rect';
}
@@ -374,6 +379,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 +434,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 +469,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,11 +495,13 @@ 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');
if (vertex.linkTarget) {
if (securityLevel === 'sandbox') {
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', '_top');
} else if (vertex.linkTarget) {
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', vertex.linkTarget);
}

View File

@@ -26,9 +26,15 @@ 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
* @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}"]`) : root.select(`[id="${svgId}"]`);
const doc = !_doc ? document : _doc;
const keys = Object.keys(vert);
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
@@ -63,13 +69,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 +299,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 +372,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 +421,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 +453,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 +476,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,13 +500,15 @@ 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');
if (vertex.linkTarget) {
if (securityLevel === 'sandbox') {
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', '_top');
} else if (vertex.linkTarget) {
link.setAttributeNS('http://www.w3.org/2000/svg', 'target', vertex.linkTarget);
}

View File

@@ -159,6 +159,40 @@ describe('[Singlenodes] when parsing', () => {
expect(vert['a'].text).toBe('A <br> end');
});
it('should handle a single double circle node', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A)));');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['a'].type).toBe('doublecircle');
});
it('should handle a single double circle node with whitespace after it', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A))) ;');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['a'].type).toBe('doublecircle');
});
it('should handle a single double circle node with html in it (SN3)', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;a(((A <br> end)));');
const vert = flow.parser.yy.getVertices();
const edges = flow.parser.yy.getEdges();
expect(edges.length).toBe(0);
expect(vert['a'].type).toBe('doublecircle');
expect(vert['a'].text).toBe('A <br> end');
});
it('should handle a single node with alphanumerics starting on a char', function () {
// Silly but syntactically correct
const res = flow.parser.parse('graph TD;id1;');

View File

@@ -121,6 +121,8 @@ that id.
"[|" return 'VERTEX_WITH_PROPS_START';
"[(" return 'CYLINDERSTART';
")]" return 'CYLINDEREND';
"(((" return 'DOUBLECIRCLESTART';
")))" return 'DOUBLECIRCLEEND';
\- return 'MINUS';
"." return 'DOT';
[\_] return 'UNDERSCORE';
@@ -373,6 +375,8 @@ node: vertex
vertex: idString SQS text SQE
{$$ = $1;yy.addVertex($1,$3,'square');}
| idString DOUBLECIRCLESTART text DOUBLECIRCLEEND
{$$ = $1;yy.addVertex($1,$3,'doublecircle');}
| idString PS PS text PE PE
{$$ = $1;yy.addVertex($1,$4,'circle');}
| idString '(-' text '-)'

View File

@@ -10,6 +10,7 @@ let axisFormat = '';
let todayMarker = '';
let includes = [];
let excludes = [];
let links = {};
let title = '';
let sections = [];
let tasks = [];
@@ -44,6 +45,7 @@ export const clear = function () {
inclusiveEndDates = false;
topAxis = false;
lastOrder = 0;
links = {};
};
export const setAxisFormat = function (txt) {
@@ -101,6 +103,10 @@ export const getExcludes = function () {
return excludes;
};
export const getLinks = function () {
return links;
};
export const setTitle = function (txt) {
title = txt;
};
@@ -505,6 +511,7 @@ export const setLink = function (ids, _linkStr) {
pushFun(id, () => {
window.open(linkStr, '_self');
});
links[id] = linkStr;
}
});
setClass(ids, 'clickable');
@@ -642,6 +649,7 @@ export default {
getExcludes,
setClickEvent,
setLink,
getLinks,
bindFunctions,
durationToDate,
isInvalidDate,

View File

@@ -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()
@@ -173,6 +185,10 @@ export const draw = function (text, id) {
// Draw the rects representing the tasks
const rectangles = svg.append('g').selectAll('rect').data(theArray).enter();
const links = ganttDb.getLinks();
// Render the tasks with links
// Render the other tasks
rectangles
.append('rect')
.attr('id', function (d) {
@@ -369,6 +385,32 @@ export const draw = function (text, id) {
return classStr + ' taskText taskText' + secNum + ' ' + taskType + ' width-' + textWidth;
}
});
const securityLevel = getConfig().securityLevel;
// Wrap the tasks in an a tag for working links without javascript
if (securityLevel === 'sandbox') {
let sandboxElement;
sandboxElement = select('#i' + id);
const root = select(sandboxElement.nodes()[0].contentDocument.body);
const doc = sandboxElement.nodes()[0].contentDocument;
rectangles
.filter(function (d) {
return typeof links[d.id] !== 'undefined';
})
.each(function (o) {
var taskRect = doc.querySelector('#' + o.id);
var taskText = doc.querySelector('#' + o.id + '-text');
const oldParent = taskRect.parentNode;
var Link = doc.createElement('a');
Link.setAttribute('xlink:href', links[o.id]);
Link.setAttribute('target', '_top');
oldParent.appendChild(Link);
Link.appendChild(taskRect);
Link.appendChild(taskText);
});
}
}
/**
* @param theGap
@@ -505,11 +547,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');

View File

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

View File

@@ -8,6 +8,7 @@
%x string
%x title
%x accDescription
%x open_directive
%x type_directive
%x arg_directive
@@ -26,6 +27,8 @@
[\s]+ /* ignore */
title { this.begin("title");return 'title'; }
<title>(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; }
accDescription { this.begin("accDescription");return 'accDescription'; }
<accDescription>(?!\n|;|#)*[^\n]* { this.popState(); return "description_value"; }
["] { this.begin("string"); }
<string>["] { this.popState(); }
<string>[^"]* { return "txt"; }
@@ -34,7 +37,6 @@ title { this.begin("ti
":"[\s]*[\d]+(?:\.[\d]+)? return "value";
<<EOF>> return 'EOF';
/lex
%start start
@@ -61,6 +63,7 @@ statement
:
| txt value { yy.addSection($1,yy.cleanupValue($2)); }
| title title_value { $$=$2.trim();yy.setTitle($$); }
| accDescription description_value { $$=$2.trim();yy.setAccDescription($$); }
| directive
;

View File

@@ -62,6 +62,37 @@ pie
expect(title).toBe('a 60/40 pie');
});
it('should handle simple pie without an acc description', function () {
const res = pie.parser.parse(`pie title a neat chart
"ash" : 60
"bat" : 40
`);
const sections = pieDb.getSections();
const title = pieDb.getTitle();
const description = pieDb.getAccDescription();
const section1 = sections['ash'];
expect(section1).toBe(60);
expect(title).toBe('a neat chart');
expect(description).toBe('');
});
it('should handle simple pie with an acc description', function () {
const res = pie.parser.parse(`pie title a neat chart
accDescription a neat description
"ash" : 60
"bat" : 40
`);
const sections = pieDb.getSections();
const title = pieDb.getTitle();
const description = pieDb.getAccDescription();
const section1 = sections['ash'];
expect(section1).toBe(60);
expect(title).toBe('a neat chart');
expect(description).toBe('a neat description');
});
it('should handle simple pie with positive decimal', function () {
const res = pie.parser.parse(`pie
"ash" : 60.67

View File

@@ -1,9 +1,12 @@
import { log } from '../../logger';
import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
import common from '../common/common';
const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig());
let sections = {};
let title = '';
let description = '';
let showData = false;
export const parseDirective = function (statement, context, type) {
@@ -11,6 +14,7 @@ export const parseDirective = function (statement, context, type) {
};
const addSection = function (id, value) {
id = common.sanitizeText(id, configApi.getConfig());
if (typeof sections[id] === 'undefined') {
sections[id] = value;
log.debug('Added new section :', id);
@@ -19,7 +23,7 @@ const addSection = function (id, value) {
const getSections = () => sections;
const setTitle = function (txt) {
title = txt;
title = common.sanitizeText(txt, configApi.getConfig());
};
const setShowData = function (toggle) {
@@ -33,6 +37,15 @@ const getShowData = function () {
const getTitle = function () {
return title;
};
const setAccDescription = function (txt) {
description = common.sanitizeText(txt, configApi.getConfig());
};
const getAccDescription = function () {
return description;
};
const cleanupValue = function (value) {
if (value.substring(0, 1) === ':') {
value = value.substring(1).trim();
@@ -62,5 +75,7 @@ export default {
getTitle,
setShowData,
getShowData,
getAccDescription,
setAccDescription,
// parseError
};

View File

@@ -5,6 +5,7 @@ import pieParser from './parser/pie';
import { log } from '../../logger';
import { configureSvgSize } from '../../utils';
import * as configApi from '../../config';
import addSVGAccessibilityFields from '../../accessibility';
let conf = configApi.getConfig();
@@ -22,11 +23,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,9 +54,10 @@ 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);
addSVGAccessibilityFields(parser.yy, diagram, id);
// Set viewBox
elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height);

View File

@@ -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({

View File

@@ -452,13 +452,20 @@ export const drawActors = function (diagram, actors, actorKeys, verticalPos) {
bounds.bumpVerticalPos(maxHeight);
};
export const drawActorsPopup = function (diagram, actors, actorKeys) {
export const drawActorsPopup = function (diagram, actors, actorKeys, doc) {
var maxHeight = 0;
var maxWidth = 0;
for (let i = 0; i < actorKeys.length; i++) {
const actor = actors[actorKeys[i]];
const minMenuWidth = getRequiredPopupWidth(actor);
var menuDimensions = svgDraw.drawPopup(diagram, actor, minMenuWidth, conf, conf.forceMenus);
var menuDimensions = svgDraw.drawPopup(
diagram,
actor,
minMenuWidth,
conf,
conf.forceMenus,
doc
);
if (menuDimensions.height > maxHeight) {
maxHeight = menuDimensions.height;
}
@@ -539,13 +546,26 @@ 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');
bounds.init();
log.debug(`C:${JSON.stringify(conf, null, 2)}`);
const diagram = select(`[id="${id}"]`);
const diagram =
securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : select(`[id="${id}"]`);
// Fetch data from the parsing
const actors = parser.yy.getActors();
@@ -733,7 +753,7 @@ export const draw = function (text, id) {
}
// only draw popups for the top row of actors.
var requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys);
var requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc);
const { bounds: box } = bounds.getBounds();

View File

@@ -30,6 +30,8 @@ export const drawRect = function (elem, rectData) {
const addPopupInteraction = (id, actorCnt) => {
addFunction(() => {
const arr = document.querySelectorAll(id);
// This will be the case when running in sandboxed mode
if (arr.length === 0) return;
arr[0].addEventListener('mouseover', function () {
popupMenuUpFunc('actor' + actorCnt + '_popup');
});

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);