Fixed test cases for sequence diagrams

Updated config to match a conversation knut and i had about the relationship between global, site, and integrator configuration
(Will update docs)
Renamed wrapEnabled to wrap
Poor man's caching for calculateTextDimensions, wrapLabel, and breakString (actually makes a huge difference)
This commit is contained in:
chris moran
2020-06-26 09:26:56 -04:00
parent 7d9bf83f66
commit 217bd1f4bf
13 changed files with 1156 additions and 1370 deletions

View File

@@ -13,7 +13,7 @@
import { select } from 'd3';
import scope from 'scope-css';
import pkg from '../package.json';
import { setConfig, getConfig } from './config';
import { setConfig, getConfig, setSiteConfig, getSiteConfig } from './config';
import { logger, setLogLevel } from './logger';
import utils, { assignWithDepth } from './utils';
import flowRenderer from './diagrams/flowchart/flowRenderer';
@@ -56,529 +56,11 @@ for (const themeName of ['default', 'forest', 'dark', 'neutral']) {
themes[themeName] = require(`./themes/${themeName}/index.scss`);
}
/**
* These are the default options which can be overridden with the initialization call like so:
* **Example 1:**
* <pre>
* mermaid.initialize({
* flowchart:{
* htmlLabels: false
* }
* });
* </pre>
*
* **Example 2:**
* <pre>
* &lt;script>
* var config = {
* startOnLoad:true,
* flowchart:{
* useMaxWidth:true,
* htmlLabels:true,
* curve:'cardinal',
* },
*
* securityLevel:'loose',
* };
* mermaid.initialize(config);
* &lt;/script>
* </pre>
* A summary of all options and their defaults is found [here](https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#mermaidapi-configuration-defaults). A description of each option follows below.
*
* @name Configuration
*/
const config = {
/** theme , the CSS style sheet
*
* **theme** - Choose one of the built-in themes:
* * default
* * forest
* * dark
* * neutral.
* To disable any pre-defined mermaid theme, use "null".
*
* **themeCSS** - Use your own CSS. This overrides **theme**.
* <pre>
* "theme": "forest",
* "themeCSS": ".node rect { fill: red; }"
* </pre>
*/
theme: 'default',
themeCSS: undefined,
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
maxTextSize: 50000,
/**
* **fontFamily** The font to be used for the rendered diagrams. Default value is \"trebuchet ms\", verdana, arial;
*/
fontFamily: '"trebuchet ms", verdana, arial;',
/**
* This option decides the amount of logging to be used.
* * debug: 1
* * info: 2
* * warn: 3
* * error: 4
* * fatal: (**default**) 5
*/
logLevel: 5,
/**
* Sets the level of trust to be used on the parsed diagrams.
* * **strict**: (**default**) tags in text are encoded, click functionality is disabeled
* * **loose**: tags in text are allowed, click functionality is enabled
*/
securityLevel: 'strict',
/**
* This options controls whether or mermaid starts when the page loads
* **Default value true**.
*/
startOnLoad: true,
/**
* This options controls whether or arrow markers in html code will be absolute paths or
* an anchor, #. This matters if you are using base tag settings.
* **Default value false**.
*/
arrowMarkerAbsolute: false,
/**
* The object containing configurations specific for flowcharts
*/
flowchart: {
/**
* Flag for setting whether or not a html tag should be used for rendering labels
* on the edges.
* **Default value true**.
*/
htmlLabels: true,
/**
* Defines the spacing between nodes on the same level (meaning horizontal spacing for
* TB or BT graphs, and the vertical spacing for LR as well as RL graphs).
* **Default value 50**.
*/
nodeSpacing: 50,
/**
* Defines the spacing between nodes on different levels (meaning vertical spacing for
* TB or BT graphs, and the horizontal spacing for LR as well as RL graphs).
* **Default value 50**.
*/
rankSpacing: 50,
/**
* How mermaid renders curves for flowcharts. Possible values are
* * basis
* * linear **default**
* * cardinal
*/
curve: 'linear',
// Only used in new experimental rendering
// repreesents the padding between the labels and the shape
padding: 15
},
/**
* The object containing configurations specific for sequence diagrams
*/
sequence: {
/**
* margin to the right and left of the sequence diagram.
* **Default value 50**.
*/
diagramMarginX: 50,
/**
* margin to the over and under the sequence diagram.
* **Default value 10**.
*/
diagramMarginY: 10,
/**
* Margin between actors.
* **Default value 50**.
*/
actorMargin: 50,
/**
* Width of actor boxes
* **Default value 150**.
*/
width: 150,
/**
* Height of actor boxes
* **Default value 65**.
*/
height: 65,
/**
* Margin around loop boxes
* **Default value 10**.
*/
boxMargin: 10,
/**
* margin around the text in loop/alt/opt boxes
* **Default value 5**.
*/
boxTextMargin: 5,
/**
* margin around notes.
* **Default value 10**.
*/
noteMargin: 10,
/**
* Space between messages.
* **Default value 35**.
*/
messageMargin: 35,
/**
* Multiline message alignment. Possible values are:
* * left
* * center **default**
* * right
*/
messageAlign: 'center',
/**
* mirror actors under diagram.
* **Default value true**.
*/
mirrorActors: true,
/**
* Depending on css styling this might need adjustment.
* Prolongs the edge of the diagram downwards.
* **Default value 1**.
*/
bottomMarginAdj: 1,
/**
* when this flag is set the height and width is set to 100% and is then scaling with the
* available space if not the absolute space required is used.
* **Default value true**.
*/
useMaxWidth: true,
/**
* This will display arrows that start and begin at the same node as right angles, rather than a curve
* **Default value false**.
*/
rightAngles: false,
/**
* This will show the node numbers
* **Default value false**.
*/
showSequenceNumbers: false,
/**
* This sets the font size of the actor's description
* **Default value 14**.
*/
actorFontSize: 14,
/**
* This sets the font family of the actor's description
* **Default value "Open-Sans", "sans-serif"**.
*/
actorFontFamily: '"Open-Sans", "sans-serif"',
/**
* This sets the font weight of the actor's description
* **Default value 400.
*/
actorFontWeight: 400,
/**
* This sets the font size of actor-attached notes.
* **Default value 14**.
*/
noteFontSize: 14,
/**
* This sets the font family of actor-attached notes.
* **Default value "trebuchet ms", verdana, arial**.
*/
noteFontFamily: '"trebuchet ms", verdana, arial',
/**
* This sets the font weight of the note's description
* **Default value 400.
*/
noteFontWeight: 400,
/**
* This sets the text alignment of actor-attached notes.
* **Default value center**.
*/
noteAlign: 'center',
/**
* This sets the font size of actor messages.
* **Default value 16**.
*/
messageFontSize: 16,
/**
* This sets the font family of actor messages.
* **Default value "trebuchet ms", verdana, arial**.
*/
messageFontFamily: '"trebuchet ms", verdana, arial',
/**
* This sets the font weight of the message's description
* **Default value 400.
*/
messageFontWeight: 400,
/**
* This sets the auto-wrap state for the diagram
* **Default value false.
*/
wrapEnabled: false,
/**
* This sets the auto-wrap padding for the diagram (sides only)
* **Default value 15.
*/
wrapPadding: 15,
/**
* This sets the width of the loop-box (loop, alt, opt, par)
* **Default value 50.
*/
labelBoxWidth: 50,
/**
* This sets the height of the loop-box (loop, alt, opt, par)
* **Default value 20.
*/
labelBoxHeight: 20
},
/**
* The object containing configurations specific for gantt diagrams*
*/
gantt: {
/**
* Margin top for the text over the gantt diagram
* **Default value 25**.
*/
titleTopMargin: 25,
/**
* The height of the bars in the graph
* **Default value 20**.
*/
barHeight: 20,
/**
* The margin between the different activities in the gantt diagram.
* **Default value 4**.
*/
barGap: 4,
/**
* Margin between title and gantt diagram and between axis and gantt diagram.
* **Default value 50**.
*/
topPadding: 50,
/**
* The space allocated for the section name to the left of the activities.
* **Default value 75**.
*/
leftPadding: 75,
/**
* Vertical starting position of the grid lines.
* **Default value 35**.
*/
gridLineStartPadding: 35,
/**
* Font size ...
* **Default value 11**.
*/
fontSize: 11,
/**
* font family ...
* **Default value '"Open-Sans", "sans-serif"'**.
*/
fontFamily: '"Open-Sans", "sans-serif"',
/**
* The number of alternating section styles.
* **Default value 4**.
*/
numberSectionStyles: 4,
/**
* Datetime format of the axis. This might need adjustment to match your locale and preferences
* **Default value '%Y-%m-%d'**.
*/
axisFormat: '%Y-%m-%d'
},
/**
* The object containing configurations specific for sequence diagrams
*/
journey: {
/**
* margin to the right and left of the sequence diagram.
* **Default value 50**.
*/
diagramMarginX: 50,
/**
* margin to the over and under the sequence diagram.
* **Default value 10**.
*/
diagramMarginY: 10,
/**
* Margin between actors.
* **Default value 50**.
*/
actorMargin: 50,
/**
* Width of actor boxes
* **Default value 150**.
*/
width: 150,
/**
* Height of actor boxes
* **Default value 65**.
*/
height: 65,
/**
* Margin around loop boxes
* **Default value 10**.
*/
boxMargin: 10,
/**
* margin around the text in loop/alt/opt boxes
* **Default value 5**.
*/
boxTextMargin: 5,
/**
* margin around notes.
* **Default value 10**.
*/
noteMargin: 10,
/**
* Space between messages.
* **Default value 35**.
*/
messageMargin: 35,
/**
* Multiline message alignment. Possible values are:
* * left
* * center **default**
* * right
*/
messageAlign: 'center',
/**
* Depending on css styling this might need adjustment.
* Prolongs the edge of the diagram downwards.
* **Default value 1**.
*/
bottomMarginAdj: 1,
/**
* when this flag is set the height and width is set to 100% and is then scaling with the
* available space if not the absolute space required is used.
* **Default value true**.
*/
useMaxWidth: true,
/**
* This will display arrows that start and begin at the same node as right angles, rather than a curve
* **Default value false**.
*/
rightAngles: false
},
class: {},
git: {},
state: {
dividerMargin: 10,
sizeUnit: 5,
padding: 8,
textHeight: 10,
titleShift: -15,
noteMargin: 10,
forkWidth: 70,
forkHeight: 7,
// Used
miniPadding: 2,
// Font size factor, this is used to guess the width of the edges labels before rendering by dagre
// layout. This might need updating if/when switching font
fontSizeFactor: 5.02,
fontSize: 24,
labelHeight: 16,
edgeLengthFactor: '20',
compositTitleSize: 35,
radius: 5
},
/**
* The object containing configurations specific for entity relationship diagrams
*/
er: {
/**
* The amount of padding around the diagram as a whole so that embedded diagrams have margins, expressed in pixels
*/
diagramPadding: 20,
/**
* Directional bias for layout of entities. Can be either 'TB', 'BT', 'LR', or 'RL',
* where T = top, B = bottom, L = left, and R = right.
*/
layoutDirection: 'TB',
/**
* The mimimum width of an entity box, expressed in pixels
*/
minEntityWidth: 100,
/**
* The minimum height of an entity box, expressed in pixels
*/
minEntityHeight: 75,
/**
* The minimum internal padding between the text in an entity box and the enclosing box borders, expressed in pixels
*/
entityPadding: 15,
/**
* Stroke color of box edges and lines
*/
stroke: 'gray',
/**
* Fill color of entity boxes
*/
fill: 'honeydew',
/**
* Font size (expressed as an integer representing a number of pixels)
*/
fontSize: 12
}
};
export const defaultConfig = Object.freeze(assignWithDepth({}, config));
config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
config.git.arrowMarkerAbsolute = config.arrowMarkerAbsolute;
setLogLevel(config.logLevel);
configApi.reset(config);
function parse(text) {
const graphInit = utils.detectInit(text);
if (graphInit) {
initialize(graphInit);
logger.debug('Init ', graphInit);
reinitialize(graphInit);
logger.debug('reinit ', graphInit);
}
const graphType = utils.detectType(text);
let parser;
@@ -640,7 +122,7 @@ function parse(text) {
parser.parser.yy = journeyDb;
break;
}
parser.parser.yy.graphType = graphType;
parser.parser.yy.parseError = (str, hash) => {
const error = { str, hash };
throw error;
@@ -722,7 +204,7 @@ const render = function(id, _txt, cb, container) {
}
const graphInit = utils.detectInit(txt);
if (graphInit) {
initialize(graphInit);
reinitialize(graphInit);
assignWithDepth(cnf, getConfig());
}
@@ -942,6 +424,79 @@ const render = function(id, _txt, cb, container) {
return svgCode;
};
let currentDirective = {};
const parseDirective = function(statement, context, type) {
try {
if (statement !== undefined) {
statement = statement.trim();
switch (context) {
case 'open_directive':
currentDirective = {};
break;
case 'type_directive':
currentDirective.type = statement.toLowerCase();
break;
case 'arg_directive':
currentDirective.args = JSON.parse(statement);
break;
case 'close_directive':
handleDirective(currentDirective, type);
currentDirective = null;
break;
}
}
} catch (error) {
logger.error(
`Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}`
);
logger.error(error.message);
}
};
const handleDirective = function(directive, type) {
logger.debug(`Directive type=${directive.type} with args:`, directive.args);
switch (directive.type) {
case 'init':
case 'initialize': {
['config'].forEach(prop => {
if (typeof directive.args[prop] !== 'undefined') {
if (type === 'flowchart-v2') {
type = 'flowchart';
}
directive.args[type] = directive.args[prop];
delete directive.args[prop];
}
});
reinitialize(directive.args);
break;
}
case 'wrap':
case 'nowrap':
directive.args = { config: { wrap: directive.type === 'wrap' } };
['config'].forEach(prop => {
if (typeof directive.args[prop] !== 'undefined') {
if (type === 'flowchart-v2') {
type = 'flowchart';
}
directive.args[type] = directive.args[prop];
delete directive.args[prop];
}
});
reinitialize(directive.args);
break;
default:
logger.warn(
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
directive.args ? directive.args : {}
)}}%%`,
directive
);
break;
}
};
function updateRendererConfigs(conf) {
gitGraphRenderer.setConf(conf.git);
flowRenderer.setConf(conf.flowchart);
@@ -961,14 +516,20 @@ function updateRendererConfigs(conf) {
errorRenderer.setConf(conf.class);
}
function initialize(options) {
console.log(`mermaidAPI.initialize: v${pkg.version}`);
function reinitialize(options) {
console.log(`mermaidAPI.reinitialize: v${pkg.version}`, options);
// Set default options
if (typeof options === 'object') {
assignWithDepth(config, options);
updateRendererConfigs(config);
}
setConfig(config);
const config = typeof options === 'object' ? setConfig(options) : getSiteConfig();
updateRendererConfigs(config);
setLogLevel(config.logLevel);
logger.debug('mermaidAPI.reinitialize: ', config);
}
function initialize(options) {
// console.log(`mermaidAPI.initialize: v${pkg.version}`);
// Set default options
const config = typeof options === 'object' ? setSiteConfig(options) : getSiteConfig();
updateRendererConfigs(config);
setLogLevel(config.logLevel);
logger.debug('mermaidAPI.initialize: ', config);
}
@@ -977,22 +538,30 @@ function initialize(options) {
// console.warn('get config')
// return config
// }
const mermaidAPI = Object.freeze({
render,
parse,
parseDirective,
initialize,
reinitialize,
getConfig,
setConfig,
getSiteConfig,
reset: () => {
// console.warn('reset');
configApi.reset(defaultConfig);
assignWithDepth(config, defaultConfig, { clobber: true });
updateRendererConfigs(config);
configApi.reset();
const siteConfig = getSiteConfig();
updateRendererConfigs(siteConfig);
},
defaultConfig
globalReset: () => {
configApi.reset(configApi.defaultConfig);
updateRendererConfigs(getConfig());
},
defaultConfig: configApi.defaultConfig
});
setLogLevel(getConfig().logLevel);
configApi.reset(getConfig());
export default mermaidAPI;
/**
* ## mermaidAPI configuration defaults