Merge pull request #5002 from ad1992/bug/4983-fix-getMessageAPI

fix: getMessageAPI so it considers entity codes
This commit is contained in:
Sidharth Vinod
2023-11-07 05:04:53 +00:00
committed by GitHub
11 changed files with 71 additions and 96 deletions

View File

@@ -16,4 +16,4 @@
#### Defined in #### Defined in
[mermaidAPI.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L59) [mermaidAPI.ts:60](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L60)

View File

@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in #### Defined in
[mermaidAPI.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L79) [mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
--- ---
@@ -51,4 +51,4 @@ The svg code for the rendered graph.
#### Defined in #### Defined in
[mermaidAPI.ts:69](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L69) [mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)

View File

@@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in #### Defined in
[mermaidAPI.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L63) [mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
## Variables ## Variables
@@ -96,7 +96,7 @@ mermaid.initialize(config);
#### Defined in #### Defined in
[mermaidAPI.ts:641](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L641) [mermaidAPI.ts:603](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L603)
## Functions ## Functions
@@ -127,7 +127,7 @@ Return the last node appended
#### Defined in #### Defined in
[mermaidAPI.ts:299](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L299) [mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
--- ---
@@ -153,7 +153,7 @@ the cleaned up svgCode
#### Defined in #### Defined in
[mermaidAPI.ts:245](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L245) [mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209)
--- ---
@@ -178,7 +178,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L175) [mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
--- ---
@@ -201,7 +201,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L222) [mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
--- ---
@@ -228,47 +228,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:160](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L160) [mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124)
---
### decodeEntities
**decodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be decoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L146)
---
### encodeEntities
**encodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be encoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L117)
--- ---
@@ -294,7 +254,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in #### Defined in
[mermaidAPI.ts:276](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L276) [mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
--- ---
@@ -319,4 +279,4 @@ Remove any existing elements from the given document
#### Defined in #### Defined in
[mermaidAPI.ts:349](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L349) [mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313)

View File

@@ -3,6 +3,8 @@ import { log } from './logger.js';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js'; 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 { UnknownDiagramError } from './errors.js'; import { UnknownDiagramError } from './errors.js';
import { encodeEntities } from './utils.js';
import type { DetailedError } from './utils.js'; import type { DetailedError } from './utils.js';
import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js'; import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js';
@@ -21,6 +23,7 @@ export class Diagram {
private detectError?: UnknownDiagramError; private detectError?: UnknownDiagramError;
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) { constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
this.text = encodeEntities(text);
this.text += '\n'; this.text += '\n';
const cnf = configApi.getConfig(); const cnf = configApi.getConfig();
try { try {

View File

@@ -2,7 +2,7 @@ import { select } from 'd3';
import { log } from '../logger.js'; import { log } from '../logger.js';
import { getConfig } from '../diagram-api/diagramAPI.js'; import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js'; import { evaluate } from '../diagrams/common/common.js';
import { decodeEntities } from '../mermaidAPI.js'; import { decodeEntities } from '../utils.js';
/** /**
* @param dom * @param dom

View File

@@ -1,9 +1,9 @@
import createLabel from '../createLabel.js'; import createLabel from '../createLabel.js';
import { createText } from '../../rendering-util/createText.js'; import { createText } from '../../rendering-util/createText.js';
import { getConfig } from '../../diagram-api/diagramAPI.js'; import { getConfig } from '../../diagram-api/diagramAPI.js';
import { decodeEntities } from '../../mermaidAPI.js';
import { select } from 'd3'; import { select } from 'd3';
import { evaluate, sanitizeText } from '../../diagrams/common/common.js'; import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
import { decodeEntities } from '../../utils.js';
export const labelHelper = async (parent, node, _classes, isNode) => { export const labelHelper = async (parent, node, _classes, isNode) => {
let classes; let classes;

View File

@@ -69,4 +69,18 @@ Expecting 'TXT', got 'NEWLINE'"
'"No diagram type detected matching given configuration for text: thor TD; A-->B"' '"No diagram type detected matching given configuration for text: thor TD; A-->B"'
); );
}); });
test('should consider entity codes when present in diagram defination', async () => {
const diagram = await getDiagramFromText(`sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!`);
// @ts-ignore: we need to add types for sequenceDb which will be done in separate PR
const messages = diagram.db?.getMessages?.();
if (!messages) {
throw new Error('Messages not found!');
}
expect(messages[0].message).toBe('I fl°°9829¶ß you!');
expect(messages[1].message).toBe('I fl°°9829¶ß you fl°infin¶ß times more!');
});
}); });

View File

@@ -38,8 +38,6 @@ import type { MermaidConfig } from './config.type.js';
import mermaidAPI, { removeExistingElements } from './mermaidAPI.js'; import mermaidAPI, { removeExistingElements } from './mermaidAPI.js';
import { import {
encodeEntities,
decodeEntities,
createCssStyles, createCssStyles,
createUserStyles, createUserStyles,
appendDivSvgG, appendDivSvgG,
@@ -68,6 +66,7 @@ vi.mock('stylis', () => {
}; };
}); });
import { compile, serialize } from 'stylis'; import { compile, serialize } from 'stylis';
import { decodeEntities, encodeEntities } from './utils.js';
/** /**
* @see https://vitest.dev/guide/mocking.html Mock part of a module * @see https://vitest.dev/guide/mocking.html Mock part of a module

View File

@@ -30,6 +30,7 @@ import isEmpty from 'lodash-es/isEmpty.js';
import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js';
import type { DiagramStyleClassDef } from './diagram-api/types.js'; import type { DiagramStyleClassDef } from './diagram-api/types.js';
import { preprocessDiagram } from './preprocess.js'; import { preprocessDiagram } from './preprocess.js';
import { decodeEntities } from './utils.js';
const MAX_TEXTLENGTH = 50_000; const MAX_TEXTLENGTH = 50_000;
const MAX_TEXTLENGTH_EXCEEDED_MSG = const MAX_TEXTLENGTH_EXCEEDED_MSG =
@@ -110,43 +111,6 @@ async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean
return true; return true;
} }
/**
* @param text - text to be encoded
* @returns
*/
export const encodeEntities = function (text: string): string {
let txt = text;
txt = txt.replace(/style.*:\S*#.*;/g, function (s): string {
return s.substring(0, s.length - 1);
});
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s): string {
return s.substring(0, s.length - 1);
});
txt = txt.replace(/#\w+;/g, function (s) {
const innerTxt = s.substring(1, s.length - 1);
const isInt = /^\+?\d+$/.test(innerTxt);
if (isInt) {
return 'fl°°' + innerTxt + '¶ß';
} else {
return 'fl°' + innerTxt + '¶ß';
}
});
return txt;
};
/**
*
* @param text - text to be decoded
* @returns
*/
export const decodeEntities = function (text: string): string {
return text.replace(/fl°°/g, '&#').replace(/fl°/g, '&').replace(/¶ß/g, ';');
};
// append !important; to each cssClass followed by a final !important, all enclosed in { } // append !important; to each cssClass followed by a final !important, all enclosed in { }
// //
/** /**
@@ -436,8 +400,6 @@ const render = async function (
appendDivSvgG(root, id, enclosingDivID); appendDivSvgG(root, id, enclosingDivID);
} }
text = encodeEntities(text);
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// Create the diagram // Create the diagram

View File

@@ -3,8 +3,8 @@
import type { Group } from '../diagram-api/types.js'; import type { Group } from '../diagram-api/types.js';
import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js'; import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js';
import { log } from '../logger.js'; import { log } from '../logger.js';
import { decodeEntities } from '../mermaidAPI.js';
import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text.js'; import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text.js';
import { decodeEntities } from '../utils.js';
import { splitLineToFitWidth } from './splitText.js'; import { splitLineToFitWidth } from './splitText.js';
import type { MarkdownLine, MarkdownWord } from './types.js'; import type { MarkdownLine, MarkdownWord } from './types.js';

View File

@@ -888,3 +888,40 @@ export default {
parseFontSize, parseFontSize,
InitIDGenerator, InitIDGenerator,
}; };
/**
* @param text - text to be encoded
* @returns
*/
export const encodeEntities = function (text: string): string {
let txt = text;
txt = txt.replace(/style.*:\S*#.*;/g, function (s): string {
return s.substring(0, s.length - 1);
});
txt = txt.replace(/classDef.*:\S*#.*;/g, function (s): string {
return s.substring(0, s.length - 1);
});
txt = txt.replace(/#\w+;/g, function (s) {
const innerTxt = s.substring(1, s.length - 1);
const isInt = /^\+?\d+$/.test(innerTxt);
if (isInt) {
return 'fl°°' + innerTxt + '¶ß';
} else {
return 'fl°' + innerTxt + '¶ß';
}
});
return txt;
};
/**
*
* @param text - text to be decoded
* @returns
*/
export const decodeEntities = function (text: string): string {
return text.replace(/fl°°/g, '&#').replace(/fl°/g, '&').replace(/¶ß/g, ';');
};