mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-18 23:09:49 +02:00

* develop: (22 commits) Fix for build by revering jsdoc Revert "chore(deps-dev): bump documentation from 13.2.0 to 14.0.0" Review comments. Add test for handling parameter names that are "default" Add test for handling parameter names that are keywords Add test for handling trailing whitespaces Add first C4 parser test chore(deps-dev): bump eslint-plugin-jest from 26.8.2 to 26.8.7 chore(deps-dev): bump documentation from 13.2.0 to 14.0.0 chore(deps-dev): bump terser-webpack-plugin from 5.3.4 to 5.3.5 chore(deps-dev): bump prettier-plugin-jsdoc from 0.3.38 to 0.4.1 test(e2e): add array and generic attributes erDiagram test test(common): add generic parser test test(parser): add tests for generics and arrays in erDiagram feat: add array and generic symbols for erDiagram Lint markdown Fix prettier formatting in vscode Prettier Fix `securityLevel` docs Update README.md ...
171 lines
4.5 KiB
TypeScript
171 lines
4.5 KiB
TypeScript
import DOMPurify from 'dompurify';
|
|
import { MermaidConfig } from '../../config.type';
|
|
|
|
/**
|
|
* Gets the rows of lines in a string
|
|
*
|
|
* @param {string | undefined} s The string to check the lines for
|
|
* @returns {string[]} The rows in that string
|
|
*/
|
|
export const getRows = (s?: string): string[] => {
|
|
if (!s) return [''];
|
|
const str = breakToPlaceholder(s).replace(/\\n/g, '#br#');
|
|
return str.split('#br#');
|
|
};
|
|
|
|
/**
|
|
* Removes script tags from a text
|
|
*
|
|
* @param {string} txt The text to sanitize
|
|
* @returns {string} The safer text
|
|
*/
|
|
export const removeScript = (txt: string): string => {
|
|
return DOMPurify.sanitize(txt);
|
|
};
|
|
|
|
const sanitizeMore = (text: string, config: MermaidConfig) => {
|
|
// TODO Q: Should this check really be here? Feels like we should be sanitizing it regardless.
|
|
if (config.flowchart?.htmlLabels !== false) {
|
|
const level = config.securityLevel;
|
|
if (level === 'antiscript' || level === 'strict') {
|
|
text = removeScript(text);
|
|
} else if (level !== 'loose') {
|
|
text = breakToPlaceholder(text);
|
|
text = text.replace(/</g, '<').replace(/>/g, '>');
|
|
text = text.replace(/=/g, '=');
|
|
text = placeholderToBreak(text);
|
|
}
|
|
}
|
|
return text;
|
|
};
|
|
|
|
export const sanitizeText = (text: string, config: MermaidConfig): string => {
|
|
if (!text) return text;
|
|
if (config.dompurifyConfig) {
|
|
text = DOMPurify.sanitize(sanitizeMore(text, config), config.dompurifyConfig).toString();
|
|
} else {
|
|
text = DOMPurify.sanitize(sanitizeMore(text, config));
|
|
}
|
|
return text;
|
|
};
|
|
|
|
export const sanitizeTextOrArray = (
|
|
a: string | string[] | string[][],
|
|
config: MermaidConfig
|
|
): string | string[] => {
|
|
if (typeof a === 'string') return sanitizeText(a, config);
|
|
// TODO Q: Do we need flat?
|
|
return a.flat().map((x: string) => sanitizeText(x, config));
|
|
};
|
|
|
|
export const lineBreakRegex = /<br\s*\/?>/gi;
|
|
|
|
/**
|
|
* Whether or not a text has any linebreaks
|
|
*
|
|
* @param {string} text The text to test
|
|
* @returns {boolean} Whether or not the text has breaks
|
|
*/
|
|
export const hasBreaks = (text: string): boolean => {
|
|
return lineBreakRegex.test(text);
|
|
};
|
|
|
|
/**
|
|
* Splits on <br> tags
|
|
*
|
|
* @param {string} text Text to split
|
|
* @returns {string[]} List of lines as strings
|
|
*/
|
|
export const splitBreaks = (text: string): string[] => {
|
|
return text.split(lineBreakRegex);
|
|
};
|
|
|
|
/**
|
|
* Converts placeholders to linebreaks in HTML
|
|
*
|
|
* @param {string} s HTML with placeholders
|
|
* @returns {string} HTML with breaks instead of placeholders
|
|
*/
|
|
const placeholderToBreak = (s: string): string => {
|
|
return s.replace(/#br#/g, '<br/>');
|
|
};
|
|
|
|
/**
|
|
* Opposite of `placeholderToBreak`, converts breaks to placeholders
|
|
*
|
|
* @param {string} s HTML string
|
|
* @returns {string} String with placeholders
|
|
*/
|
|
const breakToPlaceholder = (s: string): string => {
|
|
return s.replace(lineBreakRegex, '#br#');
|
|
};
|
|
|
|
/**
|
|
* Gets the current URL
|
|
*
|
|
* @param {boolean} useAbsolute Whether to return the absolute URL or not
|
|
* @returns {string} The current URL
|
|
*/
|
|
const getUrl = (useAbsolute: boolean): string => {
|
|
let url = '';
|
|
// TODO Q: If useAbsolute if false, empty string is returned. Bug?
|
|
if (useAbsolute) {
|
|
url =
|
|
window.location.protocol +
|
|
'//' +
|
|
window.location.host +
|
|
window.location.pathname +
|
|
window.location.search;
|
|
// TODO Q: Why is this necessary?
|
|
url = url.replaceAll(/\(/g, '\\(');
|
|
url = url.replaceAll(/\)/g, '\\)');
|
|
}
|
|
|
|
return url;
|
|
};
|
|
|
|
/**
|
|
* Converts a string/boolean into a boolean
|
|
*
|
|
* @param {string | boolean} val String or boolean to convert
|
|
* @returns {boolean} The result from the input
|
|
*/
|
|
// TODO Q: Should we make this check more specific? 'False', '0', 'null' all will evaluate to true.
|
|
export const evaluate = (val: string | boolean): boolean =>
|
|
val === 'false' || val === false ? false : true;
|
|
|
|
/**
|
|
* Makes generics in typescript syntax
|
|
*
|
|
* @example <caption>Array of array of strings in typescript syntax</caption>
|
|
* // returns "Array<Array<string>>"
|
|
* parseGenericTypes('Array~Array~string~~');
|
|
*
|
|
* @param {string} text The text to convert
|
|
* @returns {string} The converted string
|
|
*/
|
|
export const parseGenericTypes = function (text: string): string {
|
|
let cleanedText = text;
|
|
|
|
if (text.indexOf('~') != -1) {
|
|
cleanedText = cleanedText.replace('~', '<');
|
|
cleanedText = cleanedText.replace('~', '>');
|
|
|
|
return parseGenericTypes(cleanedText);
|
|
} else {
|
|
return cleanedText;
|
|
}
|
|
};
|
|
|
|
export default {
|
|
getRows,
|
|
sanitizeText,
|
|
sanitizeTextOrArray,
|
|
hasBreaks,
|
|
splitBreaks,
|
|
lineBreakRegex,
|
|
removeScript,
|
|
getUrl,
|
|
evaluate,
|
|
};
|