UNPKG

5.93 kBJavaScriptView Raw
1import { l as log, H as decodeEntities } from "./mermaid-a953d906.js";
2import { fromMarkdown } from "mdast-util-from-markdown";
3import { dedent } from "ts-dedent";
4function preprocessMarkdown(markdown) {
5 const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, "\n");
6 const withoutExtraSpaces = dedent(withoutMultipleNewlines);
7 return withoutExtraSpaces;
8}
9function markdownToLines(markdown) {
10 const preprocessedMarkdown = preprocessMarkdown(markdown);
11 const { children } = fromMarkdown(preprocessedMarkdown);
12 const lines = [[]];
13 let currentLine = 0;
14 function processNode(node, parentType = "normal") {
15 if (node.type === "text") {
16 const textLines = node.value.split("\n");
17 textLines.forEach((textLine, index) => {
18 if (index !== 0) {
19 currentLine++;
20 lines.push([]);
21 }
22 textLine.split(" ").forEach((word) => {
23 if (word) {
24 lines[currentLine].push({ content: word, type: parentType });
25 }
26 });
27 });
28 } else if (node.type === "strong" || node.type === "emphasis") {
29 node.children.forEach((contentNode) => {
30 processNode(contentNode, node.type);
31 });
32 }
33 }
34 children.forEach((treeNode) => {
35 if (treeNode.type === "paragraph") {
36 treeNode.children.forEach((contentNode) => {
37 processNode(contentNode);
38 });
39 }
40 });
41 return lines;
42}
43function markdownToHTML(markdown) {
44 const { children } = fromMarkdown(markdown);
45 function output(node) {
46 if (node.type === "text") {
47 return node.value.replace(/\n/g, "<br/>");
48 } else if (node.type === "strong") {
49 return `<strong>${node.children.map(output).join("")}</strong>`;
50 } else if (node.type === "emphasis") {
51 return `<em>${node.children.map(output).join("")}</em>`;
52 } else if (node.type === "paragraph") {
53 return `<p>${node.children.map(output).join("")}</p>`;
54 }
55 return `Unsupported markdown: ${node.type}`;
56 }
57 return children.map(output).join("");
58}
59function applyStyle(dom, styleFn) {
60 if (styleFn) {
61 dom.attr("style", styleFn);
62 }
63}
64function addHtmlSpan(element, node, width, classes, addBackground = false) {
65 const fo = element.append("foreignObject");
66 const div = fo.append("xhtml:div");
67 const label = node.label;
68 const labelClass = node.isNode ? "nodeLabel" : "edgeLabel";
69 div.html(
70 `
71 <span class="${labelClass} ${classes}" ` + (node.labelStyle ? 'style="' + node.labelStyle + '"' : "") + ">" + label + "</span>"
72 );
73 applyStyle(div, node.labelStyle);
74 div.style("display", "table-cell");
75 div.style("white-space", "nowrap");
76 div.style("max-width", width + "px");
77 div.attr("xmlns", "http://www.w3.org/1999/xhtml");
78 if (addBackground) {
79 div.attr("class", "labelBkg");
80 }
81 let bbox = div.node().getBoundingClientRect();
82 if (bbox.width === width) {
83 div.style("display", "table");
84 div.style("white-space", "break-spaces");
85 div.style("width", width + "px");
86 bbox = div.node().getBoundingClientRect();
87 }
88 fo.style("width", bbox.width);
89 fo.style("height", bbox.height);
90 return fo.node();
91}
92function createTspan(textElement, lineIndex, lineHeight) {
93 return textElement.append("tspan").attr("class", "text-outer-tspan").attr("x", 0).attr("y", lineIndex * lineHeight - 0.1 + "em").attr("dy", lineHeight + "em");
94}
95function createFormattedText(width, g, structuredText, addBackground = false) {
96 const lineHeight = 1.1;
97 const labelGroup = g.append("g");
98 let bkg = labelGroup.insert("rect").attr("class", "background");
99 const textElement = labelGroup.append("text").attr("y", "-10.1");
100 let lineIndex = -1;
101 structuredText.forEach((line) => {
102 lineIndex++;
103 let tspan = createTspan(textElement, lineIndex, lineHeight);
104 let words = [...line].reverse();
105 let currentWord;
106 let wrappedLine = [];
107 while (words.length) {
108 currentWord = words.pop();
109 wrappedLine.push(currentWord);
110 updateTextContentAndStyles(tspan, wrappedLine);
111 if (tspan.node().getComputedTextLength() > width) {
112 wrappedLine.pop();
113 words.push(currentWord);
114 updateTextContentAndStyles(tspan, wrappedLine);
115 wrappedLine = [];
116 lineIndex++;
117 tspan = createTspan(textElement, lineIndex, lineHeight);
118 }
119 }
120 });
121 if (addBackground) {
122 const bbox = textElement.node().getBBox();
123 const padding = 2;
124 bkg.attr("x", -padding).attr("y", -padding).attr("width", bbox.width + 2 * padding).attr("height", bbox.height + 2 * padding);
125 return labelGroup.node();
126 } else {
127 return textElement.node();
128 }
129}
130function updateTextContentAndStyles(tspan, wrappedLine) {
131 tspan.text("");
132 wrappedLine.forEach((word, index) => {
133 const innerTspan = tspan.append("tspan").attr("font-style", word.type === "em" ? "italic" : "normal").attr("class", "text-inner-tspan").attr("font-weight", word.type === "strong" ? "bold" : "normal");
134 if (index === 0) {
135 innerTspan.text(word.content);
136 } else {
137 innerTspan.text(" " + word.content);
138 }
139 });
140}
141const createText = (el, text = "", {
142 style = "",
143 isTitle = false,
144 classes = "",
145 useHtmlLabels = true,
146 isNode = true,
147 width,
148 addSvgBackground = false
149} = {}) => {
150 log.info("createText", text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground);
151 if (useHtmlLabels) {
152 const htmlText = markdownToHTML(text);
153 const node = {
154 isNode,
155 label: decodeEntities(htmlText).replace(
156 /fa[blrs]?:fa-[\w-]+/g,
157 (s) => `<i class='${s.replace(":", " ")}'></i>`
158 ),
159 labelStyle: style.replace("fill:", "color:")
160 };
161 let vertexNode = addHtmlSpan(el, node, width, classes, addSvgBackground);
162 return vertexNode;
163 } else {
164 const structuredText = markdownToLines(text);
165 const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground);
166 return svgLabel;
167 }
168};
169export {
170 createText as c
171};