tiptap-markdown-react 0.2.2 → 0.3.1
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/README.md +12 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +10 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +153 -2
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +1 -0
- package/dist/markdownFileDrop.d.ts +8 -0
- package/dist/markdownPaste.d.ts +23 -0
- package/dist/toc/scrollToTocHeading.d.ts +22 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -141,12 +141,24 @@ Override any of these CSS variables on an ancestor (e.g. `:root` or the editor c
|
|
|
141
141
|
| `placeholder` | `string` | Placeholder for the empty document. |
|
|
142
142
|
| `onEditorReady` | `(editor: Editor \| null) => void` | Get the Tiptap instance (for the toolbar). |
|
|
143
143
|
| `onTocChange` | `(items: TocItem[]) => void` | Fires when headings change. |
|
|
144
|
+
| `markdownPaste` | `boolean` | Auto-detect markdown in plain-text paste and convert it (Shift+paste keeps plain text). Default `true`. Init-only. |
|
|
145
|
+
| `markdownFileDrop` | `boolean` | Drop or paste `.md` / `.markdown` files into the editor to insert their parsed content. Default `true`. Init-only. |
|
|
144
146
|
| `extraExtensions` | `AnyExtension[]` | Extra Tiptap extensions to register. |
|
|
145
147
|
| `codeBlockLabels` | `Partial<CodeBlockLabels>` | Localize the code block UI. |
|
|
146
148
|
| `className` | `string` | Class on the scroll container. |
|
|
147
149
|
|
|
148
150
|
Ref handle (`MarkdownWysiwygEditorHandle`): `getMarkdown()`, `getHTML()`, `getJSON()`, `getEditor()`.
|
|
149
151
|
|
|
152
|
+
#### Markdown in: paste, drop, import
|
|
153
|
+
|
|
154
|
+
Three ways to get markdown into the editor, all built in:
|
|
155
|
+
|
|
156
|
+
- **Paste markdown text** — plain-text paste is heuristically detected (headings, lists, links, fences, tables…) and parsed into rich content. Rich-text (HTML) paste is untouched; Shift+paste always inserts plain text; pasting inside a code block is never converted. Opt out with `markdownPaste={false}`.
|
|
157
|
+
- **Drop / paste `.md` files** — drag a `.md` / `.markdown` file into the editor (inserted at drop point) or paste a copied file (inserted at cursor). Opt out with `markdownFileDrop={false}`.
|
|
158
|
+
- **Toolbar import** — "Import Markdown" in the toolbar's More menu opens a file picker and inserts the parsed file at the cursor (label: `labels.importMarkdown`).
|
|
159
|
+
|
|
160
|
+
The underlying extensions `MarkdownPaste` / `MarkdownFileDrop` (and the `looksLikeMarkdown` heuristic) are exported for custom pipelines.
|
|
161
|
+
|
|
150
162
|
### `<EditorToolbar>` (client)
|
|
151
163
|
|
|
152
164
|
| Prop | Type | Description |
|
|
@@ -19,6 +19,16 @@ export interface MarkdownWysiwygEditorProps {
|
|
|
19
19
|
onEditorReady?: (editor: Editor | null) => void;
|
|
20
20
|
/** 目录变化回调(正文标题增删改时),供侧边目录实时展示。 */
|
|
21
21
|
onTocChange?: (items: TocItem[]) => void;
|
|
22
|
+
/**
|
|
23
|
+
* 粘贴纯文本时启发式检测 markdown 并自动转富文本(Shift+粘贴保持纯文本)。
|
|
24
|
+
* 默认 true。仅初始化时生效。
|
|
25
|
+
*/
|
|
26
|
+
markdownPaste?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 支持把 .md / .markdown 文件拖拽或粘贴进编辑器,解析后插入到落点/光标处。
|
|
29
|
+
* 默认 true。仅初始化时生效。
|
|
30
|
+
*/
|
|
31
|
+
markdownFileDrop?: boolean;
|
|
22
32
|
/** 追加的 Tiptap 扩展(在内置扩展之后注册)。 */
|
|
23
33
|
extraExtensions?: AnyExtension[];
|
|
24
34
|
/** 代码块 NodeView 的本地化文案。 */
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,11 @@ export { TocPanel, type TocPanelProps } from './components/TocPanel';
|
|
|
6
6
|
export { CodeBlockView } from './components/CodeBlockView';
|
|
7
7
|
export { ReportContent, type ReportContentProps } from './ReportContent';
|
|
8
8
|
export { baseExtensions, lowlight, pureCodeBlock, pureImage, } from './extensions';
|
|
9
|
+
export { MarkdownPaste, looksLikeMarkdown } from './markdownPaste';
|
|
10
|
+
export { MarkdownFileDrop } from './markdownFileDrop';
|
|
9
11
|
export { extractToc, type TocItem } from './toc/extractToc';
|
|
10
12
|
export { makeTocGetId } from './toc/tocSlug';
|
|
13
|
+
export { scrollToTocHeading } from './toc/scrollToTocHeading';
|
|
11
14
|
export { defaultCodeBlockLabels, defaultColorPaletteLabels, defaultTocLabels, defaultToolbarLabels, type CodeBlockLabels, type ColorPaletteLabels, type TocLabels, type ToolbarLabels, } from './labels';
|
|
12
15
|
export { useIsMobile } from './hooks/useIsMobile';
|
|
13
16
|
export * from './icons';
|
package/dist/index.js
CHANGED
|
@@ -8,9 +8,95 @@ import { NodeViewWrapper, NodeViewContent, useEditor, EditorContent, ReactNodeVi
|
|
|
8
8
|
import { forwardRef, useEffect, useImperativeHandle, useState, useRef, useCallback, useContext, createContext } from "react";
|
|
9
9
|
import { s as styles$4, b as baseExtensions, l as lowlight, m as makeTocGetId, p as pureCodeBlock, a as pureImage } from "./extractToc-C7e1DuVc.js";
|
|
10
10
|
import { R, e } from "./extractToc-C7e1DuVc.js";
|
|
11
|
+
import { Extension } from "@tiptap/core";
|
|
12
|
+
import { FileHandlePlugin } from "@tiptap/extension-file-handler";
|
|
13
|
+
import { PluginKey, Plugin } from "@tiptap/pm/state";
|
|
11
14
|
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
|
|
12
15
|
import * as Popover from "@radix-ui/react-popover";
|
|
13
16
|
import { createPortal } from "react-dom";
|
|
17
|
+
const MD_FILE_RE = /\.(md|markdown)$/i;
|
|
18
|
+
const MD_MIME_TYPES = ["text/markdown", "text/x-markdown", ""];
|
|
19
|
+
async function insertMarkdownFiles(editor, files, pos) {
|
|
20
|
+
const mdFiles = files.filter((f) => MD_FILE_RE.test(f.name));
|
|
21
|
+
if (mdFiles.length === 0) return;
|
|
22
|
+
const markdown = editor.markdown;
|
|
23
|
+
if (!markdown) return;
|
|
24
|
+
const texts = await Promise.all(mdFiles.map((f) => f.text()));
|
|
25
|
+
const json = markdown.parse(texts.join("\n\n"));
|
|
26
|
+
if (pos != null) {
|
|
27
|
+
editor.chain().focus().insertContentAt(pos, json).run();
|
|
28
|
+
} else {
|
|
29
|
+
editor.chain().focus().insertContent(json).run();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const MarkdownFileDrop = Extension.create({
|
|
33
|
+
name: "markdownFileDrop",
|
|
34
|
+
addProseMirrorPlugins() {
|
|
35
|
+
const { editor } = this;
|
|
36
|
+
return [
|
|
37
|
+
FileHandlePlugin({
|
|
38
|
+
key: new PluginKey("markdownFileDrop"),
|
|
39
|
+
editor,
|
|
40
|
+
allowedMimeTypes: MD_MIME_TYPES,
|
|
41
|
+
onDrop: (ed, files, pos) => {
|
|
42
|
+
insertMarkdownFiles(ed, files, pos).catch((err) => {
|
|
43
|
+
console.error("markdown file drop failed:", err);
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
onPaste: (ed, files) => {
|
|
47
|
+
insertMarkdownFiles(ed, files).catch((err) => {
|
|
48
|
+
console.error("markdown file paste failed:", err);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
function looksLikeMarkdown(text) {
|
|
56
|
+
return /^#{1,6}\s/m.test(text) || // 标题
|
|
57
|
+
/\*\*[^*\n]+\*\*/.test(text) || // 加粗
|
|
58
|
+
/(^|[^!])\[[^\]\n]+\]\([^)\n]+\)/.test(text) || // 链接
|
|
59
|
+
/!\[[^\]\n]*\]\([^)\n]+\)/.test(text) || // 图片
|
|
60
|
+
/^[-*+]\s+\S/m.test(text) || // 无序列表
|
|
61
|
+
/^\d+\.\s+\S/m.test(text) || // 有序列表
|
|
62
|
+
/^>\s/m.test(text) || // 引用
|
|
63
|
+
/^```/m.test(text) || // 代码围栏
|
|
64
|
+
/^\|.+\|\s*$/m.test(text) || // 表格行
|
|
65
|
+
/^(-{3,}|\*{3,})\s*$/m.test(text);
|
|
66
|
+
}
|
|
67
|
+
const MarkdownPaste = Extension.create({
|
|
68
|
+
name: "markdownPaste",
|
|
69
|
+
addProseMirrorPlugins() {
|
|
70
|
+
const { editor } = this;
|
|
71
|
+
return [
|
|
72
|
+
new Plugin({
|
|
73
|
+
key: new PluginKey("markdownPaste"),
|
|
74
|
+
props: {
|
|
75
|
+
handlePaste(view, event) {
|
|
76
|
+
const clipboard = event.clipboardData;
|
|
77
|
+
if (!clipboard) return false;
|
|
78
|
+
const text = clipboard.getData("text/plain");
|
|
79
|
+
if (!text) return false;
|
|
80
|
+
const input = view.input;
|
|
81
|
+
if (input == null ? void 0 : input.shiftKey) return false;
|
|
82
|
+
if (view.state.selection.$from.parent.type.spec.code) return false;
|
|
83
|
+
if (!looksLikeMarkdown(text)) return false;
|
|
84
|
+
const markdown = editor.markdown;
|
|
85
|
+
if (!markdown) return false;
|
|
86
|
+
try {
|
|
87
|
+
const json = markdown.parse(text);
|
|
88
|
+
editor.commands.insertContent(json);
|
|
89
|
+
return true;
|
|
90
|
+
} catch (err) {
|
|
91
|
+
console.error("markdown paste parse failed:", err);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
});
|
|
14
100
|
function Svg({ size = "1em", children, ...rest }) {
|
|
15
101
|
return /* @__PURE__ */ jsx(
|
|
16
102
|
"svg",
|
|
@@ -179,6 +265,7 @@ const defaultToolbarLabels = {
|
|
|
179
265
|
more: "More",
|
|
180
266
|
codeBlock: "Code block",
|
|
181
267
|
hr: "Divider",
|
|
268
|
+
importMarkdown: "Import Markdown",
|
|
182
269
|
tableInsert: "Insert table",
|
|
183
270
|
tableAddColumnBefore: "Add column before",
|
|
184
271
|
tableAddColumnAfter: "Add column after",
|
|
@@ -370,6 +457,8 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
370
457
|
placeholder,
|
|
371
458
|
onEditorReady,
|
|
372
459
|
onTocChange,
|
|
460
|
+
markdownPaste = true,
|
|
461
|
+
markdownFileDrop = true,
|
|
373
462
|
extraExtensions,
|
|
374
463
|
codeBlockLabels,
|
|
375
464
|
className
|
|
@@ -388,6 +477,8 @@ const MarkdownWysiwygEditor = forwardRef(function MarkdownWysiwygEditor2({
|
|
|
388
477
|
);
|
|
389
478
|
}
|
|
390
479
|
}),
|
|
480
|
+
...markdownPaste ? [MarkdownPaste] : [],
|
|
481
|
+
...markdownFileDrop ? [MarkdownFileDrop] : [],
|
|
391
482
|
...extraExtensions ?? []
|
|
392
483
|
],
|
|
393
484
|
content: initialMarkdown,
|
|
@@ -457,6 +548,9 @@ function MarkdownPreview({ markdown, className }) {
|
|
|
457
548
|
}
|
|
458
549
|
);
|
|
459
550
|
}
|
|
551
|
+
function insertMarkdown(editor, markdown) {
|
|
552
|
+
editor.chain().focus().insertContent(markdown, { contentType: "markdown" }).run();
|
|
553
|
+
}
|
|
460
554
|
const toolbar = "_toolbar_i2emf_2";
|
|
461
555
|
const inner = "_inner_i2emf_15";
|
|
462
556
|
const btn = "_btn_i2emf_27";
|
|
@@ -812,6 +906,20 @@ function EditorToolbar({
|
|
|
812
906
|
onError == null ? void 0 : onError(err);
|
|
813
907
|
}
|
|
814
908
|
};
|
|
909
|
+
const mdFileInputRef = useRef(null);
|
|
910
|
+
const handleMdFileChange = async (e2) => {
|
|
911
|
+
var _a;
|
|
912
|
+
const file = (_a = e2.target.files) == null ? void 0 : _a[0];
|
|
913
|
+
e2.target.value = "";
|
|
914
|
+
if (!file) return;
|
|
915
|
+
try {
|
|
916
|
+
const text = await file.text();
|
|
917
|
+
insertMarkdown(editor, text);
|
|
918
|
+
} catch (err) {
|
|
919
|
+
console.error("markdown import failed:", err);
|
|
920
|
+
onError == null ? void 0 : onError(err);
|
|
921
|
+
}
|
|
922
|
+
};
|
|
815
923
|
const applyTextColor = (color) => {
|
|
816
924
|
if (color) chain().setColor(color).run();
|
|
817
925
|
else chain().unsetColor().run();
|
|
@@ -1169,6 +1277,13 @@ function EditorToolbar({
|
|
|
1169
1277
|
] })
|
|
1170
1278
|
}
|
|
1171
1279
|
),
|
|
1280
|
+
/* @__PURE__ */ jsx(MenuItem, { onSelect: () => {
|
|
1281
|
+
var _a;
|
|
1282
|
+
return (_a = mdFileInputRef.current) == null ? void 0 : _a.click();
|
|
1283
|
+
}, children: /* @__PURE__ */ jsxs("span", { className: styles$2.styleItem, children: [
|
|
1284
|
+
/* @__PURE__ */ jsx("span", { className: styles$2.styleIcon, children: "M↓" }),
|
|
1285
|
+
t.importMarkdown
|
|
1286
|
+
] }) }),
|
|
1172
1287
|
extraToolbarItems == null ? void 0 : extraToolbarItems.map((item2) => /* @__PURE__ */ jsx(
|
|
1173
1288
|
MenuItem,
|
|
1174
1289
|
{
|
|
@@ -1187,6 +1302,16 @@ function EditorToolbar({
|
|
|
1187
1302
|
] })
|
|
1188
1303
|
}
|
|
1189
1304
|
),
|
|
1305
|
+
/* @__PURE__ */ jsx(
|
|
1306
|
+
"input",
|
|
1307
|
+
{
|
|
1308
|
+
ref: mdFileInputRef,
|
|
1309
|
+
type: "file",
|
|
1310
|
+
accept: ".md,.markdown,text/markdown",
|
|
1311
|
+
hidden: true,
|
|
1312
|
+
onChange: handleMdFileChange
|
|
1313
|
+
}
|
|
1314
|
+
),
|
|
1190
1315
|
tableMenu && createPortal(
|
|
1191
1316
|
/* @__PURE__ */ jsxs(
|
|
1192
1317
|
"div",
|
|
@@ -1413,8 +1538,30 @@ function TocPanel({ items, activeId, onItemClick, labels }) {
|
|
|
1413
1538
|
list2
|
|
1414
1539
|
] });
|
|
1415
1540
|
}
|
|
1416
|
-
function
|
|
1417
|
-
|
|
1541
|
+
function easeOutCubic(t) {
|
|
1542
|
+
return 1 - (1 - t) * (1 - t) * (1 - t);
|
|
1543
|
+
}
|
|
1544
|
+
function scrollToTocHeading(headingId, scrollContainer, options) {
|
|
1545
|
+
const el = scrollContainer.querySelector(
|
|
1546
|
+
`[data-toc-id="${CSS.escape(headingId)}"]`
|
|
1547
|
+
);
|
|
1548
|
+
if (!el) return;
|
|
1549
|
+
const startTop = scrollContainer.scrollTop;
|
|
1550
|
+
const rootRect = scrollContainer.getBoundingClientRect();
|
|
1551
|
+
const elRect = el.getBoundingClientRect();
|
|
1552
|
+
const targetTop = startTop + (elRect.top - rootRect.top);
|
|
1553
|
+
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
1554
|
+
scrollContainer.scrollTop = targetTop;
|
|
1555
|
+
return;
|
|
1556
|
+
}
|
|
1557
|
+
const duration = (options == null ? void 0 : options.duration) ?? 400;
|
|
1558
|
+
const start = performance.now();
|
|
1559
|
+
const animate = () => {
|
|
1560
|
+
const t = Math.min((performance.now() - start) / duration, 1);
|
|
1561
|
+
scrollContainer.scrollTop = startTop + (targetTop - startTop) * easeOutCubic(t);
|
|
1562
|
+
if (t < 1) requestAnimationFrame(animate);
|
|
1563
|
+
};
|
|
1564
|
+
requestAnimationFrame(animate);
|
|
1418
1565
|
}
|
|
1419
1566
|
export {
|
|
1420
1567
|
BoldIcon,
|
|
@@ -1434,6 +1581,8 @@ export {
|
|
|
1434
1581
|
ListOrderedIcon,
|
|
1435
1582
|
ListUnorderedIcon,
|
|
1436
1583
|
LockIcon,
|
|
1584
|
+
MarkdownFileDrop,
|
|
1585
|
+
MarkdownPaste,
|
|
1437
1586
|
MarkdownPreview,
|
|
1438
1587
|
MarkdownWysiwygEditor,
|
|
1439
1588
|
MenuIcon,
|
|
@@ -1454,10 +1603,12 @@ export {
|
|
|
1454
1603
|
defaultToolbarLabels,
|
|
1455
1604
|
e as extractToc,
|
|
1456
1605
|
insertMarkdown,
|
|
1606
|
+
looksLikeMarkdown,
|
|
1457
1607
|
lowlight,
|
|
1458
1608
|
makeTocGetId,
|
|
1459
1609
|
pureCodeBlock,
|
|
1460
1610
|
pureImage,
|
|
1611
|
+
scrollToTocHeading,
|
|
1461
1612
|
useIsMobile
|
|
1462
1613
|
};
|
|
1463
1614
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/icons/index.tsx","../src/labels.ts","../src/components/CodeBlockView.tsx","../src/components/MarkdownWysiwygEditor.tsx","../src/components/MarkdownPreview.tsx","../src/components/ColorPalette.tsx","../src/components/EditorToolbar.tsx","../src/hooks/useIsMobile.ts","../src/components/TocPanel.tsx","../src/insertMarkdown.ts"],"sourcesContent":["import type { SVGProps } from 'react';\n\n/**\n * 内联 SVG 图标集(0 运行时依赖)。stroke 走 currentColor,尺寸默认 1em 跟随字号,\n * 故颜色/大小随文本与主题自动变化。图形取自 Lucide(MIT)风格。\n */\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n}\n\nfunction Svg({ size = '1em', children, ...rest }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport const BoldIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n </Svg>\n);\n\nexport const ItalicIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"19\" x2=\"10\" y1=\"4\" y2=\"4\" />\n <line x1=\"14\" x2=\"5\" y1=\"20\" y2=\"20\" />\n <line x1=\"15\" x2=\"9\" y1=\"4\" y2=\"20\" />\n </Svg>\n);\n\nexport const UnderlineIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 4v6a6 6 0 0 0 12 0V4\" />\n <line x1=\"4\" x2=\"20\" y1=\"20\" y2=\"20\" />\n </Svg>\n);\n\nexport const StrikethroughIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M16 4H9a3 3 0 0 0-2.83 4\" />\n <path d=\"M14 12a4 4 0 0 1 0 8H6\" />\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n </Svg>\n);\n\nexport const CodeIcon = (p: IconProps) => (\n <Svg {...p}>\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </Svg>\n);\n\nexport const LinkIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </Svg>\n);\n\nexport const ImageIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </Svg>\n);\n\nexport const ListUnorderedIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"8\" x2=\"21\" y1=\"6\" y2=\"6\" />\n <line x1=\"8\" x2=\"21\" y1=\"12\" y2=\"12\" />\n <line x1=\"8\" x2=\"21\" y1=\"18\" y2=\"18\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"12\" y2=\"12\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"18\" y2=\"18\" />\n </Svg>\n);\n\nexport const ListOrderedIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"10\" x2=\"21\" y1=\"6\" y2=\"6\" />\n <line x1=\"10\" x2=\"21\" y1=\"12\" y2=\"12\" />\n <line x1=\"10\" x2=\"21\" y1=\"18\" y2=\"18\" />\n <path d=\"M4 6h1v4\" />\n <path d=\"M4 10h2\" />\n <path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1\" />\n </Svg>\n);\n\nexport const ListChecksIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m3 17 2 2 4-4\" />\n <path d=\"m3 7 2 2 4-4\" />\n <path d=\"M13 6h8\" />\n <path d=\"M13 12h8\" />\n <path d=\"M13 18h8\" />\n </Svg>\n);\n\nexport const UndoIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M9 14 4 9l5-5\" />\n <path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1-5.5 5.5H11\" />\n </Svg>\n);\n\nexport const RedoIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m15 14 5-5-5-5\" />\n <path d=\"M20 9H9.5A5.5 5.5 0 0 0 4 14.5 5.5 5.5 0 0 0 9.5 20H13\" />\n </Svg>\n);\n\nexport const ChevronDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m6 9 6 6 6-6\" />\n </Svg>\n);\n\nexport const CheckIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Svg>\n);\n\nexport const TrashIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n <line x1=\"10\" x2=\"10\" y1=\"11\" y2=\"17\" />\n <line x1=\"14\" x2=\"14\" y1=\"11\" y2=\"17\" />\n </Svg>\n);\n\nexport const LockIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </Svg>\n);\n\nexport const MenuIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\n </Svg>\n);\n\n/* ── 表格行列操作图标(自绘:表格轮廓 + 目标边高亮 + 加号/叉号)── */\n\nexport const ColumnBeforeIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"10\" y=\"4\" width=\"11\" height=\"16\" rx=\"1\" />\n <path d=\"M14 4v16\" />\n <path d=\"M5 9v6\" />\n <path d=\"M2 12h6\" />\n </Svg>\n);\n\nexport const ColumnAfterIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"4\" width=\"11\" height=\"16\" rx=\"1\" />\n <path d=\"M10 4v16\" />\n <path d=\"M19 9v6\" />\n <path d=\"M16 12h6\" />\n </Svg>\n);\n\nexport const ColumnDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"1\" />\n <path d=\"M12 4v16\" />\n <path d=\"m8 9 8 6\" />\n <path d=\"m16 9-8 6\" />\n </Svg>\n);\n\nexport const RowBeforeIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"10\" width=\"16\" height=\"11\" rx=\"1\" />\n <path d=\"M4 14h16\" />\n <path d=\"M9 5h6\" />\n <path d=\"M12 2v6\" />\n </Svg>\n);\n\nexport const RowAfterIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"3\" width=\"16\" height=\"11\" rx=\"1\" />\n <path d=\"M4 10h16\" />\n <path d=\"M9 19h6\" />\n <path d=\"M12 16v6\" />\n </Svg>\n);\n\nexport const RowDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"1\" />\n <path d=\"M4 12h16\" />\n <path d=\"m9 8 6 8\" />\n <path d=\"m15 8-6 8\" />\n </Svg>\n);\n","/**\n * UI 文案(i18n 注入点)。各组件接收 `labels?: Partial<...>`,与内置英文默认合并。\n * 消费方(如中文项目)可传入本地化文案。\n */\n\nexport interface ToolbarLabels {\n undo: string;\n redo: string;\n style: string;\n normalText: string;\n /** 传入层级,返回如 \"Heading 2\"。 */\n headingLabel: (level: number) => string;\n fontSize: string;\n fontSizeDefault: string;\n bold: string;\n italic: string;\n underline: string;\n strike: string;\n code: string;\n textColor: string;\n highlight: string;\n colorNone: string;\n colorTheme: string;\n scriptMenu: string;\n scriptNormal: string;\n superscript: string;\n subscript: string;\n link: string;\n linkPrompt: string;\n image: string;\n imageUploadFailed: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n more: string;\n codeBlock: string;\n hr: string;\n tableInsert: string;\n tableAddColumnBefore: string;\n tableAddColumnAfter: string;\n tableDeleteColumn: string;\n tableAddRowBefore: string;\n tableAddRowAfter: string;\n tableDeleteRow: string;\n}\n\nexport const defaultToolbarLabels: ToolbarLabels = {\n undo: 'Undo',\n redo: 'Redo',\n style: 'Style',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n fontSize: 'Font size',\n fontSizeDefault: 'Default',\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strike: 'Strikethrough',\n code: 'Inline code',\n textColor: 'Text color',\n highlight: 'Highlight',\n colorNone: 'None',\n colorTheme: 'THEME',\n scriptMenu: 'Superscript / Subscript',\n scriptNormal: 'Normal',\n superscript: 'Superscript',\n subscript: 'Subscript',\n link: 'Link',\n linkPrompt: 'Enter URL',\n image: 'Image',\n imageUploadFailed: 'Image upload failed',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n more: 'More',\n codeBlock: 'Code block',\n hr: 'Divider',\n tableInsert: 'Insert table',\n tableAddColumnBefore: 'Add column before',\n tableAddColumnAfter: 'Add column after',\n tableDeleteColumn: 'Delete column',\n tableAddRowBefore: 'Add row before',\n tableAddRowAfter: 'Add row after',\n tableDeleteRow: 'Delete row',\n};\n\nexport interface ColorPaletteLabels {\n none: string;\n theme: string;\n}\n\nexport const defaultColorPaletteLabels: ColorPaletteLabels = {\n none: 'None',\n theme: 'THEME',\n};\n\nexport interface TocLabels {\n title: string;\n expand: string;\n collapse: string;\n}\n\nexport const defaultTocLabels: TocLabels = {\n title: 'Contents',\n expand: 'Expand',\n collapse: 'Collapse',\n};\n\nexport interface CodeBlockLabels {\n autoDetect: string;\n delete: string;\n}\n\nexport const defaultCodeBlockLabels: CodeBlockLabels = {\n autoDetect: 'Auto-detect',\n delete: 'Delete code block',\n};\n","'use client';\n\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport {\n NodeViewContent,\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport { CheckIcon, ChevronDownIcon, TrashIcon } from '../icons';\nimport { defaultCodeBlockLabels, type CodeBlockLabels } from '../labels';\nimport styles from '../styles/codeBlock.module.css';\n\n// 语言选择可选项。空 value = Auto-detect(交给 lowlight 自动识别)\nconst LANGUAGES: { value: string; label: string }[] = [\n { value: '', label: 'Auto-detect' },\n { value: 'javascript', label: 'JavaScript' },\n { value: 'typescript', label: 'TypeScript' },\n { value: 'python', label: 'Python' },\n { value: 'java', label: 'Java' },\n { value: 'go', label: 'Go' },\n { value: 'rust', label: 'Rust' },\n { value: 'c', label: 'C' },\n { value: 'cpp', label: 'C++' },\n { value: 'csharp', label: 'C#' },\n { value: 'sql', label: 'SQL' },\n { value: 'json', label: 'JSON' },\n { value: 'yaml', label: 'YAML' },\n { value: 'bash', label: 'Bash' },\n { value: 'shell', label: 'Shell' },\n { value: 'html', label: 'HTML' },\n { value: 'css', label: 'CSS' },\n { value: 'markdown', label: 'Markdown' },\n];\n\n/**\n * 代码块自定义 NodeView:右上角语言选择器(Radix DropdownMenu,支持方向键导航)+ 删除。\n * 文案(Auto-detect / 删除标题)从扩展 options.codeBlockLabels 读取,缺省用英文默认。\n */\nexport function CodeBlockView({\n node,\n updateAttributes,\n deleteNode,\n extension,\n}: NodeViewProps) {\n const labels: CodeBlockLabels = {\n ...defaultCodeBlockLabels,\n ...((extension?.options as { codeBlockLabels?: Partial<CodeBlockLabels> })\n ?.codeBlockLabels ?? {}),\n };\n const language = (node.attrs.language as string) || '';\n const current = LANGUAGES.find((l) => l.value === language);\n const currentLabel = current\n ? current.value === ''\n ? labels.autoDetect\n : current.label\n : labels.autoDetect;\n\n return (\n <NodeViewWrapper className={styles.wrapper}>\n <div className={styles.header} contentEditable={false}>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className={styles.langTrigger}\n aria-label=\"Code language\"\n >\n <span>{currentLabel}</span>\n <ChevronDownIcon size={14} className={styles.langChevron} />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className={styles.langMenu}\n sideOffset={4}\n align=\"end\"\n >\n {LANGUAGES.map((l) => {\n const optionLabel =\n l.value === '' ? labels.autoDetect : l.label;\n const selected = l.value === language;\n return (\n <DropdownMenu.Item\n key={l.value}\n className={`${styles.langItem}${selected ? ` ${styles.langItemSelected}` : ''}`}\n onSelect={() => updateAttributes({ language: l.value })}\n >\n <span className={styles.langItemCheck}>\n {selected ? <CheckIcon size={14} /> : null}\n </span>\n {optionLabel}\n </DropdownMenu.Item>\n );\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n <button\n type=\"button\"\n className={styles.deleteBtn}\n title={labels.delete}\n aria-label={labels.delete}\n onClick={() => deleteNode()}\n >\n <TrashIcon />\n </button>\n </div>\n <pre className={styles.pre}>\n {/* code 标签是代码块标准内容容器;v3 类型未含 'code',运行时有效,故断言 */}\n <NodeViewContent as={'code' as 'div'} />\n </pre>\n </NodeViewWrapper>\n );\n}\n","'use client';\n\nimport CodeBlockLowlight, {\n type CodeBlockLowlightOptions,\n} from '@tiptap/extension-code-block-lowlight';\nimport Image from '@tiptap/extension-image';\nimport { TableOfContents } from '@tiptap/extension-table-of-contents';\nimport { Markdown } from '@tiptap/markdown';\nimport {\n EditorContent,\n ReactNodeViewRenderer,\n useEditor,\n type AnyExtension,\n type Editor,\n} from '@tiptap/react';\nimport { forwardRef, useEffect, useImperativeHandle } from 'react';\nimport { baseExtensions, lowlight } from '../extensions';\nimport type { CodeBlockLabels } from '../labels';\nimport styles from '../styles/content.module.css';\nimport type { TocItem } from '../toc/extractToc';\nimport { makeTocGetId } from '../toc/tocSlug';\nimport { CodeBlockView } from './CodeBlockView';\n\n// 带语言选择器的代码块(自定义 React NodeView)。base 不含代码块,此增强版由编辑器注入。\n// addOptions 追加 codeBlockLabels,供 CodeBlockView 读取以本地化文案。\ntype CodeBlockOptions = CodeBlockLowlightOptions & {\n codeBlockLabels?: Partial<CodeBlockLabels>;\n};\n\nconst CodeBlock = CodeBlockLowlight.extend<CodeBlockOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n codeBlockLabels: undefined,\n } as CodeBlockOptions;\n },\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n addKeyboardShortcuts() {\n return {\n Backspace: () => {\n const { state } = this.editor;\n const { selection } = state;\n const { empty, $anchor } = selection;\n\n // 1) 光标在「非空代码块」内容最前面:拦截,防止拆块漏文字(空块放行可删)\n if (\n empty &&\n $anchor.parent.type.name === this.name &&\n $anchor.parentOffset === 0 &&\n $anchor.parent.content.size > 0\n ) {\n return true;\n }\n\n // 2) 光标在「代码块后方块」的开头:先选中整个代码块(二次确认),不直接删\n if (empty && $anchor.parentOffset === 0) {\n const before = $anchor.before($anchor.depth);\n const prevNode = state.doc.resolve(before).nodeBefore;\n if (prevNode?.type.name === this.name) {\n const codeBlockPos = before - prevNode.nodeSize;\n this.editor.chain().setNodeSelection(codeBlockPos).run();\n return true;\n }\n }\n\n return false;\n },\n };\n },\n});\n\n// 块级图片:Backspace 二次确认删除(与代码块一致)。\nconst ImageWithConfirmDelete = Image.extend({\n addKeyboardShortcuts() {\n return {\n Backspace: () => {\n const { state } = this.editor;\n const { selection } = state;\n const { empty, $anchor } = selection;\n if (empty) {\n const nodeBefore = $anchor.nodeBefore;\n if (nodeBefore?.type.name === this.name) {\n const imagePos = $anchor.pos - nodeBefore.nodeSize;\n this.editor.chain().setNodeSelection(imagePos).run();\n return true;\n }\n }\n return false;\n },\n };\n },\n});\n\nexport interface MarkdownWysiwygEditorHandle {\n /** 取当前正文的 markdown 字符串。 */\n getMarkdown: () => string;\n /** 取当前正文的 HTML 字符串。 */\n getHTML: () => string;\n /** 取当前正文的 Tiptap JSON。 */\n getJSON: () => Record<string, unknown>;\n /** 底层 Tiptap Editor 实例(可能为 null,未就绪时)。 */\n getEditor: () => Editor | null;\n}\n\nexport interface MarkdownWysiwygEditorProps {\n /** 初始 markdown 内容。 */\n initialMarkdown?: string;\n placeholder?: string;\n /** editor 实例就绪 / 销毁时回调,供外部工具栏使用。 */\n onEditorReady?: (editor: Editor | null) => void;\n /** 目录变化回调(正文标题增删改时),供侧边目录实时展示。 */\n onTocChange?: (items: TocItem[]) => void;\n /** 追加的 Tiptap 扩展(在内置扩展之后注册)。 */\n extraExtensions?: AnyExtension[];\n /** 代码块 NodeView 的本地化文案。 */\n codeBlockLabels?: Partial<CodeBlockLabels>;\n /** 附加到滚动容器的 class。 */\n className?: string;\n}\n\n/**\n * 所见即所得 Markdown 编辑器(基于 Tiptap v3 + 官方 @tiptap/markdown)。\n * 内容进出均为 markdown 字符串。工具栏由外部渲染——通过 onEditorReady 拿到 editor 实例。\n */\nexport const MarkdownWysiwygEditor = forwardRef<\n MarkdownWysiwygEditorHandle,\n MarkdownWysiwygEditorProps\n>(function MarkdownWysiwygEditor(\n {\n initialMarkdown = '',\n placeholder,\n onEditorReady,\n onTocChange,\n extraExtensions,\n codeBlockLabels,\n className,\n },\n ref,\n) {\n const editor = useEditor({\n extensions: [\n ...baseExtensions,\n CodeBlock.configure({ lowlight, codeBlockLabels }),\n ImageWithConfirmDelete.configure({ inline: false }),\n Markdown,\n TableOfContents.configure({\n getId: makeTocGetId(),\n onUpdate: (anchors) => {\n onTocChange?.(\n anchors\n .filter((a) => a.level <= 6)\n .map((a) => ({ id: a.id, level: a.level, text: a.textContent })),\n );\n },\n }),\n ...(extraExtensions ?? []),\n ],\n content: initialMarkdown,\n contentType: 'markdown',\n // Next.js SSR:服务端不立即渲染,避免 hydration 不一致\n immediatelyRender: false,\n editorProps: {\n attributes: {\n class: styles.editorContent,\n 'data-placeholder': placeholder ?? '',\n },\n },\n });\n\n useEffect(() => {\n onEditorReady?.(editor);\n return () => onEditorReady?.(null);\n }, [editor, onEditorReady]);\n\n useImperativeHandle(\n ref,\n () => ({\n getMarkdown: () => editor?.getMarkdown?.() ?? '',\n getHTML: () => editor?.getHTML?.() ?? '',\n getJSON: () => (editor?.getJSON?.() as Record<string, unknown>) ?? {},\n getEditor: () => editor ?? null,\n }),\n [editor],\n );\n\n return (\n <EditorContent\n editor={editor}\n className={\n className ? `${styles.editorScroll} ${className}` : styles.editorScroll\n }\n />\n );\n});\n","'use client';\n\nimport { Markdown } from '@tiptap/markdown';\nimport { EditorContent, useEditor } from '@tiptap/react';\nimport { useEffect } from 'react';\nimport { baseExtensions, pureCodeBlock, pureImage } from '../extensions';\nimport styles from '../styles/content.module.css';\n\nexport interface MarkdownPreviewProps {\n /** 要预览的 markdown 字符串。 */\n markdown: string;\n className?: string;\n}\n\n/**\n * 轻量只读 markdown 预览(Tiptap + 官方 @tiptap/markdown,editable:false)。\n * 与 MarkdownWysiwygEditor 共用同一套 base 扩展与正文样式类,渲染同源——\n * 预览所见即编辑/插入后所得。用纯版 CodeBlock/Image(无 React 视图 / 删除快捷键)。\n *\n * 这是「客户端只读预览」;若需 SEO / 无 JS 静态渲染,请改用 server 入口的\n * renderReportHtml + ReportContent。\n */\nexport function MarkdownPreview({ markdown, className }: MarkdownPreviewProps) {\n const editor = useEditor({\n extensions: [...baseExtensions, pureCodeBlock, pureImage, Markdown],\n content: markdown,\n contentType: 'markdown',\n editable: false,\n immediatelyRender: false,\n // 关键:内部 ProseMirror DOM 挂与编辑器一字不差的 editorContent class,\n // 所有内容样式都作用在该选择器下,预览才能与编辑/插入后逐像素一致。\n editorProps: {\n attributes: { class: styles.editorContent },\n },\n });\n\n useEffect(() => {\n if (!editor) return;\n editor.commands.setContent(markdown, { contentType: 'markdown' });\n }, [editor, markdown]);\n\n return (\n <EditorContent\n editor={editor}\n className={className ?? styles.editorScroll}\n />\n );\n}\n","'use client';\n\nimport { defaultColorPaletteLabels, type ColorPaletteLabels } from '../labels';\nimport styles from '../styles/colorPalette.module.css';\n\n/**\n * 色板矩阵:10 个色相 × 6 个明度。\n * 第 1 行为纯色(最饱和),下方 5 行为同色相的明→暗变体。\n */\nconst PALETTE: string[][] = [\n ['#8b0000', '#ff0000', '#ff9100', '#ffeb00', '#00e000', '#00e5ff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff'],\n ['#dba0a0', '#e8b4c0', '#f5d9b8', '#f7f0c0', '#cfe8c4', '#bcd9d4', '#c4d4ec', '#cdd4e8', '#d6c4e0', '#e8c4dc'],\n ['#d28a8a', '#dd8c9c', '#eec49a', '#f0e29c', '#a9d4a0', '#94c0bc', '#a0bce4', '#a4b0d8', '#bca0d0', '#d49cc0'],\n ['#cc4444', '#d4506c', '#e89a5c', '#e8d05c', '#7cc06c', '#5ca09c', '#5c90e0', '#6478c8', '#9460c0', '#c45c98'],\n ['#a02020', '#b01030', '#c87410', '#c8a810', '#449030', '#2c706c', '#3060c0', '#1850a0', '#6428a0', '#a02868'],\n ['#5c1010', '#700818', '#7c4808', '#7c6808', '#205818', '#10403c', '#183c78', '#0c3060', '#3c1460', '#601838'],\n];\n\n// THEME 品牌色\nconst THEME_COLORS = ['#ff6719', '#ff5500'];\n\nexport interface ColorPaletteProps {\n /** 当前已应用的颜色(用于打勾),无则不选中。 */\n value?: string;\n /** 点击某色块。null 表示「None」(清除)。 */\n onPick: (color: string | null) => void;\n labels?: Partial<ColorPaletteLabels>;\n}\n\n/** 颜色面板:None 清除行 + 色板网格 + THEME 品牌色。 */\nexport function ColorPalette({ value, onPick, labels }: ColorPaletteProps) {\n const t = { ...defaultColorPaletteLabels, ...labels };\n const current = value?.toLowerCase();\n\n return (\n <div className={styles.palette}>\n <button\n type=\"button\"\n className={styles.noneRow}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(null)}\n >\n <span className={styles.noneIcon} aria-hidden />\n <span className={styles.noneLabel}>{t.none}</span>\n </button>\n\n <div className={styles.grid}>\n {PALETTE.flat().map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`${styles.swatch} ${\n current === c.toLowerCase() ? styles.swatchActive : ''\n }`}\n style={{ background: c }}\n title={c}\n aria-label={c}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(c)}\n />\n ))}\n </div>\n\n <div className={styles.themeLabel}>{t.theme}</div>\n <div className={styles.themeRow}>\n {THEME_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`${styles.swatch} ${\n current === c.toLowerCase() ? styles.swatchActive : ''\n }`}\n style={{ background: c }}\n title={c}\n aria-label={c}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(c)}\n />\n ))}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport * as Popover from '@radix-ui/react-popover';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n BoldIcon,\n ChevronDownIcon,\n CodeIcon,\n ColumnAfterIcon,\n ColumnBeforeIcon,\n ColumnDeleteIcon,\n ImageIcon,\n ItalicIcon,\n LinkIcon,\n ListChecksIcon,\n ListOrderedIcon,\n ListUnorderedIcon,\n RedoIcon,\n RowAfterIcon,\n RowBeforeIcon,\n RowDeleteIcon,\n StrikethroughIcon,\n UnderlineIcon,\n UndoIcon,\n} from '../icons';\nimport { defaultToolbarLabels, type ToolbarLabels } from '../labels';\nimport styles from '../styles/toolbar.module.css';\nimport { ColorPalette } from './ColorPalette';\n\n/** More 菜单里注入的自定义项(宿主用它扩展工具栏,如「导入项目报告」)。 */\nexport interface ExtraToolbarItem {\n key: string;\n /** 左侧图标插槽(可选,文字或 SVG 皆可)。 */\n icon?: ReactNode;\n label: string;\n disabled?: boolean;\n /** 点击回调,拿到 editor 实例自行操作(如 insertContent)。 */\n onSelect: (editor: Editor) => void;\n}\n\nexport interface EditorToolbarProps {\n editor: Editor;\n /**\n * 图片上传回调:收到文件,返回可访问的图片 URL。未提供则不显示图片按钮。\n * 抛错会转交 onError。\n */\n onImageUpload?: (file: File) => Promise<string>;\n /** 副作用错误回调(图片上传失败等),供宿主弹自己的提示。 */\n onError?: (err: unknown) => void;\n labels?: Partial<ToolbarLabels>;\n /** 追加到 More 菜单末尾的自定义项。 */\n extraToolbarItems?: ExtraToolbarItem[];\n className?: string;\n}\n\n/** 单个工具栏按钮:激活态高亮,disabled 时灰显。 */\nfunction ToolbarButton({\n title,\n active,\n disabled,\n onClick,\n children,\n}: {\n title: string;\n active?: boolean;\n disabled?: boolean;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n aria-pressed={active}\n disabled={disabled}\n className={`${styles.btn} ${active ? styles.btnActive : ''}`}\n // mousedown + preventDefault 防止点击工具栏时编辑器失焦丢选区\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\nfunction Divider() {\n return <span className={styles.divider} aria-hidden />;\n}\n\n// 关闭当前菜单的回调(由 MenuPopover 注入,MenuItem 选中后调用以收起)。\nconst MenuCloseCtx = createContext<() => void>(() => {});\n\n/**\n * 菜单气泡:用 Radix Popover 而非 DropdownMenu——后者会强制抢焦点(menu 语义),\n * 打开即让编辑器 blur、丢选区;Popover 可 onOpenAutoFocus preventDefault 保持编辑器焦点。\n * 菜单项为普通 button(onMouseDown preventDefault 不夺焦),行为与原 antd 一致。\n */\nfunction MenuPopover({\n trigger,\n children,\n}: {\n trigger: ReactNode;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const close = useCallback(() => setOpen(false), []);\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>{trigger}</Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.menu}\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <MenuCloseCtx.Provider value={close}>\n {children}\n </MenuCloseCtx.Provider>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nfunction MenuItem({\n selected,\n disabled,\n onSelect,\n children,\n}: {\n selected?: boolean;\n disabled?: boolean;\n onSelect: () => void;\n children: ReactNode;\n}) {\n const close = useContext(MenuCloseCtx);\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={`${styles.menuItem} ${selected ? styles.menuItemSelected : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n onSelect();\n close();\n }}\n >\n {children}\n </button>\n );\n}\n\n/** 颜色气泡:点色块即应用并关闭。 */\nfunction ColorPopover({\n title,\n glyph,\n bar,\n value,\n onPick,\n paletteLabels,\n}: {\n title: string;\n glyph: string;\n bar: string;\n value?: string;\n onPick: (color: string | null) => void;\n paletteLabels: { none: string; theme: string };\n}) {\n const [open, setOpen] = useState(false);\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className={styles.btn}\n title={title}\n aria-label={title}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.colorIcon}>\n <span className={styles.colorIconGlyph}>{glyph}</span>\n <span className={styles.colorIconBar} style={{ background: bar }} />\n </span>\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.popoverContent}\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <ColorPalette\n value={value}\n onPick={(c) => {\n onPick(c);\n setOpen(false);\n }}\n labels={paletteLabels}\n />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nconst HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const;\nconst FONT_SIZES = ['12px', '14px', '16px', '18px', '20px', '24px', '30px'] as const;\n\n/**\n * 顶部操作栏(antd-free,Radix Popover 菜单 + 内联 SVG 图标)。位置由父级控制,\n * 这里只渲染按钮 + 反映 editor 激活态。不含业务耦合,扩展项经 extraToolbarItems 注入。\n */\nexport function EditorToolbar({\n editor,\n onImageUpload,\n onError,\n labels,\n extraToolbarItems,\n className,\n}: EditorToolbarProps) {\n const t: ToolbarLabels = { ...defaultToolbarLabels, ...labels };\n\n const state = useEditorState({\n editor,\n selector: ({ editor: e }) => ({\n bold: e.isActive('bold'),\n italic: e.isActive('italic'),\n underline: e.isActive('underline'),\n strike: e.isActive('strike'),\n code: e.isActive('code'),\n link: e.isActive('link'),\n taskList: e.isActive('taskList'),\n headingLevel: ([1, 2, 3, 4, 5, 6] as const).find((lv) =>\n e.isActive('heading', { level: lv }),\n ),\n fontSize: (e.getAttributes('textStyle').fontSize as string) || undefined,\n isParagraph: e.isActive('paragraph'),\n bulletList: e.isActive('bulletList'),\n orderedList: e.isActive('orderedList'),\n blockquote: e.isActive('blockquote'),\n textColor: (e.getAttributes('textStyle').color as string) || undefined,\n highlightColor:\n (e.getAttributes('highlight').color as string) || undefined,\n superscript: e.isActive('superscript'),\n subscript: e.isActive('subscript'),\n inTable: e.isActive('table'),\n inTableHeader: e.isActive('tableHeader'),\n canUndo: e.can().undo(),\n canRedo: e.can().redo(),\n }),\n });\n\n // 编辑器是否聚焦:仅正文聚焦时才允许调字号。Popover 菜单开/关已阻止抢焦点,\n // 故打开下拉不会误触 blur。\n const [editorFocused, setEditorFocused] = useState(() => editor.isFocused);\n useEffect(() => {\n const onFocus = () => setEditorFocused(true);\n const onBlur = () => setEditorFocused(false);\n editor.on('focus', onFocus);\n editor.on('blur', onBlur);\n return () => {\n editor.off('focus', onFocus);\n editor.off('blur', onBlur);\n };\n }, [editor]);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const chain = () => editor.chain().focus();\n\n // ── 表格工具条(右键召唤):右键单元格时在鼠标处弹出,点别处/Esc 隐藏 ──\n const [tableMenu, setTableMenu] = useState<{ x: number; y: number } | null>(\n null,\n );\n const closeTableMenu = useCallback(() => setTableMenu(null), []);\n\n useEffect(() => {\n const dom = editor.view.dom;\n const onContextMenu = (e: MouseEvent) => {\n const coords = editor.view.posAtCoords({\n left: e.clientX,\n top: e.clientY,\n });\n if (!coords) return;\n const $pos = editor.state.doc.resolve(coords.pos);\n let inTable = false;\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'table') {\n inTable = true;\n break;\n }\n }\n if (!inTable) return;\n e.preventDefault();\n editor.chain().focus().setTextSelection(coords.pos).run();\n setTableMenu({ x: e.clientX, y: e.clientY });\n };\n dom.addEventListener('contextmenu', onContextMenu);\n return () => dom.removeEventListener('contextmenu', onContextMenu);\n }, [editor]);\n\n useEffect(() => {\n if (!tableMenu) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') closeTableMenu();\n };\n document.addEventListener('mousedown', closeTableMenu);\n document.addEventListener('keydown', onKey, true);\n return () => {\n document.removeEventListener('mousedown', closeTableMenu);\n document.removeEventListener('keydown', onKey, true);\n };\n }, [tableMenu, closeTableMenu]);\n\n const runTable = useCallback(\n (fn: () => void) => {\n fn();\n closeTableMenu();\n },\n [closeTableMenu],\n );\n\n // ── 图片:选图 → onImageUpload → 插入返回的 URL ──\n const handlePickImage = () => fileInputRef.current?.click();\n const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file || !onImageUpload) return;\n try {\n const url = await onImageUpload(file);\n if (!url) throw new Error('empty url');\n chain().setImage({ src: url }).run();\n } catch (err) {\n console.error('image upload failed:', err);\n onError?.(err);\n }\n };\n\n const applyTextColor = (color: string | null) => {\n if (color) chain().setColor(color).run();\n else chain().unsetColor().run();\n };\n const applyHighlight = (color: string | null) => {\n if (color) chain().setHighlight({ color }).run();\n else chain().unsetHighlight().run();\n };\n\n const toggleLink = () => {\n if (state.link) {\n chain().unsetLink().run();\n return;\n }\n const url = window.prompt(t.linkPrompt);\n if (url) chain().setLink({ href: url }).run();\n };\n\n const setBlockStyle = (level: number) => {\n if (level === 0) chain().setParagraph().run();\n else\n chain()\n .toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 })\n .run();\n };\n\n const applyFontSize = (size: string) => {\n if (size) chain().setFontSize(size).run();\n else chain().unsetFontSize().run();\n };\n const canEditFontSize = editorFocused && state.isParagraph;\n\n const scriptActive = state.superscript\n ? 'superscript'\n : state.subscript\n ? 'subscript'\n : 'normal';\n\n return (\n <>\n <div\n className={\n className ? `${styles.toolbar} ${className}` : styles.toolbar\n }\n >\n <div className={styles.inner}>\n {/* 撤销 / 重做 */}\n <ToolbarButton\n title={t.undo}\n disabled={!state.canUndo}\n onClick={() => chain().undo().run()}\n >\n <UndoIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.redo}\n disabled={!state.canRedo}\n onClick={() => chain().redo().run()}\n >\n <RedoIcon />\n </ToolbarButton>\n\n <Divider />\n\n {/* 段落样式下拉(正文 / 标题 1~6) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.style}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>{t.style}</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={(state.headingLevel ?? 0) === 0}\n onSelect={() => setBlockStyle(0)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>¶</span>\n {t.normalText}\n </span>\n </MenuItem>\n {HEADING_LEVELS.map((lv) => (\n <MenuItem\n key={lv}\n selected={state.headingLevel === lv}\n onSelect={() => setBlockStyle(lv)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{`H${lv}`}</span>\n {t.headingLabel(lv)}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n\n {/* 正文字号下拉:仅正文可调 */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.fontSize}\n aria-label={t.fontSize}\n disabled={!canEditFontSize}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>\n {state.fontSize || t.fontSize}\n </span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={!state.fontSize}\n onSelect={() => applyFontSize('')}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>A</span>\n {t.fontSizeDefault}\n </span>\n </MenuItem>\n {FONT_SIZES.map((size) => (\n <MenuItem\n key={size}\n selected={state.fontSize === size}\n onSelect={() => applyFontSize(size)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{parseInt(size, 10)}</span>\n {size}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n\n <Divider />\n\n {/* 文字格式 */}\n <ToolbarButton\n title={t.bold}\n active={state.bold}\n onClick={() => chain().toggleBold().run()}\n >\n <BoldIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.italic}\n active={state.italic}\n onClick={() => chain().toggleItalic().run()}\n >\n <ItalicIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.underline}\n active={state.underline}\n onClick={() => chain().toggleUnderline().run()}\n >\n <UnderlineIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.strike}\n active={state.strike}\n onClick={() => chain().toggleStrike().run()}\n >\n <StrikethroughIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.code}\n active={state.code}\n onClick={() => chain().toggleCode().run()}\n >\n <CodeIcon />\n </ToolbarButton>\n\n {/* 文字颜色 */}\n <ColorPopover\n title={t.textColor}\n glyph=\"T\"\n bar={state.textColor || '#ff3b30'}\n value={state.textColor}\n onPick={applyTextColor}\n paletteLabels={{ none: t.colorNone, theme: t.colorTheme }}\n />\n {/* 文字高亮 */}\n <ColorPopover\n title={t.highlight}\n glyph=\"✎\"\n bar={state.highlightColor || '#ffd83d'}\n value={state.highlightColor}\n onPick={applyHighlight}\n paletteLabels={{ none: t.colorNone, theme: t.colorTheme }}\n />\n\n {/* 上标 / 下标下拉(A▾) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={`${styles.scriptTrigger} ${\n scriptActive !== 'normal' ? styles.btnActive : ''\n }`}\n title={t.scriptMenu}\n aria-label={t.scriptMenu}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.scriptTriggerGlyph}>A</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={scriptActive === 'normal'}\n onSelect={() => chain().unsetSuperscript().unsetSubscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>A</span>\n {t.scriptNormal}\n </span>\n </MenuItem>\n <MenuItem\n selected={scriptActive === 'superscript'}\n onSelect={() => chain().unsetSubscript().toggleSuperscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={`${styles.styleIcon} ${styles.scriptGlyph}`}>\n x<sup>2</sup>\n </span>\n {t.superscript}\n </span>\n </MenuItem>\n <MenuItem\n selected={scriptActive === 'subscript'}\n onSelect={() => chain().unsetSuperscript().toggleSubscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={`${styles.styleIcon} ${styles.scriptGlyph}`}>\n x<sub>2</sub>\n </span>\n {t.subscript}\n </span>\n </MenuItem>\n </MenuPopover>\n\n <Divider />\n\n {/* 插入媒体 */}\n <ToolbarButton title={t.link} active={state.link} onClick={toggleLink}>\n <LinkIcon />\n </ToolbarButton>\n {onImageUpload ? (\n <>\n <ToolbarButton title={t.image} onClick={handlePickImage}>\n <ImageIcon />\n </ToolbarButton>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n hidden\n onChange={handleImageChange}\n />\n </>\n ) : null}\n <ToolbarButton\n title={t.blockquote}\n active={state.blockquote}\n onClick={() => chain().toggleBlockquote().run()}\n >\n <span className={styles.txtIcon}>❝</span>\n </ToolbarButton>\n\n <Divider />\n\n {/* 列表 */}\n <ToolbarButton\n title={t.bulletList}\n active={state.bulletList}\n onClick={() => chain().toggleBulletList().run()}\n >\n <ListUnorderedIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.orderedList}\n active={state.orderedList}\n onClick={() => chain().toggleOrderedList().run()}\n >\n <ListOrderedIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.taskList}\n active={state.taskList}\n onClick={() => chain().toggleTaskList().run()}\n >\n <ListChecksIcon />\n </ToolbarButton>\n\n <Divider />\n\n {/* More 下拉(代码块、分割线、表格 + 宿主注入项) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.more}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>{t.more}</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem onSelect={() => chain().toggleCodeBlock().run()}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{'{ }'}</span>\n {t.codeBlock}\n </span>\n </MenuItem>\n <MenuItem onSelect={() => chain().setHorizontalRule().run()}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>—</span>\n {t.hr}\n </span>\n </MenuItem>\n <MenuItem\n disabled={state.inTable}\n onSelect={() =>\n chain()\n .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n .run()\n }\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>⊞</span>\n {t.tableInsert}\n </span>\n </MenuItem>\n {extraToolbarItems?.map((item) => (\n <MenuItem\n key={item.key}\n disabled={item.disabled}\n onSelect={() => item.onSelect(editor)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{item.icon}</span>\n {item.label}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n </div>\n </div>\n\n {/* 表格工具条(右键召唤) */}\n {tableMenu &&\n createPortal(\n <div\n className={styles.tableBubble}\n style={{ position: 'fixed', left: tableMenu.x, top: tableMenu.y }}\n onMouseDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.preventDefault()}\n >\n <ToolbarButton\n title={t.tableAddColumnBefore}\n onClick={() => runTable(() => chain().addColumnBefore().run())}\n >\n <ColumnBeforeIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableAddColumnAfter}\n onClick={() => runTable(() => chain().addColumnAfter().run())}\n >\n <ColumnAfterIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableDeleteColumn}\n onClick={() => runTable(() => chain().deleteColumn().run())}\n >\n <ColumnDeleteIcon />\n </ToolbarButton>\n <Divider />\n <ToolbarButton\n title={t.tableAddRowBefore}\n disabled={state.inTableHeader}\n onClick={() => runTable(() => chain().addRowBefore().run())}\n >\n <RowBeforeIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableAddRowAfter}\n onClick={() => runTable(() => chain().addRowAfter().run())}\n >\n <RowAfterIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableDeleteRow}\n disabled={state.inTableHeader}\n onClick={() => runTable(() => chain().deleteRow().run())}\n >\n <RowDeleteIcon />\n </ToolbarButton>\n </div>,\n document.body,\n )}\n </>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * 是否窄屏(默认 <768px)。取代原项目的 useDevice,内联为纯 matchMedia,\n * 无第三方依赖。SSR 首帧返回 false,挂载后按实际视口更新。\n */\nexport function useIsMobile(breakpoint = 768): boolean {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n const update = () => setIsMobile(mq.matches);\n update();\n mq.addEventListener('change', update);\n return () => mq.removeEventListener('change', update);\n }, [breakpoint]);\n\n return isMobile;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { useIsMobile } from '../hooks/useIsMobile';\nimport { ChevronDownIcon, ListUnorderedIcon, LockIcon, MenuIcon } from '../icons';\nimport { defaultTocLabels, type TocLabels } from '../labels';\nimport styles from '../styles/tocPanel.module.css';\nimport type { TocItem } from '../toc/extractToc';\n\nexport interface TocPanelProps {\n items: TocItem[];\n /** 当前高亮的锚点 id(阅读页由 IntersectionObserver 算、编辑页由光标章节算)。 */\n activeId?: string;\n /** 点击目录项。锁住项不触发。默认行为由调用方决定(滚动 / 跳转)。 */\n onItemClick?: (item: TocItem) => void;\n labels?: Partial<TocLabels>;\n}\n\n/**\n * 目录面板(阅读页 + 编辑页共用)。\n *\n * - 桌面:左侧粘性栏,可收起(«/»)。\n * - 移动:顶部可折叠「目录」条,选中后自动收起。\n * - 层级用左缩进;active accent 左边框 + 加粗;locked 置灰 + 锁图标不可点。\n *\n * 纯展示:滚动 / active 计算交给调用方,本组件只渲染 + 派发点击。\n */\nexport function TocPanel({ items, activeId, onItemClick, labels }: TocPanelProps) {\n const t = { ...defaultTocLabels, ...labels };\n const isMobile = useIsMobile();\n\n const [collapsed, setCollapsed] = useState(false);\n const [mobileOpen, setMobileOpen] = useState(false);\n\n const desktopNavRef = useRef<HTMLElement>(null);\n const mobilePanelRef = useRef<HTMLDivElement>(null);\n\n // activeId 变化时把当前高亮项滚入 TOC 可视区(仅在不可见时)。\n useEffect(() => {\n if (!activeId) return;\n const reduce = window.matchMedia(\n '(prefers-reduced-motion: reduce)',\n ).matches;\n const container = desktopNavRef.current || mobilePanelRef.current;\n if (!container) return;\n const el = container.querySelector(`a[href=\"#${CSS.escape(activeId)}\"]`);\n if (!el) return;\n el.scrollIntoView({\n block: 'nearest',\n behavior: reduce ? 'auto' : 'smooth',\n });\n }, [activeId]);\n\n if (!items.length) return null;\n\n const minLevel = Math.min(...items.map((i) => i.level));\n\n const handleClick = (item: TocItem) => {\n if (item.locked) return;\n onItemClick?.(item);\n if (isMobile) setMobileOpen(false);\n };\n\n const list = (\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id}>\n <a\n href={item.locked ? undefined : `#${item.id}`}\n className={`${styles.item} ${\n item.id === activeId ? styles.active : ''\n } ${item.locked ? styles.locked : ''}`}\n style={{ paddingLeft: `${(item.level - minLevel) * 12 + 12}px` }}\n aria-current={item.id === activeId ? 'true' : undefined}\n aria-disabled={item.locked ? 'true' : undefined}\n onClick={(e) => {\n e.preventDefault();\n handleClick(item);\n }}\n >\n <span className={styles.itemText}>{item.text}</span>\n {item.locked ? (\n <LockIcon className={styles.lockIcon} aria-hidden />\n ) : null}\n </a>\n </li>\n ))}\n </ul>\n );\n\n // ── 移动端:顶部可折叠条 ──\n if (isMobile) {\n return (\n <nav className={styles.mobile} aria-label={t.title}>\n <button\n type=\"button\"\n className={styles.mobileBar}\n aria-expanded={mobileOpen}\n onClick={() => setMobileOpen((v) => !v)}\n >\n <MenuIcon className={styles.mobileBarIcon} aria-hidden />\n <span>{t.title}</span>\n <span\n className={`${styles.chevron} ${\n mobileOpen ? styles.chevronUp : ''\n }`}\n aria-hidden\n >\n <ChevronDownIcon size={16} />\n </span>\n </button>\n <div\n ref={mobilePanelRef}\n className={`${styles.mobilePanel} ${\n mobileOpen ? styles.mobilePanelOpen : ''\n }`}\n >\n {list}\n </div>\n </nav>\n );\n }\n\n // ── 桌面:左侧粘性栏(可收起)──\n if (collapsed) {\n return (\n <button\n type=\"button\"\n className={styles.collapsedRail}\n aria-label={t.expand}\n title={t.expand}\n onClick={() => setCollapsed(false)}\n >\n <ListUnorderedIcon />\n </button>\n );\n }\n\n return (\n <nav className={styles.desktop} aria-label={t.title} ref={desktopNavRef}>\n <div className={styles.header}>\n <span className={styles.headerTitle}>{t.title}</span>\n <button\n type=\"button\"\n className={styles.collapseBtn}\n aria-label={t.collapse}\n title={t.collapse}\n onClick={() => setCollapsed(true)}\n >\n «\n </button>\n </div>\n {list}\n </nav>\n );\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\n\n/** 在光标处插入 markdown 片段(封装 contentType: 'markdown')。 */\nexport function insertMarkdown(editor: Editor, markdown: string): void {\n editor.chain().focus().insertContent(markdown, { contentType: 'markdown' }).run();\n}\n"],"names":["styles","MarkdownWysiwygEditor","e","active","item","list"],"mappings":";;;;;;;;;;;;;AAUA,SAAS,IAAI,EAAE,OAAO,OAAO,UAAU,GAAG,QAAmD;AAC3F,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAY;AAAA,MACZ,WAAU;AAAA,MACT,GAAG;AAAA,MAEH;AAAA,IAAA;AAAA,EAAA;AAGP;AAEO,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,wCAAA,CAAwC;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,yCAAA,CAAyC;AAAA,EAAA,CACnD;AAGK,MAAM,aAAa,CAAC,MACzB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,EACpC,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACrC,oBAAC,UAAK,IAAG,MAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAA,CAAK;AAAA,EAAA,CACtC;AAGK,MAAM,gBAAgB,CAAC,MAC5B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,0BAAA,CAA0B;AAAA,EAClC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EAAA,CACvC;AAGK,MAAM,oBAAoB,CAAC,MAChC,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,2BAAA,CAA2B;AAAA,EACnC,oBAAC,QAAA,EAAK,GAAE,yBAAA,CAAyB;AAAA,EACjC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EAAA,CACvC;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,YAAA,EAAS,QAAO,mBAAA,CAAmB;AAAA,EACpC,oBAAC,YAAA,EAAS,QAAO,gBAAA,CAAgB;AAAA,EAAA,CACnC;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,8DAAA,CAA8D;AAAA,EACtE,oBAAC,QAAA,EAAK,GAAE,+DAAA,CAA+D;AAAA,EAAA,CACzE;AAGK,MAAM,YAAY,CAAC,MACxB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,OAAM,MAAK,QAAO,MAAK,GAAE,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI;AAAA,sBACtD,UAAA,EAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI;AAAA,EAC5B,oBAAC,QAAA,EAAK,GAAE,4CAAA,CAA4C;AAAA,EAAA,CACtD;AAGK,MAAM,oBAAoB,CAAC,MAChC,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,EACnC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACrC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACrC,oBAAC,UAAK,IAAG,KAAI,IAAG,QAAO,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,EACrC,oBAAC,UAAK,IAAG,KAAI,IAAG,QAAO,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACvC,oBAAC,UAAK,IAAG,KAAI,IAAG,QAAO,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EAAA,CACzC;AAGK,MAAM,kBAAkB,CAAC,MAC9B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,EACpC,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACtC,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACtC,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,iCAAA,CAAiC;AAAA,EAAA,CAC3C;AAGK,MAAM,iBAAiB,CAAC,MAC7B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EACxB,oBAAC,QAAA,EAAK,GAAE,eAAA,CAAe;AAAA,EACvB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EAAA,CACrB;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EACxB,oBAAC,QAAA,EAAK,GAAE,2DAAA,CAA2D;AAAA,EAAA,CACrE;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,iBAAA,CAAiB;AAAA,EACzB,oBAAC,QAAA,EAAK,GAAE,yDAAA,CAAyD;AAAA,EAAA,CACnE;AAGK,MAAM,kBAAkB,CAAC,MAC9B,oBAAC,KAAA,EAAK,GAAG,GACP,UAAA,oBAAC,QAAA,EAAK,GAAE,eAAA,CAAe,EAAA,CACzB;AAGK,MAAM,YAAY,CAAC,MACxB,oBAAC,KAAA,EAAK,GAAG,GACP,UAAA,oBAAC,QAAA,EAAK,GAAE,kBAAA,CAAkB,EAAA,CAC5B;AAGK,MAAM,YAAY,CAAC,MACxB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,2CAAA,CAA2C;AAAA,EACnD,oBAAC,QAAA,EAAK,GAAE,yCAAA,CAAyC;AAAA,EACjD,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACtC,oBAAC,UAAK,IAAG,MAAK,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EAAA,CACxC;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,OAAM,MAAK,QAAO,MAAK,GAAE,KAAI,GAAE,MAAK,IAAG,KAAI,IAAG,KAAI;AAAA,EACxD,oBAAC,QAAA,EAAK,GAAE,2BAAA,CAA2B;AAAA,EAAA,CACrC;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EACrC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,KAAI,IAAG,IAAA,CAAI;AAAA,EACnC,oBAAC,UAAK,IAAG,KAAI,IAAG,MAAK,IAAG,MAAK,IAAG,KAAA,CAAK;AAAA,EAAA,CACvC;AAKK,MAAM,mBAAmB,CAAC,MAC/B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,MAAK,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EACjD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,SAAA,CAAS;AAAA,EACjB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAAA,CACpB;AAGK,MAAM,kBAAkB,CAAC,MAC9B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EAAA,CACrB;AAGK,MAAM,mBAAmB,CAAC,MAC/B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EAAA,CACtB;AAGK,MAAM,gBAAgB,CAAC,MAC5B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,MAAK,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EACjD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,SAAA,CAAS;AAAA,EACjB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAAA,CACpB;AAGK,MAAM,eAAe,CAAC,MAC3B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EAAA,CACrB;AAGK,MAAM,gBAAgB,CAAC,MAC5B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,KAAI,OAAM,MAAK,QAAO,MAAK,IAAG,IAAA,CAAI;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EAAA,CACtB;AC5KK,MAAM,uBAAsC;AAAA,EACjD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,cAAc,CAAC,UAAU,WAAW,KAAK;AAAA,EACzC,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,WAAW;AAAA,EACX,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,IAAI;AAAA,EACJ,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AAClB;AAOO,MAAM,4BAAgD;AAAA,EAC3D,MAAM;AAAA,EACN,OAAO;AACT;AAQO,MAAM,mBAA8B;AAAA,EACzC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AACZ;AAOO,MAAM,yBAA0C;AAAA,EACrD,YAAY;AAAA,EACZ,QAAQ;AACV;;;;;;;;;;;;;;;;;;;;;;;ACzGA,MAAM,YAAgD;AAAA,EACpD,EAAE,OAAO,IAAI,OAAO,cAAA;AAAA,EACpB,EAAE,OAAO,cAAc,OAAO,aAAA;AAAA,EAC9B,EAAE,OAAO,cAAc,OAAO,aAAA;AAAA,EAC9B,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,EAC1B,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,MAAM,OAAO,KAAA;AAAA,EACtB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,KAAK,OAAO,IAAA;AAAA,EACrB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,UAAU,OAAO,KAAA;AAAA,EAC1B,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,SAAS,OAAO,QAAA;AAAA,EACzB,EAAE,OAAO,QAAQ,OAAO,OAAA;AAAA,EACxB,EAAE,OAAO,OAAO,OAAO,MAAA;AAAA,EACvB,EAAE,OAAO,YAAY,OAAO,WAAA;AAC9B;AAMO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkB;;AAChB,QAAM,SAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,KAAK,4CAAW,YAAX,mBACD,oBAAmB,CAAA;AAAA,EAAC;AAE1B,QAAM,WAAY,KAAK,MAAM,YAAuB;AACpD,QAAM,UAAU,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AAC1D,QAAM,eAAe,UACjB,QAAQ,UAAU,KAChB,OAAO,aACP,QAAQ,QACV,OAAO;AAEX,SACE,qBAAC,iBAAA,EAAgB,WAAWA,SAAO,SACjC,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAWA,SAAO,QAAQ,iBAAiB,OAC9C,UAAA;AAAA,MAAA,qBAAC,aAAa,MAAb,EACC,UAAA;AAAA,QAAA,oBAAC,aAAa,SAAb,EAAqB,SAAO,MAC3B,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAWA,SAAO;AAAA,YAClB,cAAW;AAAA,YAEX,UAAA;AAAA,cAAA,oBAAC,UAAM,UAAA,aAAA,CAAa;AAAA,kCACnB,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,YAAA,CAAa;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAE9D;AAAA,QACA,oBAAC,aAAa,QAAb,EACC,UAAA;AAAA,UAAC,aAAa;AAAA,UAAb;AAAA,YACC,WAAWA,SAAO;AAAA,YAClB,YAAY;AAAA,YACZ,OAAM;AAAA,YAEL,UAAA,UAAU,IAAI,CAAC,MAAM;AACpB,oBAAM,cACJ,EAAE,UAAU,KAAK,OAAO,aAAa,EAAE;AACzC,oBAAM,WAAW,EAAE,UAAU;AAC7B,qBACE;AAAA,gBAAC,aAAa;AAAA,gBAAb;AAAA,kBAEC,WAAW,GAAGA,SAAO,QAAQ,GAAG,WAAW,IAAIA,SAAO,gBAAgB,KAAK,EAAE;AAAA,kBAC7E,UAAU,MAAM,iBAAiB,EAAE,UAAU,EAAE,OAAO;AAAA,kBAEtD,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,eACrB,UAAA,+BAAY,WAAA,EAAU,MAAM,GAAA,CAAI,IAAK,KAAA,CACxC;AAAA,oBACC;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAPI,EAAE;AAAA,cAAA;AAAA,YAUb,CAAC;AAAA,UAAA;AAAA,QAAA,EACH,CACF;AAAA,MAAA,GACF;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWA,SAAO;AAAA,UAClB,OAAO,OAAO;AAAA,UACd,cAAY,OAAO;AAAA,UACnB,SAAS,MAAM,WAAA;AAAA,UAEf,8BAAC,WAAA,CAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,IACb,GACF;AAAA,IACA,oBAAC,SAAI,WAAWA,SAAO,KAErB,UAAA,oBAAC,iBAAA,EAAgB,IAAI,OAAA,CAAiB,EAAA,CACxC;AAAA,EAAA,GACF;AAEJ;ACpFA,MAAM,YAAY,kBAAkB,OAAyB;AAAA,EAC3D,aAAa;;AACX,WAAO;AAAA,MACL,IAAG,UAAK,WAAL;AAAA,MACH,iBAAiB;AAAA,IAAA;AAAA,EAErB;AAAA,EACA,cAAc;AACZ,WAAO,sBAAsB,aAAa;AAAA,EAC5C;AAAA,EACA,uBAAuB;AACrB,WAAO;AAAA,MACL,WAAW,MAAM;AACf,cAAM,EAAE,UAAU,KAAK;AACvB,cAAM,EAAE,cAAc;AACtB,cAAM,EAAE,OAAO,QAAA,IAAY;AAG3B,YACE,SACA,QAAQ,OAAO,KAAK,SAAS,KAAK,QAClC,QAAQ,iBAAiB,KACzB,QAAQ,OAAO,QAAQ,OAAO,GAC9B;AACA,iBAAO;AAAA,QACT;AAGA,YAAI,SAAS,QAAQ,iBAAiB,GAAG;AACvC,gBAAM,SAAS,QAAQ,OAAO,QAAQ,KAAK;AAC3C,gBAAM,WAAW,MAAM,IAAI,QAAQ,MAAM,EAAE;AAC3C,eAAI,qCAAU,KAAK,UAAS,KAAK,MAAM;AACrC,kBAAM,eAAe,SAAS,SAAS;AACvC,iBAAK,OAAO,MAAA,EAAQ,iBAAiB,YAAY,EAAE,IAAA;AACnD,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,EAEJ;AACF,CAAC;AAGD,MAAM,yBAAyB,MAAM,OAAO;AAAA,EAC1C,uBAAuB;AACrB,WAAO;AAAA,MACL,WAAW,MAAM;AACf,cAAM,EAAE,UAAU,KAAK;AACvB,cAAM,EAAE,cAAc;AACtB,cAAM,EAAE,OAAO,QAAA,IAAY;AAC3B,YAAI,OAAO;AACT,gBAAM,aAAa,QAAQ;AAC3B,eAAI,yCAAY,KAAK,UAAS,KAAK,MAAM;AACvC,kBAAM,WAAW,QAAQ,MAAM,WAAW;AAC1C,iBAAK,OAAO,MAAA,EAAQ,iBAAiB,QAAQ,EAAE,IAAA;AAC/C,mBAAO;AAAA,UACT;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,EAEJ;AACF,CAAC;AAiCM,MAAM,wBAAwB,WAGnC,SAASC,uBACT;AAAA,EACE,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GACA,KACA;AACA,QAAM,SAAS,UAAU;AAAA,IACvB,YAAY;AAAA,MACV,GAAG;AAAA,MACH,UAAU,UAAU,EAAE,UAAU,iBAAiB;AAAA,MACjD,uBAAuB,UAAU,EAAE,QAAQ,OAAO;AAAA,MAClD;AAAA,MACA,gBAAgB,UAAU;AAAA,QACxB,OAAO,aAAA;AAAA,QACP,UAAU,CAAC,YAAY;AACrB;AAAA,YACE,QACG,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,OAAO,MAAM,EAAE,cAAc;AAAA;AAAA,QAErE;AAAA,MAAA,CACD;AAAA,MACD,GAAI,mBAAmB,CAAA;AAAA,IAAC;AAAA,IAE1B,SAAS;AAAA,IACT,aAAa;AAAA;AAAA,IAEb,mBAAmB;AAAA,IACnB,aAAa;AAAA,MACX,YAAY;AAAA,QACV,OAAOD,SAAO;AAAA,QACd,oBAAoB,eAAe;AAAA,MAAA;AAAA,IACrC;AAAA,EACF,CACD;AAED,YAAU,MAAM;AACd,mDAAgB;AAChB,WAAO,MAAM,+CAAgB;AAAA,EAC/B,GAAG,CAAC,QAAQ,aAAa,CAAC;AAE1B;AAAA,IACE;AAAA,IACA,OAAO;AAAA,MACL,aAAa,MAAA;;AAAM,uDAAQ,gBAAR,oCAA2B;AAAA;AAAA,MAC9C,SAAS,MAAA;;AAAM,uDAAQ,YAAR,oCAAuB;AAAA;AAAA,MACtC,SAAS,MAAA;;AAAO,uDAAQ,YAAR,oCAAmD,CAAA;AAAA;AAAA,MACnE,WAAW,MAAM,UAAU;AAAA,IAAA;AAAA,IAE7B,CAAC,MAAM;AAAA,EAAA;AAGT,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,WACE,YAAY,GAAGA,SAAO,YAAY,IAAI,SAAS,KAAKA,SAAO;AAAA,IAAA;AAAA,EAAA;AAInE,CAAC;AC7KM,SAAS,gBAAgB,EAAE,UAAU,aAAmC;AAC7E,QAAM,SAAS,UAAU;AAAA,IACvB,YAAY,CAAC,GAAG,gBAAgB,eAAe,WAAW,QAAQ;AAAA,IAClE,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA;AAAA,IAGnB,aAAa;AAAA,MACX,YAAY,EAAE,OAAOA,SAAO,cAAA;AAAA,IAAc;AAAA,EAC5C,CACD;AAED,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,SAAS,WAAW,UAAU,EAAE,aAAa,YAAY;AAAA,EAClE,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAErB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAW,aAAaA,SAAO;AAAA,IAAA;AAAA,EAAA;AAGrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACtCA,MAAM,UAAsB;AAAA,EAC1B,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC7G,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC7G,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC7G,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC7G,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAAA,EAC7G,CAAC,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,WAAW,SAAS;AAC/G;AAGA,MAAM,eAAe,CAAC,WAAW,SAAS;AAWnC,SAAS,aAAa,EAAE,OAAO,QAAQ,UAA6B;AACzE,QAAM,IAAI,EAAE,GAAG,2BAA2B,GAAG,OAAA;AAC7C,QAAM,UAAU,+BAAO;AAEvB,SACE,qBAAC,OAAA,EAAI,WAAWA,SAAO,SACrB,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWA,SAAO;AAAA,QAClB,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,IAAI;AAAA,QAE1B,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWF,SAAO,UAAU,eAAW,MAAC;AAAA,8BAC7C,QAAA,EAAK,WAAWA,SAAO,WAAY,YAAE,KAAA,CAAK;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAG7C,oBAAC,OAAA,EAAI,WAAWA,SAAO,MACpB,kBAAQ,KAAA,EAAO,IAAI,CAAC,MACnB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAW,GAAGA,SAAO,MAAM,IACzB,YAAY,EAAE,YAAA,IAAgBA,SAAO,eAAe,EACtD;AAAA,QACA,OAAO,EAAE,YAAY,EAAA;AAAA,QACrB,OAAO;AAAA,QACP,cAAY;AAAA,QACZ,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,CAAC;AAAA,MAAA;AAAA,MATlB;AAAA,IAAA,CAWR,GACH;AAAA,wBAEC,OAAA,EAAI,WAAWF,SAAO,YAAa,YAAE,OAAM;AAAA,IAC5C,oBAAC,SAAI,WAAWA,SAAO,UACpB,UAAA,aAAa,IAAI,CAAC,MACjB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,WAAW,GAAGA,SAAO,MAAM,IACzB,YAAY,EAAE,YAAA,IAAgBA,SAAO,eAAe,EACtD;AAAA,QACA,OAAO,EAAE,YAAY,EAAA;AAAA,QACrB,OAAO;AAAA,QACP,cAAY;AAAA,QACZ,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,CAAC;AAAA,MAAA;AAAA,MATlB;AAAA,IAAA,CAWR,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AChBA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA,QAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,cAAY;AAAA,MACZ,gBAAcA;AAAA,MACd;AAAA,MACA,WAAW,GAAGH,SAAO,GAAG,IAAIG,UAASH,SAAO,YAAY,EAAE;AAAA,MAE1D,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,MACtB;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,SAAS,UAAU;AACjB,6BAAQ,QAAA,EAAK,WAAWF,SAAO,SAAS,eAAW,MAAC;AACtD;AAGA,MAAM,eAAe,cAA0B,MAAM;AAAC,CAAC;AAOvD,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,QAAQ,YAAY,MAAM,QAAQ,KAAK,GAAG,CAAA,CAAE;AAClD,8BACG,QAAQ,MAAR,EAAa,MAAY,cAAc,SACtC,UAAA;AAAA,IAAA,oBAAC,QAAQ,SAAR,EAAgB,SAAO,MAAE,UAAA,SAAQ;AAAA,IAClC,oBAAC,QAAQ,QAAR,EACC,UAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,WAAWA,SAAO;AAAA,QAClB,YAAY;AAAA,QACZ,OAAM;AAAA,QACN,iBAAiB,CAACE,OAAMA,GAAE,eAAA;AAAA,QAC1B,kBAAkB,CAACA,OAAMA,GAAE,eAAA;AAAA,QAE3B,8BAAC,aAAa,UAAb,EAAsB,OAAO,OAC3B,SAAA,CACH;AAAA,MAAA;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,SAAS;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,QAAQ,WAAW,YAAY;AACrC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,WAAW,GAAGF,SAAO,QAAQ,IAAI,WAAWA,SAAO,mBAAmB,EAAE;AAAA,MACxE,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,MACtB,SAAS,MAAM;AACb,iBAAA;AACA,cAAA;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGP;AAGA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,8BACG,QAAQ,MAAR,EAAa,MAAY,cAAc,SACtC,UAAA;AAAA,IAAA,oBAAC,QAAQ,SAAR,EAAgB,SAAO,MACtB,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAWF,SAAO;AAAA,QAClB;AAAA,QACA,cAAY;AAAA,QACZ,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,QAEtB,UAAA,qBAAC,QAAA,EAAK,WAAWF,SAAO,WACtB,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,gBAAiB,UAAA,OAAM;AAAA,UAC/C,oBAAC,UAAK,WAAWA,SAAO,cAAc,OAAO,EAAE,YAAY,MAAI,CAAG;AAAA,QAAA,EAAA,CACpE;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,IACA,oBAAC,QAAQ,QAAR,EACC,UAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,WAAWA,SAAO;AAAA,QAClB,YAAY;AAAA,QACZ,OAAM;AAAA,QACN,iBAAiB,CAACE,OAAMA,GAAE,eAAA;AAAA,QAC1B,kBAAkB,CAACA,OAAMA,GAAE,eAAA;AAAA,QAE3B,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC;AAAA,YACA,QAAQ,CAAC,MAAM;AACb,qBAAO,CAAC;AACR,sBAAQ,KAAK;AAAA,YACf;AAAA,YACA,QAAQ;AAAA,UAAA;AAAA,QAAA;AAAA,MACV;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,MAAM,iBAAiB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACxC,MAAM,aAAa,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,MAAM;AAMnE,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAuB;AACrB,QAAM,IAAmB,EAAE,GAAG,sBAAsB,GAAG,OAAA;AAEvD,QAAM,QAAQ,eAAe;AAAA,IAC3B;AAAA,IACA,UAAU,CAAC,EAAE,QAAQA,UAAS;AAAA,MAC5B,MAAMA,GAAE,SAAS,MAAM;AAAA,MACvB,QAAQA,GAAE,SAAS,QAAQ;AAAA,MAC3B,WAAWA,GAAE,SAAS,WAAW;AAAA,MACjC,QAAQA,GAAE,SAAS,QAAQ;AAAA,MAC3B,MAAMA,GAAE,SAAS,MAAM;AAAA,MACvB,MAAMA,GAAE,SAAS,MAAM;AAAA,MACvB,UAAUA,GAAE,SAAS,UAAU;AAAA,MAC/B,cAAe,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAY;AAAA,QAAK,CAAC,OAChDA,GAAE,SAAS,WAAW,EAAE,OAAO,IAAI;AAAA,MAAA;AAAA,MAErC,UAAWA,GAAE,cAAc,WAAW,EAAE,YAAuB;AAAA,MAC/D,aAAaA,GAAE,SAAS,WAAW;AAAA,MACnC,YAAYA,GAAE,SAAS,YAAY;AAAA,MACnC,aAAaA,GAAE,SAAS,aAAa;AAAA,MACrC,YAAYA,GAAE,SAAS,YAAY;AAAA,MACnC,WAAYA,GAAE,cAAc,WAAW,EAAE,SAAoB;AAAA,MAC7D,gBACGA,GAAE,cAAc,WAAW,EAAE,SAAoB;AAAA,MACpD,aAAaA,GAAE,SAAS,aAAa;AAAA,MACrC,WAAWA,GAAE,SAAS,WAAW;AAAA,MACjC,SAASA,GAAE,SAAS,OAAO;AAAA,MAC3B,eAAeA,GAAE,SAAS,aAAa;AAAA,MACvC,SAASA,GAAE,IAAA,EAAM,KAAA;AAAA,MACjB,SAASA,GAAE,IAAA,EAAM,KAAA;AAAA,IAAK;AAAA,EACxB,CACD;AAID,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,MAAM,OAAO,SAAS;AACzE,YAAU,MAAM;AACd,UAAM,UAAU,MAAM,iBAAiB,IAAI;AAC3C,UAAM,SAAS,MAAM,iBAAiB,KAAK;AAC3C,WAAO,GAAG,SAAS,OAAO;AAC1B,WAAO,GAAG,QAAQ,MAAM;AACxB,WAAO,MAAM;AACX,aAAO,IAAI,SAAS,OAAO;AAC3B,aAAO,IAAI,QAAQ,MAAM;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,eAAe,OAAyB,IAAI;AAClD,QAAM,QAAQ,MAAM,OAAO,MAAA,EAAQ,MAAA;AAGnC,QAAM,CAAC,WAAW,YAAY,IAAI;AAAA,IAChC;AAAA,EAAA;AAEF,QAAM,iBAAiB,YAAY,MAAM,aAAa,IAAI,GAAG,CAAA,CAAE;AAE/D,YAAU,MAAM;AACd,UAAM,MAAM,OAAO,KAAK;AACxB,UAAM,gBAAgB,CAACA,OAAkB;AACvC,YAAM,SAAS,OAAO,KAAK,YAAY;AAAA,QACrC,MAAMA,GAAE;AAAA,QACR,KAAKA,GAAE;AAAA,MAAA,CACR;AACD,UAAI,CAAC,OAAQ;AACb,YAAM,OAAO,OAAO,MAAM,IAAI,QAAQ,OAAO,GAAG;AAChD,UAAI,UAAU;AACd,eAAS,IAAI,KAAK,OAAO,IAAI,GAAG,KAAK;AACnC,YAAI,KAAK,KAAK,CAAC,EAAE,KAAK,SAAS,SAAS;AACtC,oBAAU;AACV;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,QAAS;AACd,MAAAA,GAAE,eAAA;AACF,aAAO,MAAA,EAAQ,MAAA,EAAQ,iBAAiB,OAAO,GAAG,EAAE,IAAA;AACpD,mBAAa,EAAE,GAAGA,GAAE,SAAS,GAAGA,GAAE,SAAS;AAAA,IAC7C;AACA,QAAI,iBAAiB,eAAe,aAAa;AACjD,WAAO,MAAM,IAAI,oBAAoB,eAAe,aAAa;AAAA,EACnE,GAAG,CAAC,MAAM,CAAC;AAEX,YAAU,MAAM;AACd,QAAI,CAAC,UAAW;AAChB,UAAM,QAAQ,CAACA,OAAqB;AAClC,UAAIA,GAAE,QAAQ,SAAU,gBAAA;AAAA,IAC1B;AACA,aAAS,iBAAiB,aAAa,cAAc;AACrD,aAAS,iBAAiB,WAAW,OAAO,IAAI;AAChD,WAAO,MAAM;AACX,eAAS,oBAAoB,aAAa,cAAc;AACxD,eAAS,oBAAoB,WAAW,OAAO,IAAI;AAAA,IACrD;AAAA,EACF,GAAG,CAAC,WAAW,cAAc,CAAC;AAE9B,QAAM,WAAW;AAAA,IACf,CAAC,OAAmB;AAClB,SAAA;AACA,qBAAA;AAAA,IACF;AAAA,IACA,CAAC,cAAc;AAAA,EAAA;AAIjB,QAAM,kBAAkB,MAAA;;AAAM,8BAAa,YAAb,mBAAsB;AAAA;AACpD,QAAM,oBAAoB,OAAOA,OAA2C;;AAC1E,UAAM,QAAO,KAAAA,GAAE,OAAO,UAAT,mBAAiB;AAC9B,IAAAA,GAAE,OAAO,QAAQ;AACjB,QAAI,CAAC,QAAQ,CAAC,cAAe;AAC7B,QAAI;AACF,YAAM,MAAM,MAAM,cAAc,IAAI;AACpC,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,WAAW;AACrC,YAAA,EAAQ,SAAS,EAAE,KAAK,IAAA,CAAK,EAAE,IAAA;AAAA,IACjC,SAAS,KAAK;AACZ,cAAQ,MAAM,wBAAwB,GAAG;AACzC,yCAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,UAAyB;AAC/C,QAAI,MAAO,OAAA,EAAQ,SAAS,KAAK,EAAE,IAAA;AAAA,QAC9B,OAAA,EAAQ,WAAA,EAAa,IAAA;AAAA,EAC5B;AACA,QAAM,iBAAiB,CAAC,UAAyB;AAC/C,QAAI,eAAe,aAAa,EAAE,MAAA,CAAO,EAAE,IAAA;AAAA,QACtC,OAAA,EAAQ,eAAA,EAAiB,IAAA;AAAA,EAChC;AAEA,QAAM,aAAa,MAAM;AACvB,QAAI,MAAM,MAAM;AACd,YAAA,EAAQ,UAAA,EAAY,IAAA;AACpB;AAAA,IACF;AACA,UAAM,MAAM,OAAO,OAAO,EAAE,UAAU;AACtC,QAAI,aAAa,QAAQ,EAAE,MAAM,IAAA,CAAK,EAAE,IAAA;AAAA,EAC1C;AAEA,QAAM,gBAAgB,CAAC,UAAkB;AACvC,QAAI,UAAU,EAAG,OAAA,EAAQ,aAAA,EAAe,IAAA;AAAA;AAEtC,YAAA,EACG,cAAc,EAAE,MAAA,CAAuC,EACvD,IAAA;AAAA,EACP;AAEA,QAAM,gBAAgB,CAAC,SAAiB;AACtC,QAAI,KAAM,OAAA,EAAQ,YAAY,IAAI,EAAE,IAAA;AAAA,QAC/B,OAAA,EAAQ,cAAA,EAAgB,IAAA;AAAA,EAC/B;AACA,QAAM,kBAAkB,iBAAiB,MAAM;AAE/C,QAAM,eAAe,MAAM,cACvB,gBACA,MAAM,YACJ,cACA;AAEN,SACE,qBAAA,UAAA,EACE,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WACE,YAAY,GAAGF,SAAO,OAAO,IAAI,SAAS,KAAKA,SAAO;AAAA,QAGxD,UAAA,qBAAC,OAAA,EAAI,WAAWA,SAAO,OAErB,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,UAAU,CAAC,MAAM;AAAA,cACjB,SAAS,MAAM,MAAA,EAAQ,KAAA,EAAO,IAAA;AAAA,cAE9B,8BAAC,UAAA,CAAA,CAAS;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,UAAU,CAAC,MAAM;AAAA,cACjB,SAAS,MAAM,MAAA,EAAQ,KAAA,EAAO,IAAA;AAAA,cAE9B,8BAAC,UAAA,CAAA,CAAS;AAAA,YAAA;AAAA,UAAA;AAAA,8BAGX,SAAA,EAAQ;AAAA,UAGT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAWA,SAAO;AAAA,kBAClB,OAAO,EAAE;AAAA,kBACT,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWF,SAAO,mBAAoB,YAAE,OAAM;AAAA,wCACnD,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,kBAAA,CAAmB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIpE,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW,MAAM,gBAAgB,OAAO;AAAA,oBACxC,UAAU,MAAM,cAAc,CAAC;AAAA,oBAE/B,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,sBACnC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAED,eAAe,IAAI,CAAC,OACnB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,UAAU,MAAM,iBAAiB;AAAA,oBACjC,UAAU,MAAM,cAAc,EAAE;AAAA,oBAEhC,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,UAAK,WAAWA,SAAO,WAAY,UAAA,IAAI,EAAE,IAAG;AAAA,sBAC5C,EAAE,aAAa,EAAE;AAAA,oBAAA,EAAA,CACpB;AAAA,kBAAA;AAAA,kBAPK;AAAA,gBAAA,CASR;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAIH;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAWA,SAAO;AAAA,kBAClB,OAAO,EAAE;AAAA,kBACT,cAAY,EAAE;AAAA,kBACd,UAAU,CAAC;AAAA,kBACX,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,UAAK,WAAWF,SAAO,mBACrB,UAAA,MAAM,YAAY,EAAE,SAAA,CACvB;AAAA,wCACC,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,kBAAA,CAAmB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIpE,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,UAAU,CAAC,MAAM;AAAA,oBACjB,UAAU,MAAM,cAAc,EAAE;AAAA,oBAEhC,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,sBACnC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAED,WAAW,IAAI,CAAC,SACf;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,UAAU,MAAM,aAAa;AAAA,oBAC7B,UAAU,MAAM,cAAc,IAAI;AAAA,oBAElC,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,UAAK,WAAWA,SAAO,WAAY,UAAA,SAAS,MAAM,EAAE,GAAE;AAAA,sBACtD;AAAA,oBAAA,EAAA,CACH;AAAA,kBAAA;AAAA,kBAPK;AAAA,gBAAA,CASR;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,8BAGF,SAAA,EAAQ;AAAA,UAGT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,WAAA,EAAa,IAAA;AAAA,cAEpC,8BAAC,UAAA,CAAA,CAAS;AAAA,YAAA;AAAA,UAAA;AAAA,UAEZ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,aAAA,EAAe,IAAA;AAAA,cAEtC,8BAAC,YAAA,CAAA,CAAW;AAAA,YAAA;AAAA,UAAA;AAAA,UAEd;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,gBAAA,EAAkB,IAAA;AAAA,cAEzC,8BAAC,eAAA,CAAA,CAAc;AAAA,YAAA;AAAA,UAAA;AAAA,UAEjB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,aAAA,EAAe,IAAA;AAAA,cAEtC,8BAAC,mBAAA,CAAA,CAAkB;AAAA,YAAA;AAAA,UAAA;AAAA,UAErB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,WAAA,EAAa,IAAA;AAAA,cAEpC,8BAAC,UAAA,CAAA,CAAS;AAAA,YAAA;AAAA,UAAA;AAAA,UAIZ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,OAAM;AAAA,cACN,KAAK,MAAM,aAAa;AAAA,cACxB,OAAO,MAAM;AAAA,cACb,QAAQ;AAAA,cACR,eAAe,EAAE,MAAM,EAAE,WAAW,OAAO,EAAE,WAAA;AAAA,YAAW;AAAA,UAAA;AAAA,UAG1D;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,OAAM;AAAA,cACN,KAAK,MAAM,kBAAkB;AAAA,cAC7B,OAAO,MAAM;AAAA,cACb,QAAQ;AAAA,cACR,eAAe,EAAE,MAAM,EAAE,WAAW,OAAO,EAAE,WAAA;AAAA,YAAW;AAAA,UAAA;AAAA,UAI1D;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAW,GAAGA,SAAO,aAAa,IAChC,iBAAiB,WAAWA,SAAO,YAAY,EACjD;AAAA,kBACA,OAAO,EAAE;AAAA,kBACT,cAAY,EAAE;AAAA,kBACd,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWF,SAAO,oBAAoB,UAAA,KAAC;AAAA,wCAC5C,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,kBAAA,CAAmB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIpE,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,UAAU,iBAAiB;AAAA,oBAC3B,UAAU,MAAM,MAAA,EAAQ,mBAAmB,eAAA,EAAiB,IAAA;AAAA,oBAE5D,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,sBACnC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEF;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,UAAU,iBAAiB;AAAA,oBAC3B,UAAU,MAAM,MAAA,EAAQ,iBAAiB,kBAAA,EAAoB,IAAA;AAAA,oBAE7D,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,qBAAC,QAAA,EAAK,WAAW,GAAGA,SAAO,SAAS,IAAIA,SAAO,WAAW,IAAI,UAAA;AAAA,wBAAA;AAAA,wBAC3D,oBAAC,SAAI,UAAA,IAAA,CAAC;AAAA,sBAAA,GACT;AAAA,sBACC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEF;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,UAAU,iBAAiB;AAAA,oBAC3B,UAAU,MAAM,MAAA,EAAQ,mBAAmB,gBAAA,EAAkB,IAAA;AAAA,oBAE7D,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,qBAAC,QAAA,EAAK,WAAW,GAAGA,SAAO,SAAS,IAAIA,SAAO,WAAW,IAAI,UAAA;AAAA,wBAAA;AAAA,wBAC3D,oBAAC,SAAI,UAAA,IAAA,CAAC;AAAA,sBAAA,GACT;AAAA,sBACC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACF;AAAA,YAAA;AAAA,UAAA;AAAA,8BAGD,SAAA,EAAQ;AAAA,UAGT,oBAAC,eAAA,EAAc,OAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,SAAS,YACzD,UAAA,oBAAC,UAAA,CAAA,CAAS,GACZ;AAAA,UACC,gBACC,qBAAA,UAAA,EACE,UAAA;AAAA,YAAA,oBAAC,eAAA,EAAc,OAAO,EAAE,OAAO,SAAS,iBACtC,UAAA,oBAAC,aAAU,EAAA,CACb;AAAA,YACA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAK;AAAA,gBACL,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,QAAM;AAAA,gBACN,UAAU;AAAA,cAAA;AAAA,YAAA;AAAA,UACZ,EAAA,CACF,IACE;AAAA,UACJ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,iBAAA,EAAmB,IAAA;AAAA,cAE1C,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,SAAS,UAAA,IAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,8BAGnC,SAAA,EAAQ;AAAA,UAGT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,iBAAA,EAAmB,IAAA;AAAA,cAE1C,8BAAC,mBAAA,CAAA,CAAkB;AAAA,YAAA;AAAA,UAAA;AAAA,UAErB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,kBAAA,EAAoB,IAAA;AAAA,cAE3C,8BAAC,iBAAA,CAAA,CAAgB;AAAA,YAAA;AAAA,UAAA;AAAA,UAEnB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ,MAAM;AAAA,cACd,SAAS,MAAM,MAAA,EAAQ,eAAA,EAAiB,IAAA;AAAA,cAExC,8BAAC,gBAAA,CAAA,CAAe;AAAA,YAAA;AAAA,UAAA;AAAA,8BAGjB,SAAA,EAAQ;AAAA,UAGT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAWA,SAAO;AAAA,kBAClB,OAAO,EAAE;AAAA,kBACT,aAAa,CAACE,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWF,SAAO,mBAAoB,YAAE,MAAK;AAAA,wCAClD,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,kBAAA,CAAmB;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIpE,UAAA;AAAA,gBAAA,oBAAC,UAAA,EAAS,UAAU,MAAM,MAAA,EAAQ,kBAAkB,IAAA,GAClD,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,kBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAY,UAAA,OAAM;AAAA,kBACzC,EAAE;AAAA,gBAAA,EAAA,CACL,EAAA,CACF;AAAA,gBACA,oBAAC,UAAA,EAAS,UAAU,MAAM,QAAQ,oBAAoB,IAAA,GACpD,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,kBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,kBACnC,EAAE;AAAA,gBAAA,EAAA,CACL,EAAA,CACF;AAAA,gBACA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,UAAU,MAAM;AAAA,oBAChB,UAAU,MACR,MAAA,EACG,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,KAAA,CAAM,EACrD,IAAA;AAAA,oBAGL,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,sBACnC,EAAE;AAAA,oBAAA,EAAA,CACL;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAED,uDAAmB,IAAI,CAACI,UACvB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,UAAUA,MAAK;AAAA,oBACf,UAAU,MAAMA,MAAK,SAAS,MAAM;AAAA,oBAEpC,UAAA,qBAAC,QAAA,EAAK,WAAWJ,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAY,gBAAK,MAAK;AAAA,sBAC7CI,MAAK;AAAA,oBAAA,EAAA,CACR;AAAA,kBAAA;AAAA,kBAPKA,MAAK;AAAA,gBAAA;AAAA,cASb;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,IAID,aACC;AAAA,MACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWJ,SAAO;AAAA,UAClB,OAAO,EAAE,UAAU,SAAS,MAAM,UAAU,GAAG,KAAK,UAAU,EAAA;AAAA,UAC9D,aAAa,CAACE,OAAMA,GAAE,gBAAA;AAAA,UACtB,eAAe,CAACA,OAAMA,GAAE,eAAA;AAAA,UAExB,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,SAAS,MAAM,SAAS,MAAM,QAAQ,gBAAA,EAAkB,KAAK;AAAA,gBAE7D,8BAAC,kBAAA,CAAA,CAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,YAEpB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,SAAS,MAAM,SAAS,MAAM,QAAQ,eAAA,EAAiB,KAAK;AAAA,gBAE5D,8BAAC,iBAAA,CAAA,CAAgB;AAAA,cAAA;AAAA,YAAA;AAAA,YAEnB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,SAAS,MAAM,SAAS,MAAM,QAAQ,aAAA,EAAe,KAAK;AAAA,gBAE1D,8BAAC,kBAAA,CAAA,CAAiB;AAAA,cAAA;AAAA,YAAA;AAAA,gCAEnB,SAAA,EAAQ;AAAA,YACT;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,UAAU,MAAM;AAAA,gBAChB,SAAS,MAAM,SAAS,MAAM,QAAQ,aAAA,EAAe,KAAK;AAAA,gBAE1D,8BAAC,eAAA,CAAA,CAAc;AAAA,cAAA;AAAA,YAAA;AAAA,YAEjB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,SAAS,MAAM,SAAS,MAAM,QAAQ,YAAA,EAAc,KAAK;AAAA,gBAEzD,8BAAC,cAAA,CAAA,CAAa;AAAA,cAAA;AAAA,YAAA;AAAA,YAEhB;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,OAAO,EAAE;AAAA,gBACT,UAAU,MAAM;AAAA,gBAChB,SAAS,MAAM,SAAS,MAAM,QAAQ,UAAA,EAAY,KAAK;AAAA,gBAEvD,8BAAC,eAAA,CAAA,CAAc;AAAA,cAAA;AAAA,YAAA;AAAA,UACjB;AAAA,QAAA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;ACvvBO,SAAS,YAAY,aAAa,KAAc;AACrD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,YAAU,MAAM;AACd,UAAM,KAAK,OAAO,WAAW,eAAe,aAAa,CAAC,KAAK;AAC/D,UAAM,SAAS,MAAM,YAAY,GAAG,OAAO;AAC3C,WAAA;AACA,OAAG,iBAAiB,UAAU,MAAM;AACpC,WAAO,MAAM,GAAG,oBAAoB,UAAU,MAAM;AAAA,EACtD,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACSO,SAAS,SAAS,EAAE,OAAO,UAAU,aAAa,UAAyB;AAChF,QAAM,IAAI,EAAE,GAAG,kBAAkB,GAAG,OAAA;AACpC,QAAM,WAAW,YAAA;AAEjB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,gBAAgB,OAAoB,IAAI;AAC9C,QAAM,iBAAiB,OAAuB,IAAI;AAGlD,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,UAAM,SAAS,OAAO;AAAA,MACpB;AAAA,IAAA,EACA;AACF,UAAM,YAAY,cAAc,WAAW,eAAe;AAC1D,QAAI,CAAC,UAAW;AAChB,UAAM,KAAK,UAAU,cAAc,YAAY,IAAI,OAAO,QAAQ,CAAC,IAAI;AACvE,QAAI,CAAC,GAAI;AACT,OAAG,eAAe;AAAA,MAChB,OAAO;AAAA,MACP,UAAU,SAAS,SAAS;AAAA,IAAA,CAC7B;AAAA,EACH,GAAG,CAAC,QAAQ,CAAC;AAEb,MAAI,CAAC,MAAM,OAAQ,QAAO;AAE1B,QAAM,WAAW,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAEtD,QAAM,cAAc,CAACE,UAAkB;AACrC,QAAIA,MAAK,OAAQ;AACjB,+CAAcA;AACd,QAAI,wBAAwB,KAAK;AAAA,EACnC;AAEA,QAAMC,QACJ,oBAAC,MAAA,EAAG,WAAW,OAAO,MACnB,UAAA,MAAM,IAAI,CAACD,UACV,oBAAC,MAAA,EACC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAMA,MAAK,SAAS,SAAY,IAAIA,MAAK,EAAE;AAAA,MAC3C,WAAW,GAAG,OAAO,IAAI,IACvBA,MAAK,OAAO,WAAW,OAAO,SAAS,EACzC,IAAIA,MAAK,SAAS,OAAO,SAAS,EAAE;AAAA,MACpC,OAAO,EAAE,aAAa,IAAIA,MAAK,QAAQ,YAAY,KAAK,EAAE,KAAA;AAAA,MAC1D,gBAAcA,MAAK,OAAO,WAAW,SAAS;AAAA,MAC9C,iBAAeA,MAAK,SAAS,SAAS;AAAA,MACtC,SAAS,CAACF,OAAM;AACd,QAAAA,GAAE,eAAA;AACF,oBAAYE,KAAI;AAAA,MAClB;AAAA,MAEA,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAW,OAAO,UAAW,gBAAK,MAAK;AAAA,QAC5CA,MAAK,SACJ,oBAAC,UAAA,EAAS,WAAW,OAAO,UAAU,eAAW,KAAA,CAAC,IAChD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,EACN,GAlBOA,MAAK,EAmBd,CACD,GACH;AAIF,MAAI,UAAU;AACZ,gCACG,OAAA,EAAI,WAAW,OAAO,QAAQ,cAAY,EAAE,OAC3C,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,OAAO;AAAA,UAClB,iBAAe;AAAA,UACf,SAAS,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;AAAA,UAEtC,UAAA;AAAA,YAAA,oBAAC,UAAA,EAAS,WAAW,OAAO,eAAe,eAAW,MAAC;AAAA,YACvD,oBAAC,QAAA,EAAM,UAAA,EAAE,MAAA,CAAM;AAAA,YACf;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW,GAAG,OAAO,OAAO,IAC1B,aAAa,OAAO,YAAY,EAClC;AAAA,gBACA,eAAW;AAAA,gBAEX,UAAA,oBAAC,iBAAA,EAAgB,MAAM,GAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAC7B;AAAA,QAAA;AAAA,MAAA;AAAA,MAEF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,WAAW,GAAG,OAAO,WAAW,IAC9B,aAAa,OAAO,kBAAkB,EACxC;AAAA,UAEC,UAAAC;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GACF;AAAA,EAEJ;AAGA,MAAI,WAAW;AACb,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW,OAAO;AAAA,QAClB,cAAY,EAAE;AAAA,QACd,OAAO,EAAE;AAAA,QACT,SAAS,MAAM,aAAa,KAAK;AAAA,QAEjC,8BAAC,mBAAA,CAAA,CAAkB;AAAA,MAAA;AAAA,IAAA;AAAA,EAGzB;AAEA,SACE,qBAAC,SAAI,WAAW,OAAO,SAAS,cAAY,EAAE,OAAO,KAAK,eACxD,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAW,OAAO,QACrB,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAW,OAAO,aAAc,YAAE,OAAM;AAAA,MAC9C;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAW,OAAO;AAAA,UAClB,cAAY,EAAE;AAAA,UACd,OAAO,EAAE;AAAA,UACT,SAAS,MAAM,aAAa,IAAI;AAAA,UACjC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,GACF;AAAA,IACCA;AAAA,EAAA,GACH;AAEJ;ACvJO,SAAS,eAAe,QAAgB,UAAwB;AACrE,SAAO,MAAA,EAAQ,MAAA,EAAQ,cAAc,UAAU,EAAE,aAAa,YAAY,EAAE,IAAA;AAC9E;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/markdownFileDrop.ts","../src/markdownPaste.ts","../src/icons/index.tsx","../src/labels.ts","../src/components/CodeBlockView.tsx","../src/components/MarkdownWysiwygEditor.tsx","../src/components/MarkdownPreview.tsx","../src/insertMarkdown.ts","../src/components/ColorPalette.tsx","../src/components/EditorToolbar.tsx","../src/hooks/useIsMobile.ts","../src/components/TocPanel.tsx","../src/toc/scrollToTocHeading.ts"],"sourcesContent":["// 副作用:增强 Editor.markdown(MarkdownManager)的类型。\nimport '@tiptap/markdown';\nimport { Extension, type Editor } from '@tiptap/core';\nimport { FileHandlePlugin } from '@tiptap/extension-file-handler';\nimport { PluginKey } from '@tiptap/pm/state';\n\n/** .md / .markdown 扩展名(不区分大小写)。 */\nconst MD_FILE_RE = /\\.(md|markdown)$/i;\n\n/**\n * .md 的 MIME 类型在各平台不稳定(text/markdown / text/x-markdown / 空串),\n * 而 FileHandlePlugin 的 allowedMimeTypes 是严格 `includes(file.type)` 匹配\n * (源码确认,不支持扩展名)。故列表包含空串兜住「系统未注册 MIME」的 .md,\n * 真正的判定在回调里按文件名做。副作用:拖入其它空 MIME 文件会被吞成 no-op\n * ——好过浏览器默认导航打开该文件。\n */\nconst MD_MIME_TYPES = ['text/markdown', 'text/x-markdown', ''];\n\n/** 读 .md 文件文本 → markdown.parse → 插入(drop 时插到落点,paste 时插到光标)。 */\nasync function insertMarkdownFiles(\n editor: Editor,\n files: File[],\n pos?: number,\n): Promise<void> {\n const mdFiles = files.filter((f) => MD_FILE_RE.test(f.name));\n if (mdFiles.length === 0) return;\n // markdown manager 仅在注册了 @tiptap/markdown 扩展后存在\n const markdown = editor.markdown;\n if (!markdown) return;\n const texts = await Promise.all(mdFiles.map((f) => f.text()));\n const json = markdown.parse(texts.join('\\n\\n'));\n if (pos != null) {\n editor.chain().focus().insertContentAt(pos, json).run();\n } else {\n editor.chain().focus().insertContent(json).run();\n }\n}\n\n/**\n * 把 .md / .markdown 文件拖拽或粘贴进编辑器,解析后插入内容。\n * 复用官方 @tiptap/extension-file-handler 的底层 FileHandlePlugin,但注册在\n * 自有 PluginKey 下——宿主仍可通过 extraExtensions 注入自己的 FileHandler\n * (如图片上传)而不撞 key。\n */\nexport const MarkdownFileDrop = Extension.create({\n name: 'markdownFileDrop',\n\n addProseMirrorPlugins() {\n const { editor } = this;\n return [\n FileHandlePlugin({\n key: new PluginKey('markdownFileDrop'),\n editor,\n allowedMimeTypes: MD_MIME_TYPES,\n onDrop: (ed, files, pos) => {\n insertMarkdownFiles(ed, files, pos).catch((err) => {\n console.error('markdown file drop failed:', err);\n });\n },\n onPaste: (ed, files) => {\n insertMarkdownFiles(ed, files).catch((err) => {\n console.error('markdown file paste failed:', err);\n });\n },\n }),\n ];\n },\n});\n","// 副作用:增强 Editor.markdown(MarkdownManager)的类型。\nimport '@tiptap/markdown';\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\n\n/**\n * 启发式判断一段纯文本是否「像 markdown」。\n * 只要命中任一块级/行内特征即认为是——宁可偶尔把带星号的普通文本转掉,\n * 也不漏掉真 markdown(用户可用 Shift+粘贴逃生)。\n */\nexport function looksLikeMarkdown(text: string): boolean {\n return (\n /^#{1,6}\\s/m.test(text) || // 标题\n /\\*\\*[^*\\n]+\\*\\*/.test(text) || // 加粗\n /(^|[^!])\\[[^\\]\\n]+\\]\\([^)\\n]+\\)/.test(text) || // 链接\n /!\\[[^\\]\\n]*\\]\\([^)\\n]+\\)/.test(text) || // 图片\n /^[-*+]\\s+\\S/m.test(text) || // 无序列表\n /^\\d+\\.\\s+\\S/m.test(text) || // 有序列表\n /^>\\s/m.test(text) || // 引用\n /^```/m.test(text) || // 代码围栏\n /^\\|.+\\|\\s*$/m.test(text) || // 表格行\n /^(-{3,}|\\*{3,})\\s*$/m.test(text) // 分割线\n );\n}\n\n/**\n * 粘贴 markdown 纯文本自动转富文本(官方 @tiptap/markdown 不内置此能力,\n * 实现方式取自官方文档 \"Paste Markdown Detection\" 配方并调整边界)。\n *\n * 判定只看 text/plain 的内容,不看剪贴板是否带 text/html——很多来源\n * (Xcode/VS Code 等编辑器经 RTF/语法高亮 HTML)复制 markdown 源码时会\n * 附带一份仅是\"字面文本+样式\"的 HTML,按 HTML 标签判定来源不可枚举。\n * 而真富文本(Word/网页文章)的 text/plain 降级不含 markdown 符号,\n * 启发式天然不命中,仍走默认富文本粘贴。\n *\n * 放行(不转换)的边界:\n * - Shift+粘贴(粘贴为纯文本)→ 保留逃生通道\n * - 光标在代码块内 → markdown 源码原样贴入\n * - looksLikeMarkdown 未命中 → 默认粘贴\n */\nexport const MarkdownPaste = Extension.create({\n name: 'markdownPaste',\n\n addProseMirrorPlugins() {\n const { editor } = this;\n return [\n new Plugin({\n key: new PluginKey('markdownPaste'),\n props: {\n handlePaste(view, event) {\n const clipboard = event.clipboardData;\n if (!clipboard) return false;\n const text = clipboard.getData('text/plain');\n if (!text) return false;\n // Shift+粘贴 = 用户显式要纯文本(shiftKey 是 prosemirror-view\n // 内部状态,无公开 API,容错访问;拿不到则照常转换)\n const input = (view as unknown as { input?: { shiftKey?: boolean } })\n .input;\n if (input?.shiftKey) return false;\n // 代码块内粘贴 markdown 源码是常见操作,不转换\n if (view.state.selection.$from.parent.type.spec.code) return false;\n if (!looksLikeMarkdown(text)) return false;\n // markdown manager 仅在注册了 @tiptap/markdown 扩展后存在\n const markdown = editor.markdown;\n if (!markdown) return false;\n try {\n const json = markdown.parse(text);\n editor.commands.insertContent(json);\n return true;\n } catch (err) {\n console.error('markdown paste parse failed:', err);\n return false; // 解析失败回退默认纯文本粘贴\n }\n },\n },\n }),\n ];\n },\n});\n","import type { SVGProps } from 'react';\n\n/**\n * 内联 SVG 图标集(0 运行时依赖)。stroke 走 currentColor,尺寸默认 1em 跟随字号,\n * 故颜色/大小随文本与主题自动变化。图形取自 Lucide(MIT)风格。\n */\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n size?: number | string;\n}\n\nfunction Svg({ size = '1em', children, ...rest }: IconProps & { children: React.ReactNode }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n {...rest}\n >\n {children}\n </svg>\n );\n}\n\nexport const BoldIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\n </Svg>\n);\n\nexport const ItalicIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"19\" x2=\"10\" y1=\"4\" y2=\"4\" />\n <line x1=\"14\" x2=\"5\" y1=\"20\" y2=\"20\" />\n <line x1=\"15\" x2=\"9\" y1=\"4\" y2=\"20\" />\n </Svg>\n);\n\nexport const UnderlineIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M6 4v6a6 6 0 0 0 12 0V4\" />\n <line x1=\"4\" x2=\"20\" y1=\"20\" y2=\"20\" />\n </Svg>\n);\n\nexport const StrikethroughIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M16 4H9a3 3 0 0 0-2.83 4\" />\n <path d=\"M14 12a4 4 0 0 1 0 8H6\" />\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n </Svg>\n);\n\nexport const CodeIcon = (p: IconProps) => (\n <Svg {...p}>\n <polyline points=\"16 18 22 12 16 6\" />\n <polyline points=\"8 6 2 12 8 18\" />\n </Svg>\n);\n\nexport const LinkIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\" />\n <path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\" />\n </Svg>\n);\n\nexport const ImageIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\" />\n <circle cx=\"9\" cy=\"9\" r=\"2\" />\n <path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\" />\n </Svg>\n);\n\nexport const ListUnorderedIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"8\" x2=\"21\" y1=\"6\" y2=\"6\" />\n <line x1=\"8\" x2=\"21\" y1=\"12\" y2=\"12\" />\n <line x1=\"8\" x2=\"21\" y1=\"18\" y2=\"18\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"12\" y2=\"12\" />\n <line x1=\"3\" x2=\"3.01\" y1=\"18\" y2=\"18\" />\n </Svg>\n);\n\nexport const ListOrderedIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"10\" x2=\"21\" y1=\"6\" y2=\"6\" />\n <line x1=\"10\" x2=\"21\" y1=\"12\" y2=\"12\" />\n <line x1=\"10\" x2=\"21\" y1=\"18\" y2=\"18\" />\n <path d=\"M4 6h1v4\" />\n <path d=\"M4 10h2\" />\n <path d=\"M6 18H4c0-1 2-2 2-3s-1-1.5-2-1\" />\n </Svg>\n);\n\nexport const ListChecksIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m3 17 2 2 4-4\" />\n <path d=\"m3 7 2 2 4-4\" />\n <path d=\"M13 6h8\" />\n <path d=\"M13 12h8\" />\n <path d=\"M13 18h8\" />\n </Svg>\n);\n\nexport const UndoIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M9 14 4 9l5-5\" />\n <path d=\"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5 5.5 5.5 0 0 1-5.5 5.5H11\" />\n </Svg>\n);\n\nexport const RedoIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m15 14 5-5-5-5\" />\n <path d=\"M20 9H9.5A5.5 5.5 0 0 0 4 14.5 5.5 5.5 0 0 0 9.5 20H13\" />\n </Svg>\n);\n\nexport const ChevronDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m6 9 6 6 6-6\" />\n </Svg>\n);\n\nexport const CheckIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Svg>\n);\n\nexport const TrashIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n <line x1=\"10\" x2=\"10\" y1=\"11\" y2=\"17\" />\n <line x1=\"14\" x2=\"14\" y1=\"11\" y2=\"17\" />\n </Svg>\n);\n\nexport const LockIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\n </Svg>\n);\n\nexport const MenuIcon = (p: IconProps) => (\n <Svg {...p}>\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\n </Svg>\n);\n\n/* ── 表格行列操作图标(自绘:表格轮廓 + 目标边高亮 + 加号/叉号)── */\n\nexport const ColumnBeforeIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"10\" y=\"4\" width=\"11\" height=\"16\" rx=\"1\" />\n <path d=\"M14 4v16\" />\n <path d=\"M5 9v6\" />\n <path d=\"M2 12h6\" />\n </Svg>\n);\n\nexport const ColumnAfterIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"4\" width=\"11\" height=\"16\" rx=\"1\" />\n <path d=\"M10 4v16\" />\n <path d=\"M19 9v6\" />\n <path d=\"M16 12h6\" />\n </Svg>\n);\n\nexport const ColumnDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"1\" />\n <path d=\"M12 4v16\" />\n <path d=\"m8 9 8 6\" />\n <path d=\"m16 9-8 6\" />\n </Svg>\n);\n\nexport const RowBeforeIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"10\" width=\"16\" height=\"11\" rx=\"1\" />\n <path d=\"M4 14h16\" />\n <path d=\"M9 5h6\" />\n <path d=\"M12 2v6\" />\n </Svg>\n);\n\nexport const RowAfterIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"3\" width=\"16\" height=\"11\" rx=\"1\" />\n <path d=\"M4 10h16\" />\n <path d=\"M9 19h6\" />\n <path d=\"M12 16v6\" />\n </Svg>\n);\n\nexport const RowDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"1\" />\n <path d=\"M4 12h16\" />\n <path d=\"m9 8 6 8\" />\n <path d=\"m15 8-6 8\" />\n </Svg>\n);\n","/**\n * UI 文案(i18n 注入点)。各组件接收 `labels?: Partial<...>`,与内置英文默认合并。\n * 消费方(如中文项目)可传入本地化文案。\n */\n\nexport interface ToolbarLabels {\n undo: string;\n redo: string;\n style: string;\n normalText: string;\n /** 传入层级,返回如 \"Heading 2\"。 */\n headingLabel: (level: number) => string;\n fontSize: string;\n fontSizeDefault: string;\n bold: string;\n italic: string;\n underline: string;\n strike: string;\n code: string;\n textColor: string;\n highlight: string;\n colorNone: string;\n colorTheme: string;\n scriptMenu: string;\n scriptNormal: string;\n superscript: string;\n subscript: string;\n link: string;\n linkPrompt: string;\n image: string;\n imageUploadFailed: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n more: string;\n codeBlock: string;\n hr: string;\n importMarkdown: string;\n tableInsert: string;\n tableAddColumnBefore: string;\n tableAddColumnAfter: string;\n tableDeleteColumn: string;\n tableAddRowBefore: string;\n tableAddRowAfter: string;\n tableDeleteRow: string;\n}\n\nexport const defaultToolbarLabels: ToolbarLabels = {\n undo: 'Undo',\n redo: 'Redo',\n style: 'Style',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n fontSize: 'Font size',\n fontSizeDefault: 'Default',\n bold: 'Bold',\n italic: 'Italic',\n underline: 'Underline',\n strike: 'Strikethrough',\n code: 'Inline code',\n textColor: 'Text color',\n highlight: 'Highlight',\n colorNone: 'None',\n colorTheme: 'THEME',\n scriptMenu: 'Superscript / Subscript',\n scriptNormal: 'Normal',\n superscript: 'Superscript',\n subscript: 'Subscript',\n link: 'Link',\n linkPrompt: 'Enter URL',\n image: 'Image',\n imageUploadFailed: 'Image upload failed',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n more: 'More',\n codeBlock: 'Code block',\n hr: 'Divider',\n importMarkdown: 'Import Markdown',\n tableInsert: 'Insert table',\n tableAddColumnBefore: 'Add column before',\n tableAddColumnAfter: 'Add column after',\n tableDeleteColumn: 'Delete column',\n tableAddRowBefore: 'Add row before',\n tableAddRowAfter: 'Add row after',\n tableDeleteRow: 'Delete row',\n};\n\nexport interface ColorPaletteLabels {\n none: string;\n theme: string;\n}\n\nexport const defaultColorPaletteLabels: ColorPaletteLabels = {\n none: 'None',\n theme: 'THEME',\n};\n\nexport interface TocLabels {\n title: string;\n expand: string;\n collapse: string;\n}\n\nexport const defaultTocLabels: TocLabels = {\n title: 'Contents',\n expand: 'Expand',\n collapse: 'Collapse',\n};\n\nexport interface CodeBlockLabels {\n autoDetect: string;\n delete: string;\n}\n\nexport const defaultCodeBlockLabels: CodeBlockLabels = {\n autoDetect: 'Auto-detect',\n delete: 'Delete code block',\n};\n","'use client';\n\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport {\n NodeViewContent,\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport { CheckIcon, ChevronDownIcon, TrashIcon } from '../icons';\nimport { defaultCodeBlockLabels, type CodeBlockLabels } from '../labels';\nimport styles from '../styles/codeBlock.module.css';\n\n// 语言选择可选项。空 value = Auto-detect(交给 lowlight 自动识别)\nconst LANGUAGES: { value: string; label: string }[] = [\n { value: '', label: 'Auto-detect' },\n { value: 'javascript', label: 'JavaScript' },\n { value: 'typescript', label: 'TypeScript' },\n { value: 'python', label: 'Python' },\n { value: 'java', label: 'Java' },\n { value: 'go', label: 'Go' },\n { value: 'rust', label: 'Rust' },\n { value: 'c', label: 'C' },\n { value: 'cpp', label: 'C++' },\n { value: 'csharp', label: 'C#' },\n { value: 'sql', label: 'SQL' },\n { value: 'json', label: 'JSON' },\n { value: 'yaml', label: 'YAML' },\n { value: 'bash', label: 'Bash' },\n { value: 'shell', label: 'Shell' },\n { value: 'html', label: 'HTML' },\n { value: 'css', label: 'CSS' },\n { value: 'markdown', label: 'Markdown' },\n];\n\n/**\n * 代码块自定义 NodeView:右上角语言选择器(Radix DropdownMenu,支持方向键导航)+ 删除。\n * 文案(Auto-detect / 删除标题)从扩展 options.codeBlockLabels 读取,缺省用英文默认。\n */\nexport function CodeBlockView({\n node,\n updateAttributes,\n deleteNode,\n extension,\n}: NodeViewProps) {\n const labels: CodeBlockLabels = {\n ...defaultCodeBlockLabels,\n ...((extension?.options as { codeBlockLabels?: Partial<CodeBlockLabels> })\n ?.codeBlockLabels ?? {}),\n };\n const language = (node.attrs.language as string) || '';\n const current = LANGUAGES.find((l) => l.value === language);\n const currentLabel = current\n ? current.value === ''\n ? labels.autoDetect\n : current.label\n : labels.autoDetect;\n\n return (\n <NodeViewWrapper className={styles.wrapper}>\n <div className={styles.header} contentEditable={false}>\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n type=\"button\"\n className={styles.langTrigger}\n aria-label=\"Code language\"\n >\n <span>{currentLabel}</span>\n <ChevronDownIcon size={14} className={styles.langChevron} />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className={styles.langMenu}\n sideOffset={4}\n align=\"end\"\n >\n {LANGUAGES.map((l) => {\n const optionLabel =\n l.value === '' ? labels.autoDetect : l.label;\n const selected = l.value === language;\n return (\n <DropdownMenu.Item\n key={l.value}\n className={`${styles.langItem}${selected ? ` ${styles.langItemSelected}` : ''}`}\n onSelect={() => updateAttributes({ language: l.value })}\n >\n <span className={styles.langItemCheck}>\n {selected ? <CheckIcon size={14} /> : null}\n </span>\n {optionLabel}\n </DropdownMenu.Item>\n );\n })}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n <button\n type=\"button\"\n className={styles.deleteBtn}\n title={labels.delete}\n aria-label={labels.delete}\n onClick={() => deleteNode()}\n >\n <TrashIcon />\n </button>\n </div>\n <pre className={styles.pre}>\n {/* code 标签是代码块标准内容容器;v3 类型未含 'code',运行时有效,故断言 */}\n <NodeViewContent as={'code' as 'div'} />\n </pre>\n </NodeViewWrapper>\n );\n}\n","'use client';\n\nimport CodeBlockLowlight, {\n type CodeBlockLowlightOptions,\n} from '@tiptap/extension-code-block-lowlight';\nimport Image from '@tiptap/extension-image';\nimport { TableOfContents } from '@tiptap/extension-table-of-contents';\nimport { Markdown } from '@tiptap/markdown';\nimport {\n EditorContent,\n ReactNodeViewRenderer,\n useEditor,\n type AnyExtension,\n type Editor,\n} from '@tiptap/react';\nimport { forwardRef, useEffect, useImperativeHandle } from 'react';\nimport { baseExtensions, lowlight } from '../extensions';\nimport type { CodeBlockLabels } from '../labels';\nimport { MarkdownFileDrop } from '../markdownFileDrop';\nimport { MarkdownPaste } from '../markdownPaste';\nimport styles from '../styles/content.module.css';\nimport type { TocItem } from '../toc/extractToc';\nimport { makeTocGetId } from '../toc/tocSlug';\nimport { CodeBlockView } from './CodeBlockView';\n\n// 带语言选择器的代码块(自定义 React NodeView)。base 不含代码块,此增强版由编辑器注入。\n// addOptions 追加 codeBlockLabels,供 CodeBlockView 读取以本地化文案。\ntype CodeBlockOptions = CodeBlockLowlightOptions & {\n codeBlockLabels?: Partial<CodeBlockLabels>;\n};\n\nconst CodeBlock = CodeBlockLowlight.extend<CodeBlockOptions>({\n addOptions() {\n return {\n ...this.parent?.(),\n codeBlockLabels: undefined,\n } as CodeBlockOptions;\n },\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n addKeyboardShortcuts() {\n return {\n Backspace: () => {\n const { state } = this.editor;\n const { selection } = state;\n const { empty, $anchor } = selection;\n\n // 1) 光标在「非空代码块」内容最前面:拦截,防止拆块漏文字(空块放行可删)\n if (\n empty &&\n $anchor.parent.type.name === this.name &&\n $anchor.parentOffset === 0 &&\n $anchor.parent.content.size > 0\n ) {\n return true;\n }\n\n // 2) 光标在「代码块后方块」的开头:先选中整个代码块(二次确认),不直接删\n if (empty && $anchor.parentOffset === 0) {\n const before = $anchor.before($anchor.depth);\n const prevNode = state.doc.resolve(before).nodeBefore;\n if (prevNode?.type.name === this.name) {\n const codeBlockPos = before - prevNode.nodeSize;\n this.editor.chain().setNodeSelection(codeBlockPos).run();\n return true;\n }\n }\n\n return false;\n },\n };\n },\n});\n\n// 块级图片:Backspace 二次确认删除(与代码块一致)。\nconst ImageWithConfirmDelete = Image.extend({\n addKeyboardShortcuts() {\n return {\n Backspace: () => {\n const { state } = this.editor;\n const { selection } = state;\n const { empty, $anchor } = selection;\n if (empty) {\n const nodeBefore = $anchor.nodeBefore;\n if (nodeBefore?.type.name === this.name) {\n const imagePos = $anchor.pos - nodeBefore.nodeSize;\n this.editor.chain().setNodeSelection(imagePos).run();\n return true;\n }\n }\n return false;\n },\n };\n },\n});\n\nexport interface MarkdownWysiwygEditorHandle {\n /** 取当前正文的 markdown 字符串。 */\n getMarkdown: () => string;\n /** 取当前正文的 HTML 字符串。 */\n getHTML: () => string;\n /** 取当前正文的 Tiptap JSON。 */\n getJSON: () => Record<string, unknown>;\n /** 底层 Tiptap Editor 实例(可能为 null,未就绪时)。 */\n getEditor: () => Editor | null;\n}\n\nexport interface MarkdownWysiwygEditorProps {\n /** 初始 markdown 内容。 */\n initialMarkdown?: string;\n placeholder?: string;\n /** editor 实例就绪 / 销毁时回调,供外部工具栏使用。 */\n onEditorReady?: (editor: Editor | null) => void;\n /** 目录变化回调(正文标题增删改时),供侧边目录实时展示。 */\n onTocChange?: (items: TocItem[]) => void;\n /**\n * 粘贴纯文本时启发式检测 markdown 并自动转富文本(Shift+粘贴保持纯文本)。\n * 默认 true。仅初始化时生效。\n */\n markdownPaste?: boolean;\n /**\n * 支持把 .md / .markdown 文件拖拽或粘贴进编辑器,解析后插入到落点/光标处。\n * 默认 true。仅初始化时生效。\n */\n markdownFileDrop?: boolean;\n /** 追加的 Tiptap 扩展(在内置扩展之后注册)。 */\n extraExtensions?: AnyExtension[];\n /** 代码块 NodeView 的本地化文案。 */\n codeBlockLabels?: Partial<CodeBlockLabels>;\n /** 附加到滚动容器的 class。 */\n className?: string;\n}\n\n/**\n * 所见即所得 Markdown 编辑器(基于 Tiptap v3 + 官方 @tiptap/markdown)。\n * 内容进出均为 markdown 字符串。工具栏由外部渲染——通过 onEditorReady 拿到 editor 实例。\n */\nexport const MarkdownWysiwygEditor = forwardRef<\n MarkdownWysiwygEditorHandle,\n MarkdownWysiwygEditorProps\n>(function MarkdownWysiwygEditor(\n {\n initialMarkdown = '',\n placeholder,\n onEditorReady,\n onTocChange,\n markdownPaste = true,\n markdownFileDrop = true,\n extraExtensions,\n codeBlockLabels,\n className,\n },\n ref,\n) {\n const editor = useEditor({\n extensions: [\n ...baseExtensions,\n CodeBlock.configure({ lowlight, codeBlockLabels }),\n ImageWithConfirmDelete.configure({ inline: false }),\n Markdown,\n TableOfContents.configure({\n getId: makeTocGetId(),\n onUpdate: (anchors) => {\n onTocChange?.(\n anchors\n .filter((a) => a.level <= 6)\n .map((a) => ({ id: a.id, level: a.level, text: a.textContent })),\n );\n },\n }),\n ...(markdownPaste ? [MarkdownPaste] : []),\n ...(markdownFileDrop ? [MarkdownFileDrop] : []),\n ...(extraExtensions ?? []),\n ],\n content: initialMarkdown,\n contentType: 'markdown',\n // Next.js SSR:服务端不立即渲染,避免 hydration 不一致\n immediatelyRender: false,\n editorProps: {\n attributes: {\n class: styles.editorContent,\n 'data-placeholder': placeholder ?? '',\n },\n },\n });\n\n useEffect(() => {\n onEditorReady?.(editor);\n return () => onEditorReady?.(null);\n }, [editor, onEditorReady]);\n\n useImperativeHandle(\n ref,\n () => ({\n getMarkdown: () => editor?.getMarkdown?.() ?? '',\n getHTML: () => editor?.getHTML?.() ?? '',\n getJSON: () => (editor?.getJSON?.() as Record<string, unknown>) ?? {},\n getEditor: () => editor ?? null,\n }),\n [editor],\n );\n\n return (\n <EditorContent\n editor={editor}\n className={\n className ? `${styles.editorScroll} ${className}` : styles.editorScroll\n }\n />\n );\n});\n","'use client';\n\nimport { Markdown } from '@tiptap/markdown';\nimport { EditorContent, useEditor } from '@tiptap/react';\nimport { useEffect } from 'react';\nimport { baseExtensions, pureCodeBlock, pureImage } from '../extensions';\nimport styles from '../styles/content.module.css';\n\nexport interface MarkdownPreviewProps {\n /** 要预览的 markdown 字符串。 */\n markdown: string;\n className?: string;\n}\n\n/**\n * 轻量只读 markdown 预览(Tiptap + 官方 @tiptap/markdown,editable:false)。\n * 与 MarkdownWysiwygEditor 共用同一套 base 扩展与正文样式类,渲染同源——\n * 预览所见即编辑/插入后所得。用纯版 CodeBlock/Image(无 React 视图 / 删除快捷键)。\n *\n * 这是「客户端只读预览」;若需 SEO / 无 JS 静态渲染,请改用 server 入口的\n * renderReportHtml + ReportContent。\n */\nexport function MarkdownPreview({ markdown, className }: MarkdownPreviewProps) {\n const editor = useEditor({\n extensions: [...baseExtensions, pureCodeBlock, pureImage, Markdown],\n content: markdown,\n contentType: 'markdown',\n editable: false,\n immediatelyRender: false,\n // 关键:内部 ProseMirror DOM 挂与编辑器一字不差的 editorContent class,\n // 所有内容样式都作用在该选择器下,预览才能与编辑/插入后逐像素一致。\n editorProps: {\n attributes: { class: styles.editorContent },\n },\n });\n\n useEffect(() => {\n if (!editor) return;\n editor.commands.setContent(markdown, { contentType: 'markdown' });\n }, [editor, markdown]);\n\n return (\n <EditorContent\n editor={editor}\n className={className ?? styles.editorScroll}\n />\n );\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\n\n/** 在光标处插入 markdown 片段(封装 contentType: 'markdown')。 */\nexport function insertMarkdown(editor: Editor, markdown: string): void {\n editor.chain().focus().insertContent(markdown, { contentType: 'markdown' }).run();\n}\n","'use client';\n\nimport { defaultColorPaletteLabels, type ColorPaletteLabels } from '../labels';\nimport styles from '../styles/colorPalette.module.css';\n\n/**\n * 色板矩阵:10 个色相 × 6 个明度。\n * 第 1 行为纯色(最饱和),下方 5 行为同色相的明→暗变体。\n */\nconst PALETTE: string[][] = [\n ['#8b0000', '#ff0000', '#ff9100', '#ffeb00', '#00e000', '#00e5ff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff'],\n ['#dba0a0', '#e8b4c0', '#f5d9b8', '#f7f0c0', '#cfe8c4', '#bcd9d4', '#c4d4ec', '#cdd4e8', '#d6c4e0', '#e8c4dc'],\n ['#d28a8a', '#dd8c9c', '#eec49a', '#f0e29c', '#a9d4a0', '#94c0bc', '#a0bce4', '#a4b0d8', '#bca0d0', '#d49cc0'],\n ['#cc4444', '#d4506c', '#e89a5c', '#e8d05c', '#7cc06c', '#5ca09c', '#5c90e0', '#6478c8', '#9460c0', '#c45c98'],\n ['#a02020', '#b01030', '#c87410', '#c8a810', '#449030', '#2c706c', '#3060c0', '#1850a0', '#6428a0', '#a02868'],\n ['#5c1010', '#700818', '#7c4808', '#7c6808', '#205818', '#10403c', '#183c78', '#0c3060', '#3c1460', '#601838'],\n];\n\n// THEME 品牌色\nconst THEME_COLORS = ['#ff6719', '#ff5500'];\n\nexport interface ColorPaletteProps {\n /** 当前已应用的颜色(用于打勾),无则不选中。 */\n value?: string;\n /** 点击某色块。null 表示「None」(清除)。 */\n onPick: (color: string | null) => void;\n labels?: Partial<ColorPaletteLabels>;\n}\n\n/** 颜色面板:None 清除行 + 色板网格 + THEME 品牌色。 */\nexport function ColorPalette({ value, onPick, labels }: ColorPaletteProps) {\n const t = { ...defaultColorPaletteLabels, ...labels };\n const current = value?.toLowerCase();\n\n return (\n <div className={styles.palette}>\n <button\n type=\"button\"\n className={styles.noneRow}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(null)}\n >\n <span className={styles.noneIcon} aria-hidden />\n <span className={styles.noneLabel}>{t.none}</span>\n </button>\n\n <div className={styles.grid}>\n {PALETTE.flat().map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`${styles.swatch} ${\n current === c.toLowerCase() ? styles.swatchActive : ''\n }`}\n style={{ background: c }}\n title={c}\n aria-label={c}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(c)}\n />\n ))}\n </div>\n\n <div className={styles.themeLabel}>{t.theme}</div>\n <div className={styles.themeRow}>\n {THEME_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n className={`${styles.swatch} ${\n current === c.toLowerCase() ? styles.swatchActive : ''\n }`}\n style={{ background: c }}\n title={c}\n aria-label={c}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(c)}\n />\n ))}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport * as Popover from '@radix-ui/react-popover';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n BoldIcon,\n ChevronDownIcon,\n CodeIcon,\n ColumnAfterIcon,\n ColumnBeforeIcon,\n ColumnDeleteIcon,\n ImageIcon,\n ItalicIcon,\n LinkIcon,\n ListChecksIcon,\n ListOrderedIcon,\n ListUnorderedIcon,\n RedoIcon,\n RowAfterIcon,\n RowBeforeIcon,\n RowDeleteIcon,\n StrikethroughIcon,\n UnderlineIcon,\n UndoIcon,\n} from '../icons';\nimport { defaultToolbarLabels, type ToolbarLabels } from '../labels';\nimport { insertMarkdown } from '../insertMarkdown';\nimport styles from '../styles/toolbar.module.css';\nimport { ColorPalette } from './ColorPalette';\n\n/** More 菜单里注入的自定义项(宿主用它扩展工具栏,如「导入项目报告」)。 */\nexport interface ExtraToolbarItem {\n key: string;\n /** 左侧图标插槽(可选,文字或 SVG 皆可)。 */\n icon?: ReactNode;\n label: string;\n disabled?: boolean;\n /** 点击回调,拿到 editor 实例自行操作(如 insertContent)。 */\n onSelect: (editor: Editor) => void;\n}\n\nexport interface EditorToolbarProps {\n editor: Editor;\n /**\n * 图片上传回调:收到文件,返回可访问的图片 URL。未提供则不显示图片按钮。\n * 抛错会转交 onError。\n */\n onImageUpload?: (file: File) => Promise<string>;\n /** 副作用错误回调(图片上传失败等),供宿主弹自己的提示。 */\n onError?: (err: unknown) => void;\n labels?: Partial<ToolbarLabels>;\n /** 追加到 More 菜单末尾的自定义项。 */\n extraToolbarItems?: ExtraToolbarItem[];\n className?: string;\n}\n\n/** 单个工具栏按钮:激活态高亮,disabled 时灰显。 */\nfunction ToolbarButton({\n title,\n active,\n disabled,\n onClick,\n children,\n}: {\n title: string;\n active?: boolean;\n disabled?: boolean;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n title={title}\n aria-label={title}\n aria-pressed={active}\n disabled={disabled}\n className={`${styles.btn} ${active ? styles.btnActive : ''}`}\n // mousedown + preventDefault 防止点击工具栏时编辑器失焦丢选区\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n >\n {children}\n </button>\n );\n}\n\nfunction Divider() {\n return <span className={styles.divider} aria-hidden />;\n}\n\n// 关闭当前菜单的回调(由 MenuPopover 注入,MenuItem 选中后调用以收起)。\nconst MenuCloseCtx = createContext<() => void>(() => {});\n\n/**\n * 菜单气泡:用 Radix Popover 而非 DropdownMenu——后者会强制抢焦点(menu 语义),\n * 打开即让编辑器 blur、丢选区;Popover 可 onOpenAutoFocus preventDefault 保持编辑器焦点。\n * 菜单项为普通 button(onMouseDown preventDefault 不夺焦),行为与原 antd 一致。\n */\nfunction MenuPopover({\n trigger,\n children,\n}: {\n trigger: ReactNode;\n children: ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n const close = useCallback(() => setOpen(false), []);\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>{trigger}</Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.menu}\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <MenuCloseCtx.Provider value={close}>\n {children}\n </MenuCloseCtx.Provider>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nfunction MenuItem({\n selected,\n disabled,\n onSelect,\n children,\n}: {\n selected?: boolean;\n disabled?: boolean;\n onSelect: () => void;\n children: ReactNode;\n}) {\n const close = useContext(MenuCloseCtx);\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={`${styles.menuItem} ${selected ? styles.menuItemSelected : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n onSelect();\n close();\n }}\n >\n {children}\n </button>\n );\n}\n\n/** 颜色气泡:点色块即应用并关闭。 */\nfunction ColorPopover({\n title,\n glyph,\n bar,\n value,\n onPick,\n paletteLabels,\n}: {\n title: string;\n glyph: string;\n bar: string;\n value?: string;\n onPick: (color: string | null) => void;\n paletteLabels: { none: string; theme: string };\n}) {\n const [open, setOpen] = useState(false);\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n className={styles.btn}\n title={title}\n aria-label={title}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.colorIcon}>\n <span className={styles.colorIconGlyph}>{glyph}</span>\n <span className={styles.colorIconBar} style={{ background: bar }} />\n </span>\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.popoverContent}\n sideOffset={4}\n align=\"start\"\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <ColorPalette\n value={value}\n onPick={(c) => {\n onPick(c);\n setOpen(false);\n }}\n labels={paletteLabels}\n />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nconst HEADING_LEVELS = [1, 2, 3, 4, 5, 6] as const;\nconst FONT_SIZES = ['12px', '14px', '16px', '18px', '20px', '24px', '30px'] as const;\n\n/**\n * 顶部操作栏(antd-free,Radix Popover 菜单 + 内联 SVG 图标)。位置由父级控制,\n * 这里只渲染按钮 + 反映 editor 激活态。不含业务耦合,扩展项经 extraToolbarItems 注入。\n */\nexport function EditorToolbar({\n editor,\n onImageUpload,\n onError,\n labels,\n extraToolbarItems,\n className,\n}: EditorToolbarProps) {\n const t: ToolbarLabels = { ...defaultToolbarLabels, ...labels };\n\n const state = useEditorState({\n editor,\n selector: ({ editor: e }) => ({\n bold: e.isActive('bold'),\n italic: e.isActive('italic'),\n underline: e.isActive('underline'),\n strike: e.isActive('strike'),\n code: e.isActive('code'),\n link: e.isActive('link'),\n taskList: e.isActive('taskList'),\n headingLevel: ([1, 2, 3, 4, 5, 6] as const).find((lv) =>\n e.isActive('heading', { level: lv }),\n ),\n fontSize: (e.getAttributes('textStyle').fontSize as string) || undefined,\n isParagraph: e.isActive('paragraph'),\n bulletList: e.isActive('bulletList'),\n orderedList: e.isActive('orderedList'),\n blockquote: e.isActive('blockquote'),\n textColor: (e.getAttributes('textStyle').color as string) || undefined,\n highlightColor:\n (e.getAttributes('highlight').color as string) || undefined,\n superscript: e.isActive('superscript'),\n subscript: e.isActive('subscript'),\n inTable: e.isActive('table'),\n inTableHeader: e.isActive('tableHeader'),\n canUndo: e.can().undo(),\n canRedo: e.can().redo(),\n }),\n });\n\n // 编辑器是否聚焦:仅正文聚焦时才允许调字号。Popover 菜单开/关已阻止抢焦点,\n // 故打开下拉不会误触 blur。\n const [editorFocused, setEditorFocused] = useState(() => editor.isFocused);\n useEffect(() => {\n const onFocus = () => setEditorFocused(true);\n const onBlur = () => setEditorFocused(false);\n editor.on('focus', onFocus);\n editor.on('blur', onBlur);\n return () => {\n editor.off('focus', onFocus);\n editor.off('blur', onBlur);\n };\n }, [editor]);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n const chain = () => editor.chain().focus();\n\n // ── 表格工具条(右键召唤):右键单元格时在鼠标处弹出,点别处/Esc 隐藏 ──\n const [tableMenu, setTableMenu] = useState<{ x: number; y: number } | null>(\n null,\n );\n const closeTableMenu = useCallback(() => setTableMenu(null), []);\n\n useEffect(() => {\n const dom = editor.view.dom;\n const onContextMenu = (e: MouseEvent) => {\n const coords = editor.view.posAtCoords({\n left: e.clientX,\n top: e.clientY,\n });\n if (!coords) return;\n const $pos = editor.state.doc.resolve(coords.pos);\n let inTable = false;\n for (let d = $pos.depth; d > 0; d--) {\n if ($pos.node(d).type.name === 'table') {\n inTable = true;\n break;\n }\n }\n if (!inTable) return;\n e.preventDefault();\n editor.chain().focus().setTextSelection(coords.pos).run();\n setTableMenu({ x: e.clientX, y: e.clientY });\n };\n dom.addEventListener('contextmenu', onContextMenu);\n return () => dom.removeEventListener('contextmenu', onContextMenu);\n }, [editor]);\n\n useEffect(() => {\n if (!tableMenu) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') closeTableMenu();\n };\n document.addEventListener('mousedown', closeTableMenu);\n document.addEventListener('keydown', onKey, true);\n return () => {\n document.removeEventListener('mousedown', closeTableMenu);\n document.removeEventListener('keydown', onKey, true);\n };\n }, [tableMenu, closeTableMenu]);\n\n const runTable = useCallback(\n (fn: () => void) => {\n fn();\n closeTableMenu();\n },\n [closeTableMenu],\n );\n\n // ── 图片:选图 → onImageUpload → 插入返回的 URL ──\n const handlePickImage = () => fileInputRef.current?.click();\n const handleImageChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file || !onImageUpload) return;\n try {\n const url = await onImageUpload(file);\n if (!url) throw new Error('empty url');\n chain().setImage({ src: url }).run();\n } catch (err) {\n console.error('image upload failed:', err);\n onError?.(err);\n }\n };\n\n // ── 导入 Markdown:选 .md 文件 → 读文本 → 解析插入光标处 ──\n const mdFileInputRef = useRef<HTMLInputElement>(null);\n const handleMdFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file) return;\n try {\n const text = await file.text();\n insertMarkdown(editor, text);\n } catch (err) {\n console.error('markdown import failed:', err);\n onError?.(err);\n }\n };\n\n const applyTextColor = (color: string | null) => {\n if (color) chain().setColor(color).run();\n else chain().unsetColor().run();\n };\n const applyHighlight = (color: string | null) => {\n if (color) chain().setHighlight({ color }).run();\n else chain().unsetHighlight().run();\n };\n\n const toggleLink = () => {\n if (state.link) {\n chain().unsetLink().run();\n return;\n }\n const url = window.prompt(t.linkPrompt);\n if (url) chain().setLink({ href: url }).run();\n };\n\n const setBlockStyle = (level: number) => {\n if (level === 0) chain().setParagraph().run();\n else\n chain()\n .toggleHeading({ level: level as 1 | 2 | 3 | 4 | 5 | 6 })\n .run();\n };\n\n const applyFontSize = (size: string) => {\n if (size) chain().setFontSize(size).run();\n else chain().unsetFontSize().run();\n };\n const canEditFontSize = editorFocused && state.isParagraph;\n\n const scriptActive = state.superscript\n ? 'superscript'\n : state.subscript\n ? 'subscript'\n : 'normal';\n\n return (\n <>\n <div\n className={\n className ? `${styles.toolbar} ${className}` : styles.toolbar\n }\n >\n <div className={styles.inner}>\n {/* 撤销 / 重做 */}\n <ToolbarButton\n title={t.undo}\n disabled={!state.canUndo}\n onClick={() => chain().undo().run()}\n >\n <UndoIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.redo}\n disabled={!state.canRedo}\n onClick={() => chain().redo().run()}\n >\n <RedoIcon />\n </ToolbarButton>\n\n <Divider />\n\n {/* 段落样式下拉(正文 / 标题 1~6) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.style}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>{t.style}</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={(state.headingLevel ?? 0) === 0}\n onSelect={() => setBlockStyle(0)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>¶</span>\n {t.normalText}\n </span>\n </MenuItem>\n {HEADING_LEVELS.map((lv) => (\n <MenuItem\n key={lv}\n selected={state.headingLevel === lv}\n onSelect={() => setBlockStyle(lv)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{`H${lv}`}</span>\n {t.headingLabel(lv)}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n\n {/* 正文字号下拉:仅正文可调 */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.fontSize}\n aria-label={t.fontSize}\n disabled={!canEditFontSize}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>\n {state.fontSize || t.fontSize}\n </span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={!state.fontSize}\n onSelect={() => applyFontSize('')}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>A</span>\n {t.fontSizeDefault}\n </span>\n </MenuItem>\n {FONT_SIZES.map((size) => (\n <MenuItem\n key={size}\n selected={state.fontSize === size}\n onSelect={() => applyFontSize(size)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{parseInt(size, 10)}</span>\n {size}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n\n <Divider />\n\n {/* 文字格式 */}\n <ToolbarButton\n title={t.bold}\n active={state.bold}\n onClick={() => chain().toggleBold().run()}\n >\n <BoldIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.italic}\n active={state.italic}\n onClick={() => chain().toggleItalic().run()}\n >\n <ItalicIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.underline}\n active={state.underline}\n onClick={() => chain().toggleUnderline().run()}\n >\n <UnderlineIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.strike}\n active={state.strike}\n onClick={() => chain().toggleStrike().run()}\n >\n <StrikethroughIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.code}\n active={state.code}\n onClick={() => chain().toggleCode().run()}\n >\n <CodeIcon />\n </ToolbarButton>\n\n {/* 文字颜色 */}\n <ColorPopover\n title={t.textColor}\n glyph=\"T\"\n bar={state.textColor || '#ff3b30'}\n value={state.textColor}\n onPick={applyTextColor}\n paletteLabels={{ none: t.colorNone, theme: t.colorTheme }}\n />\n {/* 文字高亮 */}\n <ColorPopover\n title={t.highlight}\n glyph=\"✎\"\n bar={state.highlightColor || '#ffd83d'}\n value={state.highlightColor}\n onPick={applyHighlight}\n paletteLabels={{ none: t.colorNone, theme: t.colorTheme }}\n />\n\n {/* 上标 / 下标下拉(A▾) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={`${styles.scriptTrigger} ${\n scriptActive !== 'normal' ? styles.btnActive : ''\n }`}\n title={t.scriptMenu}\n aria-label={t.scriptMenu}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.scriptTriggerGlyph}>A</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem\n selected={scriptActive === 'normal'}\n onSelect={() => chain().unsetSuperscript().unsetSubscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>A</span>\n {t.scriptNormal}\n </span>\n </MenuItem>\n <MenuItem\n selected={scriptActive === 'superscript'}\n onSelect={() => chain().unsetSubscript().toggleSuperscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={`${styles.styleIcon} ${styles.scriptGlyph}`}>\n x<sup>2</sup>\n </span>\n {t.superscript}\n </span>\n </MenuItem>\n <MenuItem\n selected={scriptActive === 'subscript'}\n onSelect={() => chain().unsetSuperscript().toggleSubscript().run()}\n >\n <span className={styles.styleItem}>\n <span className={`${styles.styleIcon} ${styles.scriptGlyph}`}>\n x<sub>2</sub>\n </span>\n {t.subscript}\n </span>\n </MenuItem>\n </MenuPopover>\n\n <Divider />\n\n {/* 插入媒体 */}\n <ToolbarButton title={t.link} active={state.link} onClick={toggleLink}>\n <LinkIcon />\n </ToolbarButton>\n {onImageUpload ? (\n <>\n <ToolbarButton title={t.image} onClick={handlePickImage}>\n <ImageIcon />\n </ToolbarButton>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n hidden\n onChange={handleImageChange}\n />\n </>\n ) : null}\n <ToolbarButton\n title={t.blockquote}\n active={state.blockquote}\n onClick={() => chain().toggleBlockquote().run()}\n >\n <span className={styles.txtIcon}>❝</span>\n </ToolbarButton>\n\n <Divider />\n\n {/* 列表 */}\n <ToolbarButton\n title={t.bulletList}\n active={state.bulletList}\n onClick={() => chain().toggleBulletList().run()}\n >\n <ListUnorderedIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.orderedList}\n active={state.orderedList}\n onClick={() => chain().toggleOrderedList().run()}\n >\n <ListOrderedIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.taskList}\n active={state.taskList}\n onClick={() => chain().toggleTaskList().run()}\n >\n <ListChecksIcon />\n </ToolbarButton>\n\n <Divider />\n\n {/* More 下拉(代码块、分割线、表格 + 宿主注入项) */}\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={t.more}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>{t.more}</span>\n <ChevronDownIcon size={12} className={styles.styleTriggerCaret} />\n </button>\n }\n >\n <MenuItem onSelect={() => chain().toggleCodeBlock().run()}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{'{ }'}</span>\n {t.codeBlock}\n </span>\n </MenuItem>\n <MenuItem onSelect={() => chain().setHorizontalRule().run()}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>—</span>\n {t.hr}\n </span>\n </MenuItem>\n <MenuItem\n disabled={state.inTable}\n onSelect={() =>\n chain()\n .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n .run()\n }\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>⊞</span>\n {t.tableInsert}\n </span>\n </MenuItem>\n <MenuItem onSelect={() => mdFileInputRef.current?.click()}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>M↓</span>\n {t.importMarkdown}\n </span>\n </MenuItem>\n {extraToolbarItems?.map((item) => (\n <MenuItem\n key={item.key}\n disabled={item.disabled}\n onSelect={() => item.onSelect(editor)}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>{item.icon}</span>\n {item.label}\n </span>\n </MenuItem>\n ))}\n </MenuPopover>\n </div>\n </div>\n\n {/* 导入 Markdown 的隐藏文件选择器(More 菜单项触发) */}\n <input\n ref={mdFileInputRef}\n type=\"file\"\n accept=\".md,.markdown,text/markdown\"\n hidden\n onChange={handleMdFileChange}\n />\n\n {/* 表格工具条(右键召唤) */}\n {tableMenu &&\n createPortal(\n <div\n className={styles.tableBubble}\n style={{ position: 'fixed', left: tableMenu.x, top: tableMenu.y }}\n onMouseDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.preventDefault()}\n >\n <ToolbarButton\n title={t.tableAddColumnBefore}\n onClick={() => runTable(() => chain().addColumnBefore().run())}\n >\n <ColumnBeforeIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableAddColumnAfter}\n onClick={() => runTable(() => chain().addColumnAfter().run())}\n >\n <ColumnAfterIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableDeleteColumn}\n onClick={() => runTable(() => chain().deleteColumn().run())}\n >\n <ColumnDeleteIcon />\n </ToolbarButton>\n <Divider />\n <ToolbarButton\n title={t.tableAddRowBefore}\n disabled={state.inTableHeader}\n onClick={() => runTable(() => chain().addRowBefore().run())}\n >\n <RowBeforeIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableAddRowAfter}\n onClick={() => runTable(() => chain().addRowAfter().run())}\n >\n <RowAfterIcon />\n </ToolbarButton>\n <ToolbarButton\n title={t.tableDeleteRow}\n disabled={state.inTableHeader}\n onClick={() => runTable(() => chain().deleteRow().run())}\n >\n <RowDeleteIcon />\n </ToolbarButton>\n </div>,\n document.body,\n )}\n </>\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * 是否窄屏(默认 <768px)。取代原项目的 useDevice,内联为纯 matchMedia,\n * 无第三方依赖。SSR 首帧返回 false,挂载后按实际视口更新。\n */\nexport function useIsMobile(breakpoint = 768): boolean {\n const [isMobile, setIsMobile] = useState(false);\n\n useEffect(() => {\n const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);\n const update = () => setIsMobile(mq.matches);\n update();\n mq.addEventListener('change', update);\n return () => mq.removeEventListener('change', update);\n }, [breakpoint]);\n\n return isMobile;\n}\n","'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { useIsMobile } from '../hooks/useIsMobile';\nimport { ChevronDownIcon, ListUnorderedIcon, LockIcon, MenuIcon } from '../icons';\nimport { defaultTocLabels, type TocLabels } from '../labels';\nimport styles from '../styles/tocPanel.module.css';\nimport type { TocItem } from '../toc/extractToc';\n\nexport interface TocPanelProps {\n items: TocItem[];\n /** 当前高亮的锚点 id(阅读页由 IntersectionObserver 算、编辑页由光标章节算)。 */\n activeId?: string;\n /** 点击目录项。锁住项不触发。默认行为由调用方决定(滚动 / 跳转)。 */\n onItemClick?: (item: TocItem) => void;\n labels?: Partial<TocLabels>;\n}\n\n/**\n * 目录面板(阅读页 + 编辑页共用)。\n *\n * - 桌面:左侧粘性栏,可收起(«/»)。\n * - 移动:顶部可折叠「目录」条,选中后自动收起。\n * - 层级用左缩进;active accent 左边框 + 加粗;locked 置灰 + 锁图标不可点。\n *\n * 纯展示:滚动 / active 计算交给调用方,本组件只渲染 + 派发点击。\n */\nexport function TocPanel({ items, activeId, onItemClick, labels }: TocPanelProps) {\n const t = { ...defaultTocLabels, ...labels };\n const isMobile = useIsMobile();\n\n const [collapsed, setCollapsed] = useState(false);\n const [mobileOpen, setMobileOpen] = useState(false);\n\n const desktopNavRef = useRef<HTMLElement>(null);\n const mobilePanelRef = useRef<HTMLDivElement>(null);\n\n // activeId 变化时把当前高亮项滚入 TOC 可视区(仅在不可见时)。\n useEffect(() => {\n if (!activeId) return;\n const reduce = window.matchMedia(\n '(prefers-reduced-motion: reduce)',\n ).matches;\n const container = desktopNavRef.current || mobilePanelRef.current;\n if (!container) return;\n const el = container.querySelector(`a[href=\"#${CSS.escape(activeId)}\"]`);\n if (!el) return;\n el.scrollIntoView({\n block: 'nearest',\n behavior: reduce ? 'auto' : 'smooth',\n });\n }, [activeId]);\n\n if (!items.length) return null;\n\n const minLevel = Math.min(...items.map((i) => i.level));\n\n const handleClick = (item: TocItem) => {\n if (item.locked) return;\n onItemClick?.(item);\n if (isMobile) setMobileOpen(false);\n };\n\n const list = (\n <ul className={styles.list}>\n {items.map((item) => (\n <li key={item.id}>\n <a\n href={item.locked ? undefined : `#${item.id}`}\n className={`${styles.item} ${\n item.id === activeId ? styles.active : ''\n } ${item.locked ? styles.locked : ''}`}\n style={{ paddingLeft: `${(item.level - minLevel) * 12 + 12}px` }}\n aria-current={item.id === activeId ? 'true' : undefined}\n aria-disabled={item.locked ? 'true' : undefined}\n onClick={(e) => {\n e.preventDefault();\n handleClick(item);\n }}\n >\n <span className={styles.itemText}>{item.text}</span>\n {item.locked ? (\n <LockIcon className={styles.lockIcon} aria-hidden />\n ) : null}\n </a>\n </li>\n ))}\n </ul>\n );\n\n // ── 移动端:顶部可折叠条 ──\n if (isMobile) {\n return (\n <nav className={styles.mobile} aria-label={t.title}>\n <button\n type=\"button\"\n className={styles.mobileBar}\n aria-expanded={mobileOpen}\n onClick={() => setMobileOpen((v) => !v)}\n >\n <MenuIcon className={styles.mobileBarIcon} aria-hidden />\n <span>{t.title}</span>\n <span\n className={`${styles.chevron} ${\n mobileOpen ? styles.chevronUp : ''\n }`}\n aria-hidden\n >\n <ChevronDownIcon size={16} />\n </span>\n </button>\n <div\n ref={mobilePanelRef}\n className={`${styles.mobilePanel} ${\n mobileOpen ? styles.mobilePanelOpen : ''\n }`}\n >\n {list}\n </div>\n </nav>\n );\n }\n\n // ── 桌面:左侧粘性栏(可收起)──\n if (collapsed) {\n return (\n <button\n type=\"button\"\n className={styles.collapsedRail}\n aria-label={t.expand}\n title={t.expand}\n onClick={() => setCollapsed(false)}\n >\n <ListUnorderedIcon />\n </button>\n );\n }\n\n return (\n <nav className={styles.desktop} aria-label={t.title} ref={desktopNavRef}>\n <div className={styles.header}>\n <span className={styles.headerTitle}>{t.title}</span>\n <button\n type=\"button\"\n className={styles.collapseBtn}\n aria-label={t.collapse}\n title={t.collapse}\n onClick={() => setCollapsed(true)}\n >\n «\n </button>\n </div>\n {list}\n </nav>\n );\n}\n","/**\n * 目录点击 → 平滑滚到对应标题。\n *\n * 不依赖浏览器 `scrollTo({behavior:'smooth'})` / `scrollIntoView({behavior:'smooth'})`——\n * 在 flex + overflow 嵌套布局下(父级 `overflow:hidden`、自身 `flex:1; overflow-y:auto`),\n * Chrome 的 compositor 驱动 smooth scroll 会静默失效。\n *\n * 改用 `requestAnimationFrame` + easeOutCubic 缓动,直接操作 `scrollTop`,\n * 主线程一次性 400ms 动画,点击触发的单次滚动无感知性能差异。\n *\n * 尊重 `prefers-reduced-motion: reduce`——此时瞬间跳转,无动画。\n */\n\n/** 缓动:easeOutCubic。t ∈ [0, 1]。 */\nfunction easeOutCubic(t: number): number {\n return 1 - (1 - t) * (1 - t) * (1 - t);\n}\n\n/**\n * 平滑滚动(或瞬间跳转)到指定 `data-toc-id` 的标题。\n *\n * @param headingId - TOC item 的 id,对应 DOM 上 `data-toc-id` 属性值\n * @param scrollContainer - 滚动容器(如 `.scrollArea`)\n * @param options - `duration`:动画时长 ms,默认 400\n */\nexport function scrollToTocHeading(\n headingId: string,\n scrollContainer: HTMLElement,\n options?: { duration?: number },\n): void {\n const el = scrollContainer.querySelector<HTMLElement>(\n `[data-toc-id=\"${CSS.escape(headingId)}\"]`,\n );\n if (!el) return;\n\n const startTop = scrollContainer.scrollTop;\n const rootRect = scrollContainer.getBoundingClientRect();\n const elRect = el.getBoundingClientRect();\n const targetTop = startTop + (elRect.top - rootRect.top);\n\n // prefers-reduced-motion:瞬间跳转\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n scrollContainer.scrollTop = targetTop;\n return;\n }\n\n // 手动平滑滚动\n const duration = options?.duration ?? 400;\n const start = performance.now();\n const animate = () => {\n const t = Math.min((performance.now() - start) / duration, 1);\n scrollContainer.scrollTop = startTop + (targetTop - startTop) * easeOutCubic(t);\n if (t < 1) requestAnimationFrame(animate);\n };\n requestAnimationFrame(animate);\n}\n"],"names":["styles","MarkdownWysiwygEditor","e","active","item","list"],"mappings":"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"}
|
package/dist/labels.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* 把 .md / .markdown 文件拖拽或粘贴进编辑器,解析后插入内容。
|
|
4
|
+
* 复用官方 @tiptap/extension-file-handler 的底层 FileHandlePlugin,但注册在
|
|
5
|
+
* 自有 PluginKey 下——宿主仍可通过 extraExtensions 注入自己的 FileHandler
|
|
6
|
+
* (如图片上传)而不撞 key。
|
|
7
|
+
*/
|
|
8
|
+
export declare const MarkdownFileDrop: Extension<any, any>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* 启发式判断一段纯文本是否「像 markdown」。
|
|
4
|
+
* 只要命中任一块级/行内特征即认为是——宁可偶尔把带星号的普通文本转掉,
|
|
5
|
+
* 也不漏掉真 markdown(用户可用 Shift+粘贴逃生)。
|
|
6
|
+
*/
|
|
7
|
+
export declare function looksLikeMarkdown(text: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* 粘贴 markdown 纯文本自动转富文本(官方 @tiptap/markdown 不内置此能力,
|
|
10
|
+
* 实现方式取自官方文档 "Paste Markdown Detection" 配方并调整边界)。
|
|
11
|
+
*
|
|
12
|
+
* 判定只看 text/plain 的内容,不看剪贴板是否带 text/html——很多来源
|
|
13
|
+
* (Xcode/VS Code 等编辑器经 RTF/语法高亮 HTML)复制 markdown 源码时会
|
|
14
|
+
* 附带一份仅是"字面文本+样式"的 HTML,按 HTML 标签判定来源不可枚举。
|
|
15
|
+
* 而真富文本(Word/网页文章)的 text/plain 降级不含 markdown 符号,
|
|
16
|
+
* 启发式天然不命中,仍走默认富文本粘贴。
|
|
17
|
+
*
|
|
18
|
+
* 放行(不转换)的边界:
|
|
19
|
+
* - Shift+粘贴(粘贴为纯文本)→ 保留逃生通道
|
|
20
|
+
* - 光标在代码块内 → markdown 源码原样贴入
|
|
21
|
+
* - looksLikeMarkdown 未命中 → 默认粘贴
|
|
22
|
+
*/
|
|
23
|
+
export declare const MarkdownPaste: Extension<any, any>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 目录点击 → 平滑滚到对应标题。
|
|
3
|
+
*
|
|
4
|
+
* 不依赖浏览器 `scrollTo({behavior:'smooth'})` / `scrollIntoView({behavior:'smooth'})`——
|
|
5
|
+
* 在 flex + overflow 嵌套布局下(父级 `overflow:hidden`、自身 `flex:1; overflow-y:auto`),
|
|
6
|
+
* Chrome 的 compositor 驱动 smooth scroll 会静默失效。
|
|
7
|
+
*
|
|
8
|
+
* 改用 `requestAnimationFrame` + easeOutCubic 缓动,直接操作 `scrollTop`,
|
|
9
|
+
* 主线程一次性 400ms 动画,点击触发的单次滚动无感知性能差异。
|
|
10
|
+
*
|
|
11
|
+
* 尊重 `prefers-reduced-motion: reduce`——此时瞬间跳转,无动画。
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* 平滑滚动(或瞬间跳转)到指定 `data-toc-id` 的标题。
|
|
15
|
+
*
|
|
16
|
+
* @param headingId - TOC item 的 id,对应 DOM 上 `data-toc-id` 属性值
|
|
17
|
+
* @param scrollContainer - 滚动容器(如 `.scrollArea`)
|
|
18
|
+
* @param options - `duration`:动画时长 ms,默认 400
|
|
19
|
+
*/
|
|
20
|
+
export declare function scrollToTocHeading(headingId: string, scrollContainer: HTMLElement, options?: {
|
|
21
|
+
duration?: number;
|
|
22
|
+
}): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptap-markdown-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A batteries-included, self-styled Markdown WYSIWYG editor and reader suite built on Tiptap v3. Markdown in/out, SSR/static rendering, table of contents, themeable via CSS variables, zero Ant Design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"@radix-ui/react-popover": "^1.1.15",
|
|
63
63
|
"@tiptap/core": "3.27.1",
|
|
64
64
|
"@tiptap/extension-code-block-lowlight": "3.27.1",
|
|
65
|
+
"@tiptap/extension-file-handler": "^3.27.1",
|
|
65
66
|
"@tiptap/extension-highlight": "3.27.1",
|
|
66
67
|
"@tiptap/extension-image": "3.27.1",
|
|
67
68
|
"@tiptap/extension-subscript": "3.27.1",
|