mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-17 21:19:41 +02:00
fix: Sanitize Katex
This commit is contained in:
@@ -311,9 +311,8 @@ export const hasKatex = (text: string): boolean => (text.match(katexRegex)?.leng
|
||||
* @returns Object containing \{width, height\}
|
||||
*/
|
||||
export const calculateMathMLDimensions = async (text: string, config: MermaidConfig) => {
|
||||
text = await renderKatex(text, config);
|
||||
const divElem = document.createElement('div');
|
||||
divElem.innerHTML = text;
|
||||
divElem.innerHTML = await renderKatexSanitized(text, config);
|
||||
divElem.id = 'katex-temp';
|
||||
divElem.style.visibility = 'hidden';
|
||||
divElem.style.position = 'absolute';
|
||||
@@ -325,14 +324,7 @@ export const calculateMathMLDimensions = async (text: string, config: MermaidCon
|
||||
return dim;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to render and return the KaTeX portion of a string with MathML
|
||||
*
|
||||
* @param text - The text to test
|
||||
* @param config - Configuration for Mermaid
|
||||
* @returns String containing MathML if KaTeX is supported, or an error message if it is not and stylesheets aren't present
|
||||
*/
|
||||
export const renderKatex = async (text: string, config: MermaidConfig): Promise<string> => {
|
||||
const renderKatexUnsanitized = async (text: string, config: MermaidConfig): Promise<string> => {
|
||||
if (!hasKatex(text)) {
|
||||
return text;
|
||||
}
|
||||
@@ -366,6 +358,20 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise<
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to render and return the KaTeX portion of a string with MathML
|
||||
*
|
||||
* @param text - The text to test
|
||||
* @param config - Configuration for Mermaid
|
||||
* @returns String containing MathML if KaTeX is supported, or an error message if it is not and stylesheets aren't present
|
||||
*/
|
||||
export const renderKatexSanitized = async (
|
||||
text: string,
|
||||
config: MermaidConfig
|
||||
): Promise<string> => {
|
||||
return sanitizeText(await renderKatexUnsanitized(text, config), config);
|
||||
};
|
||||
|
||||
export default {
|
||||
getRows,
|
||||
sanitizeText,
|
||||
|
@@ -1,13 +1,12 @@
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { select, curveLinear, selectAll } from 'd3';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import utils from '../../utils.js';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import { curveLinear, select, selectAll } from 'd3';
|
||||
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import { log } from '../../logger.js';
|
||||
import common, { evaluate, renderKatex } from '../common/common.js';
|
||||
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import utils, { getStylesFromArray, interpolateToCurve } from '../../utils.js';
|
||||
import common, { evaluate, renderKatexSanitized } from '../common/common.js';
|
||||
|
||||
const conf = {};
|
||||
export const setConf = function (cnf) {
|
||||
@@ -140,7 +139,7 @@ export const addVertices = async function (vert, g, svgId, root, doc, diagObj) {
|
||||
default:
|
||||
_shape = 'rect';
|
||||
}
|
||||
const labelText = await renderKatex(vertexText, getConfig());
|
||||
const labelText = await renderKatexSanitized(vertexText, getConfig());
|
||||
|
||||
// Add the node
|
||||
g.setNode(vertex.id, {
|
||||
@@ -315,7 +314,10 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
edgeData.labelpos = 'c';
|
||||
}
|
||||
edgeData.labelType = edge.labelType;
|
||||
edgeData.label = await renderKatex(edge.text.replace(common.lineBreakRegex, '\n'), getConfig());
|
||||
edgeData.label = await renderKatexSanitized(
|
||||
edge.text.replace(common.lineBreakRegex, '\n'),
|
||||
getConfig()
|
||||
);
|
||||
|
||||
if (edge.style === undefined) {
|
||||
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;';
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { select, curveLinear, selectAll } from 'd3';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import { curveLinear, select, selectAll } from 'd3';
|
||||
import { render as Render } from 'dagre-d3-es';
|
||||
import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
|
||||
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
||||
import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import { log } from '../../logger.js';
|
||||
import common, { evaluate, renderKatex } from '../common/common.js';
|
||||
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import { getStylesFromArray, interpolateToCurve } from '../../utils.js';
|
||||
import common, { evaluate, renderKatexSanitized } from '../common/common.js';
|
||||
import flowChartShapes from './flowChartShapes.js';
|
||||
|
||||
const conf = {};
|
||||
@@ -57,7 +57,7 @@ export const addVertices = async function (vert, g, svgId, root, _doc, diagObj)
|
||||
if (evaluate(getConfig().flowchart.htmlLabels)) {
|
||||
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
|
||||
const node = {
|
||||
label: await renderKatex(
|
||||
label: await renderKatexSanitized(
|
||||
vertexText.replace(
|
||||
/fa[blrs]?:fa-[\w-]+/g, // cspell:disable-line
|
||||
(s) => `<i class='${s.replace(':', ' ')}'></i>`
|
||||
@@ -242,7 +242,7 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
edgeData.labelType = 'html';
|
||||
edgeData.label = `<span id="L-${linkId}" class="edgeLabel L-${linkNameStart}' L-${linkNameEnd}" style="${
|
||||
edgeData.labelStyle
|
||||
}">${await renderKatex(
|
||||
}">${await renderKatexSanitized(
|
||||
edge.text.replace(
|
||||
/fa[blrs]?:fa-[\w-]+/g, // cspell:disable-line
|
||||
(s) => `<i class='${s.replace(':', ' ')}'></i>`
|
||||
|
@@ -1,9 +1,12 @@
|
||||
import common, { calculateMathMLDimensions, hasKatex, renderKatex } from '../common/common.js';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
import { addFunction } from '../../interactionDb.js';
|
||||
import { ZERO_WIDTH_SPACE, parseFontSize } from '../../utils.js';
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import * as configApi from '../../config.js';
|
||||
import { ZERO_WIDTH_SPACE, parseFontSize } from '../../utils.js';
|
||||
import common, {
|
||||
calculateMathMLDimensions,
|
||||
hasKatex,
|
||||
renderKatexSanitized,
|
||||
} from '../common/common.js';
|
||||
import * as svgDrawCommon from '../common/svgDrawCommon.js';
|
||||
|
||||
export const ACTOR_TYPE_WIDTH = 18 * 2;
|
||||
const TOP_ACTOR_CLASS = 'actor-top';
|
||||
@@ -86,13 +89,13 @@ const popupMenuToggle = function (popId) {
|
||||
|
||||
export const drawKatex = async function (elem, textData, msgModel = null) {
|
||||
let textElem = elem.append('foreignObject');
|
||||
const lines = await renderKatex(textData.text, configApi.getConfig());
|
||||
const linesSanitized = await renderKatexSanitized(textData.text, configApi.getConfig());
|
||||
|
||||
const divElem = textElem
|
||||
.append('xhtml:div')
|
||||
.attr('style', 'width: fit-content;')
|
||||
.attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||
.html(lines);
|
||||
.html(linesSanitized);
|
||||
const dim = divElem.node().getBoundingClientRect();
|
||||
|
||||
textElem.attr('height', Math.round(dim.height)).attr('width', Math.round(dim.width));
|
||||
@@ -963,7 +966,7 @@ const _drawTextCandidateFunc = (function () {
|
||||
.append('div')
|
||||
.style('text-align', 'center')
|
||||
.style('vertical-align', 'middle')
|
||||
.html(await renderKatex(content, configApi.getConfig()));
|
||||
.html(await renderKatexSanitized(content, configApi.getConfig()));
|
||||
|
||||
byTspan(content, s, x, y, width, height, textAttrs, conf);
|
||||
_setTextAttrs(text, textAttrs);
|
||||
|
@@ -1,6 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// @ts-nocheck TODO: Fix types
|
||||
import { getConfig } from '../config.js';
|
||||
import type { Group } from '../diagram-api/types.js';
|
||||
import { sanitizeText } from '../diagrams/common/common.js';
|
||||
import type { D3TSpanElement, D3TextElement } from '../diagrams/common/commonTypes.js';
|
||||
import { log } from '../logger.js';
|
||||
import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text.js';
|
||||
@@ -21,12 +23,15 @@ function addHtmlSpan(element, node, width, classes, addBackground = false) {
|
||||
const label = node.label;
|
||||
const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel';
|
||||
div.html(
|
||||
`
|
||||
sanitizeText(
|
||||
`
|
||||
<span class="${labelClass} ${classes}" ` +
|
||||
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
|
||||
'>' +
|
||||
label +
|
||||
'</span>'
|
||||
(node.labelStyle ? 'style="' + node.labelStyle + '"' : '') +
|
||||
'>' +
|
||||
label +
|
||||
'</span>',
|
||||
getConfig()
|
||||
)
|
||||
);
|
||||
|
||||
applyStyle(div, node.labelStyle);
|
||||
|
Reference in New Issue
Block a user