mirror of https://github.com/mermaid-js/mermaid
chore: Remove all non async render/parse/init
parent
45adc5fb6b
commit
d22e8d92c6
|
@ -17,7 +17,7 @@ example-diagram
|
|||
|
||||
await mermaid.registerExternalDiagrams([exampleDiagram]);
|
||||
await mermaid.initialize({ logLevel: 0 });
|
||||
await mermaid.initThrowsErrorsAsync();
|
||||
await mermaid.initThrowsErrors();
|
||||
if (window.Cypress) {
|
||||
window.rendered = true;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
|
|||
|
||||
### mermaidAPI
|
||||
|
||||
• `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseError?`: `ParseErrorFunction`) => `boolean` ; `parseAsync`: (`text`: `string`, `parseError?`: `ParseErrorFunction`) => `Promise`<`boolean`> ; `parseDirective`: (`p`: `any`, `statement`: `string`, `context`: `string`, `type`: `string`) => `void` ; `render`: (`id`: `string`, `text`: `string`, `cb?`: (`svgCode`: `string`, `bindFunctions?`: (`element`: `Element`) => `void`) => `void`, `svgContainingElement?`: `Element`) => `string` ; `renderAsync`: (`id`: `string`, `text`: `string`, `cb?`: (`svgCode`: `string`, `bindFunctions?`: (`element`: `Element`) => `void`) => `void`, `svgContainingElement?`: `Element`) => `Promise`<`string`> ; `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; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseError?`: `ParseErrorFunction`) => `Promise`<`boolean`> ; `parseDirective`: (`p`: `any`, `statement`: `string`, `context`: `string`, `type`: `string`) => `void` ; `render`: (`id`: `string`, `text`: `string`, `cb?`: (`svgCode`: `string`, `bindFunctions?`: (`element`: `Element`) => `void`) => `void`, `svgContainingElement?`: `Element`) => `Promise`<`string`> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }>
|
||||
|
||||
## mermaidAPI configuration defaults
|
||||
|
||||
|
@ -90,7 +90,7 @@ mermaid.initialize(config);
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:887](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L887)
|
||||
[mermaidAPI.ts:671](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L671)
|
||||
|
||||
## Functions
|
||||
|
||||
|
@ -121,7 +121,7 @@ Return the last node appended
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:288](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L288)
|
||||
[mermaidAPI.ts:278](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L278)
|
||||
|
||||
---
|
||||
|
||||
|
@ -147,7 +147,7 @@ the cleaned up svgCode
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:239](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L239)
|
||||
[mermaidAPI.ts:229](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L229)
|
||||
|
||||
---
|
||||
|
||||
|
@ -173,7 +173,7 @@ the string with all the user styles
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L168)
|
||||
[mermaidAPI.ts:158](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L158)
|
||||
|
||||
---
|
||||
|
||||
|
@ -196,7 +196,7 @@ the string with all the user styles
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:216](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L216)
|
||||
[mermaidAPI.ts:206](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L206)
|
||||
|
||||
---
|
||||
|
||||
|
@ -223,7 +223,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:152](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L152)
|
||||
[mermaidAPI.ts:142](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L142)
|
||||
|
||||
---
|
||||
|
||||
|
@ -243,7 +243,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L132)
|
||||
[mermaidAPI.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L122)
|
||||
|
||||
---
|
||||
|
||||
|
@ -263,7 +263,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:103](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L103)
|
||||
[mermaidAPI.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L93)
|
||||
|
||||
---
|
||||
|
||||
|
@ -289,7 +289,7 @@ Put the svgCode into an iFrame. Return the iFrame code
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:267](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L267)
|
||||
[mermaidAPI.ts:257](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L257)
|
||||
|
||||
---
|
||||
|
||||
|
@ -314,4 +314,4 @@ Remove any existing elements from the given document
|
|||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:338](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L338)
|
||||
[mermaidAPI.ts:328](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L328)
|
||||
|
|
|
@ -276,6 +276,4 @@ From version 9.4.0 you can simplify this code to:
|
|||
</script>
|
||||
```
|
||||
|
||||
Note that more complex integrations that use the **render** function directly need to use the **renderAsync** method instead in order to render mind maps.
|
||||
|
||||
You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
|
||||
|
|
|
@ -471,6 +471,4 @@ You can use this method to add mermaid including the timeline diagram to a web p
|
|||
</script>
|
||||
```
|
||||
|
||||
Note that more complex integrations that the **render** function directly need to use the **renderAsync** method instead in order to render timeline.
|
||||
|
||||
You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
|
||||
|
|
|
@ -21,7 +21,6 @@ function parse(text: string, parseError?: ParseErrorFunction): boolean {
|
|||
// original version cannot be modified since it was frozen with `Object.freeze()`
|
||||
export const mermaidAPI = {
|
||||
render: vi.fn(),
|
||||
renderAsync: vi.fn(),
|
||||
parse,
|
||||
parseDirective: vi.fn(),
|
||||
initialize: vi.fn(),
|
||||
|
|
|
@ -2,6 +2,6 @@ import mermaid, { type MermaidConfig } from 'mermaid';
|
|||
|
||||
export const render = async (id: string, code: string, config: MermaidConfig): Promise<string> => {
|
||||
mermaid.initialize(config);
|
||||
const svg = await mermaid.renderAsync(id, code);
|
||||
const svg = await mermaid.render(id, code);
|
||||
return svg;
|
||||
};
|
||||
|
|
|
@ -184,6 +184,4 @@ From version 9.4.0 you can simplify this code to:
|
|||
</script>
|
||||
```
|
||||
|
||||
Note that more complex integrations that use the **render** function directly need to use the **renderAsync** method instead in order to render mind maps.
|
||||
|
||||
You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
|
||||
|
|
|
@ -303,6 +303,4 @@ You can use this method to add mermaid including the timeline diagram to a web p
|
|||
</script>
|
||||
```
|
||||
|
||||
Note that more complex integrations that the **render** function directly need to use the **renderAsync** method instead in order to render timeline.
|
||||
|
||||
You can also refer the implementation in the live editor [here](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('when using mermaid and ', function () {
|
|||
const node = document.createElement('div');
|
||||
node.appendChild(document.createTextNode('graph TD;\na;'));
|
||||
|
||||
mermaid.initThrowsErrors(undefined, node);
|
||||
await mermaid.initThrowsErrors(undefined, node);
|
||||
// mermaidAPI.render function has been mocked, since it doesn't yet work
|
||||
// in Node.JS (only works in browser)
|
||||
expect(mermaidAPI.render).toHaveBeenCalled();
|
||||
|
@ -72,9 +72,9 @@ describe('when using mermaid and ', function () {
|
|||
)
|
||||
).rejects.toThrow('Failed to load 1 external diagrams');
|
||||
|
||||
expect(() => mermaid.initThrowsErrorsAsync(undefined, node)).not.toThrow();
|
||||
expect(() => mermaid.initThrowsErrors(undefined, node)).not.toThrow();
|
||||
// should still render, even if lazyLoadedDiagrams fails
|
||||
expect(mermaidAPI.renderAsync).toHaveBeenCalled();
|
||||
expect(mermaidAPI.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should defer diagram load based on parameter', async () => {
|
||||
|
|
|
@ -50,7 +50,7 @@ const init = async function (
|
|||
callback?: Function
|
||||
) {
|
||||
try {
|
||||
await initThrowsErrorsAsync(config, nodes, callback);
|
||||
await initThrowsErrors(config, nodes, callback);
|
||||
} catch (e) {
|
||||
log.warn('Syntax Error rendering');
|
||||
if (isDetailedError(e)) {
|
||||
|
@ -87,96 +87,6 @@ const handleError = (error: unknown, errors: DetailedError[], parseError?: Parse
|
|||
}
|
||||
};
|
||||
|
||||
const initThrowsErrors = function (
|
||||
config?: MermaidConfig,
|
||||
// eslint-disable-next-line no-undef
|
||||
nodes?: string | HTMLElement | NodeListOf<HTMLElement>,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
callback?: Function
|
||||
) {
|
||||
const conf = mermaidAPI.getConfig();
|
||||
if (config) {
|
||||
// This is a legacy way of setting config. It is not documented and should be removed in the future.
|
||||
// @ts-ignore: TODO Fix ts errors
|
||||
mermaid.sequenceConfig = config;
|
||||
}
|
||||
|
||||
// if last argument is a function this is the callback function
|
||||
log.debug(`${!callback ? 'No ' : ''}Callback function found`);
|
||||
let nodesToProcess: ArrayLike<HTMLElement>;
|
||||
if (nodes === undefined) {
|
||||
nodesToProcess = document.querySelectorAll('.mermaid');
|
||||
} else if (typeof nodes === 'string') {
|
||||
nodesToProcess = document.querySelectorAll(nodes);
|
||||
} else if (nodes instanceof HTMLElement) {
|
||||
nodesToProcess = [nodes];
|
||||
} else if (nodes instanceof NodeList) {
|
||||
nodesToProcess = nodes;
|
||||
} else {
|
||||
throw new Error('Invalid argument nodes for mermaid.init');
|
||||
}
|
||||
|
||||
log.debug(`Found ${nodesToProcess.length} diagrams`);
|
||||
if (config?.startOnLoad !== undefined) {
|
||||
log.debug('Start On Load: ' + config?.startOnLoad);
|
||||
mermaidAPI.updateSiteConfig({ startOnLoad: config?.startOnLoad });
|
||||
}
|
||||
|
||||
// generate the id of the diagram
|
||||
const idGenerator = new utils.initIdGenerator(conf.deterministicIds, conf.deterministicIDSeed);
|
||||
|
||||
let txt: string;
|
||||
const errors: DetailedError[] = [];
|
||||
|
||||
// element is the current div with mermaid class
|
||||
// eslint-disable-next-line unicorn/prefer-spread
|
||||
for (const element of Array.from(nodesToProcess)) {
|
||||
log.info('Rendering diagram: ' + element.id);
|
||||
/*! Check if previously processed */
|
||||
if (element.getAttribute('data-processed')) {
|
||||
continue;
|
||||
}
|
||||
element.setAttribute('data-processed', 'true');
|
||||
|
||||
const id = `mermaid-${idGenerator.next()}`;
|
||||
|
||||
// Fetch the graph definition including tags
|
||||
txt = element.innerHTML;
|
||||
|
||||
// transforms the html to pure text
|
||||
txt = dedent(utils.entityDecode(txt)) // removes indentation, required for YAML parsing
|
||||
.trim()
|
||||
.replace(/<br\s*\/?>/gi, '<br/>');
|
||||
|
||||
const init = utils.detectInit(txt);
|
||||
if (init) {
|
||||
log.debug('Detected early reinit: ', init);
|
||||
}
|
||||
try {
|
||||
mermaidAPI.render(
|
||||
id,
|
||||
txt,
|
||||
(svgCode: string, bindFunctions?: (el: Element) => void) => {
|
||||
element.innerHTML = svgCode;
|
||||
if (callback !== undefined) {
|
||||
callback(id);
|
||||
}
|
||||
if (bindFunctions) {
|
||||
bindFunctions(element);
|
||||
}
|
||||
},
|
||||
element
|
||||
);
|
||||
} catch (error) {
|
||||
handleError(error, errors, mermaid.parseError);
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
// TODO: We should be throwing an error object.
|
||||
throw errors[0];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an internal function and should not be made public, as it will likely change.
|
||||
* @internal
|
||||
|
@ -204,10 +114,6 @@ const loadExternalDiagrams = async (...diagrams: ExternalDiagramDefinition[]) =>
|
|||
/**
|
||||
* Equivalent to {@link init}, except an error will be thrown on error.
|
||||
*
|
||||
* @alpha
|
||||
* @deprecated This is an internal function and will very likely be modified in v10, or earlier.
|
||||
* We recommend staying with {@link initThrowsErrors} if you don't need `lazyLoadedDiagrams`.
|
||||
*
|
||||
* @param config - **Deprecated** Mermaid sequenceConfig.
|
||||
* @param nodes - One of:
|
||||
* - A DOM Node
|
||||
|
@ -216,7 +122,7 @@ const loadExternalDiagrams = async (...diagrams: ExternalDiagramDefinition[]) =>
|
|||
* @param callback - Function that is called with the id of each generated mermaid diagram.
|
||||
* @returns Resolves on success, otherwise the {@link Promise} will be rejected.
|
||||
*/
|
||||
const initThrowsErrorsAsync = async function (
|
||||
const initThrowsErrors = async function (
|
||||
config?: MermaidConfig,
|
||||
nodes?: string | HTMLElement | NodeListOf<HTMLElement>,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
|
@ -282,7 +188,7 @@ const initThrowsErrorsAsync = async function (
|
|||
log.debug('Detected early reinit: ', init);
|
||||
}
|
||||
try {
|
||||
await mermaidAPI.renderAsync(
|
||||
await mermaidAPI.render(
|
||||
id,
|
||||
txt,
|
||||
(svgCode: string, bindFunctions?: (el: Element) => void) => {
|
||||
|
@ -369,10 +275,6 @@ const setParseErrorHandler = function (newParseErrorHandler: (err: any, hash: an
|
|||
mermaid.parseError = newParseErrorHandler;
|
||||
};
|
||||
|
||||
const parse = (txt: string) => {
|
||||
return mermaidAPI.parse(txt, mermaid.parseError);
|
||||
};
|
||||
|
||||
const executionQueue: (() => Promise<unknown>)[] = [];
|
||||
let executionQueueRunning = false;
|
||||
const executeQueue = async () => {
|
||||
|
@ -395,15 +297,14 @@ const executeQueue = async () => {
|
|||
|
||||
/**
|
||||
* @param txt - The mermaid code to be parsed.
|
||||
* @deprecated This is an internal function and should not be used. Will be removed in v10.
|
||||
*/
|
||||
const parseAsync = (txt: string): Promise<boolean> => {
|
||||
const parse = (txt: string): Promise<boolean> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// This promise will resolve when the mermaidAPI.render call is done.
|
||||
// It will be queued first and will be executed when it is first in line
|
||||
const performCall = () =>
|
||||
new Promise((res, rej) => {
|
||||
mermaidAPI.parseAsync(txt, mermaid.parseError).then(
|
||||
mermaidAPI.parse(txt, mermaid.parseError).then(
|
||||
(r) => {
|
||||
// This resolves for the promise for the queue handling
|
||||
res(r);
|
||||
|
@ -422,10 +323,7 @@ const parseAsync = (txt: string): Promise<boolean> => {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated This is an internal function and should not be used. Will be removed in v10.
|
||||
*/
|
||||
const renderAsync = (
|
||||
const render = (
|
||||
id: string,
|
||||
text: string,
|
||||
cb?: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
||||
|
@ -436,7 +334,7 @@ const renderAsync = (
|
|||
// It will be queued first and will be executed when it is first in line
|
||||
const performCall = () =>
|
||||
new Promise((res, rej) => {
|
||||
mermaidAPI.renderAsync(id, text, cb, container).then(
|
||||
mermaidAPI.render(id, text, cb, container).then(
|
||||
(r) => {
|
||||
// This resolves for the promise for the queue handling
|
||||
res(r);
|
||||
|
@ -461,12 +359,9 @@ const mermaid: {
|
|||
parseError?: ParseErrorFunction;
|
||||
mermaidAPI: typeof mermaidAPI;
|
||||
parse: typeof parse;
|
||||
parseAsync: typeof parseAsync;
|
||||
render: typeof mermaidAPI.render;
|
||||
renderAsync: typeof renderAsync;
|
||||
render: typeof render;
|
||||
init: typeof init;
|
||||
initThrowsErrors: typeof initThrowsErrors;
|
||||
initThrowsErrorsAsync: typeof initThrowsErrorsAsync;
|
||||
registerExternalDiagrams: typeof registerExternalDiagrams;
|
||||
initialize: typeof initialize;
|
||||
contentLoaded: typeof contentLoaded;
|
||||
|
@ -476,12 +371,9 @@ const mermaid: {
|
|||
diagrams: {},
|
||||
mermaidAPI,
|
||||
parse,
|
||||
parseAsync,
|
||||
render: mermaidAPI.render,
|
||||
renderAsync,
|
||||
render,
|
||||
init,
|
||||
initThrowsErrors,
|
||||
initThrowsErrorsAsync,
|
||||
registerExternalDiagrams,
|
||||
initialize,
|
||||
parseError: undefined,
|
||||
|
|
|
@ -720,10 +720,10 @@ describe('mermaidAPI', function () {
|
|||
const diagramText = `${diagramType}\n accTitle: ${a11yTitle}\n accDescr: ${a11yDescr}\n`;
|
||||
const expectedDiagramType = testedDiagram.expectedType;
|
||||
|
||||
it('aria-roledscription is set to the diagram type, addSVGa11yTitleDescription is called', () => {
|
||||
it('aria-roledscription is set to the diagram type, addSVGa11yTitleDescription is called', async () => {
|
||||
const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo');
|
||||
const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription');
|
||||
mermaidAPI.render(id, diagramText);
|
||||
await mermaidAPI.render(id, diagramText);
|
||||
expect(a11yDiagramInfo_spy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expectedDiagramType
|
||||
|
@ -735,7 +735,7 @@ describe('mermaidAPI', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('renderAsync', () => {
|
||||
describe('render', () => {
|
||||
// Be sure to add async before each test (anonymous) method
|
||||
|
||||
// These are more like integration tests right now because nothing is mocked.
|
||||
|
@ -775,7 +775,7 @@ describe('mermaidAPI', function () {
|
|||
it('aria-roledscription is set to the diagram type, addSVGa11yTitleDescription is called', async () => {
|
||||
const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo');
|
||||
const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription');
|
||||
await mermaidAPI.renderAsync(id, diagramText);
|
||||
await mermaidAPI.render(id, diagramText);
|
||||
expect(a11yDiagramInfo_spy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expectedDiagramType
|
||||
|
|
|
@ -80,17 +80,7 @@ export type D3Element = any;
|
|||
* @param text - The mermaid diagram definition.
|
||||
* @param parseError - If set, handles errors.
|
||||
*/
|
||||
function parse(text: string, parseError?: ParseErrorFunction): boolean {
|
||||
addDiagrams();
|
||||
const diagram = new Diagram(text, parseError);
|
||||
return diagram.parse(text, parseError);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param text - The mermaid diagram definition.
|
||||
* @param parseError - If set, handles errors.
|
||||
*/
|
||||
async function parseAsync(text: string, parseError?: ParseErrorFunction): Promise<boolean> {
|
||||
async function parse(text: string, parseError?: ParseErrorFunction): Promise<boolean> {
|
||||
addDiagrams();
|
||||
const diagram = await getDiagramFromText(text, parseError);
|
||||
return diagram.parse(text, parseError);
|
||||
|
@ -375,214 +365,8 @@ export const removeExistingElements = (
|
|||
* element will be removed when rendering is completed.
|
||||
* @returns Returns the rendered element as a string containing the SVG definition.
|
||||
*/
|
||||
const render = function (
|
||||
id: string,
|
||||
text: string,
|
||||
cb?: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
||||
svgContainingElement?: Element
|
||||
): string {
|
||||
addDiagrams();
|
||||
|
||||
configApi.reset();
|
||||
|
||||
// Add Directives. Must do this before getting the config and before creating the diagram.
|
||||
const graphInit = utils.detectInit(text);
|
||||
if (graphInit) {
|
||||
directiveSanitizer(graphInit);
|
||||
configApi.addDirective(graphInit);
|
||||
}
|
||||
|
||||
const config = configApi.getConfig();
|
||||
log.debug(config);
|
||||
|
||||
// Check the maximum allowed text size
|
||||
// TODO: Remove magic number
|
||||
if (text.length > (config?.maxTextSize ?? 50000)) {
|
||||
text = MAX_TEXTLENGTH_EXCEEDED_MSG;
|
||||
}
|
||||
|
||||
// clean up text CRLFs
|
||||
text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;;
|
||||
|
||||
const idSelector = '#' + id;
|
||||
const iFrameID = 'i' + id;
|
||||
const iFrameID_selector = '#' + iFrameID;
|
||||
const enclosingDivID = 'd' + id;
|
||||
const enclosingDivID_selector = '#' + enclosingDivID;
|
||||
|
||||
let root: any = select('body');
|
||||
|
||||
const isSandboxed = config.securityLevel === SECURITY_LVL_SANDBOX;
|
||||
const isLooseSecurityLevel = config.securityLevel === SECURITY_LVL_LOOSE;
|
||||
|
||||
const fontFamily = config.fontFamily;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Define the root d3 node
|
||||
// In regular execution the svgContainingElement will be the element with a mermaid class
|
||||
|
||||
if (svgContainingElement !== undefined) {
|
||||
if (svgContainingElement) {
|
||||
svgContainingElement.innerHTML = '';
|
||||
}
|
||||
|
||||
if (isSandboxed) {
|
||||
// If we are in sandboxed mode, we do everything mermaid related in a (sandboxed )iFrame
|
||||
const iframe = sandboxedIframe(select(svgContainingElement), iFrameID);
|
||||
root = select(iframe.nodes()[0]!.contentDocument!.body);
|
||||
root.node().style.margin = 0;
|
||||
} else {
|
||||
root = select(svgContainingElement);
|
||||
}
|
||||
appendDivSvgG(root, id, enclosingDivID, `font-family: ${fontFamily}`, XMLNS_XLINK_STD);
|
||||
} else {
|
||||
// No svgContainingElement was provided
|
||||
|
||||
// If there is an existing element with the id, we remove it. This likely a previously rendered diagram
|
||||
removeExistingElements(document, id, enclosingDivID, iFrameID);
|
||||
|
||||
// Add the temporary div used for rendering with the enclosingDivID.
|
||||
// This temporary div will contain a svg with the id == id
|
||||
|
||||
if (isSandboxed) {
|
||||
// If we are in sandboxed mode, we do everything mermaid related in a (sandboxed) iFrame
|
||||
const iframe = sandboxedIframe(select('body'), iFrameID);
|
||||
root = select(iframe.nodes()[0]!.contentDocument!.body);
|
||||
root.node().style.margin = 0;
|
||||
} else {
|
||||
root = select('body');
|
||||
}
|
||||
|
||||
appendDivSvgG(root, id, enclosingDivID);
|
||||
}
|
||||
|
||||
text = encodeEntities(text);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Create the diagram
|
||||
|
||||
// Important that we do not create the diagram until after the directives have been included
|
||||
let diag;
|
||||
let parseEncounteredException;
|
||||
|
||||
try {
|
||||
// diag = new Diagram(text);
|
||||
diag = getDiagramFromText(text);
|
||||
if ('then' in diag) {
|
||||
throw new Error('Diagram is a promise. Use renderAsync.');
|
||||
}
|
||||
} catch (error) {
|
||||
diag = new Diagram('error');
|
||||
parseEncounteredException = error;
|
||||
}
|
||||
|
||||
// Get the temporary div element containing the svg (the parent HTML Element)
|
||||
const element = root.select(enclosingDivID_selector).node();
|
||||
const graphType = diag.type;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Create and insert the styles (user styles, theme styles, config styles)
|
||||
// These are dealing with HTML Elements, not d3 nodes.
|
||||
|
||||
// Insert an element into svg. This is where we put the styles
|
||||
const svg = element.firstChild;
|
||||
const firstChild = svg.firstChild;
|
||||
const diagramClassDefs = CLASSDEF_DIAGRAMS.includes(graphType)
|
||||
? diag.renderer.getClasses(text, diag)
|
||||
: {};
|
||||
|
||||
const rules = createUserStyles(
|
||||
config,
|
||||
graphType,
|
||||
// @ts-ignore convert renderer to TS.
|
||||
diagramClassDefs,
|
||||
idSelector
|
||||
);
|
||||
|
||||
// svg is a HTML element (not a d3 node)
|
||||
const style1 = document.createElement('style');
|
||||
style1.innerHTML = rules;
|
||||
svg.insertBefore(style1, firstChild);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Draw the diagram with the renderer
|
||||
try {
|
||||
diag.renderer.draw(text, id, version, diag);
|
||||
} catch (e) {
|
||||
errorRenderer.draw(text, id, version);
|
||||
throw e;
|
||||
}
|
||||
|
||||
// This is the d3 node for the svg element
|
||||
const svgNode = root.select(`${enclosingDivID_selector} svg`);
|
||||
const a11yTitle = diag.db.getAccTitle?.();
|
||||
const a11yDescr = diag.db.getAccDescription?.();
|
||||
addA11yInfo(graphType, svgNode, a11yTitle, a11yDescr);
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Clean up SVG code
|
||||
root.select(`[id="${id}"]`).selectAll('foreignobject > *').attr('xmlns', XMLNS_XHTML_STD);
|
||||
|
||||
// Fix for when the base tag is used
|
||||
let svgCode = root.select(enclosingDivID_selector).node().innerHTML;
|
||||
|
||||
log.debug('config.arrowMarkerAbsolute', config.arrowMarkerAbsolute);
|
||||
svgCode = cleanUpSvgCode(svgCode, isSandboxed, evaluate(config.arrowMarkerAbsolute));
|
||||
|
||||
if (isSandboxed) {
|
||||
const svgEl = root.select(enclosingDivID_selector + ' svg').node();
|
||||
svgCode = putIntoIFrame(svgCode, svgEl);
|
||||
} else if (!isLooseSecurityLevel) {
|
||||
// Sanitize the svgCode using DOMPurify
|
||||
svgCode = DOMPurify.sanitize(svgCode, {
|
||||
ADD_TAGS: DOMPURIFY_TAGS,
|
||||
ADD_ATTR: DOMPURIFY_ATTR,
|
||||
});
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Do any callbacks (cb = callback)
|
||||
if (cb !== undefined) {
|
||||
switch (graphType) {
|
||||
case 'flowchart':
|
||||
case 'flowchart-v2':
|
||||
cb(svgCode, flowDb.bindFunctions);
|
||||
break;
|
||||
case 'gantt':
|
||||
cb(svgCode, ganttDb.bindFunctions);
|
||||
break;
|
||||
case 'class':
|
||||
case 'classDiagram':
|
||||
cb(svgCode, classDb.bindFunctions);
|
||||
break;
|
||||
default:
|
||||
cb(svgCode);
|
||||
}
|
||||
} else {
|
||||
log.debug('CB = undefined!');
|
||||
}
|
||||
attachFunctions();
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Remove the temporary element if appropriate
|
||||
const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector;
|
||||
const node = select(tmpElementSelector).node();
|
||||
if (node && 'remove' in node) {
|
||||
node.remove();
|
||||
}
|
||||
|
||||
if (parseEncounteredException) {
|
||||
throw parseEncounteredException;
|
||||
}
|
||||
|
||||
return svgCode;
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated This is an internal function and should not be used. Will be removed in v10.
|
||||
*/
|
||||
|
||||
const renderAsync = async function (
|
||||
const render = async function (
|
||||
id: string,
|
||||
text: string,
|
||||
cb?: (svgCode: string, bindFunctions?: (element: Element) => void) => void,
|
||||
|
@ -886,9 +670,7 @@ function addA11yInfo(
|
|||
|
||||
export const mermaidAPI = Object.freeze({
|
||||
render,
|
||||
renderAsync,
|
||||
parse,
|
||||
parseAsync,
|
||||
parseDirective,
|
||||
initialize,
|
||||
getConfig: configApi.getConfig,
|
||||
|
|
|
@ -4,7 +4,7 @@ const mermaid = require('mermaid');
|
|||
import mindmap from '@mermaid-js/mermaid-mindmap';
|
||||
|
||||
const render = async (graph) => {
|
||||
const svg = await mermaid.renderAsync('dummy', graph);
|
||||
const svg = await mermaid.render('dummy', graph);
|
||||
console.log(svg);
|
||||
document.getElementById('graphDiv').innerHTML = svg;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue