dishui 0.0.76 → 0.0.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js +2 -26
- package/dist/components/pro/RichTextEditor/BubbleToolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.d.ts +2 -1
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js +57 -22
- package/dist/components/pro/RichTextEditor/Toolbar/ColorPicker.js.map +1 -1
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js +2 -22
- package/dist/components/pro/RichTextEditor/Toolbar/Toolbar.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js +71 -70
- package/dist/components/pro/RichTextEditor/extensions/MarkdownBlock.js.map +1 -1
- package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.d.ts +2 -0
- package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js +96 -0
- package/dist/components/pro/RichTextEditor/extensions/legacyMermaid.js.map +1 -0
- package/dist/dishui.css +1 -1
- package/package.json +1 -1
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import l from "react-
|
|
6
|
-
import u from "
|
|
7
|
-
import d from "
|
|
8
|
-
import f from "
|
|
9
|
-
import p from "
|
|
1
|
+
import { normalizeLegacyMermaid as e } from "./legacyMermaid.js";
|
|
2
|
+
import { useCallback as t, useEffect as n, useRef as r, useState as i, useSyncExternalStore as a } from "react";
|
|
3
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
4
|
+
import { Prism as c } from "react-syntax-highlighter";
|
|
5
|
+
import { oneLight as l } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
6
|
+
import u from "react-markdown";
|
|
7
|
+
import d from "remark-gfm";
|
|
8
|
+
import f from "rehype-katex";
|
|
9
|
+
import p from "remark-math";
|
|
10
|
+
import m from "mermaid";
|
|
10
11
|
import "katex/dist/katex.min.css";
|
|
11
|
-
import { Node as
|
|
12
|
+
import { Node as h, NodeViewWrapper as g, ReactNodeViewRenderer as _, mergeAttributes as v } from "@tiptap/react";
|
|
12
13
|
//#region src/components/pro/RichTextEditor/extensions/MarkdownBlock.tsx
|
|
13
|
-
function
|
|
14
|
-
let n =
|
|
15
|
-
|
|
16
|
-
}), [
|
|
17
|
-
return
|
|
14
|
+
function y(e) {
|
|
15
|
+
let n = t((t) => (e.on("update", t), e.on("transaction", t), e.on("destroy", t), () => {
|
|
16
|
+
e.off("update", t), e.off("transaction", t), e.off("destroy", t);
|
|
17
|
+
}), [e]);
|
|
18
|
+
return a(n, () => !e.isDestroyed && e.isEditable, () => !1);
|
|
18
19
|
}
|
|
19
|
-
var
|
|
20
|
-
function
|
|
21
|
-
let n =
|
|
20
|
+
var b = Promise.resolve();
|
|
21
|
+
function x(e, t) {
|
|
22
|
+
let n = b.then(() => (m.initialize({
|
|
22
23
|
startOnLoad: !1,
|
|
23
24
|
theme: "default",
|
|
24
25
|
securityLevel: "strict",
|
|
@@ -28,35 +29,35 @@ function b(e, t) {
|
|
|
28
29
|
useMaxWidth: !0,
|
|
29
30
|
htmlLabels: !1
|
|
30
31
|
}
|
|
31
|
-
}),
|
|
32
|
-
return
|
|
32
|
+
}), m.mermaidAPI.render(e, t)));
|
|
33
|
+
return b = n.catch(() => void 0), n;
|
|
33
34
|
}
|
|
34
|
-
var
|
|
35
|
-
let
|
|
36
|
-
return
|
|
37
|
-
if (!
|
|
38
|
-
let
|
|
35
|
+
var S = ({ code: t }) => {
|
|
36
|
+
let i = r(null);
|
|
37
|
+
return n(() => {
|
|
38
|
+
if (!i.current || (i.current.replaceChildren(), !t.trim())) return;
|
|
39
|
+
let n = !1;
|
|
39
40
|
return (async () => {
|
|
40
41
|
try {
|
|
41
|
-
let { svg:
|
|
42
|
-
!
|
|
42
|
+
let { svg: r } = await x(`mermaid-md-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`, e(t));
|
|
43
|
+
!n && i.current && (i.current.innerHTML = r);
|
|
43
44
|
} catch (e) {
|
|
44
|
-
!
|
|
45
|
+
!n && i.current && (i.current.textContent = String(e));
|
|
45
46
|
}
|
|
46
47
|
})(), () => {
|
|
47
|
-
|
|
48
|
+
n = !0;
|
|
48
49
|
};
|
|
49
|
-
}, [
|
|
50
|
-
ref:
|
|
50
|
+
}, [t]), /* @__PURE__ */ o("div", {
|
|
51
|
+
ref: i,
|
|
51
52
|
className: "rte-mermaid-container"
|
|
52
53
|
});
|
|
53
|
-
},
|
|
54
|
-
remarkPlugins: [
|
|
55
|
-
rehypePlugins: [
|
|
54
|
+
}, C = ({ content: e }) => /* @__PURE__ */ o(u, {
|
|
55
|
+
remarkPlugins: [d, p],
|
|
56
|
+
rehypePlugins: [f],
|
|
56
57
|
components: { code({ className: e, children: t, ...n }) {
|
|
57
58
|
let r = /language-(\w+)/.exec(e || "")?.[1], i = String(t).replace(/\n$/, "");
|
|
58
|
-
return r === "mermaid" ? /* @__PURE__ */
|
|
59
|
-
style:
|
|
59
|
+
return r === "mermaid" ? /* @__PURE__ */ o(S, { code: i }) : r ? /* @__PURE__ */ o(c, {
|
|
60
|
+
style: l,
|
|
60
61
|
language: r,
|
|
61
62
|
PreTag: "div",
|
|
62
63
|
customStyle: {
|
|
@@ -66,51 +67,51 @@ var x = ({ code: e }) => {
|
|
|
66
67
|
margin: "0.5em 0"
|
|
67
68
|
},
|
|
68
69
|
children: i
|
|
69
|
-
}) : /* @__PURE__ */
|
|
70
|
+
}) : /* @__PURE__ */ o("code", {
|
|
70
71
|
className: e,
|
|
71
72
|
...n,
|
|
72
73
|
children: t
|
|
73
74
|
});
|
|
74
75
|
} },
|
|
75
76
|
children: e
|
|
76
|
-
}),
|
|
77
|
-
let u =
|
|
78
|
-
|
|
79
|
-
m(
|
|
80
|
-
}, [
|
|
81
|
-
d &&
|
|
77
|
+
}), w = ({ node: e, editor: a, updateAttributes: c, selected: l }) => {
|
|
78
|
+
let u = y(a), [d, f] = i(!1), [p, m] = i(e.attrs.content || ""), h = r(null);
|
|
79
|
+
n(() => {
|
|
80
|
+
m(e.attrs.content || ""), f(!1);
|
|
81
|
+
}, [e.attrs.content, u]), n(() => {
|
|
82
|
+
d && h.current && (h.current.focus(), _(h.current));
|
|
82
83
|
}, [d]);
|
|
83
84
|
let _ = (e) => {
|
|
84
85
|
e.style.height = "auto", e.style.height = e.scrollHeight + "px";
|
|
85
|
-
},
|
|
86
|
+
}, v = t((e) => {
|
|
86
87
|
m(e.target.value), _(e.target);
|
|
87
|
-
}, []), b =
|
|
88
|
-
!
|
|
88
|
+
}, []), b = t(() => {
|
|
89
|
+
!a.isDestroyed && a.isEditable && c({ content: p }), f(!1);
|
|
89
90
|
}, [
|
|
90
|
-
|
|
91
|
+
a,
|
|
91
92
|
p,
|
|
92
93
|
c
|
|
93
|
-
]), x =
|
|
94
|
+
]), x = t((e) => {
|
|
94
95
|
e.key === "Escape" && b();
|
|
95
|
-
}, [b]),
|
|
96
|
-
return /* @__PURE__ */
|
|
96
|
+
}, [b]), S = p || "# Markdown Block\n\nWrite your **markdown** here.\n\n```mermaid\ngraph LR\n A[Start] --> B[End]\n```\n";
|
|
97
|
+
return /* @__PURE__ */ s(g, {
|
|
97
98
|
contentEditable: !1,
|
|
98
99
|
className: `rte-markdown-block ${l ? "rte-markdown-block--selected" : ""}`,
|
|
99
|
-
children: [/* @__PURE__ */
|
|
100
|
+
children: [/* @__PURE__ */ s("div", {
|
|
100
101
|
className: "rte-markdown-block__header",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
102
|
+
children: [/* @__PURE__ */ o("span", {
|
|
102
103
|
className: "rte-markdown-block__label",
|
|
103
104
|
children: "Markdown"
|
|
104
|
-
}), /* @__PURE__ */
|
|
105
|
+
}), /* @__PURE__ */ s("button", {
|
|
105
106
|
type: "button",
|
|
106
107
|
className: `rte-markdown-block__toggle ${d ? "rte-markdown-block__toggle--active" : ""}`,
|
|
107
108
|
disabled: !u,
|
|
108
109
|
onMouseDown: (e) => e.preventDefault(),
|
|
109
110
|
onClick: () => {
|
|
110
|
-
!
|
|
111
|
+
!a.isDestroyed && a.isEditable && (d && c({ content: p }), f(!d));
|
|
111
112
|
},
|
|
112
113
|
title: d ? "Preview" : "Edit",
|
|
113
|
-
children: [d ? /* @__PURE__ */
|
|
114
|
+
children: [d ? /* @__PURE__ */ s("svg", {
|
|
114
115
|
width: "14",
|
|
115
116
|
height: "14",
|
|
116
117
|
viewBox: "0 0 24 24",
|
|
@@ -119,12 +120,12 @@ var x = ({ code: e }) => {
|
|
|
119
120
|
strokeWidth: "2",
|
|
120
121
|
strokeLinecap: "round",
|
|
121
122
|
strokeLinejoin: "round",
|
|
122
|
-
children: [/* @__PURE__ */
|
|
123
|
+
children: [/* @__PURE__ */ o("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }), /* @__PURE__ */ o("circle", {
|
|
123
124
|
cx: "12",
|
|
124
125
|
cy: "12",
|
|
125
126
|
r: "3"
|
|
126
127
|
})]
|
|
127
|
-
}) : /* @__PURE__ */
|
|
128
|
+
}) : /* @__PURE__ */ s("svg", {
|
|
128
129
|
width: "14",
|
|
129
130
|
height: "14",
|
|
130
131
|
viewBox: "0 0 24 24",
|
|
@@ -133,33 +134,33 @@ var x = ({ code: e }) => {
|
|
|
133
134
|
strokeWidth: "2",
|
|
134
135
|
strokeLinecap: "round",
|
|
135
136
|
strokeLinejoin: "round",
|
|
136
|
-
children: [/* @__PURE__ */
|
|
137
|
-
}), /* @__PURE__ */
|
|
137
|
+
children: [/* @__PURE__ */ o("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), /* @__PURE__ */ o("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })]
|
|
138
|
+
}), /* @__PURE__ */ o("span", { children: d ? "Preview" : "Edit" })]
|
|
138
139
|
})]
|
|
139
|
-
}), /* @__PURE__ */
|
|
140
|
+
}), /* @__PURE__ */ o("div", {
|
|
140
141
|
className: "rte-markdown-block__body",
|
|
141
|
-
children: d && u ? /* @__PURE__ */
|
|
142
|
-
ref:
|
|
142
|
+
children: d && u ? /* @__PURE__ */ o("textarea", {
|
|
143
|
+
ref: h,
|
|
143
144
|
className: "rte-markdown-block__editor",
|
|
144
145
|
value: p,
|
|
145
|
-
onChange:
|
|
146
|
+
onChange: v,
|
|
146
147
|
onBlur: b,
|
|
147
148
|
onKeyDown: x,
|
|
148
149
|
placeholder: "Enter Markdown content...",
|
|
149
150
|
rows: 5
|
|
150
|
-
}) : /* @__PURE__ */
|
|
151
|
+
}) : /* @__PURE__ */ o("div", {
|
|
151
152
|
className: "rte-markdown-block__preview prose",
|
|
152
153
|
onDoubleClick: () => {
|
|
153
|
-
!
|
|
154
|
+
!a.isDestroyed && a.isEditable && f(!0);
|
|
154
155
|
},
|
|
155
|
-
children:
|
|
156
|
+
children: S.trim() ? /* @__PURE__ */ o(C, { content: S }) : /* @__PURE__ */ o("p", {
|
|
156
157
|
className: "rte-markdown-block__placeholder",
|
|
157
158
|
children: "Double-click to edit Markdown content..."
|
|
158
159
|
})
|
|
159
160
|
})
|
|
160
161
|
})]
|
|
161
162
|
});
|
|
162
|
-
},
|
|
163
|
+
}, T = h.create({
|
|
163
164
|
name: "markdownBlock",
|
|
164
165
|
group: "block",
|
|
165
166
|
atom: !0,
|
|
@@ -171,13 +172,13 @@ var x = ({ code: e }) => {
|
|
|
171
172
|
return [{ tag: "div[data-type=\"markdown-block\"]" }];
|
|
172
173
|
},
|
|
173
174
|
renderHTML({ HTMLAttributes: e }) {
|
|
174
|
-
return ["div",
|
|
175
|
+
return ["div", v(e, { "data-type": "markdown-block" })];
|
|
175
176
|
},
|
|
176
177
|
addNodeView() {
|
|
177
|
-
return
|
|
178
|
+
return _(w);
|
|
178
179
|
}
|
|
179
180
|
});
|
|
180
181
|
//#endregion
|
|
181
|
-
export {
|
|
182
|
+
export { T as MarkdownBlockExtension, T as default, S as MermaidRenderer, y as useNodeEditable };
|
|
182
183
|
|
|
183
184
|
//# sourceMappingURL=MarkdownBlock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkdownBlock.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/MarkdownBlock.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';\nimport { Node, mergeAttributes } from '@tiptap/react';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\n\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport mermaid from 'mermaid';\nimport 'katex/dist/katex.min.css';\n\nexport function useNodeEditable(editor: NodeViewProps['editor']) {\n const subscribe = useCallback((notify: () => void) => {\n // setEditable emits update, not transaction, in Tiptap 3.\n editor.on('update', notify);\n editor.on('transaction', notify);\n editor.on('destroy', notify);\n return () => {\n editor.off('update', notify);\n editor.off('transaction', notify);\n editor.off('destroy', notify);\n };\n }, [editor]);\n return useSyncExternalStore(subscribe, () => !editor.isDestroyed && editor.isEditable, () => false);\n}\n\nlet renderQueue: Promise<unknown> = Promise.resolve();\n\nfunction renderMermaid(id: string, code: string) {\n const result = renderQueue.then(() => {\n // Capture strict config when rendering starts, not before Mermaid's global queue runs.\n mermaid.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'strict',\n suppressErrorRendering: true,\n fontFamily: 'inherit',\n flowchart: { useMaxWidth: true, htmlLabels: false },\n });\n return mermaid.mermaidAPI.render(id, code);\n });\n renderQueue = result.catch(() => undefined);\n return result;\n}\n\nexport const MermaidRenderer: React.FC<{ code: string }> = ({ code }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!containerRef.current) return;\n containerRef.current.replaceChildren();\n if (!code.trim()) return;\n\n let cancelled = false;\n const render = async () => {\n try {\n const id = `mermaid-md-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const { svg } = await renderMermaid(id, code);\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = svg;\n }\n } catch (err) {\n if (!cancelled && containerRef.current) {\n containerRef.current.textContent = String(err);\n }\n }\n };\n render();\n return () => { cancelled = true; };\n }, [code]);\n\n return <div ref={containerRef} className=\"rte-mermaid-container\" />;\n};\n\nconst MarkdownPreview: React.FC<{ content: string }> = ({ content }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') {\n return <MermaidRenderer code={text} />;\n }\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0.5em 0',\n }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {content}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownBlockView: React.FC<NodeViewProps> = ({\n node,\n editor,\n updateAttributes,\n selected,\n}) => {\n const editable = useNodeEditable(editor);\n const [isEditing, setIsEditing] = useState(false);\n const [localContent, setLocalContent] = useState(node.attrs.content || '');\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n setLocalContent(node.attrs.content || '');\n setIsEditing(false);\n }, [node.attrs.content, editable]);\n\n useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus();\n adjustTextareaHeight(textareaRef.current);\n }\n }, [isEditing]);\n\n const adjustTextareaHeight = (el: HTMLTextAreaElement) => {\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n };\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalContent(e.target.value);\n adjustTextareaHeight(e.target);\n }, []);\n\n const handleBlur = useCallback(() => {\n if (!editor.isDestroyed && editor.isEditable) updateAttributes({ content: localContent });\n setIsEditing(false);\n }, [editor, localContent, updateAttributes]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleBlur();\n }\n }, [handleBlur]);\n\n const defaultContent = `# Markdown Block\n\nWrite your **markdown** here.\n\n\\`\\`\\`mermaid\ngraph LR\n A[Start] --> B[End]\n\\`\\`\\`\n`;\n\n const displayContent = localContent || defaultContent;\n\n return (\n <NodeViewWrapper contentEditable={false} className={`rte-markdown-block ${selected ? 'rte-markdown-block--selected' : ''}`}>\n <div className=\"rte-markdown-block__header\">\n <span className=\"rte-markdown-block__label\">Markdown</span>\n <button\n type=\"button\"\n className={`rte-markdown-block__toggle ${isEditing ? 'rte-markdown-block__toggle--active' : ''}`}\n disabled={!editable}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (isEditing) {\n updateAttributes({ content: localContent });\n }\n setIsEditing(!isEditing);\n }}\n title={isEditing ? 'Preview' : 'Edit'}\n >\n {isEditing ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n )}\n <span>{isEditing ? 'Preview' : 'Edit'}</span>\n </button>\n </div>\n\n <div className=\"rte-markdown-block__body\">\n {isEditing && editable ? (\n <textarea\n ref={textareaRef}\n className=\"rte-markdown-block__editor\"\n value={localContent}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder=\"Enter Markdown content...\"\n rows={5}\n />\n ) : (\n <div\n className=\"rte-markdown-block__preview prose\"\n onDoubleClick={() => { if (!editor.isDestroyed && editor.isEditable) setIsEditing(true); }}\n >\n {displayContent.trim() ? (\n <MarkdownPreview content={displayContent} />\n ) : (\n <p className=\"rte-markdown-block__placeholder\">\n Double-click to edit Markdown content...\n </p>\n )}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n};\n\nexport const MarkdownBlockExtension = Node.create({\n name: 'markdownBlock',\n group: 'block',\n atom: true,\n draggable: true,\n\n addAttributes() {\n return {\n content: {\n default: '',\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"markdown-block\"]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'markdown-block' })];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(MarkdownBlockView);\n },\n});\n\nexport default MarkdownBlockExtension;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MarkdownBlock.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/MarkdownBlock.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';\nimport { Node, mergeAttributes } from '@tiptap/react';\nimport { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';\nimport type { NodeViewProps } from '@tiptap/react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport rehypeKatex from 'rehype-katex';\n\nimport { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';\nimport { oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';\nimport mermaid from 'mermaid';\nimport { normalizeLegacyMermaid } from './legacyMermaid';\nimport 'katex/dist/katex.min.css';\n\nexport function useNodeEditable(editor: NodeViewProps['editor']) {\n const subscribe = useCallback((notify: () => void) => {\n // setEditable emits update, not transaction, in Tiptap 3.\n editor.on('update', notify);\n editor.on('transaction', notify);\n editor.on('destroy', notify);\n return () => {\n editor.off('update', notify);\n editor.off('transaction', notify);\n editor.off('destroy', notify);\n };\n }, [editor]);\n return useSyncExternalStore(subscribe, () => !editor.isDestroyed && editor.isEditable, () => false);\n}\n\nlet renderQueue: Promise<unknown> = Promise.resolve();\n\nfunction renderMermaid(id: string, code: string) {\n const result = renderQueue.then(() => {\n // Capture strict config when rendering starts, not before Mermaid's global queue runs.\n mermaid.initialize({\n startOnLoad: false,\n theme: 'default',\n securityLevel: 'strict',\n suppressErrorRendering: true,\n fontFamily: 'inherit',\n flowchart: { useMaxWidth: true, htmlLabels: false },\n });\n return mermaid.mermaidAPI.render(id, code);\n });\n renderQueue = result.catch(() => undefined);\n return result;\n}\n\nexport const MermaidRenderer: React.FC<{ code: string }> = ({ code }) => {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!containerRef.current) return;\n containerRef.current.replaceChildren();\n if (!code.trim()) return;\n\n let cancelled = false;\n const render = async () => {\n try {\n const id = `mermaid-md-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n const { svg } = await renderMermaid(id, normalizeLegacyMermaid(code));\n if (!cancelled && containerRef.current) {\n containerRef.current.innerHTML = svg;\n }\n } catch (err) {\n if (!cancelled && containerRef.current) {\n containerRef.current.textContent = String(err);\n }\n }\n };\n render();\n return () => { cancelled = true; };\n }, [code]);\n\n return <div ref={containerRef} className=\"rte-mermaid-container\" />;\n};\n\nconst MarkdownPreview: React.FC<{ content: string }> = ({ content }) => {\n return (\n <ReactMarkdown\n remarkPlugins={[remarkGfm, remarkMath]}\n rehypePlugins={[rehypeKatex]}\n components={{\n code({ className, children, ...props }) {\n const match = /language-(\\w+)/.exec(className || '');\n const lang = match?.[1];\n const text = String(children).replace(/\\n$/, '');\n\n if (lang === 'mermaid') {\n return <MermaidRenderer code={text} />;\n }\n\n if (lang) {\n return (\n <SyntaxHighlighter\n style={oneLight as Record<string, React.CSSProperties>}\n language={lang}\n PreTag=\"div\"\n customStyle={{\n borderRadius: '0.5rem',\n fontSize: '0.875em',\n padding: '1em',\n margin: '0.5em 0',\n }}\n >\n {text}\n </SyntaxHighlighter>\n );\n }\n return <code className={className} {...props}>{children}</code>;\n },\n }}\n >\n {content}\n </ReactMarkdown>\n );\n};\n\nconst MarkdownBlockView: React.FC<NodeViewProps> = ({\n node,\n editor,\n updateAttributes,\n selected,\n}) => {\n const editable = useNodeEditable(editor);\n const [isEditing, setIsEditing] = useState(false);\n const [localContent, setLocalContent] = useState(node.attrs.content || '');\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n setLocalContent(node.attrs.content || '');\n setIsEditing(false);\n }, [node.attrs.content, editable]);\n\n useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus();\n adjustTextareaHeight(textareaRef.current);\n }\n }, [isEditing]);\n\n const adjustTextareaHeight = (el: HTMLTextAreaElement) => {\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n };\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setLocalContent(e.target.value);\n adjustTextareaHeight(e.target);\n }, []);\n\n const handleBlur = useCallback(() => {\n if (!editor.isDestroyed && editor.isEditable) updateAttributes({ content: localContent });\n setIsEditing(false);\n }, [editor, localContent, updateAttributes]);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleBlur();\n }\n }, [handleBlur]);\n\n const defaultContent = `# Markdown Block\n\nWrite your **markdown** here.\n\n\\`\\`\\`mermaid\ngraph LR\n A[Start] --> B[End]\n\\`\\`\\`\n`;\n\n const displayContent = localContent || defaultContent;\n\n return (\n <NodeViewWrapper contentEditable={false} className={`rte-markdown-block ${selected ? 'rte-markdown-block--selected' : ''}`}>\n <div className=\"rte-markdown-block__header\">\n <span className=\"rte-markdown-block__label\">Markdown</span>\n <button\n type=\"button\"\n className={`rte-markdown-block__toggle ${isEditing ? 'rte-markdown-block__toggle--active' : ''}`}\n disabled={!editable}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n if (editor.isDestroyed || !editor.isEditable) return;\n if (isEditing) {\n updateAttributes({ content: localContent });\n }\n setIsEditing(!isEditing);\n }}\n title={isEditing ? 'Preview' : 'Edit'}\n >\n {isEditing ? (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ) : (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7\" />\n <path d=\"M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z\" />\n </svg>\n )}\n <span>{isEditing ? 'Preview' : 'Edit'}</span>\n </button>\n </div>\n\n <div className=\"rte-markdown-block__body\">\n {isEditing && editable ? (\n <textarea\n ref={textareaRef}\n className=\"rte-markdown-block__editor\"\n value={localContent}\n onChange={handleChange}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n placeholder=\"Enter Markdown content...\"\n rows={5}\n />\n ) : (\n <div\n className=\"rte-markdown-block__preview prose\"\n onDoubleClick={() => { if (!editor.isDestroyed && editor.isEditable) setIsEditing(true); }}\n >\n {displayContent.trim() ? (\n <MarkdownPreview content={displayContent} />\n ) : (\n <p className=\"rte-markdown-block__placeholder\">\n Double-click to edit Markdown content...\n </p>\n )}\n </div>\n )}\n </div>\n </NodeViewWrapper>\n );\n};\n\nexport const MarkdownBlockExtension = Node.create({\n name: 'markdownBlock',\n group: 'block',\n atom: true,\n draggable: true,\n\n addAttributes() {\n return {\n content: {\n default: '',\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'div[data-type=\"markdown-block\"]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return ['div', mergeAttributes(HTMLAttributes, { 'data-type': 'markdown-block' })];\n },\n\n addNodeView() {\n return ReactNodeViewRenderer(MarkdownBlockView);\n },\n});\n\nexport default MarkdownBlockExtension;\n"],"mappings":";;;;;;;;;;;;;AAeA,SAAgB,EAAgB,GAAiC;CAC/D,IAAM,IAAY,GAAa,OAE7B,EAAO,GAAG,UAAU,CAAM,GAC1B,EAAO,GAAG,eAAe,CAAM,GAC/B,EAAO,GAAG,WAAW,CAAM,SACd;EAGX,AAFA,EAAO,IAAI,UAAU,CAAM,GAC3B,EAAO,IAAI,eAAe,CAAM,GAChC,EAAO,IAAI,WAAW,CAAM;CAC9B,IACC,CAAC,CAAM,CAAC;CACX,OAAO,EAAqB,SAAiB,CAAC,EAAO,eAAe,EAAO,kBAAkB,EAAK;AACpG;AAEA,IAAI,IAAgC,QAAQ,QAAQ;AAEpD,SAAS,EAAc,GAAY,GAAc;CAC/C,IAAM,IAAS,EAAY,YAEzB,EAAQ,WAAW;EACjB,aAAa;EACb,OAAO;EACP,eAAe;EACf,wBAAwB;EACxB,YAAY;EACZ,WAAW;GAAE,aAAa;GAAM,YAAY;EAAM;CACpD,CAAC,GACM,EAAQ,WAAW,OAAO,GAAI,CAAI,EAC1C;CAED,OADA,IAAc,EAAO,YAAY,KAAA,CAAS,GACnC;AACT;AAEA,IAAa,KAA+C,EAAE,cAAW;CACvE,IAAM,IAAe,EAAuB,IAAI;CAyBhD,OAvBA,QAAgB;EAGd,IAFI,CAAC,EAAa,YAClB,EAAa,QAAQ,gBAAgB,GACjC,CAAC,EAAK,KAAK,IAAG;EAElB,IAAI,IAAY;EAehB,QADA,YAb2B;GACzB,IAAI;IAEF,IAAM,EAAE,WAAQ,MAAM,EAAc,cADX,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,KACpC,EAAuB,CAAI,CAAC;IACpE,AAAI,CAAC,KAAa,EAAa,YAC7B,EAAa,QAAQ,YAAY;GAErC,SAAS,GAAK;IACZ,AAAI,CAAC,KAAa,EAAa,YAC7B,EAAa,QAAQ,cAAc,OAAO,CAAG;GAEjD;EACF,EACA,CAAO,SACM;GAAE,IAAY;EAAM;CACnC,GAAG,CAAC,CAAI,CAAC,GAEF,kBAAC,OAAD;EAAK,KAAK;EAAc,WAAU;CAAyB,CAAA;AACpE,GAEM,KAAkD,EAAE,iBAEtD,kBAAC,GAAD;CACE,eAAe,CAAC,GAAW,CAAU;CACrC,eAAe,CAAC,CAAW;CAC3B,YAAY,EACV,KAAK,EAAE,cAAW,aAAU,GAAG,KAAS;EAEtC,IAAM,IADQ,iBAAiB,KAAK,KAAa,EACpC,CAAA,GAAQ,IACf,IAAO,OAAO,CAAQ,CAAC,CAAC,QAAQ,OAAO,EAAE;EAuB/C,OArBI,MAAS,YACJ,kBAAC,GAAD,EAAiB,MAAM,EAAO,CAAA,IAGnC,IAEA,kBAAC,GAAD;GACE,OAAO;GACP,UAAU;GACV,QAAO;GACP,aAAa;IACX,cAAc;IACd,UAAU;IACV,SAAS;IACT,QAAQ;GACV;GAEC,UAAA;EACgB,CAAA,IAGhB,kBAAC,QAAD;GAAiB;GAAW,GAAI;GAAQ;EAAe,CAAA;CAChE,EACF;CAEC,UAAA;AACY,CAAA,GAIb,KAA8C,EAClD,SACA,WACA,qBACA,kBACI;CACJ,IAAM,IAAW,EAAgB,CAAM,GACjC,CAAC,GAAW,KAAgB,EAAS,EAAK,GAC1C,CAAC,GAAc,KAAmB,EAAS,EAAK,MAAM,WAAW,EAAE,GACnE,IAAc,EAA4B,IAAI;CAOpD,AALA,QAAgB;EAEd,AADA,EAAgB,EAAK,MAAM,WAAW,EAAE,GACxC,EAAa,EAAK;CACpB,GAAG,CAAC,EAAK,MAAM,SAAS,CAAQ,CAAC,GAEjC,QAAgB;EACd,AAAI,KAAa,EAAY,YAC3B,EAAY,QAAQ,MAAM,GAC1B,EAAqB,EAAY,OAAO;CAE5C,GAAG,CAAC,CAAS,CAAC;CAEd,IAAM,KAAwB,MAA4B;EAExD,AADA,EAAG,MAAM,SAAS,QAClB,EAAG,MAAM,SAAS,EAAG,eAAe;CACtC,GAEM,IAAe,GAAa,MAA8C;EAE9E,AADA,EAAgB,EAAE,OAAO,KAAK,GAC9B,EAAqB,EAAE,MAAM;CAC/B,GAAG,CAAC,CAAC,GAEC,IAAa,QAAkB;EAEnC,AADI,CAAC,EAAO,eAAe,EAAO,cAAY,EAAiB,EAAE,SAAS,EAAa,CAAC,GACxF,EAAa,EAAK;CACpB,GAAG;EAAC;EAAQ;EAAc;CAAgB,CAAC,GAErC,IAAgB,GAAa,MAA2B;EAC5D,AAAI,EAAE,QAAQ,YACZ,EAAW;CAEf,GAAG,CAAC,CAAU,CAAC,GAYT,IAAiB,KAAgB;CAEvC,OACE,kBAAC,GAAD;EAAiB,iBAAiB;EAAO,WAAW,sBAAsB,IAAW,iCAAiC;EAAtH,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,QAAD;IAAM,WAAU;IAA4B,UAAA;GAAc,CAAA,GAC1D,kBAAC,UAAD;IACE,MAAK;IACL,WAAW,8BAA8B,IAAY,uCAAuC;IAC5F,UAAU,CAAC;IACX,cAAc,MAAM,EAAE,eAAe;IACrC,eAAe;KACT,GAAO,eAAgB,EAAO,eAC9B,KACF,EAAiB,EAAE,SAAS,EAAa,CAAC,GAE5C,EAAa,CAAC,CAAS;IACzB;IACA,OAAO,IAAY,YAAY;IAZjC,UAAA,CAcG,IACC,kBAAC,OAAD;KAAK,OAAM;KAAK,QAAO;KAAK,SAAQ;KAAY,MAAK;KAAO,QAAO;KAAe,aAAY;KAAI,eAAc;KAAQ,gBAAe;KAAvI,UAAA,CACE,kBAAC,QAAD,EAAM,GAAE,+CAAgD,CAAA,GACxD,kBAAC,UAAD;MAAQ,IAAG;MAAK,IAAG;MAAK,GAAE;KAAK,CAAA,CAC5B;IAEL,CAAA,IAAA,kBAAC,OAAD;KAAK,OAAM;KAAK,QAAO;KAAK,SAAQ;KAAY,MAAK;KAAO,QAAO;KAAe,aAAY;KAAI,eAAc;KAAQ,gBAAe;KAAvI,UAAA,CACE,kBAAC,QAAD,EAAM,GAAE,wDAAyD,CAAA,GACjE,kBAAC,QAAD,EAAM,GAAE,wDAAyD,CAAA,CAC9D;IAEP,CAAA,GAAA,kBAAC,QAAD,EAAA,UAAO,IAAY,YAAY,OAAa,CAAA,CACtC;GACL,CAAA,CAAA;EAEL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GACZ,UAAA,KAAa,IACZ,kBAAC,YAAD;IACE,KAAK;IACL,WAAU;IACV,OAAO;IACP,UAAU;IACV,QAAQ;IACR,WAAW;IACX,aAAY;IACZ,MAAM;GACP,CAAA,IAED,kBAAC,OAAD;IACE,WAAU;IACV,qBAAqB;KAAE,AAAI,CAAC,EAAO,eAAe,EAAO,cAAY,EAAa,EAAI;IAAG;IAExF,UAAA,EAAe,KAAK,IACnB,kBAAC,GAAD,EAAiB,SAAS,EAAiB,CAAA,IAE3C,kBAAC,KAAD;KAAG,WAAU;KAAkC,UAAA;IAE5C,CAAA;GAEF,CAAA;EAEJ,CAAA,CACU;;AAErB,GAEa,IAAyB,EAAK,OAAO;CAChD,MAAM;CACN,OAAO;CACP,MAAM;CACN,WAAW;CAEX,gBAAgB;EACd,OAAO,EACL,SAAS,EACP,SAAS,GACX,EACF;CACF;CAEA,YAAY;EACV,OAAO,CACL,EACE,KAAK,oCACP,CACF;CACF;CAEA,WAAW,EAAE,qBAAkB;EAC7B,OAAO,CAAC,OAAO,EAAgB,GAAgB,EAAE,aAAa,iBAAiB,CAAC,CAAC;CACnF;CAEA,cAAc;EACZ,OAAO,EAAsB,CAAiB;CAChD;AACF,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//#region src/components/pro/RichTextEditor/extensions/legacyMermaid.ts
|
|
2
|
+
function e(e) {
|
|
3
|
+
return Array.from(e, (e) => /[\p{L}\p{N} ,.!?_-]/u.test(e) ? e : `#${e.codePointAt(0)};`).join("");
|
|
4
|
+
}
|
|
5
|
+
function t(t) {
|
|
6
|
+
let n = t.split(/\r?\n/), r = n[0].trim();
|
|
7
|
+
if (r !== "flow" && r !== "seq") return t;
|
|
8
|
+
let i = (e, t) => {
|
|
9
|
+
throw Error(`Legacy ${r}, line ${e + 1}: ${t}`);
|
|
10
|
+
}, a = n.map((e, t) => ({
|
|
11
|
+
value: e.trim(),
|
|
12
|
+
line: t
|
|
13
|
+
})).slice(1).filter(({ value: e }) => e && !e.startsWith("#"));
|
|
14
|
+
if (a.length || i(0, "Empty diagram"), r === "seq") {
|
|
15
|
+
let t = /* @__PURE__ */ new Map(), n = (e, n) => (e = e.trim(), (!e || /[\r\n:<>]/.test(e)) && i(n, "Invalid participant name"), t.has(e) || t.set(e, `p${t.size}`), t.get(e)), r = [], o = {
|
|
16
|
+
"->": "->>",
|
|
17
|
+
"-->": "-->>",
|
|
18
|
+
"->>": "->",
|
|
19
|
+
"-->>": "-->"
|
|
20
|
+
};
|
|
21
|
+
for (let { value: t, line: s } of a) {
|
|
22
|
+
let a = /^Note\s+(right of|left of|over)\s+([^:]+):\s*(.*)$/i.exec(t);
|
|
23
|
+
if (a) {
|
|
24
|
+
let t = a[1].toLowerCase(), o = a[2].split(",");
|
|
25
|
+
o.length > (t === "over" ? 2 : 1) && i(s, "Unsupported note participants"), r.push(`Note ${t} ${o.map((e) => n(e, s)).join(",")}: ${e(a[3])}`);
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
let c = /^([^:<>]+?)(-->>|->>|-->|->)([^:<>]+):\s*(.*)$/.exec(t);
|
|
29
|
+
(!c || /[-]$/.test(c[1].trim())) && i(s, "Unsupported sequence statement or arrow"), r.push(`${n(c[1], s)}${o[c[2]]}${n(c[3], s)}: ${e(c[4])}`);
|
|
30
|
+
}
|
|
31
|
+
return [
|
|
32
|
+
"sequenceDiagram",
|
|
33
|
+
...Array.from(t, ([t, n]) => `participant ${n} as ${e(t)}`),
|
|
34
|
+
...r
|
|
35
|
+
].join("\n");
|
|
36
|
+
}
|
|
37
|
+
let o = /* @__PURE__ */ new Map(), s = [], c = [], l = {
|
|
38
|
+
start: ["([", "])"],
|
|
39
|
+
end: ["([", "])"],
|
|
40
|
+
operation: ["[", "]"],
|
|
41
|
+
condition: ["{", "}"],
|
|
42
|
+
inputoutput: ["[/", "/]"],
|
|
43
|
+
subroutine: ["[[", "]]"]
|
|
44
|
+
};
|
|
45
|
+
for (let { value: t, line: n } of a) {
|
|
46
|
+
if (!t.includes("=>")) continue;
|
|
47
|
+
let r = /^([A-Za-z_][\w]*)=>([a-z]+)(?::\s*(.*))?$/.exec(t);
|
|
48
|
+
(!r || !Object.hasOwn(l, r[2])) && i(n, "Unsupported node declaration/type");
|
|
49
|
+
let [, a, c, u] = r;
|
|
50
|
+
o.has(a) && i(n, `Duplicate node: ${a}`), u && /\||:>/.test(u) && i(n, "Node styles and links are unsupported");
|
|
51
|
+
let d = `n${o.size}`;
|
|
52
|
+
o.set(a, {
|
|
53
|
+
id: d,
|
|
54
|
+
type: c
|
|
55
|
+
});
|
|
56
|
+
let [f, p] = l[c];
|
|
57
|
+
s.push(`${d}${f}"${e(u ?? c)}"${p}`);
|
|
58
|
+
}
|
|
59
|
+
let u, d = {
|
|
60
|
+
right: "LR",
|
|
61
|
+
left: "RL",
|
|
62
|
+
top: "BT",
|
|
63
|
+
bottom: "TD"
|
|
64
|
+
};
|
|
65
|
+
for (let { value: e, line: t } of a) {
|
|
66
|
+
if (e.includes("=>")) continue;
|
|
67
|
+
let n = e.split("->");
|
|
68
|
+
n.length < 2 && i(t, "Unsupported flow statement");
|
|
69
|
+
let r = n.map((e) => {
|
|
70
|
+
let n = /^\s*([A-Za-z_][\w]*)(?:\(([^()]+)\))?\s*$/.exec(e);
|
|
71
|
+
return (!n || !o.has(n[1])) && i(t, "Invalid or undefined node reference"), {
|
|
72
|
+
node: o.get(n[1]),
|
|
73
|
+
options: n[2]?.split(",").map((e) => e.trim()) ?? []
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
for (let e = 0; e < r.length; e++) {
|
|
77
|
+
let { node: n, options: a } = r[e];
|
|
78
|
+
if (e === r.length - 1) {
|
|
79
|
+
a.length && i(t, "Options on a terminal reference are unsupported");
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
let o, s;
|
|
83
|
+
for (let e of a) (e === "yes" || e === "no") && n.type === "condition" && !o ? o = e : Object.hasOwn(d, e) && !s ? s = d[e] : i(t, `Unsupported branch/direction: ${e}`);
|
|
84
|
+
s && (u && u !== s && i(t, "Mixed edge directions cannot be represented reliably"), u = s), c.push(`${n.id} -->${o ? `|${o}|` : ""} ${r[e + 1].node.id}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return o.size || i(0, "No node declarations"), [
|
|
88
|
+
`flowchart ${u ?? "TD"}`,
|
|
89
|
+
...s,
|
|
90
|
+
...c
|
|
91
|
+
].join("\n");
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { t as normalizeLegacyMermaid };
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=legacyMermaid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacyMermaid.js","names":[],"sources":["../../../../../src/components/pro/RichTextEditor/extensions/legacyMermaid.ts"],"sourcesContent":["// Encode user text before embedding it in Mermaid syntax (including entity-like input).\nfunction text(value: string): string {\n return Array.from(value, char => /[\\p{L}\\p{N} ,.!?_-]/u.test(char)\n ? char : `#${char.codePointAt(0)};`).join('');\n}\n\n/** Convert only explicit legacy headers. Unsupported syntax fails rather than changing meaning. */\nexport function normalizeLegacyMermaid(source: string): string {\n const lines = source.split(/\\r?\\n/);\n const kind = lines[0].trim();\n if (kind !== 'flow' && kind !== 'seq') return source;\n const fail = (line: number, reason: string): never => {\n throw new Error(`Legacy ${kind}, line ${line + 1}: ${reason}`);\n };\n const body = lines.map((value, line) => ({ value: value.trim(), line }))\n .slice(1).filter(({ value }) => value && !value.startsWith('#'));\n if (!body.length) fail(0, 'Empty diagram');\n\n if (kind === 'seq') {\n const actors = new Map<string, string>();\n const actor = (name: string, line: number) => {\n name = name.trim();\n if (!name || /[\\r\\n:<>]/.test(name)) fail(line, 'Invalid participant name');\n if (!actors.has(name)) actors.set(name, `p${actors.size}`);\n return actors.get(name)!;\n };\n const output: string[] = [];\n const arrows: Record<string, string> = { '->': '->>', '-->': '-->>', '->>': '->', '-->>': '-->' };\n for (const { value, line } of body) {\n const note = /^Note\\s+(right of|left of|over)\\s+([^:]+):\\s*(.*)$/i.exec(value);\n if (note) {\n const placement = note[1].toLowerCase();\n const names = note[2].split(',');\n if (names.length > (placement === 'over' ? 2 : 1)) fail(line, 'Unsupported note participants');\n output.push(`Note ${placement} ${names.map(name => actor(name, line)).join(',')}: ${text(note[3])}`);\n continue;\n }\n const message = /^([^:<>]+?)(-->>|->>|-->|->)([^:<>]+):\\s*(.*)$/.exec(value);\n if (!message || /[-]$/.test(message[1].trim())) fail(line, 'Unsupported sequence statement or arrow');\n output.push(`${actor(message![1], line)}${arrows[message![2]]}${actor(message![3], line)}: ${text(message![4])}`);\n }\n return ['sequenceDiagram', ...Array.from(actors, ([name, id]) => `participant ${id} as ${text(name)}`), ...output].join('\\n');\n }\n\n const nodes = new Map<string, { id: string; type: string }>();\n const declarations: string[] = [];\n const edges: string[] = [];\n const shapes: Record<string, [string, string]> = {\n start: ['([', '])'], end: ['([', '])'], operation: ['[', ']'],\n condition: ['{', '}'], inputoutput: ['[/', '/]'], subroutine: ['[[', ']]'],\n };\n for (const { value, line } of body) {\n if (!value.includes('=>')) continue;\n const match = /^([A-Za-z_][\\w]*)=>([a-z]+)(?::\\s*(.*))?$/.exec(value);\n if (!match || !Object.hasOwn(shapes, match[2])) fail(line, 'Unsupported node declaration/type');\n const [, name, type, label] = match!;\n if (nodes.has(name)) fail(line, `Duplicate node: ${name}`);\n // flowchart.js uses these as state/link metadata, not literal label text.\n if (label && /\\||:>/.test(label)) fail(line, 'Node styles and links are unsupported');\n const id = `n${nodes.size}`;\n nodes.set(name, { id, type });\n const [open, close] = shapes[type];\n declarations.push(`${id}${open}\"${text(label ?? type)}\"${close}`);\n }\n let direction: string | undefined;\n const directions: Record<string, string> = { right: 'LR', left: 'RL', top: 'BT', bottom: 'TD' };\n for (const { value, line } of body) {\n if (value.includes('=>')) continue;\n const parts = value.split('->');\n if (parts.length < 2) fail(line, 'Unsupported flow statement');\n const refs = parts.map(part => {\n const match = /^\\s*([A-Za-z_][\\w]*)(?:\\(([^()]+)\\))?\\s*$/.exec(part);\n if (!match || !nodes.has(match[1])) fail(line, 'Invalid or undefined node reference');\n return { node: nodes.get(match![1])!, options: match![2]?.split(',').map(option => option.trim()) ?? [] };\n });\n for (let i = 0; i < refs.length; i++) {\n const { node, options } = refs[i];\n if (i === refs.length - 1) {\n if (options.length) fail(line, 'Options on a terminal reference are unsupported');\n break;\n }\n let branch: string | undefined;\n let hint: string | undefined;\n for (const option of options) {\n if ((option === 'yes' || option === 'no') && node.type === 'condition' && !branch) branch = option;\n else if (Object.hasOwn(directions, option) && !hint) hint = directions[option];\n else fail(line, `Unsupported branch/direction: ${option}`);\n }\n if (hint) {\n if (direction && direction !== hint) fail(line, 'Mixed edge directions cannot be represented reliably');\n direction = hint;\n }\n edges.push(`${node.id} -->${branch ? `|${branch}|` : ''} ${refs[i + 1].node.id}`);\n }\n }\n if (!nodes.size) fail(0, 'No node declarations');\n return [`flowchart ${direction ?? 'TD'}`, ...declarations, ...edges].join('\\n');\n}\n"],"mappings":"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"}
|