mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-31 19:04:16 +01:00 
			
		
		
		
	fix: sanitize HTML for spans
This commit is contained in:
		| @@ -2,9 +2,8 @@ | ||||
| // @ts-nocheck TODO: Fix types | ||||
| import { select } from 'd3'; | ||||
| import type { MermaidConfig } from '../config.type.js'; | ||||
| import { getConfig, sanitizeText } from '../diagram-api/diagramAPI.js'; | ||||
| import type { SVGGroup } from '../diagram-api/types.js'; | ||||
| import common, { hasKatex, renderKatexSanitized } from '../diagrams/common/common.js'; | ||||
| import common, { hasKatex, renderKatexSanitized, 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'; | ||||
| @@ -19,7 +18,15 @@ function applyStyle(dom, styleFn) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| async function addHtmlSpan(element, node, width, classes, addBackground = false) { | ||||
| async function addHtmlSpan( | ||||
|   element, | ||||
|   node, | ||||
|   width, | ||||
|   classes, | ||||
|   addBackground = false, | ||||
|   // TODO: Make config mandatory | ||||
|   config: MermaidConfig = {} | ||||
| ) { | ||||
|   const fo = element.append('foreignObject'); | ||||
|   // This is not the final width but used in order to make sure the foreign | ||||
|   // object in firefox gets a width at all. The final width is fetched from the div | ||||
| @@ -27,16 +34,12 @@ async function addHtmlSpan(element, node, width, classes, addBackground = false) | ||||
|   fo.attr('height', `${10 * width}px`); | ||||
|  | ||||
|   const div = fo.append('xhtml:div'); | ||||
|   let label = node.label; | ||||
|   if (node.label && hasKatex(node.label)) { | ||||
|     label = await renderKatexSanitized( | ||||
|       node.label.replace(common.lineBreakRegex, '\n'), | ||||
|       getConfig() | ||||
|     ); | ||||
|   } | ||||
|   const sanitizedLabel = hasKatex(label) | ||||
|     ? await renderKatexSanitized(node.label.replace(common.lineBreakRegex, '\n'), config) | ||||
|     : sanitizeText(label, config); | ||||
|   const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; | ||||
|   const span = div.append('span'); | ||||
|   span.html(label); | ||||
|   span.html(sanitizedLabel); | ||||
|   applyStyle(span, node.labelStyle); | ||||
|   span.attr('class', `${labelClass} ${classes}`); | ||||
|  | ||||
| @@ -59,9 +62,6 @@ async function addHtmlSpan(element, node, width, classes, addBackground = false) | ||||
|     bbox = div.node().getBoundingClientRect(); | ||||
|   } | ||||
|  | ||||
|   // fo.style('width', bbox.width); | ||||
|   // fo.style('height', bbox.height); | ||||
|  | ||||
|   return fo.node(); | ||||
| } | ||||
|  | ||||
| @@ -184,9 +184,14 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) { | ||||
| /** | ||||
|  * Convert fontawesome labels into fontawesome icons by using a regex pattern | ||||
|  * @param text - The raw string to convert | ||||
|  * @param config - Mermaid config | ||||
|  * @returns string with fontawesome icons as svg if the icon is registered otherwise as i tags | ||||
|  */ | ||||
| export async function replaceIconSubstring(text: string) { | ||||
| export async function replaceIconSubstring( | ||||
|   text: string, | ||||
|   // TODO: Make config mandatory | ||||
|   config: MermaidConfig = {} | ||||
| ): Promise<string> { | ||||
|   const pendingReplacements: Promise<string>[] = []; | ||||
|   // cspell: disable-next-line | ||||
|   text.replace(/(fa[bklrs]?):fa-([\w-]+)/g, (fullMatch, prefix, iconName) => { | ||||
| @@ -196,7 +201,7 @@ export async function replaceIconSubstring(text: string) { | ||||
|         if (await isIconAvailable(registeredIconName)) { | ||||
|           return await getIconSVG(registeredIconName, undefined, { class: 'label-icon' }); | ||||
|         } else { | ||||
|           return `<i class='${sanitizeText(fullMatch).replace(':', ' ')}'></i>`; | ||||
|           return `<i class='${sanitizeText(fullMatch, config).replace(':', ' ')}'></i>`; | ||||
|         } | ||||
|       })() | ||||
|     ); | ||||
| @@ -239,7 +244,7 @@ export const createText = async ( | ||||
|     // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? | ||||
|  | ||||
|     const htmlText = markdownToHTML(text, config); | ||||
|     const decodedReplacedText = await replaceIconSubstring(decodeEntities(htmlText)); | ||||
|     const decodedReplacedText = await replaceIconSubstring(decodeEntities(htmlText), config); | ||||
|  | ||||
|     //for Katex the text could contain escaped characters, \\relax that should be transformed to \relax | ||||
|     const inputForKatex = text.replace(/\\\\/g, '\\'); | ||||
| @@ -249,7 +254,7 @@ export const createText = async ( | ||||
|       label: hasKatex(text) ? inputForKatex : decodedReplacedText, | ||||
|       labelStyle: style.replace('fill:', 'color:'), | ||||
|     }; | ||||
|     const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground); | ||||
|     const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground, config); | ||||
|     return vertexNode; | ||||
|   } else { | ||||
|     //sometimes the user might add br tags with 1 or more spaces in between, so we need to replace them with <br/> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Sidharth Vinod
					Sidharth Vinod