From 35cd3918df5aa51e90cb502567095068ab382bfe Mon Sep 17 00:00:00 2001 From: Julian Amelung Date: Mon, 23 Nov 2020 23:05:41 +0100 Subject: [PATCH 1/2] Add different id generators --- src/defaultConfig.js | 15 +++++++++++++++ src/mermaid.js | 6 ++++-- src/utils.js | 13 +++++++++++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/defaultConfig.js b/src/defaultConfig.js index c9be98dca..9fb279bb2 100644 --- a/src/defaultConfig.js +++ b/src/defaultConfig.js @@ -119,6 +119,21 @@ const config = { */ secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'], + /** + * This option controls if the generated ids of nodes in the SVG are generated randomly or based on a seed. + * If set to false, the IDs are generated based on the current date and thus are not deterministic. This is the default behaviour. + * + *## Notes**: This matters if your files are checked into sourcecontrol e.g. git and should not change unless content is changed. + ***Default value: false** + */ + deterministicIds: false, + + /** + * This option is the optional seed for deterministic ids. if set to undefined but deterministicIds is true, a simple number iterator is used. + * You can set this attribute to base the seed on a static string. + */ + deterministicIDSeed: undefined, + /** * The object containing configurations specific for flowcharts */ diff --git a/src/mermaid.js b/src/mermaid.js index 966db20fd..64016e26a 100644 --- a/src/mermaid.js +++ b/src/mermaid.js @@ -4,8 +4,8 @@ */ // import { decode } from 'he'; import decode from 'entity-decode/browser'; -import mermaidAPI from './mermaidAPI'; import { logger } from './logger'; +import mermaidAPI from './mermaidAPI'; import utils from './utils'; /** @@ -78,6 +78,8 @@ const init = function() { mermaidAPI.updateSiteConfig({ gantt: mermaid.ganttConfig }); } + const nextId = utils.initIdGeneratior(conf.deterministicIds, conf.deterministicIDSeed); + let txt; for (let i = 0; i < nodes.length; i++) { @@ -90,7 +92,7 @@ const init = function() { continue; } - const id = `mermaid-${Date.now()}`; + const id = `mermaid-${nextId()}`; // Fetch the graph definition including tags txt = element.innerHTML; diff --git a/src/utils.js b/src/utils.js index f41b5af5a..471fddd44 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,4 @@ +import { sanitizeUrl } from '@braintree/sanitize-url'; import { curveBasis, curveBasisClosed, @@ -12,9 +13,8 @@ import { curveStepBefore, select } from 'd3'; -import { logger } from './logger'; -import { sanitizeUrl } from '@braintree/sanitize-url'; import common from './diagrams/common/common'; +import { logger } from './logger'; // import cryptoRandomString from 'crypto-random-string'; // Effectively an enum of the supported curve types, accessible by name @@ -790,6 +790,15 @@ export const configureSvgSize = function(svgElem, height, width, useMaxWidth) { d3Attrs(svgElem, attrs); }; +export const initIdGeneratior = function(deterministic, seed) { + if (!deterministic) return () => Date.now(); + const iterator = function() { + return this.count++; + }; + iterator.seed = seed ? seed.length : 0; + return iterator; +}; + export default { assignWithDepth, wrapLabel, From c47202492188dde585716de1a131c6ee88e3dd5a Mon Sep 17 00:00:00 2001 From: Julian Amelung Date: Mon, 23 Nov 2020 23:34:47 +0100 Subject: [PATCH 2/2] Add test cases for utils.initIdGeneratior --- src/mermaid.js | 2 +- src/utils.js | 19 ++++++++++++------- src/utils.spec.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/mermaid.js b/src/mermaid.js index 64016e26a..94fec80fc 100644 --- a/src/mermaid.js +++ b/src/mermaid.js @@ -78,7 +78,7 @@ const init = function() { mermaidAPI.updateSiteConfig({ gantt: mermaid.ganttConfig }); } - const nextId = utils.initIdGeneratior(conf.deterministicIds, conf.deterministicIDSeed); + const nextId = utils.initIdGeneratior(conf.deterministicIds, conf.deterministicIDSeed).next; let txt; diff --git a/src/utils.js b/src/utils.js index 471fddd44..18e35f738 100644 --- a/src/utils.js +++ b/src/utils.js @@ -791,12 +791,16 @@ export const configureSvgSize = function(svgElem, height, width, useMaxWidth) { }; export const initIdGeneratior = function(deterministic, seed) { - if (!deterministic) return () => Date.now(); - const iterator = function() { - return this.count++; - }; - iterator.seed = seed ? seed.length : 0; - return iterator; + if (!deterministic) return { next: () => Date.now() }; + class iterator { + constructor() { + return (this.count = seed ? seed.length : 0); + } + next() { + return this.count++; + } + } + return new iterator(); }; export default { @@ -820,5 +824,6 @@ export default { generateId, random, memoize, - runFunc + runFunc, + initIdGeneratior }; diff --git a/src/utils.spec.js b/src/utils.spec.js index 756ad3794..66b13a276 100644 --- a/src/utils.spec.js +++ b/src/utils.spec.js @@ -253,3 +253,34 @@ describe('when calculating SVG size', function() { expect(attrs.get('width')).toEqual(200); }); }); + +describe('when initializing the id generator', function () { + it('should return a random number generator based on Date', function (done) { + const idGenerator = utils.initIdGeneratior(false) + expect(typeof idGenerator.next).toEqual('function') + const lastId = idGenerator.next() + setTimeout(() => { + expect(idGenerator.next() > lastId).toBe(true) + done() + }, 5) + }); + + it('should return a non random number generator', function () { + const idGenerator = utils.initIdGeneratior(true) + expect(typeof idGenerator.next).toEqual('function') + const start = 0 + const lastId = idGenerator.next() + expect(start).toEqual(lastId) + expect(idGenerator.next()).toEqual(lastId +1) + }); + + it('should return a non random number generator based on seed', function () { + const idGenerator = utils.initIdGeneratior(true, 'thisIsASeed') + expect(typeof idGenerator.next).toEqual('function') + const start = 11 + const lastId = idGenerator.next() + expect(start).toEqual(lastId) + expect(idGenerator.next()).toEqual(lastId +1) + }); + +})