Merge branch 'develop' into sidv/esbuild

* develop:
  Replace GoogleAnalytics with Plausible
  fix(git): support single character branch names
  Cleanup unused variables and some commented out code
  Release 9.1.7
  Fix for broken rendering test
  Fix for issue #3428, load the configured diagrams even when initialize has not been called.
  #3395 Renabling the error graph which is rendered on error
  #3395 Fix for lopp stopping at first failure
This commit is contained in:
Sidharth Vinod 2022-09-16 17:30:07 +05:30
commit 2f41013740
No known key found for this signature in database
GPG Key ID: FB5CCD378D3907CD
13 changed files with 130 additions and 75 deletions

View File

@ -38,7 +38,15 @@
</style> </style>
</head> </head>
<body> <body>
<pre class="mermaid2" style="width: 50%">
flowchart LR
a ---
</pre>
<pre class="mermaid" style="width: 50%"> <pre class="mermaid" style="width: 50%">
flowchart LR
a2 ---
</pre>
<pre class="mermaid2" style="width: 50%">
flowchart LR flowchart LR
classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px; classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px;
classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px; classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px;
@ -73,7 +81,31 @@ flowchart TD
</pre> </pre>
<pre class="mermaid" style="width: 50%"> <pre class="mermaid" style="width: 50%">
flowchart TD flowchart TD
id
release-branch[Create Release Branch]:::relClass
develop-branch[Update Develop Branch]:::relClass
github-release-draft[GitHub Release Draft]:::relClass
trigger-pipeline[Trigger Jenkins pipeline]:::fixClass
github-release[GitHub Release]:::postClass
build-ready --> release-branch
build-ready --> develop-branch
release-branch --> jenkins-release-build
jenkins-release-build --> github-release-draft
jenkins-release-build --> install-release
install-release --> verify-release
jenkins-release-build --> announce
github-release-draft --> github-release
verify-release --> verify-check
verify-check -- Yes --> github-release
verify-check -- No --> release-fix
release-fix --> release-branch-pr
verify-check -- No --> delete-artifacts
release-branch-pr --> trigger-pipeline
delete-artifacts --> trigger-pipeline
trigger-pipeline --> jenkins-release-build
</pre> </pre>
<pre class="mermaid2" style="width: 50%"> <pre class="mermaid2" style="width: 50%">
flowchart LR flowchart LR
@ -357,6 +389,11 @@ flowchart TD
document.getElementsByTagName('body')[0].appendChild(div); document.getElementsByTagName('body')[0].appendChild(div);
} }
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script> </script>
</body> </body>
</html> </html>

View File

@ -21,22 +21,13 @@
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"
/> />
<script src="//cdn.jsdelivr.net/npm/mermaid@9.1.6/dist/mermaid.min.js"></script> <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script>
<!-- <script src="http://localhost:9000/mermaid.js"></script> --> <!-- <script src="http://localhost:9000/mermaid.js"></script> -->
<script> <script
// prettier-ignore defer
(function (i, s, o, g, r, a, m) { data-domain="mermaid-js.github.io"
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () { src="https://plausible.io/js/plausible.js"
(i[r].q = i[r].q || []).push(arguments) ></script>
}, i[r].l = 1 * new Date(); a = s.createElement(o),
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-153180559-1', 'auto');
if (location) {
ga('send', 'pageview', location.hash);
}
</script>
<script> <script>
var require = { var require = {
paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' }, paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.29.1/min/vs' },

View File

@ -97,7 +97,29 @@ import journeyDb from '../diagrams/user-journey/journeyDb';
import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; import journeyRenderer from '../diagrams/user-journey/journeyRenderer';
import journeyStyles from '../diagrams/user-journey/styles'; import journeyStyles from '../diagrams/user-journey/styles';
import errorRenderer from '../diagrams/error/errorRenderer';
import errorStyles from '../diagrams/error/styles';
export const addDiagrams = () => { export const addDiagrams = () => {
registerDiagram(
'error',
// Special diagram with error messages but setup as a regular diagram
{
db: {},
styles: errorStyles,
renderer: errorRenderer,
parser: {
parser: { yy: {} },
parse: () => {
// no op
},
},
init: () => {
// no op
},
},
(text) => text.toLowerCase().trim() === 'error'
);
registerDiagram( registerDiagram(
'c4', 'c4',
{ {

View File

@ -1,7 +1,7 @@
/** Created by knut on 14-12-11. */ /** Created by knut on 14-12-11. */
import { select } from 'd3'; import { select } from 'd3';
import { log } from './logger'; import { log } from '../../logger';
import { getErrorMessage } from './utils'; import { getErrorMessage } from '../../utils';
let conf = {}; let conf = {};
@ -72,22 +72,22 @@ export const draw = (id: string, mermaidVersion: string) => {
g.append('text') // text label for the x axis g.append('text') // text label for the x axis
.attr('class', 'error-text') .attr('class', 'error-text')
.attr('x', 1240) .attr('x', 1440)
.attr('y', 250) .attr('y', 250)
.attr('font-size', '150px') .attr('font-size', '150px')
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text('Syntax error in graph'); .text('Syntax error in graph');
g.append('text') // text label for the x axis g.append('text') // text label for the x axis
.attr('class', 'error-text') .attr('class', 'error-text')
.attr('x', 1050) .attr('x', 1250)
.attr('y', 400) .attr('y', 400)
.attr('font-size', '100px') .attr('font-size', '100px')
.style('text-anchor', 'middle') .style('text-anchor', 'middle')
.text('mermaid version ' + mermaidVersion); .text('mermaid version ' + mermaidVersion);
svg.attr('height', 100); svg.attr('height', 100);
svg.attr('width', 400); svg.attr('width', 500);
svg.attr('viewBox', '768 0 512 512'); svg.attr('viewBox', '768 0 912 512');
} catch (e) { } catch (e) {
log.error('Error while rendering info diagram'); log.error('Error while rendering info diagram');
log.error(getErrorMessage(e)); log.error(getErrorMessage(e));

View File

@ -0,0 +1,3 @@
const getStyles = () => ``;
export default getStyles;

View File

@ -372,14 +372,16 @@ describe('when parsing a gitGraph', function () {
branch cherry-pick03 branch cherry-pick03
branch branch/example-branch branch branch/example-branch
branch merge/test_merge branch merge/test_merge
%% single character branch name
branch A
`; `;
parser.parse(str); parser.parse(str);
const commits = parser.yy.getCommits(); const commits = parser.yy.getCommits();
expect(Object.keys(commits).length).toBe(1); expect(Object.keys(commits).length).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('merge/test_merge'); expect(parser.yy.getCurrentBranch()).toBe('A');
expect(parser.yy.getDirection()).toBe('LR'); expect(parser.yy.getDirection()).toBe('LR');
expect(Object.keys(parser.yy.getBranches()).length).toBe(6); expect(Object.keys(parser.yy.getBranches()).length).toBe(7);
expect(Object.keys(parser.yy.getBranches())).toEqual( expect(Object.keys(parser.yy.getBranches())).toEqual(
expect.arrayContaining([ expect.arrayContaining([
'branch01', 'branch01',
@ -387,6 +389,7 @@ describe('when parsing a gitGraph', function () {
'cherry-pick03', 'cherry-pick03',
'branch/example-branch', 'branch/example-branch',
'merge/test_merge', 'merge/test_merge',
'A',
]) ])
); );
}); });

View File

@ -91,7 +91,9 @@ const drawCommits = (svg, commits, modifyGraph) => {
if (modifyGraph) { if (modifyGraph) {
let typeClass; let typeClass;
let commitSymbolType = let commitSymbolType =
typeof commit.customType !== 'undefined' ? commit.customType : commit.type; typeof commit.customType !== 'undefined' && commit.customType !== ''
? commit.customType
: commit.type;
switch (commitSymbolType) { switch (commitSymbolType) {
case commitType.NORMAL: case commitType.NORMAL:
typeClass = 'commit-normal'; typeClass = 'commit-normal';

View File

@ -61,7 +61,7 @@ checkout(?=\s|$) return 'CHECKOUT';
<string>["] this.popState(); <string>["] this.popState();
<string>[^"]* return 'STR'; <string>[^"]* return 'STR';
[0-9]+(?=\s|$) return 'NUM'; [0-9]+(?=\s|$) return 'NUM';
\w[-\./\w]*[-\w] return 'ID'; // only a subset of https://git-scm.com/docs/git-check-ref-format \w([-\./\w]*[-\w])? return 'ID'; // only a subset of https://git-scm.com/docs/git-check-ref-format
<<EOF>> return 'EOF'; <<EOF>> return 'EOF';
\s+ /* skip all whitespace */ // lowest priority so we can use lookaheads in earlier regex \s+ /* skip all whitespace */ // lowest priority so we can use lookaheads in earlier regex

View File

@ -85,9 +85,8 @@ function rightToLeft(mindmap) {
/** /**
* @param mindmap * @param mindmap
* @param dir * @param dir
* @param conf
*/ */
function layout(mindmap, dir, conf) { function layout(mindmap, dir) {
const bb = new BoundingBox(30, 60); const bb = new BoundingBox(30, 60);
const layout = new Layout(bb); const layout = new Layout(bb);

View File

@ -47,9 +47,9 @@ function wrap(text, width) {
}); });
} }
const defaultBkg = function (elem, node, section, conf) { const defaultBkg = function (elem, node, section) {
const rd = 5; const rd = 5;
const r = elem elem
.append('path') .append('path')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
@ -68,25 +68,22 @@ const defaultBkg = function (elem, node, section, conf) {
.attr('x2', node.width) .attr('x2', node.width)
.attr('y2', node.height); .attr('y2', node.height);
}; };
const rectBkg = function (elem, node, section, conf) { const rectBkg = function (elem, node) {
const r = elem elem
.append('rect') .append('rect')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
.attr('height', node.height) .attr('height', node.height)
.attr('width', node.width); .attr('width', node.width);
}; };
const cloudBkg = function (elem, node, section, conf) { const cloudBkg = function (elem, node) {
const rd = 5;
const r = elem;
const w = node.width; const w = node.width;
const h = node.height; const h = node.height;
const r0 = 0.1 * w;
const r1 = 0.15 * w; const r1 = 0.15 * w;
const r2 = 0.25 * w; const r2 = 0.25 * w;
const r3 = 0.35 * w; const r3 = 0.35 * w;
const r4 = 0.2 * w; const r4 = 0.2 * w;
const p = elem elem
.append('path') .append('path')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
@ -109,12 +106,11 @@ const cloudBkg = function (elem, node, section, conf) {
H0 V0 Z` H0 V0 Z`
); );
}; };
const bangBkg = function (elem, node, section, conf) { const bangBkg = function (elem, node) {
const rd = 5;
const w = node.width; const w = node.width;
const h = node.height; const h = node.height;
const r = 0.15 * w; const r = 0.15 * w;
const p = elem elem
.append('path') .append('path')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
@ -141,16 +137,15 @@ const bangBkg = function (elem, node, section, conf) {
H0 V0 Z` H0 V0 Z`
); );
}; };
const circleBkg = function (elem, node, section, conf) { const circleBkg = function (elem, node) {
const r = elem elem
.append('circle') .append('circle')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
.attr('r', node.width / 2); .attr('r', node.width / 2);
// .attr('width', node.width);
}; };
const roundedRectBkg = function (elem, node, section, conf) { const roundedRectBkg = function (elem, node) {
const r = elem elem
.append('rect') .append('rect')
.attr('id', 'node-' + node.id) .attr('id', 'node-' + node.id)
.attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr('class', 'node-bkg node-' + db.type2Str(node.type))
@ -183,7 +178,6 @@ export const drawNode = function (elem, node, section, conf) {
.append('text') .append('text')
.text(node.descr) .text(node.descr)
.attr('dy', '1em') .attr('dy', '1em')
// .attr('dy', '0')
.attr('alignment-baseline', 'middle') .attr('alignment-baseline', 'middle')
.attr('dominant-baseline', 'middle') .attr('dominant-baseline', 'middle')
.attr('text-anchor', 'middle') .attr('text-anchor', 'middle')
@ -195,18 +189,12 @@ export const drawNode = function (elem, node, section, conf) {
if (node.icon) { if (node.icon) {
if (node.type === db.nodeType.CIRCLE) { if (node.type === db.nodeType.CIRCLE) {
node.height += 50; node.height += 50;
const orgWidth = node.width;
node.width += 50; node.width += 50;
// node.width = Math.max(orgWidth, 100);
const widthDiff = Math.abs(node.width - orgWidth);
const icon = nodeElem const icon = nodeElem
.append('foreignObject') .append('foreignObject')
.attr('height', '50px') .attr('height', '50px')
.attr('width', node.width) .attr('width', node.width)
.attr('style', 'text-align: center;'); .attr('style', 'text-align: center;');
// .attr('x', 0)
// .attr('y', 0)
// .attr('class', 'node-icon ' + node.icon);
icon icon
.append('div') .append('div')
.attr('class', 'icon-container') .attr('class', 'icon-container')
@ -226,9 +214,7 @@ export const drawNode = function (elem, node, section, conf) {
.attr('width', '60px') .attr('width', '60px')
.attr('height', node.height) .attr('height', node.height)
.attr('style', 'text-align: center;margin-top:' + heightDiff / 2 + 'px;'); .attr('style', 'text-align: center;margin-top:' + heightDiff / 2 + 'px;');
// .attr('x', 0)
// .attr('y', 0)
// .attr('class', 'node-icon ' + node.icon);
icon icon
.append('div') .append('div')
.attr('class', 'icon-container') .attr('class', 'icon-container')
@ -258,15 +244,11 @@ export const drawNode = function (elem, node, section, conf) {
circleBkg(bkgElem, node, section, conf); circleBkg(bkgElem, node, section, conf);
break; break;
case db.nodeType.CLOUD: case db.nodeType.CLOUD:
// bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')');
cloudBkg(bkgElem, node, section, conf); cloudBkg(bkgElem, node, section, conf);
break; break;
case db.nodeType.BANG: case db.nodeType.BANG:
// bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')');
bangBkg(bkgElem, node, section, conf); bangBkg(bkgElem, node, section, conf);
break; break;
default:
// defaultBkg(bkgElem, node, section, conf);
} }
// Position the node to its coordinate // Position the node to its coordinate
@ -277,17 +259,7 @@ export const drawNode = function (elem, node, section, conf) {
return node.height; return node.height;
}; };
export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, section, conf) { export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, section) {
// edgesElem
// .append('line')
// .attr('x1', parent.x + parent.width / 2)
// .attr('y1', parent.y + parent.height / 2)
// .attr('x2', mindmap.x + mindmap.width / 2)
// .attr('y2', mindmap.y + mindmap.height / 2)
// .attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth);
//<path d="M100,250 Q250,100 400,250 T700,250" />
const sx = parent.x + parent.width / 2; const sx = parent.x + parent.width / 2;
const sy = parent.y + parent.height / 2; const sy = parent.y + parent.height / 2;
const ex = mindmap.x + mindmap.width / 2; const ex = mindmap.x + mindmap.width / 2;
@ -308,7 +280,7 @@ export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, sec
.attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth); .attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth);
}; };
export const positionNode = function (node, conf) { export const positionNode = function (node) {
const nodeElem = db.getElementById(node.id); const nodeElem = db.getElementById(node.id);
const x = node.x || 0; const x = node.x || 0;

View File

@ -95,9 +95,11 @@ const initThrowsErrors = function (
const idGenerator = new utils.initIdGenerator(conf.deterministicIds, conf.deterministicIDSeed); const idGenerator = new utils.initIdGenerator(conf.deterministicIds, conf.deterministicIDSeed);
let txt; let txt;
const errors = [];
// element is the current div with mermaid class // element is the current div with mermaid class
for (const element of Array.from(nodesToProcess)) { for (const element of Array.from(nodesToProcess)) {
log.info('Rendering diagram: ' + element.id);
/*! Check if previously processed */ /*! Check if previously processed */
if (element.getAttribute('data-processed')) { if (element.getAttribute('data-processed')) {
continue; continue;
@ -135,10 +137,17 @@ const initThrowsErrors = function (
} catch (error) { } catch (error) {
log.warn('Catching Error (bootstrap)', error); log.warn('Catching Error (bootstrap)', error);
// @ts-ignore: TODO Fix ts errors // @ts-ignore: TODO Fix ts errors
// TODO: We should be throwing an error object. const mermaidError = { error, str: error.str, hash: error.hash, message: error.str };
throw { error, message: error.str }; if (typeof mermaid.parseError === 'function') {
mermaid.parseError(mermaidError);
}
errors.push(mermaidError);
} }
} }
if (errors.length > 0) {
// TODO: We should be throwing an error object.
throw errors[0];
}
}; };
const initialize = function (config: MermaidConfig) { const initialize = function (config: MermaidConfig) {

View File

@ -26,7 +26,7 @@ import flowDb from './diagrams/flowchart/flowDb';
import flowRenderer from './diagrams/flowchart/flowRenderer'; import flowRenderer from './diagrams/flowchart/flowRenderer';
import ganttDb from './diagrams/gantt/ganttDb'; import ganttDb from './diagrams/gantt/ganttDb';
import Diagram from './Diagram'; import Diagram from './Diagram';
import errorRenderer from './errorRenderer'; import errorRenderer from './diagrams/error/errorRenderer';
import { attachFunctions } from './interactionDb'; import { attachFunctions } from './interactionDb';
import { log, setLogLevel } from './logger'; import { log, setLogLevel } from './logger';
import getStyles from './styles'; import getStyles from './styles';
@ -124,6 +124,10 @@ const render = function (
cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void, cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
container?: Element container?: Element
): void { ): void {
if (!hasLoadedDiagrams) {
addDiagrams();
hasLoadedDiagrams = true;
}
configApi.reset(); configApi.reset();
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;; text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
const graphInit = utils.detectInit(text); const graphInit = utils.detectInit(text);
@ -228,7 +232,14 @@ const render = function (
text = encodeEntities(text); text = encodeEntities(text);
// Important that we do not create the diagram until after the directives have been included // Important that we do not create the diagram until after the directives have been included
const diag = new Diagram(text); let diag;
let parseEncounteredException;
try {
diag = new Diagram(text);
} catch (error) {
diag = new Diagram('error');
parseEncounteredException = error;
}
// Get the tmp element containing the the svg // Get the tmp element containing the the svg
const element = root.select('#d' + id).node(); const element = root.select('#d' + id).node();
const graphType = diag.type; const graphType = diag.type;
@ -371,6 +382,10 @@ const render = function (
node.remove(); node.remove();
} }
if (parseEncounteredException) {
throw parseEncounteredException;
}
return svgCode; return svgCode;
}; };

View File

@ -1,5 +1,6 @@
import classDiagram from './diagrams/class/styles'; import classDiagram from './diagrams/class/styles';
import er from './diagrams/er/styles'; import er from './diagrams/er/styles';
import error from './diagrams/error/styles';
import flowchart from './diagrams/flowchart/styles'; import flowchart from './diagrams/flowchart/styles';
import gantt from './diagrams/gantt/styles'; import gantt from './diagrams/gantt/styles';
// import gitGraph from './diagrams/git/styles'; // import gitGraph from './diagrams/git/styles';
@ -28,6 +29,7 @@ const themes: Record<string, any> = {
info, info,
pie, pie,
er, er,
error,
journey, journey,
requirement, requirement,
c4, c4,