Merge branch 'develop' into release/10.4.0

This commit is contained in:
Knut Sveidqvist
2023-08-11 11:46:30 +02:00
13 changed files with 34 additions and 102 deletions

View File

@@ -10,7 +10,7 @@
#### Grammar #### Grammar
This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
For instance: For instance:
@@ -60,7 +60,7 @@ Place the renderer in the diagram folder.
### Step 3: Detection of the new diagram type ### Step 3: Detection of the new diagram type
The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type. The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type.
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type. [This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram. would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.

View File

@@ -96,7 +96,7 @@ mermaid.initialize(config);
#### Defined in #### Defined in
[mermaidAPI.ts:669](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L669) [mermaidAPI.ts:668](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L668)
## Functions ## Functions
@@ -127,7 +127,7 @@ Return the last node appended
#### Defined in #### Defined in
[mermaidAPI.ts:310](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L310) [mermaidAPI.ts:309](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L309)
--- ---
@@ -153,7 +153,7 @@ the cleaned up svgCode
#### Defined in #### Defined in
[mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256) [mermaidAPI.ts:255](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L255)
--- ---
@@ -179,7 +179,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185) [mermaidAPI.ts:184](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L184)
--- ---
@@ -202,7 +202,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233) [mermaidAPI.ts:232](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L232)
--- ---
@@ -229,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169) [mermaidAPI.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L168)
--- ---
@@ -249,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155) [mermaidAPI.ts:154](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L154)
--- ---
@@ -269,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L126) [mermaidAPI.ts:125](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L125)
--- ---
@@ -295,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in #### Defined in
[mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287) [mermaidAPI.ts:286](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L286)
--- ---
@@ -320,4 +320,4 @@ Remove any existing elements from the given document
#### Defined in #### Defined in
[mermaidAPI.ts:360](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L360) [mermaidAPI.ts:359](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L359)

View File

@@ -4,8 +4,9 @@ import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
import { detectType, getDiagramLoader } from './diagram-api/detectType.js'; import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
import { extractFrontMatter } from './diagram-api/frontmatter.js'; import { extractFrontMatter } from './diagram-api/frontmatter.js';
import { UnknownDiagramError } from './errors.js'; import { UnknownDiagramError } from './errors.js';
import { DetailedError } from './utils.js';
import { cleanupComments } from './diagram-api/comments.js'; import { cleanupComments } from './diagram-api/comments.js';
import type { DetailedError } from './utils.js';
import type { DiagramDefinition } from './diagram-api/types.js';
export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void; export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;
@@ -15,9 +16,11 @@ export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?:
*/ */
export class Diagram { export class Diagram {
type = 'graph'; type = 'graph';
parser; parser: DiagramDefinition['parser'];
renderer; renderer: DiagramDefinition['renderer'];
db; db: DiagramDefinition['db'];
private init?: DiagramDefinition['init'];
private detectError?: UnknownDiagramError; private detectError?: UnknownDiagramError;
constructor(public text: string) { constructor(public text: string) {
this.text += '\n'; this.text += '\n';
@@ -32,7 +35,6 @@ export class Diagram {
log.debug('Type ' + this.type); log.debug('Type ' + this.type);
// Setup diagram // Setup diagram
this.db = diagram.db; this.db = diagram.db;
this.db.clear?.();
this.renderer = diagram.renderer; this.renderer = diagram.renderer;
this.parser = diagram.parser; this.parser = diagram.parser;
const originalParse = this.parser.parse.bind(this.parser); const originalParse = this.parser.parse.bind(this.parser);
@@ -49,10 +51,7 @@ export class Diagram {
originalParse(cleanupComments(extractFrontMatter(text, this.db))); originalParse(cleanupComments(extractFrontMatter(text, this.db)));
this.parser.parser.yy = this.db; this.parser.parser.yy = this.db;
if (diagram.init) { this.init = diagram.init;
diagram.init(cnf);
log.info('Initialized diagram ' + this.type, cnf);
}
this.parse(); this.parse();
} }
@@ -61,6 +60,7 @@ export class Diagram {
throw this.detectError; throw this.detectError;
} }
this.db.clear?.(); this.db.clear?.();
this.init?.(configApi.getConfig());
this.parser.parse(this.text); this.parser.parse(this.text);
} }

View File

@@ -69,11 +69,11 @@ export const getDiagram = (name: string): DiagramDefinition => {
if (name in diagrams) { if (name in diagrams) {
return diagrams[name]; return diagrams[name];
} }
throw new Error(`Diagram ${name} not found.`); throw new DiagramNotFoundError(name);
}; };
export class DiagramNotFoundError extends Error { export class DiagramNotFoundError extends Error {
constructor(message: string) { constructor(name: string) {
super(`Diagram ${message} not found.`); super(`Diagram ${name} not found.`);
} }
} }

View File

@@ -555,7 +555,6 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) {
export const draw = function (text, id, _version, diagObj) { export const draw = function (text, id, _version, diagObj) {
conf = getConfig().er; conf = getConfig().er;
log.info('Drawing ER diagram'); log.info('Drawing ER diagram');
// diag.db.clear();
const securityLevel = getConfig().securityLevel; const securityLevel = getConfig().securityLevel;
// Handle root and Document for when rendering in sandbox mode // Handle root and Document for when rendering in sandbox mode
let sandboxElement; let sandboxElement;

View File

@@ -655,14 +655,7 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb
*/ */
export const getClasses = function (text, diagObj) { export const getClasses = function (text, diagObj) {
log.info('Extracting classes'); log.info('Extracting classes');
diagObj.db.clear('ver-2');
try {
// Parse the graph definition
diagObj.parse(text);
return diagObj.db.getClasses(); return diagObj.db.getClasses();
} catch (e) {
return {};
}
}; };
const addSubGraphs = function (db) { const addSubGraphs = function (db) {
@@ -766,14 +759,8 @@ const insertChildren = (nodeArray, parentLookupDb) => {
*/ */
export const draw = async function (text, id, _version, diagObj) { export const draw = async function (text, id, _version, diagObj) {
// Add temporary render element
diagObj.db.clear();
nodeDb = {}; nodeDb = {};
portPos = {}; portPos = {};
diagObj.db.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy'); const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
let graph = { let graph = {
id: 'root', id: 'root',

View File

@@ -1,10 +1,7 @@
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
import { select, curveLinear, selectAll } from 'd3'; import { select, curveLinear, selectAll } from 'd3';
import flowDb from './flowDb.js';
import { getConfig } from '../../config.js'; import { getConfig } from '../../config.js';
import utils from '../../utils.js'; import utils from '../../utils.js';
import { render } from '../../dagre-wrapper/index.js'; import { render } from '../../dagre-wrapper/index.js';
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
import { log } from '../../logger.js'; import { log } from '../../logger.js';
@@ -344,15 +341,7 @@ export const addEdges = function (edges, g, diagObj) {
* @returns {object} ClassDef styles * @returns {object} ClassDef styles
*/ */
export const getClasses = function (text, diagObj) { export const getClasses = function (text, diagObj) {
log.info('Extracting classes');
diagObj.db.clear();
try {
// Parse the graph definition
diagObj.parse(text);
return diagObj.db.getClasses(); return diagObj.db.getClasses();
} catch (e) {
return;
}
}; };
/** /**
@@ -364,10 +353,6 @@ export const getClasses = function (text, diagObj) {
export const draw = async function (text, id, _version, diagObj) { export const draw = async function (text, id, _version, diagObj) {
log.info('Drawing flowchart'); log.info('Drawing flowchart');
diagObj.db.clear();
flowDb.setGen('gen-2');
// Parse the graph definition
diagObj.parser.parse(text);
// Fetch the default direction, use TD if none was found // Fetch the default direction, use TD if none was found
let dir = diagObj.db.getDirection(); let dir = diagObj.db.getDirection();

View File

@@ -273,15 +273,7 @@ export const addEdges = function (edges, g, diagObj) {
*/ */
export const getClasses = function (text, diagObj) { export const getClasses = function (text, diagObj) {
log.info('Extracting classes'); log.info('Extracting classes');
diagObj.db.clear();
try {
// Parse the graph definition
diagObj.parse(text);
return diagObj.db.getClasses(); return diagObj.db.getClasses();
} catch (e) {
log.error(e);
return {};
}
}; };
/** /**
@@ -294,7 +286,6 @@ export const getClasses = function (text, diagObj) {
*/ */
export const draw = function (text, id, _version, diagObj) { export const draw = function (text, id, _version, diagObj) {
log.info('Drawing flowchart'); log.info('Drawing flowchart');
diagObj.db.clear();
const { securityLevel, flowchart: conf } = getConfig(); const { securityLevel, flowchart: conf } = getConfig();
let sandboxElement; let sandboxElement;
if (securityLevel === 'sandbox') { if (securityLevel === 'sandbox') {

View File

@@ -172,14 +172,11 @@ describe('more than one sequence diagram', () => {
describe('when parsing a sequenceDiagram', function () { describe('when parsing a sequenceDiagram', function () {
beforeEach(function () { beforeEach(function () {
// diagram.db = sequenceDb;
// diagram.db.clear();
diagram = new Diagram(` diagram = new Diagram(`
sequenceDiagram sequenceDiagram
Alice->Bob:Hello Bob, how are you? Alice->Bob:Hello Bob, how are you?
Note right of Bob: Bob thinks Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!`); Bob-->Alice: I am good thanks!`);
diagram.db.clear();
}); });
it('should handle a sequenceDiagram definition', async function () { it('should handle a sequenceDiagram definition', async function () {
const str = ` const str = `
@@ -1482,8 +1479,6 @@ describe('when checking the bounds in a sequenceDiagram', function () {
let conf; let conf;
beforeEach(function () { beforeEach(function () {
mermaidAPI.reset(); mermaidAPI.reset();
// diagram.db = sequenceDb;
// diagram.db.clear();
diagram.renderer.bounds.init(); diagram.renderer.bounds.init();
conf = diagram.db.getConfig(); conf = diagram.db.getConfig();
}); });
@@ -1635,7 +1630,6 @@ sequenceDiagram
Alice->Bob:Hello Bob, how are you? Alice->Bob:Hello Bob, how are you?
Note right of Bob: Bob thinks Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!`); Bob-->Alice: I am good thanks!`);
diagram.db.clear();
}); });
['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) {
it(` it(`
@@ -2009,8 +2003,6 @@ describe('when rendering a sequenceDiagram with actor mirror activated', () => {
let conf; let conf;
beforeEach(function () { beforeEach(function () {
mermaidAPI.reset(); mermaidAPI.reset();
// diagram.db = sequenceDb;
diagram.db.clear();
conf = diagram.db.getConfig(); conf = diagram.db.getConfig();
diagram.renderer.bounds.init(); diagram.renderer.bounds.init();
}); });
@@ -2052,12 +2044,8 @@ describe('when rendering a sequenceDiagram with directives', () => {
mermaidAPI.initialize({ sequence: conf }); mermaidAPI.initialize({ sequence: conf });
}); });
let conf;
beforeEach(function () { beforeEach(function () {
mermaidAPI.reset(); mermaidAPI.reset();
// diagram.db = sequenceDb;
diagram.db.clear();
conf = diagram.db.getConfig();
diagram.renderer.bounds.init(); diagram.renderer.bounds.init();
}); });
@@ -2069,10 +2057,7 @@ sequenceDiagram
participant Alice participant Alice
`; `;
diagram = new Diagram(str); diagram = new Diagram(str);
diagram.renderer.bounds.init(); diagram.renderer.bounds.init();
await mermaidAPI.parse(str);
diagram.renderer.draw(str, 'tst', '1.2.3', diagram); diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
const { bounds, models } = diagram.renderer.bounds.getBounds(); const { bounds, models } = diagram.renderer.bounds.getBounds();
@@ -2093,7 +2078,7 @@ sequenceDiagram
participant Alice participant Alice
`; `;
diagram.parse(str); diagram = new Diagram(str);
diagram.renderer.draw(str, 'tst', '1.2.3', diagram); diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
const { bounds, models } = diagram.renderer.bounds.getBounds(); const { bounds, models } = diagram.renderer.bounds.getBounds();
@@ -2114,7 +2099,7 @@ Alice->Bob:Hello Bob, how are you?
Note right of Bob: Bob thinks Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!`; Bob-->Alice: I am good thanks!`;
await mermaidAPI.parse(str1); diagram = new Diagram(str1);
diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers
expect(diagram.db.showSequenceNumbers()).toBe(true); expect(diagram.db.showSequenceNumbers()).toBe(true);
@@ -2124,7 +2109,7 @@ Alice->Bob:Hello Bob, how are you?
Note right of Bob: Bob thinks Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!`; Bob-->Alice: I am good thanks!`;
await mermaidAPI.parse(str2); diagram = new Diagram(str2);
diagram.renderer.draw(str2, 'tst', '1.2.3', diagram); diagram.renderer.draw(str2, 'tst', '1.2.3', diagram);
expect(diagram.db.showSequenceNumbers()).toBe(false); expect(diagram.db.showSequenceNumbers()).toBe(false);
}); });

View File

@@ -749,9 +749,6 @@ function adjustCreatedDestroyedData(
export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) { export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) {
const { securityLevel, sequence } = configApi.getConfig(); const { securityLevel, sequence } = configApi.getConfig();
conf = sequence; conf = sequence;
diagObj.db.clear();
// Parse the graph definition
diagObj.parser.parse(_text);
// Handle root and Document for when rendering in sandbox mode // Handle root and Document for when rendering in sandbox mode
let sandboxElement; let sandboxElement;
if (securityLevel === 'sandbox') { if (securityLevel === 'sandbox') {

View File

@@ -84,17 +84,7 @@ export const setConf = function (cnf) {
* @returns {object} ClassDef styles (a Map with keys = strings, values = ) * @returns {object} ClassDef styles (a Map with keys = strings, values = )
*/ */
export const getClasses = function (text, diagramObj) { export const getClasses = function (text, diagramObj) {
log.trace('Extracting classes');
diagramObj.db.clear();
try {
// Parse the graph definition
diagramObj.parser.parse(text);
// must run extract() to turn the parsed statements into states, relationships, classes, etc.
diagramObj.db.extract(diagramObj.db.getRootDocV2());
return diagramObj.db.getClasses(); return diagramObj.db.getClasses();
} catch (e) {
return e;
}
}; };
/** /**
@@ -384,7 +374,6 @@ const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
*/ */
export const draw = async function (text, id, _version, diag) { export const draw = async function (text, id, _version, diag) {
log.info('Drawing state diagram (v2)', id); log.info('Drawing state diagram (v2)', id);
// diag.sb.clear();
nodeDb = {}; nodeDb = {};
// Fetch the default direction, use TD if none was found // Fetch the default direction, use TD if none was found
let dir = diag.db.getDirection(); let dir = diag.db.getDirection();

View File

@@ -4,7 +4,7 @@
#### Grammar #### Grammar
This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
For instance: For instance:
@@ -55,7 +55,7 @@ Place the renderer in the diagram folder.
### Step 3: Detection of the new diagram type ### Step 3: Detection of the new diagram type
The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type. The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type.
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type. [This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram. would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.

View File

@@ -108,8 +108,7 @@ export interface RenderResult {
async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> { async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> {
addDiagrams(); addDiagrams();
try { try {
const diagram = await getDiagramFromText(text); await getDiagramFromText(text);
diagram.parse();
} catch (error) { } catch (error) {
if (parseOptions?.suppressErrors) { if (parseOptions?.suppressErrors) {
return false; return false;