mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-16 13:59:54 +02:00
refactor: Move directive processing before parsing
Directives and fronmatter will be preprocessed and removed from the text before parsing.
This commit is contained in:
@@ -25,7 +25,7 @@ import {
|
||||
select,
|
||||
} from 'd3';
|
||||
import common from './diagrams/common/common.js';
|
||||
import { configKeys } from './defaultConfig.js';
|
||||
import { sanitizeDirective } from './utils/sanitizeDirective.js';
|
||||
import { log } from './logger.js';
|
||||
import { detectType } from './diagram-api/detectType.js';
|
||||
import assignWithDepth from './assignWithDepth.js';
|
||||
@@ -62,7 +62,6 @@ const d3CurveTypes = {
|
||||
|
||||
const directiveWithoutOpen =
|
||||
/\s*(?:(\w+)(?=:):|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi;
|
||||
|
||||
/**
|
||||
* Detects the init config object from the text
|
||||
*
|
||||
@@ -197,6 +196,10 @@ export const detectDirective = function (
|
||||
}
|
||||
};
|
||||
|
||||
export const removeDirectives = function (text: string): string {
|
||||
return text.replace(directiveRegex, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* Detects whether a substring in present in a given array
|
||||
*
|
||||
@@ -842,88 +845,6 @@ export const entityDecode = function (html: string): string {
|
||||
return unescape(decoder.textContent);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitizes directive objects
|
||||
*
|
||||
* @param args - Directive's JSON
|
||||
*/
|
||||
export const sanitizeDirective = (args: unknown): void => {
|
||||
log.debug('sanitizeDirective called with', args);
|
||||
|
||||
// Return if not an object
|
||||
if (typeof args !== 'object' || args == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize each element if an array
|
||||
if (Array.isArray(args)) {
|
||||
args.forEach((arg) => sanitizeDirective(arg));
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize each key if an object
|
||||
for (const key of Object.keys(args)) {
|
||||
log.debug('Checking key', key);
|
||||
if (
|
||||
key.startsWith('__') ||
|
||||
key.includes('proto') ||
|
||||
key.includes('constr') ||
|
||||
!configKeys.has(key) ||
|
||||
args[key] == null
|
||||
) {
|
||||
log.debug('sanitize deleting key: ', key);
|
||||
delete args[key];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Recurse if an object
|
||||
if (typeof args[key] === 'object') {
|
||||
log.debug('sanitizing object', key);
|
||||
sanitizeDirective(args[key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
const cssMatchers = ['themeCSS', 'fontFamily', 'altFontFamily'];
|
||||
for (const cssKey of cssMatchers) {
|
||||
if (key.includes(cssKey)) {
|
||||
log.debug('sanitizing css option', key);
|
||||
args[key] = sanitizeCss(args[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.themeVariables) {
|
||||
for (const k of Object.keys(args.themeVariables)) {
|
||||
const val = args.themeVariables[k];
|
||||
if (val?.match && !val.match(/^[\d "#%(),.;A-Za-z]+$/)) {
|
||||
args.themeVariables[k] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug('After sanitization', args);
|
||||
};
|
||||
|
||||
export const sanitizeCss = (str: string): string => {
|
||||
let startCnt = 0;
|
||||
let endCnt = 0;
|
||||
|
||||
for (const element of str) {
|
||||
if (startCnt < endCnt) {
|
||||
return '{ /* ERROR: Unbalanced CSS */ }';
|
||||
}
|
||||
if (element === '{') {
|
||||
startCnt++;
|
||||
} else if (element === '}') {
|
||||
endCnt++;
|
||||
}
|
||||
}
|
||||
if (startCnt !== endCnt) {
|
||||
return '{ /* ERROR: Unbalanced CSS */ }';
|
||||
}
|
||||
// Todo add more checks here
|
||||
return str;
|
||||
};
|
||||
|
||||
export interface DetailedError {
|
||||
str: string;
|
||||
hash: any;
|
||||
@@ -1021,8 +942,6 @@ export default {
|
||||
runFunc,
|
||||
entityDecode,
|
||||
initIdGenerator,
|
||||
sanitizeDirective,
|
||||
sanitizeCss,
|
||||
insertTitle,
|
||||
parseFontSize,
|
||||
};
|
||||
|
Reference in New Issue
Block a user