feat: Add diagramType to RenderResult and ParseResult #5117

This commit is contained in:
Sidharth Vinod
2023-12-06 21:11:07 +05:30
parent 000b432bb2
commit c3c7ccd78a
5 changed files with 78 additions and 32 deletions

View File

@@ -39,7 +39,19 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in #### Defined in
[mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80) [mermaidAPI.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L96)
---
### diagramType
**diagramType**: `string`
The diagram type, e.g. 'flowchart', 'sequence', etc.
#### Defined in
[mermaidAPI.ts:86](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L86)
--- ---
@@ -51,4 +63,4 @@ The svg code for the rendered graph.
#### Defined in #### Defined in
[mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70) [mermaidAPI.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L82)

View File

@@ -25,13 +25,23 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in #### Defined in
[mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64) [mermaidAPI.ts:76](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L76)
---
### ParseResult
Ƭ **ParseResult**: { `diagramType`: `string` ; `isValid`: `true` } | { `isValid`: `false` }
#### Defined in
[mermaidAPI.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L63)
## Variables ## Variables
### mermaidAPI ### mermaidAPI
`Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean`> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<[`ParseResult`](mermaidAPI.md#parseresult)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }>
## mermaidAPI configuration defaults ## mermaidAPI configuration defaults
@@ -96,7 +106,7 @@ mermaid.initialize(config);
#### Defined in #### Defined in
[mermaidAPI.ts:608](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L608) [mermaidAPI.ts:621](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L621)
## Functions ## Functions
@@ -127,7 +137,7 @@ Return the last node appended
#### Defined in #### Defined in
[mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263) [mermaidAPI.ts:275](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L275)
--- ---
@@ -153,7 +163,7 @@ the cleaned up svgCode
#### Defined in #### Defined in
[mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209) [mermaidAPI.ts:221](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L221)
--- ---
@@ -178,7 +188,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139) [mermaidAPI.ts:151](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L151)
--- ---
@@ -201,7 +211,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186) [mermaidAPI.ts:198](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L198)
--- ---
@@ -228,7 +238,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124) [mermaidAPI.ts:136](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L136)
--- ---
@@ -254,7 +264,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in #### Defined in
[mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240) [mermaidAPI.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L252)
--- ---
@@ -279,4 +289,4 @@ Remove any existing elements from the given document
#### Defined in #### Defined in
[mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313) [mermaidAPI.ts:325](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L325)

View File

@@ -6,7 +6,7 @@ import { dedent } from 'ts-dedent';
import type { MermaidConfig } from './config.type.js'; import type { MermaidConfig } from './config.type.js';
import { log } from './logger.js'; import { log } from './logger.js';
import utils from './utils.js'; import utils from './utils.js';
import type { ParseOptions, RenderResult } from './mermaidAPI.js'; import type { ParseOptions, ParseResult, RenderResult } from './mermaidAPI.js';
import { mermaidAPI } from './mermaidAPI.js'; import { mermaidAPI } from './mermaidAPI.js';
import { registerLazyLoadedDiagrams, detectType } from './diagram-api/detectType.js'; import { registerLazyLoadedDiagrams, detectType } from './diagram-api/detectType.js';
import { loadRegisteredDiagrams } from './diagram-api/loadDiagram.js'; import { loadRegisteredDiagrams } from './diagram-api/loadDiagram.js';
@@ -24,6 +24,7 @@ export type {
ParseErrorFunction, ParseErrorFunction,
RenderResult, RenderResult,
ParseOptions, ParseOptions,
ParseResult,
UnknownDiagramError, UnknownDiagramError,
}; };
@@ -314,10 +315,10 @@ const executeQueue = async () => {
* Parse the text and validate the syntax. * Parse the text and validate the syntax.
* @param text - The mermaid diagram definition. * @param text - The mermaid diagram definition.
* @param parseOptions - Options for parsing. * @param parseOptions - Options for parsing.
* @returns true if the diagram is valid, false otherwise if parseOptions.suppressErrors is true. * @returns - If the diagram is valid, returns an object with isValid set to true and the diagramType set to type of the diagram.
* @throws Error if the diagram is invalid and parseOptions.suppressErrors is false. * @throws Error if the diagram is invalid and parseOptions.suppressErrors is false.
*/ */
const parse = async (text: string, parseOptions?: ParseOptions): Promise<boolean | void> => { const parse = async (text: string, parseOptions?: ParseOptions): Promise<ParseResult | void> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// This promise will resolve when the render call is done. // This promise will resolve when the render call is done.
// It will be queued first and will be executed when it is first in line // It will be queued first and will be executed when it is first in line

View File

@@ -1,5 +1,5 @@
'use strict'; 'use strict';
import { vi } from 'vitest'; import { vi, it, expect, describe, beforeEach } from 'vitest';
// ------------------------------------- // -------------------------------------
// Mocks and mocking // Mocks and mocking
@@ -682,17 +682,26 @@ describe('mermaidAPI', () => {
it('returns false for invalid definition with silent option', async () => { it('returns false for invalid definition with silent option', async () => {
await expect( await expect(
mermaidAPI.parse('this is not a mermaid diagram definition', { suppressErrors: true }) mermaidAPI.parse('this is not a mermaid diagram definition', { suppressErrors: true })
).resolves.toBe(false); ).resolves.toStrictEqual({ isValid: false });
}); });
it('resolves for valid definition', async () => { it('resolves for valid definition', async () => {
await expect( await expect(mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).resolves
mermaidAPI.parse('graph TD;A--x|text including URL space|B;') .toMatchInlineSnapshot(`
).resolves.toBeTruthy(); {
"diagramType": "flowchart-v2",
"isValid": true,
}
`);
}); });
it('returns true for valid definition with silent option', async () => { it('returns true for valid definition with silent option', async () => {
await expect( await expect(
mermaidAPI.parse('graph TD;A--x|text including URL space|B;', { suppressErrors: true }) mermaidAPI.parse('graph TD;A--x|text including URL space|B;', { suppressErrors: true })
).resolves.toBe(true); ).resolves.toMatchInlineSnapshot(`
{
"diagramType": "flowchart-v2",
"isValid": true,
}
`);
}); });
}); });
@@ -734,7 +743,8 @@ describe('mermaidAPI', () => {
it('should set aria-roledscription to the diagram type AND should call addSVGa11yTitleDescription', async () => { it('should set aria-roledscription to the diagram type AND should call addSVGa11yTitleDescription', async () => {
const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo'); const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo');
const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription'); const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription');
await mermaidAPI.render(id, diagramText); const result = await mermaidAPI.render(id, diagramText);
expect(result.diagramType).toBe(expectedDiagramType);
expect(a11yDiagramInfo_spy).toHaveBeenCalledWith( expect(a11yDiagramInfo_spy).toHaveBeenCalledWith(
expect.anything(), expect.anything(),
expectedDiagramType expectedDiagramType

View File

@@ -60,6 +60,18 @@ export interface ParseOptions {
suppressErrors?: boolean; suppressErrors?: boolean;
} }
export type ParseResult =
| {
isValid: true;
/**
* The diagram type, e.g. 'flowchart', 'sequence', etc.
*/
diagramType: string;
}
| {
isValid: false;
};
// This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type. // This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type.
export type D3Element = any; export type D3Element = any;
@@ -68,6 +80,10 @@ export interface RenderResult {
* The svg code for the rendered graph. * The svg code for the rendered graph.
*/ */
svg: string; svg: string;
/**
* The diagram type, e.g. 'flowchart', 'sequence', etc.
*/
diagramType: string;
/** /**
* Bind function to be called after the svg has been inserted into the DOM. * Bind function to be called after the svg has been inserted into the DOM.
* This is necessary for adding event listeners to the elements in the svg. * This is necessary for adding event listeners to the elements in the svg.
@@ -91,28 +107,24 @@ function processAndSetConfigs(text: string) {
* Parse the text and validate the syntax. * Parse the text and validate the syntax.
* @param text - The mermaid diagram definition. * @param text - The mermaid diagram definition.
* @param parseOptions - Options for parsing. * @param parseOptions - Options for parsing.
* @returns true if the diagram is valid, false otherwise if parseOptions.suppressErrors is true. * @returns - If the diagram is valid, returns an object with isValid set to true and the diagramType set to type of the diagram.
* @throws Error if the diagram is invalid and parseOptions.suppressErrors is false. * @throws Error if the diagram is invalid and parseOptions.suppressErrors is false.
*/ */
async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> { async function parse(text: string, parseOptions?: ParseOptions): Promise<ParseResult> {
addDiagrams(); addDiagrams();
text = processAndSetConfigs(text).code;
try { try {
await getDiagramFromText(text); const { code } = processAndSetConfigs(text);
const diagram = await getDiagramFromText(code);
return { isValid: true, diagramType: diagram.type };
} catch (error) { } catch (error) {
if (parseOptions?.suppressErrors) { if (parseOptions?.suppressErrors) {
return false; return { isValid: false };
} }
throw error; throw error;
} }
return true;
} }
// append !important; to each cssClass followed by a final !important, all enclosed in { }
//
/** /**
* Create a CSS style that starts with the given class name, then the element, * Create a CSS style that starts with the given class name, then the element,
* with an enclosing block that has each of the cssClasses followed by !important; * with an enclosing block that has each of the cssClasses followed by !important;
@@ -483,6 +495,7 @@ const render = async function (
} }
return { return {
diagramType,
svg: svgCode, svg: svgCode,
bindFunctions: diag.db.bindFunctions, bindFunctions: diag.db.bindFunctions,
}; };