diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index a7ccad650..fd8baf278 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -8,6 +8,8 @@ import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdo import { decodeEntities } from '../utils.js'; import { splitLineToFitWidth } from './splitText.js'; import type { MarkdownLine, MarkdownWord } from './types.js'; +import common, { renderKatex } from '$root/diagrams/common/common.js'; +import { getConfig } from '$root/diagram-api/diagramAPI.js'; function applyStyle(dom, styleFn) { if (styleFn) { @@ -15,11 +17,16 @@ function applyStyle(dom, styleFn) { } } -function addHtmlSpan(element, node, width, classes, addBackground = false) { +async function addHtmlSpan(element, node, width, classes, addBackground = false) { const fo = element.append('foreignObject'); const div = fo.append('xhtml:div'); - const label = node.label; + // const label = node.label; + let label = ''; + + if (node.label) { + label = await renderKatex(node.label.replace(common.lineBreakRegex, '\n'), getConfig()); + } const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; div.html( ` to sett classes to'nodeLabel' when isNode=true otherwise 'edgeLabel' // When not using htmlLabels => to set classes to 'title-row' when isTitle=true otherwise 'title-row' -export const createText = ( +export const createText = async ( el, text = '', { @@ -218,7 +225,7 @@ export const createText = ( label: decodedReplacedText, labelStyle: style.replace('fill:', 'color:'), }; - const vertexNode = addHtmlSpan(el, node, width, classes, addSvgBackground); + const vertexNode = await addHtmlSpan(el, node, width, classes, addSvgBackground); return vertexNode; } else { const structuredText = markdownToLines(text, config); diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index d33a3523a..7defd950d 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -120,19 +120,35 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit }) ); - // Insert labels, this will insert them into the dom so that the width can be calculated - // Also figure out which edges point to/from clusters and adjust them accordingly - // Edges from/to clusters really points to the first child in the cluster. - // TODO: pick optimal child in the cluster to us as link anchor - graph.edges().forEach(function (e) { - const edge = graph.edge(e.v, e.w, e.name); - log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); - log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); + const processEdges = async () => { + const edgePromises = graph.edges().map(async function (e) { + const edge = graph.edge(e.v, e.w, e.name); + log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); + log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); - // Check if link is either from or to a cluster - log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]); - insertEdgeLabel(edgeLabels, edge); - }); + // Check if link is either from or to a cluster + log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]); + await insertEdgeLabel(edgeLabels, edge); + }); + + await Promise.all(edgePromises); + }; + + await processEdges(); + + // // Insert labels, this will insert them into the dom so that the width can be calculated + // // Also figure out which edges point to/from clusters and adjust them accordingly + // // Edges from/to clusters really points to the first child in the cluster. + // // TODO: pick optimal child in the cluster to us as link anchor + // await graph.edges().forEach(async function (e) { + // const edge = graph.edge(e.v, e.w, e.name); + // log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); + // log.info('Edge ' + e.v + ' -> ' + e.w + ': ', e, ' ', JSON.stringify(graph.edge(e))); + + // // Check if link is either from or to a cluster + // log.info('Fix', clusterDb, 'ids:', e.v, e.w, 'Translating: ', clusterDb[e.v], clusterDb[e.w]); + // await insertEdgeLabel(edgeLabels, edge); + // }); graph.edges().forEach(function (e) { log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e)); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 6baccfedf..23de549e6 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -10,7 +10,7 @@ import createLabel from './createLabel.js'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; -const rect = (parent, node) => { +const rect = async (parent, node) => { log.info('Creating subgraph rect for ', node.id, node); const siteConfig = getConfig(); const { themeVariables, handdrawnSeed } = siteConfig; @@ -29,8 +29,8 @@ const rect = (parent, node) => { // .appendChild(createLabel(node.label, node.labelStyle, undefined, true)); const text = node.labelType === 'markdown' - ? createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels }) - : labelEl.node().appendChild(createLabel(node.label, node.labelStyle, undefined, true)); + ? await createText(labelEl, node.label, { style: node.labelStyle, useHtmlLabels }) + : labelEl.node().appendChild(await createLabel(node.label, node.labelStyle, undefined, true)); // Get the size of the label let bbox = text.getBBox(); @@ -154,7 +154,7 @@ const noteGroup = (parent, node) => { return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } }; }; -const roundedWithTitle = (parent, node) => { +const roundedWithTitle = async (parent, node) => { const siteConfig = getConfig(); const { themeVariables, handdrawnSeed } = siteConfig; @@ -177,7 +177,9 @@ const roundedWithTitle = (parent, node) => { const label = shapeSvg.insert('g').attr('class', 'cluster-label'); let innerRect = shapeSvg.append('rect'); - const text = label.node().appendChild(createLabel(node.label, node.labelStyle, undefined, true)); + const text = label + .node() + .appendChild(await createLabel(node.label, node.labelStyle, undefined, true)); // Get the size of the label let bbox = text.getBBox(); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js index c018c46e5..7641b7752 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js @@ -1,7 +1,7 @@ import { select } from 'd3'; import { log } from '$root/logger.js'; import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import { evaluate } from '$root/diagrams/common/common.js'; +import common, { evaluate, renderKatex } from '$root/diagrams/common/common.js'; import { decodeEntities } from '$root/utils.js'; /** @@ -18,11 +18,14 @@ function applyStyle(dom, styleFn) { * @param {any} node * @returns {SVGForeignObjectElement} Node */ -function addHtmlLabel(node) { +async function addHtmlLabel(node) { const fo = select(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')); const div = fo.append('xhtml:div'); - const label = node.label; + let label = node.label; + if (node.label) { + label = await renderKatex(node.label.replace(common.lineBreakRegex, '\n'), getConfig()); + } const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; div.html( '