tiptap-markdown-react 0.17.0 → 0.18.0
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 +75 -3
- package/dist/{ReportContent-CwcppHl8.js → ReportContent-MgbebxPV.js} +8 -8
- package/dist/{ReportContent-CwcppHl8.js.map → ReportContent-MgbebxPV.js.map} +1 -1
- package/dist/components/EditorToolbar.d.ts +12 -1
- package/dist/components/EditorToolbar.dom.test.d.ts +1 -0
- package/dist/components/FindReplaceBar.d.ts +0 -7
- package/dist/components/LinkPopover.d.ts +28 -0
- package/dist/components/LinkPopover.dom.test.d.ts +1 -0
- package/dist/components/MarkdownWysiwygEditor.d.ts +12 -0
- package/dist/components/TableHandles.d.ts +19 -0
- package/dist/components/TableHandles.dom.test.d.ts +1 -0
- package/dist/components/findEntry.dom.test.d.ts +1 -0
- package/dist/{extractToc-CheLC9kh.js → extractToc-BaR6LP1f.js} +42 -4
- package/dist/extractToc-BaR6LP1f.js.map +1 -0
- package/dist/findReplace.d.ts +18 -4
- package/dist/icons/index.d.ts +6 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1320 -608
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +41 -1
- package/dist/linkEditing.d.ts +45 -0
- package/dist/linkEditing.test.d.ts +1 -0
- package/dist/placeholder.test.d.ts +1 -0
- package/dist/reader.js +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js → scrollToTocHeading-BTQWajGD.js} +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js.map → scrollToTocHeading-BTQWajGD.js.map} +1 -1
- package/dist/server.js +4 -4
- package/dist/style-inline.css +398 -174
- package/dist/style.css +398 -174
- package/dist/supSubMarkdown.test.d.ts +1 -0
- package/dist/supSubServer.test.d.ts +1 -0
- package/dist/tableSelection.d.ts +25 -5
- package/package.json +1 -1
- package/dist/extractToc-CheLC9kh.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/components/CitationRefView.tsx","../src/createCitationRef.ts","../src/commentAnchor/commentAnchorPlugin.ts","../src/commentAnchor/commentAnchorController.ts","../src/findReplace.ts","../src/icons/index.tsx","../src/labels.ts","../src/components/FindReplaceBar.tsx","../src/importPlaceholder.ts","../src/slashMenu/items.ts","../src/slashMenu/SlashMenuPopup.tsx","../src/slashMenu/SlashMenuExtension.ts","../src/shortcuts/types.ts","../src/shortcuts/ShortcutPanel.tsx","../src/markdownFileDrop.ts","../src/pendingAnchor.ts","../src/selectionKind.ts","../src/markdownPaste.ts","../src/components/ChartView.tsx","../src/chart/createChart.ts","../src/components/CodeBlockView.tsx","../src/components/MarkdownWysiwygEditor.tsx","../src/components/MarkdownPreview.tsx","../src/importMenu.ts","../src/insertMarkdown.ts","../src/tableSelection.ts","../src/components/ColorPalette.tsx","../src/components/MathEditorPopover.tsx","../src/components/EditorToolbar.tsx","../src/hooks/useIsMobile.ts","../src/components/TocPanel.tsx","../src/commentAnchor/CommentPopover.tsx","../src/anchorRange.ts","../src/markdownRange.ts","../src/normalizeMarkdown.ts","../src/replaceRange.ts","../src/slashMenu/insertSlashMarkdown.ts"],"sourcesContent":["'use client';\n\nimport {\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport type { RenderCitation } from '../citationTypes';\n\n/**\n * 脚注圆标 React NodeView。\n * 无 `renderCitation` 时渲默认 pill(有 url 则可点);有插槽时把 defaultDom 交给消费方。\n */\nexport function CitationRefView({ node, extension }: NodeViewProps) {\n const index = String(node.attrs.index ?? '');\n const url = (node.attrs.url as string | null) || null;\n const title = (node.attrs.title as string | null) || '';\n const renderCitation = extension.options.renderCitation as\n | RenderCitation\n | undefined;\n\n const pill = (\n <span\n className=\"citation-ref\"\n data-index={index}\n {...(url ? { 'data-url': url } : {})}\n {...(title ? { 'data-title': title } : {})}\n >\n {!renderCitation && url ? (\n <a\n href={url}\n title={title}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {index}\n </a>\n ) : (\n index\n )}\n </span>\n );\n\n const content = renderCitation\n ? renderCitation({\n index,\n attrs: { index, url, title: title || null },\n defaultDom: pill,\n })\n : pill;\n\n return (\n <NodeViewWrapper\n as=\"span\"\n data-citation-ref=\"\"\n style={{ display: 'inline' }}\n >\n {content}\n </NodeViewWrapper>\n );\n}\n","'use client';\n\nimport { ReactNodeViewRenderer } from '@tiptap/react';\nimport { CitationRef, type CitationRefOptions } from './CitationRef';\nimport type { RenderCitation } from './citationTypes';\nimport { CitationRefView } from './components/CitationRefView';\n\nexport type CitationRefViewOptions = CitationRefOptions & {\n renderCitation?: RenderCitation;\n};\n\n/**\n * 客户端增强版 CitationRef:挂 React NodeView,支持 `renderCitation` 插槽。\n * server / SSR 请继续用纯 {@link CitationRef}(无 React)。\n */\nexport function createCitationRef(\n options: { renderCitation?: RenderCitation } = {},\n) {\n return CitationRef.extend<CitationRefViewOptions>({\n addOptions() {\n return {\n HTMLAttributes: {},\n ...this.parent?.(),\n renderCitation: options.renderCitation,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(CitationRefView);\n },\n }).configure({\n renderCitation: options.renderCitation,\n });\n}\n","/**\n * 评论锚定客户端插件:\n * - 装饰:block 左缘 gutter 气泡(showGutter)、active 评论的 mark/block 高亮;\n * - 交互:点击 mark / gutter 通过 transaction meta 上报(宿主经 editor.on('transaction')\n * 接收,规避扩展创建时闭包 stale 的问题);\n * - 守卫:粘贴 / 拖拽的 slice 剥离 commentAnchor mark,防止幽灵高亮。\n *\n * 只读态(MarkdownPreview)不注入本插件、不接评论 —— 评论是编辑会话专属。\n */\n\nimport {\n Fragment,\n Slice,\n type MarkType,\n type Node as PMNode,\n} from '@tiptap/pm/model';\nimport { Extension } from '@tiptap/core';\nimport {\n Plugin,\n PluginKey,\n type EditorState,\n} from '@tiptap/pm/state';\nimport {\n Decoration,\n DecorationSet,\n type EditorView,\n} from '@tiptap/pm/view';\nimport type { CommentClickPayload } from './commentTypes';\n\nexport const COMMENT_ACTIVE_META = 'tmr:comment:active';\nexport const COMMENT_CLICK_META = 'tmr:comment:click';\nexport const COMMENT_GUTTER_META = 'tmr:comment:gutter';\n\nexport interface CommentGutterPayload {\n commentIds: string[];\n pos: number;\n}\n\nexport interface CommentAnchorPluginOptions {\n /** 是否在 block 左缘渲染评论 gutter 气泡,默认 true。 */\n showGutter?: boolean;\n /**\n * 编辑器内点 mark 是否参与交互(默认 true:设 active + 上报 click meta)。\n * 设 false 后点击 mark 完全惰性(不设 active、不上报),适合「只靠侧栏单项\n * 驱动滚动定位」的宿主。\n */\n interactive?: boolean;\n}\n\nexport interface CommentAnchorPluginState {\n activeCommentId: string | null;\n}\n\nexport const commentAnchorPluginKey = new PluginKey<CommentAnchorPluginState>(\n 'tmrCommentAnchor',\n);\n\n/** 从 Slice 中剔除 commentAnchor mark(粘贴/拖拽守卫)。 */\nexport function stripCommentAnchorMarks(\n slice: Slice,\n markType: MarkType,\n): Slice {\n const strip = (fragment: Fragment): Fragment => {\n const children: PMNode[] = [];\n fragment.forEach((child) => {\n if (child.isText && child.marks.some((m) => m.type === markType)) {\n children.push(\n child.mark(child.marks.filter((m) => m.type !== markType)),\n );\n } else if (child.content.size > 0) {\n children.push(child.copy(strip(child.content)));\n } else {\n children.push(child);\n }\n });\n return Fragment.fromArray(children);\n };\n return new Slice(strip(slice.content), slice.openStart, slice.openEnd);\n}\n\nfunction sliceHasCommentMarks(slice: Slice, markType: MarkType): boolean {\n let found = false;\n slice.content.descendants((node) => {\n if (node.isText && node.marks.some((m) => m.type === markType)) {\n found = true;\n return false;\n }\n return true;\n });\n return found;\n}\n\n/** 顶层 block 边界。 */\nfunction blockBounds(doc: PMNode): Array<{ start: number; end: number }> {\n const bounds: Array<{ start: number; end: number }> = [];\n doc.forEach((child, offset) => {\n bounds.push({ start: offset, end: offset + child.nodeSize });\n });\n return bounds;\n}\n\n/** commentId → 文本区间(从 doc 内 commentAnchor mark 收集)。 */\nfunction collectCommentRanges(\n doc: PMNode,\n): Map<string, Array<{ from: number; to: number }>> {\n const byId = new Map<string, Array<{ from: number; to: number }>>();\n doc.descendants((node, pos) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n const ids = (m.attrs.commentIds as string[]) ?? [];\n for (const id of ids) {\n const arr = byId.get(id) ?? [];\n arr.push({ from: pos, to: pos + node.nodeSize });\n byId.set(id, arr);\n }\n }\n return true;\n });\n return byId;\n}\n\nfunction rangesIntersectBlock(\n ranges: Array<{ from: number; to: number }>,\n start: number,\n end: number,\n): boolean {\n return ranges.some((r) => r.from < end && r.to > start);\n}\n\nfunction gutterDom(\n commentIds: string[],\n view: EditorView,\n blockPos: number,\n): HTMLElement {\n const el = document.createElement('span');\n el.className = 'tmr-comment-gutter';\n el.setAttribute('data-comment-ids', commentIds.join(' '));\n el.textContent = String(commentIds.length);\n el.title = `${commentIds.length}`;\n // 不抢编辑器焦点/选区\n el.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n el.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n view.dispatch(\n view.state.tr\n .setMeta(COMMENT_ACTIVE_META, commentIds[0] ?? null)\n .setMeta(COMMENT_GUTTER_META, {\n commentIds,\n pos: blockPos,\n } satisfies CommentGutterPayload),\n );\n });\n return el;\n}\n\nexport function commentAnchorPlugin(\n options: CommentAnchorPluginOptions = {},\n): Plugin<CommentAnchorPluginState> {\n const showGutter = options.showGutter !== false;\n const interactive = options.interactive !== false;\n\n return new Plugin<CommentAnchorPluginState>({\n key: commentAnchorPluginKey,\n state: {\n init: () => ({ activeCommentId: null }),\n apply: (tr, value) => {\n const active = tr.getMeta(COMMENT_ACTIVE_META);\n return active !== undefined\n ? { activeCommentId: active as string | null }\n : value;\n },\n },\n props: {\n decorations(state: EditorState) {\n const byId = collectCommentRanges(state.doc);\n if (byId.size === 0) return DecorationSet.empty;\n\n const decos: Decoration[] = [];\n const bounds = blockBounds(state.doc);\n\n if (showGutter) {\n for (const b of bounds) {\n const idsInBlock: string[] = [];\n for (const [id, ranges] of byId) {\n if (rangesIntersectBlock(ranges, b.start, b.end)) {\n idsInBlock.push(id);\n }\n }\n if (idsInBlock.length > 0) {\n decos.push(\n Decoration.widget(\n b.start,\n (view) => gutterDom(idsInBlock, view, b.start),\n { side: -1, key: `tmr-gutter:${b.start}` },\n ),\n );\n }\n }\n }\n\n const activeId =\n commentAnchorPluginKey.getState(state)?.activeCommentId ?? null;\n if (activeId) {\n const ranges = byId.get(activeId) ?? [];\n for (const r of ranges) {\n decos.push(\n Decoration.inline(r.from, r.to, { class: 'tmr-comment-active' }),\n );\n }\n for (const b of bounds) {\n if (rangesIntersectBlock(ranges, b.start, b.end)) {\n decos.push(\n Decoration.node(b.start, b.end, {\n class: 'tmr-comment-block-active',\n }),\n );\n }\n }\n }\n\n return DecorationSet.create(state.doc, decos);\n },\n\n handleClick(view: EditorView, pos: number, event: MouseEvent) {\n // 惰性模式:编辑器内点击 mark 不产生任何交互(侧栏单项驱动)。\n if (!interactive) return false;\n const target = event.target as Element | null;\n const el = target?.closest?.(\n 'mark.tmr-comment[data-comment-ids]',\n ) as HTMLElement | null;\n if (!el) return false;\n const commentIds = (el.getAttribute('data-comment-ids') ?? '')\n .split(' ')\n .filter(Boolean);\n if (commentIds.length === 0) return false;\n view.dispatch(\n view.state.tr\n .setMeta(COMMENT_ACTIVE_META, commentIds[0] ?? null)\n .setMeta(COMMENT_CLICK_META, {\n commentIds,\n anchorEl: el,\n pos,\n } satisfies CommentClickPayload),\n );\n return true;\n },\n\n // 粘贴 / 拖拽 / 编辑器内拖动的 slice 统一走这里:剥离评论 mark,\n // 防止复制粘贴产生幽灵高亮。正文内容不变,只是丢掉会话级元数据。\n transformPasted(slice: Slice, view: EditorView) {\n const markType = view.state.schema.marks.commentAnchor;\n if (!markType || !sliceHasCommentMarks(slice, markType)) return slice;\n return stripCommentAnchorMarks(slice, markType);\n },\n },\n });\n}\n\n/**\n * Tiptap Extension 包装:把评论锚定 Plugin 挂进 useEditor / Editor 的 extensions。\n * 只读态(MarkdownPreview)不要注入本扩展 —— 评论是编辑会话专属。\n */\nexport function commentAnchorExtension(\n options: CommentAnchorPluginOptions = {},\n) {\n return Extension.create({\n name: 'tmrCommentAnchor',\n addProseMirrorPlugins() {\n return [commentAnchorPlugin(options)];\n },\n });\n}\n","/**\n * 编辑会话内的评论锚定控制器(纯函数,供宿主 / 组件 handle 复用)。\n *\n * 职责:\n * - applyCommentAnchorsToEditor:comments 装载时把 segments 映射成 mark 铺入 doc;\n * - focusComment / nextComment:active 状态 + 滚动 + 选区;\n * - collectCommentIds / commentRangesById:供宿主查询。\n */\n\nimport type { Editor } from '@tiptap/core';\nimport {\n COMMENT_ACTIVE_META,\n commentAnchorPluginKey,\n} from './commentAnchorPlugin';\nimport {\n mapCommentAnchors,\n mergeCommentIntervals,\n type CommentRange,\n} from './commentMapper';\nimport type { CommentRef } from './commentTypes';\n\n/** 先清后铺,幂等;无评论时清空全部 mark。 */\nexport function applyCommentAnchorsToEditor(\n editor: Editor,\n comments: CommentRef[],\n): void {\n // 只读态不接评论(库契约:评论锚定 = 编辑会话专属)。\n if (!editor.isEditable) return;\n const intervals =\n comments.length > 0\n ? mergeCommentIntervals(\n mapCommentAnchors(\n editor.state.doc,\n comments.map((c) => ({ commentId: c.commentId, segments: c.segments })),\n ).map((r) => ({ commentId: r.commentId, ranges: r.ranges })),\n )\n : [];\n const chain = editor.chain().clearCommentAnchors();\n if (intervals.length > 0) chain.applyCommentAnchors(intervals);\n chain.run();\n}\n\n/** 文档顺序去重的 commentId 列表(gutter / 导航顺序)。 */\nexport function collectCommentIds(editor: Editor): string[] {\n const ids: string[] = [];\n editor.state.doc.descendants((node) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n for (const id of (m.attrs.commentIds as string[]) ?? []) {\n if (!ids.includes(id)) ids.push(id);\n }\n }\n return true;\n });\n return ids;\n}\n\nexport function commentRangesById(\n editor: Editor,\n commentId: string,\n): CommentRange[] {\n const ranges: CommentRange[] = [];\n editor.state.doc.descendants((node, pos) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n const ids = (m.attrs.commentIds as string[]) ?? [];\n if (ids.includes(commentId)) {\n ranges.push({ from: pos, to: pos + node.nodeSize });\n }\n }\n return true;\n });\n return ranges;\n}\n\nfunction setActive(editor: Editor, commentId: string | null): void {\n editor.view.dispatch(\n editor.state.tr.setMeta(COMMENT_ACTIVE_META, commentId),\n );\n}\n\nfunction getActive(editor: Editor): string | null {\n return commentAnchorPluginKey.getState(editor.state)?.activeCommentId ?? null;\n}\n\n/**\n * 聚焦某条评论:设置 active(mark/block 高亮)+ 滚动到第一个 mark + 光标落到\n * 区间起点。找不到(outdated)时清空 active 并返回 false。\n */\nexport function focusComment(editor: Editor, commentId: string): boolean {\n const ranges = commentRangesById(editor, commentId);\n if (ranges.length === 0) {\n setActive(editor, null);\n return false;\n }\n setActive(editor, commentId);\n const markEl = editor.view.dom.querySelector<HTMLElement>(\n `mark.tmr-comment[data-comment-ids~=\"${CSS.escape(commentId)}\"]`,\n );\n markEl?.scrollIntoView?.({ block: 'center', behavior: 'smooth' });\n editor.chain().setTextSelection(ranges[0].from).run();\n return true;\n}\n\n/** 按文档顺序在评论间循环跳转(dir: next / prev)。 */\nexport function nextComment(\n editor: Editor,\n dir: 'next' | 'prev' = 'next',\n): string | null {\n const ids = collectCommentIds(editor);\n if (ids.length === 0) return null;\n const active = getActive(editor);\n const current = active ? ids.indexOf(active) : -1;\n const nextIdx =\n dir === 'next'\n ? (current + 1) % ids.length\n : (current - 1 + ids.length) % ids.length;\n const target = ids[nextIdx];\n focusComment(editor, target);\n return target;\n}\n","/**\n * 查找替换的适配层。\n *\n * 匹配 / 高亮 / 替换全部由官方 `@tiptap/extension-find-and-replace` 承担(命令 + storage +\n * decoration),宿主与 AI 侧可以直接用 `editor.commands.setSearchTerm / replaceAll …`。\n * 这个文件只收拾 Tiptap 3.31.3 上的一个坑,以及库内的默认防抖。\n */\n\n/**\n * 输入防抖(毫秒)。\n *\n * 注意:注册扩展时必须把官方选项 `searchDebounceMs` 设为 **0**。官方防抖走 `setTimeout`,\n * 真正的 dispatch 发生在异步回调里,下面 `runFindCommand` 的守卫就兜不住那次抛错。\n * 防抖改由调用方(浮动条)自己做,语义一样但全程同步。\n */\nexport const FIND_DEBOUNCE_MS = 120;\n\nconst MISMATCH_RE = /Applying a mismatched transaction/;\n\n/**\n * 跑一条官方查找替换命令,兜掉 Tiptap 3.31.3 的一处事务错配。\n *\n * 成因:官方扩展的 `setSearchTerm` 不走 CommandManager 给的 dispatch,而是自己\n * `editor.state.tr` + `view.dispatch`(见扩展 dist 的 `applySearchTerm`)。CommandManager\n * 在命令结束后仍会派发它「命令开始时创建」的那个 tr。若这次派发触发了 TrailingNode 的\n * appendTransaction(**文末是代码块 / 表格 / 图表**时它会补一个空段落,starter-kit 自带),\n * doc 已经前进,那个旧 tr 的 `before` 就对不上当前 doc → `RangeError: Applying a mismatched\n * transaction`。\n *\n * 此时查询其实已经生效(扩展自己那次 dispatch 成功了、尾段落也补上了),只是紧随其后的\n * 第二次派发炸掉。所以捕获这一种错并重试一次即可收敛——重试时文末空段落已在,TrailingNode\n * 不再插手。其它错误照抛,不吞。\n */\nexport function runFindCommand(run: () => void): void {\n try {\n run();\n } catch (error) {\n if (error instanceof RangeError && MISMATCH_RE.test(error.message)) {\n run();\n return;\n }\n throw error;\n }\n}\n","import type { SVGProps } from 'react';\n\n/**\n * 内联 SVG 图标集(0 运行时依赖)。stroke 走 currentColor,尺寸默认 1em 跟随字号,\n * 故颜色/大小随文本与主题自动变化。\n *\n * 通用图标(粗体/斜体/下划线/列表/撤销/查找等,本文件表格图标之前的部分)的 path 取自\n * Lucide,其许可证为 ISC,其中部分图形源自 Feather 的 MIT——完整版权声明见\n * 仓库根目录 THIRD_PARTY_LICENSES.md。表格行列操作图标(Column / Row / TableDelete 系列)为自绘。\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 ImportIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M12 3v12\" />\n <path d=\"m8 11 4 4 4-4\" />\n <path d=\"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4\" />\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\nexport const SearchIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </Svg>\n);\n\nexport const XIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Svg>\n);\n\nexport const ChevronUpIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m18 15-6-6-6 6\" />\n </Svg>\n);\n\nexport const ReplaceIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 4a1 1 0 0 1 1-1\" />\n <path d=\"M15 10a1 1 0 0 1-1-1\" />\n <path d=\"M21 4a1 1 0 0 0-1-1\" />\n <path d=\"M21 9a1 1 0 0 1-1 1\" />\n <path d=\"m3 7 3 3 3-3\" />\n <path d=\"M6 10V5a2 2 0 0 1 2-2h2\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n </Svg>\n);\n\nexport const ReplaceAllIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 14a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1\" />\n <path d=\"M14 4a1 1 0 0 1 1-1\" />\n <path d=\"M15 10a1 1 0 0 1-1-1\" />\n <path d=\"M19 14a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1\" />\n <path d=\"M21 4a1 1 0 0 0-1-1\" />\n <path d=\"M21 9a1 1 0 0 1-1 1\" />\n <path d=\"m3 7 3 3 3-3\" />\n <path d=\"M6 10V5a2 2 0 0 1 2-2h2\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\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\nexport const TableDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"1\" />\n <path d=\"M3 9h18\" />\n <path d=\"M9 5v14\" />\n <path d=\"M15 5v14\" />\n <path d=\"m7 2 10 20\" />\n </Svg>\n);\n\nexport const CopyIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </Svg>\n);\n\nexport const ChevronsUpDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </Svg>\n);\n\nexport const KeyboardIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"M6 8h.01\" />\n <path d=\"M10 8h.01\" />\n <path d=\"M14 8h.01\" />\n <path d=\"M18 8h.01\" />\n <path d=\"M6 12h.01\" />\n <path d=\"M10 12h.01\" />\n <path d=\"M14 12h.01\" />\n <path d=\"M18 12h.01\" />\n <path d=\"M7 16h10\" />\n </Svg>\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 /** Markdown 文件导入失败(与图片上传共用 onError 回调时,便于宿主区分文案)。 */\n importMarkdownFailed: string;\n /** 主栏导入下拉触发器上的短文案(对齐 style / fontSize)。 */\n importDocument: string;\n /** 导入触发器 title / aria-label。 */\n importDocumentHint: string;\n /** 未传 importMenuItems、但传了 onImportDocument + importAccept 时的第二项。 */\n importDocumentOther: string;\n /** 导入进行中的按钮 title。 */\n importDocumentBusy: string;\n /** 光标占位:上传阶段,传入 0–100。 */\n importDocumentUploading: (percent: number) => string;\n /** 光标占位:转换阶段,不要百分比。 */\n importDocumentConverting: string;\n /** 非 Markdown 文件导入失败(onError 的 source === 'import')。 */\n importDocumentFailed: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n more: string;\n codeBlock: string;\n hr: string;\n /** 导入下拉里的 Markdown 项。 */\n importMarkdown: string;\n tableInsert: string;\n /** 网格选择器底部尺寸文案,如 \"3 × 4\"。参数顺序:列、行。 */\n tableSizeSelected: (cols: number, rows: number) => string;\n tableAddColumnBefore: string;\n tableAddColumnAfter: string;\n tableDeleteColumn: string;\n tableAddRowBefore: string;\n tableAddRowAfter: string;\n tableDeleteRow: string;\n /** 多格选区:在左侧插入 N 列。 */\n tableAddColumnBeforeN: (n: number) => string;\n /** 多格选区:在右侧插入 N 列。 */\n tableAddColumnAfterN: (n: number) => string;\n /** 多格选区:删除 N 列。 */\n tableDeleteColumnN: (n: number) => string;\n /** 多格选区:在上方插入 N 行。 */\n tableAddRowBeforeN: (n: number) => string;\n /** 多格选区:在下方插入 N 行。 */\n tableAddRowAfterN: (n: number) => string;\n /** 多格选区:删除 N 行。 */\n tableDeleteRowN: (n: number) => string;\n tableDeleteTable: string;\n inlineMath: string;\n blockMath: string;\n mathPlaceholder: string;\n mathDone: string;\n mathCancel: string;\n mathNewInline: string;\n mathNewBlock: string;\n}\n\n/** 斜杠菜单(键入 / 唤起的块级插入弹窗)文案。 */\nexport interface SlashMenuLabels {\n /** 弹窗 aria-label。 */\n menuLabel: string;\n /** 分组标题:文本块。 */\n groupText: string;\n /** 分组标题:列表。 */\n groupList: string;\n /** 分组标题:结构 / 高级块。 */\n groupAdvanced: string;\n normalText: string;\n headingLabel: (level: number) => string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n blockquote: string;\n codeBlock: string;\n divider: string;\n table: string;\n inlineMath: string;\n blockMath: string;\n}\n\nexport interface ChartLabels {\n /** Tab label when config has no title. */\n tabLabel: (chartType: string, index: number) => string;\n done: string;\n cancel: string;\n configLabel: string;\n tableLabel: string;\n /** Modal dialog title. */\n editTitle: string;\n}\n\nexport const defaultChartLabels: ChartLabels = {\n tabLabel: (chartType, index) => `${chartType} ${index + 1}`,\n done: 'Done',\n cancel: 'Cancel',\n configLabel: 'Chart config (JSON)',\n tableLabel: 'Data table (Markdown)',\n editTitle: 'Edit chart',\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 importMarkdownFailed: 'Markdown import failed',\n importDocument: 'Import',\n importDocumentHint: 'Import a file',\n importDocumentOther: 'Document',\n importDocumentBusy: 'Importing…',\n importDocumentUploading: (percent) => `Uploading ${percent}%`,\n importDocumentConverting: 'Converting…',\n importDocumentFailed: 'Import 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: 'Markdown',\n tableInsert: 'Insert table',\n tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,\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 tableAddColumnBeforeN: (n) => `Add ${n} columns before`,\n tableAddColumnAfterN: (n) => `Add ${n} columns after`,\n tableDeleteColumnN: (n) => `Delete ${n} columns`,\n tableAddRowBeforeN: (n) => `Add ${n} rows before`,\n tableAddRowAfterN: (n) => `Add ${n} rows after`,\n tableDeleteRowN: (n) => `Delete ${n} rows`,\n tableDeleteTable: 'Delete table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n mathPlaceholder: 'E = mc^2',\n mathDone: 'Done',\n mathCancel: 'Cancel',\n mathNewInline: 'New equation',\n mathNewBlock: 'Add a TeX equation',\n};\n\nexport const defaultSlashMenuLabels: SlashMenuLabels = {\n menuLabel: 'Insert block',\n groupText: 'Text',\n groupList: 'Lists',\n groupAdvanced: 'Advanced',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n blockquote: 'Blockquote',\n codeBlock: 'Code block',\n divider: 'Divider',\n table: 'Table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n};\n\n/** 快捷键抽屉面板(键位 + Markdown 触发写法对照)文案。 */\nexport interface ShortcutLabels {\n /** 抽屉标题。 */\n panelTitle: string;\n /** 关闭按钮 aria / title。 */\n close: string;\n /** 三列表头:格式 / 快捷键 / Markdown。 */\n colFormat: string;\n colShortcut: string;\n colMarkdown: string;\n /** 分组标题。 */\n formatGroup: string;\n insertGroup: string;\n editGroup: string;\n bold: string;\n italic: string;\n strike: string;\n underline: string;\n inlineCode: string;\n highlight: string;\n headingLabel: (level: number) => string;\n paragraph: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n codeBlock: string;\n divider: string;\n undo: string;\n redo: string;\n hardBreak: string;\n findReplace: string;\n}\n\nexport const defaultShortcutLabels: ShortcutLabels = {\n panelTitle: 'Shortcuts',\n close: 'Close',\n colFormat: 'Format',\n colShortcut: 'Shortcut',\n colMarkdown: 'Markdown',\n formatGroup: 'Formatting',\n insertGroup: 'Insert',\n editGroup: 'Editing',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n underline: 'Underline',\n inlineCode: 'Inline code',\n highlight: 'Highlight',\n headingLabel: (level) => `Heading ${level}`,\n paragraph: 'Normal text',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n codeBlock: 'Code block',\n divider: 'Divider',\n undo: 'Undo',\n redo: 'Redo',\n hardBreak: 'Hard break',\n findReplace: 'Find & replace',\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 copy: string;\n /** 只读态:展开超出限高的代码块。 */\n expand: string;\n /** 只读态:收起已展开的代码块。 */\n collapse: string;\n}\n\nexport const defaultCodeBlockLabels: CodeBlockLabels = {\n autoDetect: 'Auto-detect',\n delete: 'Delete code block',\n copy: 'Copy code',\n expand: 'Expand code',\n collapse: 'Collapse code',\n};\n\nexport interface CommentLabels {\n open: string;\n resolved: string;\n dismissed: string;\n outdated: string;\n ambiguous: string;\n partial: string;\n gutterTitle: string;\n}\n\nexport const defaultCommentLabels: CommentLabels = {\n open: 'Open',\n resolved: 'Resolved',\n dismissed: 'Dismissed',\n outdated: 'Outdated',\n ambiguous: 'Ambiguous',\n partial: 'Partially matched',\n gutterTitle: 'Comment',\n};\n\nexport interface FindLabels {\n /** 查找输入框的占位与无障碍名,也用作浮动条的 aria-label。 */\n find: string;\n /** 替换输入框的占位与无障碍名。 */\n replace: string;\n next: string;\n previous: string;\n replaceOne: string;\n replaceAll: string;\n close: string;\n caseSensitive: string;\n wholeWord: string;\n useRegex: string;\n /** 计数文案。无结果时 current 传 0。 */\n counter: (current: number, total: number) => string;\n /** 正则模式下模式非法(RE2 不支持 lookaround / backreference 等,见官方扩展)。 */\n invalidRegex: string;\n /** 只读态提示:可查不可换。 */\n readOnly: string;\n}\n\nexport const defaultFindLabels: FindLabels = {\n find: 'Find',\n replace: 'Replace with',\n next: 'Next match',\n previous: 'Previous match',\n replaceOne: 'Replace',\n replaceAll: 'Replace all',\n close: 'Close',\n caseSensitive: 'Match case',\n wholeWord: 'Whole word',\n useRegex: 'Use regular expression',\n counter: (current, total) => `${current} / ${total}`,\n invalidRegex: 'Invalid pattern',\n readOnly: 'Read-only',\n};\n","'use client';\n\nimport {\n createSearchRegex,\n FindAndReplacePluginKey,\n} from '@tiptap/extension-find-and-replace';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type RefObject,\n} from 'react';\nimport { FIND_DEBOUNCE_MS, runFindCommand } from '../findReplace';\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ReplaceAllIcon,\n ReplaceIcon,\n SearchIcon,\n XIcon,\n} from '../icons';\nimport { defaultFindLabels, type FindLabels } from '../labels';\nimport styles from '../styles/findBar.module.css';\n\nexport interface FindReplaceBarProps {\n /** 编辑器实例(由 `<MarkdownWysiwygEditor>` 提供,浮动条不自行创建编辑器)。 */\n editor: Editor;\n /** 关闭(Esc / ×):宿主负责收起浮动条并把焦点还给编辑器。 */\n onClose: () => void;\n labels?: Partial<FindLabels>;\n /**\n * 查找输入框 ref。宿主拿它实现「再按一次 Mod+F 聚焦并全选当前查询」。\n * 也用于浮动条打开时自动聚焦。\n */\n inputRef?: RefObject<HTMLInputElement | null>;\n /** 定位 / 层级 class,由宿主给(浮动条自身只负责内部布局)。 */\n className?: string;\n /** 根节点内联样式(编辑器用它落 findBarOffset;宿主自绘时也可用)。 */\n style?: CSSProperties;\n}\n\n/**\n * 查找替换浮动条。匹配、高亮、替换全部由官方\n * `@tiptap/extension-find-and-replace` 承担(含 RE2 安全正则、跨标记匹配、单事务全部替换),\n * 这里只做输入、计数、开关与键位。\n *\n * 打开即把查询推给编辑器,关闭时 `clearSearch()`——高亮是会话级的,不留残影。\n */\nexport function FindReplaceBar({\n editor,\n onClose,\n labels,\n inputRef,\n className,\n style,\n}: FindReplaceBarProps) {\n const t: FindLabels = { ...defaultFindLabels, ...labels };\n const [term, setTerm] = useState('');\n const [replaceTerm, setReplaceTerm] = useState('');\n\n // 宿主自己摆条子时可能把 findReplace 关了——那时扩展没注册,命令与插件 state 都不存在。\n // 不拦住的话下面每个 effect 都会 TypeError 把宿主的树带崩;这里退化为不渲染并留一句提示。\n const hasExtension = typeof editor.commands.setSearchTerm === 'function';\n useEffect(() => {\n if (!hasExtension) {\n console.warn(\n '[tiptap-markdown-react] FindReplaceBar 需要官方 find 扩展:' +\n '请让 <MarkdownWysiwygEditor findReplace> 保持开启(默认 true),' +\n '否则 setSearchTerm / replaceAll 等命令不存在。',\n );\n }\n }, [hasExtension]);\n\n const state = useEditorState({\n editor,\n selector: ({ editor: instance }) => {\n const plugin = FindAndReplacePluginKey.getState(instance.state);\n return {\n currentIndex: plugin?.currentIndex ?? null,\n total: plugin?.results.length ?? 0,\n caseSensitive: plugin?.caseSensitive ?? false,\n wholeWord: plugin?.wholeWord ?? false,\n useRegex: plugin?.useRegex ?? false,\n };\n },\n });\n\n /** 所有命令都从这里走:扩展缺席时直接跳过(见上面 hasExtension)。 */\n const runCommand = useCallback(\n (run: () => void) => {\n if (!hasExtension) return;\n runFindCommand(run);\n },\n [hasExtension],\n );\n\n // 查询词防抖由这里做(扩展注册时 searchDebounceMs: 0,原因见 findReplace.ts):\n // 输入时延迟推给编辑器,回车 / 替换等动作前先 flush,否则会拿着旧查询执行。\n const appliedTermRef = useRef<string | null>(null);\n const pushTerm = useCallback(\n (value: string) => {\n appliedTermRef.current = value;\n runCommand(() => editor.commands.setSearchTerm(value));\n },\n [editor, runCommand],\n );\n const flushTerm = useCallback(() => {\n if (appliedTermRef.current !== term) pushTerm(term);\n }, [pushTerm, term]);\n\n useEffect(() => {\n if (appliedTermRef.current === term) return;\n const timer = setTimeout(() => pushTerm(term), FIND_DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [term, pushTerm]);\n\n useEffect(() => {\n runCommand(() => editor.commands.setReplaceTerm(replaceTerm));\n }, [editor, replaceTerm, runCommand]);\n\n // 关闭 / 卸载时清空查询与高亮。\n useEffect(() => {\n return () => {\n if (!editor.isDestroyed) runCommand(() => editor.commands.clearSearch());\n };\n }, [editor, runCommand]);\n\n /** 动作类命令(导航 / 替换):先落定查询词,再执行。 */\n const runAction = useCallback(\n (action: () => void) => {\n flushTerm();\n runCommand(action);\n },\n [flushTerm, runCommand],\n );\n\n // RE2 模式非法(lookaround / backreference 等):官方返回零结果不报错,这里给个提示,\n // 否则「输入了正则却一直 0 / 0」没有解释。\n const invalidPattern = useMemo(\n () =>\n term !== '' &&\n state.useRegex &&\n createSearchRegex(term, {\n caseSensitive: state.caseSensitive,\n useRegex: true,\n wholeWord: false,\n }) === null,\n [term, state.useRegex, state.caseSensitive],\n );\n\n const counter = t.counter(\n state.total === 0 ? 0 : (state.currentIndex ?? 0) + 1,\n state.total,\n );\n\n const keepFocus = (e: ReactMouseEvent) => e.preventDefault();\n\n const onFindKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n runAction(() => {\n if (e.shiftKey) editor.commands.goToPreviousResult();\n else editor.commands.goToNextResult();\n });\n }\n };\n\n const onReplaceKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n runAction(() => editor.commands.replace());\n }\n };\n\n const toggle = (key: 'caseSensitive' | 'wholeWord', value: boolean) => {\n runCommand(() => {\n if (key === 'caseSensitive') editor.commands.setCaseSensitive(value);\n else editor.commands.setWholeWord(value);\n });\n };\n\n if (!hasExtension) return null;\n\n const toggleClass = (on: boolean) =>\n `${styles.btn} ${styles.toggle}${on ? ` ${styles.toggleOn}` : ''}`;\n\n return (\n <div\n className={className ? `${styles.bar} ${className}` : styles.bar}\n style={style}\n role=\"dialog\"\n aria-label={t.find}\n onKeyDown={(e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n }}\n >\n <div className={styles.row}>\n <span className={styles.field}>\n <SearchIcon size={14} className={styles.fieldIcon} />\n <input\n ref={inputRef}\n className={styles.input}\n value={term}\n onChange={(e) => setTerm(e.target.value)}\n onKeyDown={onFindKeyDown}\n placeholder={t.find}\n aria-label={t.find}\n autoFocus\n spellCheck={false}\n />\n <span\n className={`${styles.counter}${invalidPattern ? ` ${styles.counterInvalid}` : ''}`}\n aria-live=\"polite\"\n title={invalidPattern ? t.invalidRegex : undefined}\n >\n {invalidPattern ? t.invalidRegex : counter}\n </span>\n </span>\n <button\n type=\"button\"\n className={toggleClass(state.caseSensitive)}\n title={t.caseSensitive}\n aria-label={t.caseSensitive}\n aria-pressed={state.caseSensitive}\n onMouseDown={keepFocus}\n onClick={() => toggle('caseSensitive', !state.caseSensitive)}\n >\n Aa\n </button>\n <button\n type=\"button\"\n className={toggleClass(state.wholeWord)}\n title={t.wholeWord}\n aria-label={t.wholeWord}\n aria-pressed={state.wholeWord}\n onMouseDown={keepFocus}\n onClick={() => toggle('wholeWord', !state.wholeWord)}\n >\n ab\n </button>\n\n <span className={styles.spacer} />\n <span className={styles.iconGroup}>\n <button\n type=\"button\"\n className={styles.btn}\n title={t.previous}\n aria-label={t.previous}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.goToPreviousResult())}\n >\n <ChevronUpIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n title={t.next}\n aria-label={t.next}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.goToNextResult())}\n >\n <ChevronDownIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n title={t.close}\n aria-label={t.close}\n onClick={onClose}\n >\n <XIcon size={16} />\n </button>\n </span>\n </div>\n\n {editor.isEditable ? (\n <div className={styles.row}>\n <span className={styles.field}>\n <input\n className={styles.input}\n value={replaceTerm}\n onChange={(e) => setReplaceTerm(e.target.value)}\n onKeyDown={onReplaceKeyDown}\n placeholder={t.replace}\n aria-label={t.replace}\n spellCheck={false}\n />\n </span>\n <span className={styles.spacer} />\n <button\n type=\"button\"\n className={styles.btn}\n title={t.replaceOne}\n aria-label={t.replaceOne}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.replace())}\n >\n <ReplaceIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n title={t.replaceAll}\n aria-label={t.replaceAll}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.replaceAll())}\n >\n <ReplaceAllIcon size={16} />\n </button>\n </div>\n ) : (\n <div className={styles.row}>\n <span className={styles.readOnly}>{t.readOnly}</span>\n </div>\n )}\n </div>\n );\n}\n","import { Node } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n importPlaceholder: {\n insertImportPlaceholder: (label: string) => ReturnType;\n updateImportPlaceholder: (label: string) => ReturnType;\n removeImportPlaceholder: () => ReturnType;\n };\n }\n}\n\nfunction findPlaceholderPos(doc: {\n descendants: (\n f: (node: { type: { name: string } }, pos: number) => boolean | void,\n ) => void;\n}): number | null {\n let found: number | null = null;\n doc.descendants((node, pos) => {\n if (node.type.name === 'importPlaceholder') {\n found = pos;\n return false;\n }\n });\n return found;\n}\n\n/** 导入进行中插在光标处的占位块。不进 Markdown,autosave 不会把进度文案落库。 */\nexport const ImportPlaceholder = Node.create({\n name: 'importPlaceholder',\n group: 'block',\n atom: true,\n selectable: false,\n draggable: false,\n\n addAttributes() {\n return {\n label: {\n default: '',\n parseHTML: (el) => el.getAttribute('data-label') ?? '',\n renderHTML: (attrs) =>\n attrs.label ? { 'data-label': attrs.label } : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'div[data-type=\"import-placeholder\"]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const label = String(node.attrs.label ?? '');\n return [\n 'div',\n {\n ...HTMLAttributes,\n 'data-type': 'import-placeholder',\n class: 'tmr-import-placeholder',\n contenteditable: 'false',\n 'aria-live': 'polite',\n 'aria-busy': 'true',\n },\n ['span', { class: 'tmr-import-placeholder-spin', 'aria-hidden': 'true' }],\n ['span', { class: 'tmr-import-placeholder-label' }, label],\n ];\n },\n\n renderMarkdown() {\n return '';\n },\n\n addCommands() {\n return {\n insertImportPlaceholder:\n (label) =>\n ({ chain }) =>\n chain()\n .focus()\n .insertContent({\n type: this.name,\n attrs: { label },\n })\n .command(({ tr }) => {\n tr.setMeta('addToHistory', false);\n tr.setMeta('preventUpdate', true);\n return true;\n })\n .run(),\n updateImportPlaceholder:\n (label) =>\n ({ tr, dispatch, state }) => {\n const pos = findPlaceholderPos(state.doc);\n if (pos == null) return false;\n if (dispatch) {\n dispatch(\n tr\n .setNodeMarkup(pos, undefined, { label })\n .setMeta('addToHistory', false)\n .setMeta('preventUpdate', true),\n );\n }\n return true;\n },\n removeImportPlaceholder:\n () =>\n ({ tr, dispatch, state }) => {\n const pos = findPlaceholderPos(state.doc);\n if (pos == null) return false;\n const node = state.doc.nodeAt(pos);\n if (!node) return false;\n if (dispatch) {\n dispatch(\n tr\n .delete(pos, pos + node.nodeSize)\n .setMeta('addToHistory', false)\n .setMeta('preventUpdate', true),\n );\n }\n return true;\n },\n };\n },\n});\n","import type { Editor } from '@tiptap/core';\nimport {\n defaultSlashMenuLabels,\n type SlashMenuLabels,\n} from '../labels';\nimport type { SlashMenuItem } from './types';\n\n/**\n * 默认斜杠命令项:全部是「可序列化为 markdown」的块级操作。\n * 图片、附件、AI、二级子菜单、最近使用不在 v1 范围。\n *\n * 图标沿用工具栏下拉菜单的文字字形语言(`{ }` / `√x` / `∑` / `—` / `❝`),\n * 三组(文本 / 列表 / 高级)在弹窗里分节展示。\n */\nexport function createDefaultSlashMenuItems(\n labels: SlashMenuLabels = defaultSlashMenuLabels,\n): SlashMenuItem[] {\n return [\n {\n id: 'normal-text',\n title: labels.normalText,\n group: labels.groupText,\n icon: '¶',\n aliases: ['zhengwen', '正文', 'paragraph', 'text'],\n order: 0,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).setParagraph().run();\n },\n },\n ...([1, 2, 3] as const).map((level): SlashMenuItem => ({\n id: `heading-${level}`,\n title: labels.headingLabel(level),\n group: labels.groupText,\n icon: `H${level}`,\n aliases: [`h${level}`, 'biaoti', '标题', 'heading'],\n order: level,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setHeading({ level })\n .run();\n },\n })),\n {\n id: 'bullet-list',\n title: labels.bulletList,\n group: labels.groupList,\n icon: '•',\n aliases: ['wuxu', '无序', '列表', 'bullet', 'ul'],\n order: 4,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleBulletList().run();\n },\n },\n {\n id: 'ordered-list',\n title: labels.orderedList,\n group: labels.groupList,\n icon: '1.',\n aliases: ['youxu', '有序', '列表', 'ordered', 'ol'],\n order: 5,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleOrderedList().run();\n },\n },\n {\n id: 'task-list',\n title: labels.taskList,\n group: labels.groupList,\n icon: '✓',\n aliases: ['renwu', '任务', '待办', 'task', 'todo', 'checklist'],\n order: 6,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleTaskList().run();\n },\n },\n {\n id: 'blockquote',\n title: labels.blockquote,\n group: labels.groupAdvanced,\n icon: '❝',\n aliases: ['yinyong', '引用', 'quote', 'blockquote'],\n order: 7,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleBlockquote().run();\n },\n },\n {\n id: 'code-block',\n title: labels.codeBlock,\n group: labels.groupAdvanced,\n icon: '{ }',\n aliases: ['daima', '代码', 'code', 'fence'],\n order: 8,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleCodeBlock().run();\n },\n },\n {\n id: 'divider',\n title: labels.divider,\n group: labels.groupAdvanced,\n icon: '—',\n aliases: ['fenge', '分割线', '分隔线', 'hr', 'divider'],\n order: 9,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).setHorizontalRule().run();\n },\n },\n {\n id: 'table',\n title: labels.table,\n group: labels.groupAdvanced,\n icon: '▦',\n aliases: ['biaoge', '表格', 'table'],\n order: 10,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n .run();\n },\n },\n {\n id: 'inline-math',\n title: labels.inlineMath,\n group: labels.groupAdvanced,\n icon: '√x',\n aliases: ['gongshi', '公式', '行内公式', 'math', 'latex'],\n order: 11,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({ type: 'inlineMath', attrs: { latex: 'E=mc^2' } })\n .run();\n },\n },\n {\n id: 'block-math',\n title: labels.blockMath,\n group: labels.groupAdvanced,\n icon: '∑',\n aliases: ['gongshi', '公式', '块级公式', 'mathblock', 'latex'],\n order: 12,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({ type: 'blockMath', attrs: { latex: 'E=mc^2' } })\n .run();\n },\n },\n ];\n}\n\n/** 按 title / aliases 做小写 includes 过滤;空 query 返回全部。 */\nexport function filterSlashItems(\n items: SlashMenuItem[],\n query: string,\n): SlashMenuItem[] {\n const q = query.trim().toLowerCase();\n if (!q) return items;\n return items.filter(\n (item) =>\n item.title.toLowerCase().includes(q) ||\n item.aliases?.some((alias) => alias.toLowerCase().includes(q)),\n );\n}\n","import {\n Fragment,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useState,\n type ReactNode,\n} from 'react';\nimport styles from '../styles/slashMenu.module.css';\nimport type { SlashMenuItem } from './types';\n\nexport interface SlashMenuPopupHandle {\n /** 编辑器键盘事件经 IME 守卫后委托进来;返回 true 表示已消费。 */\n onKeyDown: (event: KeyboardEvent) => boolean;\n}\n\nexport interface SlashMenuPopupProps {\n items: SlashMenuItem[];\n query: string;\n menuLabel: string;\n command: (item: SlashMenuItem) => void;\n}\n\n/**\n * 把有序列表切成「相邻同名组」的节:返回 [组名 | null, 项][]。\n * 组首项的行携带组名(渲染为节标题 + 该项),其余行组名为 null。\n */\nfunction withGroupHeaders(\n items: SlashMenuItem[],\n): Array<[ReactNode, SlashMenuItem]> {\n const rows: Array<[ReactNode, SlashMenuItem]> = [];\n let lastGroup: string | undefined;\n for (const item of items) {\n if (item.group && item.group !== lastGroup) {\n rows.push([item.group, item]);\n lastGroup = item.group;\n } else {\n if (!item.group) lastGroup = undefined;\n rows.push([null, item]);\n }\n }\n return rows;\n}\n\n/**\n * 斜杠菜单弹层。样式对齐工具栏下拉菜单(radix 面板 + 文字字形图标 +\n * 品牌色高亮);定位由 @tiptap/suggestion 的 mount(floating-ui)接管。\n * 零匹配时渲染 null:弹层隐藏但 suggestion 保持激活,query 恢复命中时\n * 重新出现。\n */\nexport const SlashMenuPopup = forwardRef<\n SlashMenuPopupHandle,\n SlashMenuPopupProps\n>(function SlashMenuPopup({ items, query, menuLabel, command }, ref) {\n const [index, setIndex] = useState(0);\n\n // query 变化(过滤)后选区回到第一项\n useEffect(() => {\n setIndex(0);\n }, [query]);\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown(event) {\n if (!items.length) return false;\n if (event.key === 'ArrowDown' || (event.key === 'Tab' && !event.shiftKey)) {\n setIndex((i) => (i + 1) % items.length);\n return true;\n }\n if (event.key === 'ArrowUp' || (event.key === 'Tab' && event.shiftKey)) {\n setIndex((i) => (i - 1 + items.length) % items.length);\n return true;\n }\n if (event.key === 'Enter') {\n const item = items[index];\n if (!item) return false;\n command(item);\n return true;\n }\n return false;\n },\n }),\n [items, index, command],\n );\n\n if (!items.length) return null;\n\n // 键盘索引按「可选项」计;分组头不占位\n let optionIndex = -1;\n\n return (\n <div className={styles.menu} role=\"listbox\" aria-label={menuLabel}>\n {withGroupHeaders(items).map(([header, item]) => {\n optionIndex += 1;\n const i = optionIndex;\n return (\n <Fragment key={item.id}>\n {header !== null ? (\n <div className={styles.groupLabel} aria-hidden=\"true\">\n {header}\n </div>\n ) : null}\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={i === index}\n title={item.title}\n className={i === index ? styles.itemActive : styles.item}\n // 键盘焦点留在编辑器里,↑↓/Enter 才能继续驱动弹层\n tabIndex={-1}\n onMouseEnter={() => setIndex(i)}\n onMouseDown={(e) => {\n // 用 mousedown 抢在编辑器 blur 之前执行,避免选区先被抖掉\n e.preventDefault();\n command(item);\n }}\n >\n {item.icon != null ? (\n <span className={styles.itemIcon} aria-hidden=\"true\">\n {item.icon}\n </span>\n ) : (\n <span className={styles.itemIcon} aria-hidden=\"true\" />\n )}\n <span className={styles.itemTitle}>{item.title}</span>\n </button>\n </Fragment>\n );\n })}\n </div>\n );\n});\n","import { Extension } from '@tiptap/core';\nimport { ReactRenderer } from '@tiptap/react';\nimport Suggestion, {\n type SuggestionKeyDownProps,\n type SuggestionProps,\n} from '@tiptap/suggestion';\nimport { PluginKey } from '@tiptap/pm/state';\nimport {\n defaultSlashMenuLabels,\n type SlashMenuLabels,\n} from '../labels';\nimport styles from '../styles/slashMenu.module.css';\nimport { createDefaultSlashMenuItems, filterSlashItems } from './items';\nimport { SlashMenuPopup, type SlashMenuPopupHandle } from './SlashMenuPopup';\nimport type { SlashMenuItem } from './types';\n\nexport interface SlashMenuOptions {\n /** 追加的宿主自定义命令项(排在默认项之后)。 */\n items?: SlashMenuItem[];\n /** 弹窗文案,与默认英文文案合并。 */\n labels?: Partial<SlashMenuLabels>;\n}\n\n/** 输入法组合态下的按键交给 IME 自己处理(上游 suggestion 不查 composing)。 */\nfunction isComposing(event: KeyboardEvent, view: { composing: boolean }): boolean {\n return view.composing || event.isComposing || event.keyCode === 229;\n}\n\n/**\n * 斜杠菜单:键入 `/` 唤起块级插入弹窗。\n *\n * - 触发规则:行首或空白后(`allowedPrefixes`,空白含全角 U+3000);\n * 正文里「和/或」这类合法斜杠不会触发。\n * - 代码块内不触发;表格单元格内触发(见 allow)。\n * - 定位/滚动跟随/点外关闭全走官方 `props.mount`(floating-ui),\n * 弹层挂 document.body(逃出宿主 overflow 裁剪),`--tmr-*` 主题\n * 变量从编辑器解析后复制到弹层宿主。\n * - 只读态由 suggestion 状态机自身拦截(isEditable 短路)。\n */\nexport const SlashMenu = Extension.create<SlashMenuOptions>({\n name: 'slashMenu',\n\n addOptions() {\n return { items: undefined, labels: undefined };\n },\n\n addProseMirrorPlugins() {\n const { items: extraItems, labels } = this.options;\n const allItems = [\n ...createDefaultSlashMenuItems({ ...defaultSlashMenuLabels, ...labels }),\n ...(extraItems ?? []),\n ];\n\n let renderer: ReactRenderer<SlashMenuPopupHandle> | null = null;\n let unmountPopup: (() => void) | null = null;\n\n return [\n Suggestion<SlashMenuItem>({\n editor: this.editor,\n pluginKey: new PluginKey('tmrSlashMenu'),\n char: '/',\n // 行首(节点内起始,空 prefix 天然放行)或空白后触发\n allowedPrefixes: [' ', '\\t', '\\u3000'],\n allowSpaces: false,\n decorationClass: 'tmr-slash-suggestion',\n decorationEmptyClass: 'tmr-slash-suggestion-empty',\n items: ({ query }) => filterSlashItems(allItems, query),\n command: ({ editor, range, props: item }) => {\n item.apply(editor, range);\n },\n allow: ({ editor }) => editor.isEditable && !editor.isActive('codeBlock'),\n render: () => ({\n onStart: (props: SuggestionProps<SlashMenuItem>) => {\n renderer = new ReactRenderer(\n SlashMenuPopup,\n {\n editor: props.editor,\n props: {\n items: props.items,\n query: props.query,\n menuLabel:\n this.options.labels?.menuLabel ?? defaultSlashMenuLabels.menuLabel,\n command: props.command,\n },\n className: styles.popupHost,\n },\n );\n // 挂到 body(suggestion 默认容器):弹层要能浮出编辑器,宿主在\n // 编辑器外层套 overflow:hidden(圆角窗口/滚动容器)时不会被裁。\n // 主题变量随行:编辑器子树上的 --tmr-* 解析值复制到弹层宿主,\n // 宿主把变量定义在任意深度的子树里也能保持配色一致。\n const pmStyle = getComputedStyle(props.editor.view.dom);\n for (const name of [\n '--tmr-text',\n '--tmr-accent',\n '--tmr-toolbar-border',\n '--tmr-toolbar-muted',\n ]) {\n const value = pmStyle.getPropertyValue(name);\n if (value) renderer.element.style.setProperty(name, value);\n }\n unmountPopup = props.mount(renderer.element);\n },\n onUpdate: (props: SuggestionProps<SlashMenuItem>) => {\n renderer?.updateProps({\n items: props.items,\n query: props.query,\n command: props.command,\n });\n },\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (!renderer || isComposing(props.event, props.view)) return false;\n return renderer.ref?.onKeyDown(props.event) ?? false;\n },\n onExit: () => {\n unmountPopup?.();\n unmountPopup = null;\n renderer?.destroy();\n renderer = null;\n },\n }),\n }),\n ];\n },\n});\n","import type { ShortcutLabels } from '../labels';\n\n/**\n * 快捷键面板数据模型。keys 里的 'Mod' / 'Alt' 按平台渲染\n * (macOS: Cmd / Opt;其他: Ctrl / Alt)。\n * markdown.terminator 为触发终止键;无 terminator 的包裹型语法\n * (如 **x**)在键入收尾字符时即触发。\n */\nexport interface ShortcutEntry {\n id: string;\n /** 展示名(已本地化)。 */\n label: string;\n /** 键帽序列;不传表示无默认键位。 */\n keys?: string[];\n /** Markdown 触发写法;不传表示无对应 input rule。 */\n markdown?: {\n /** 触发片段,如 '**x**' 或 '#'。 */\n marker: string;\n /** 终止键(如 Space / Enter)。 */\n terminator?: string;\n };\n}\n\nexport interface ShortcutGroup {\n id: string;\n title: string;\n entries: ShortcutEntry[];\n}\n\n/**\n * 快捷键注册表。**每一条都必须真实**:键位来自所装 Tiptap 扩展的\n * addKeyboardShortcuts 默认值,markdown 触发来自对应 input rule\n * (上标/下标/链接在本库无默认键位与 input rule,故不列)。\n */\nexport function buildShortcutGroups(labels: ShortcutLabels): ShortcutGroup[] {\n return [\n {\n id: 'format',\n title: labels.formatGroup,\n entries: [\n { id: 'bold', label: labels.bold, keys: ['Mod', 'b'], markdown: { marker: '**x**' } },\n { id: 'italic', label: labels.italic, keys: ['Mod', 'i'], markdown: { marker: '*x*' } },\n { id: 'strike', label: labels.strike, keys: ['Mod', 'Shift', 's'], markdown: { marker: '~~x~~' } },\n { id: 'underline', label: labels.underline, keys: ['Mod', 'u'] },\n { id: 'inline-code', label: labels.inlineCode, keys: ['Mod', 'e'], markdown: { marker: '`x`' } },\n { id: 'highlight', label: labels.highlight, keys: ['Mod', 'Shift', 'h'], markdown: { marker: '==x==' } },\n ...([1, 2, 3, 4, 5, 6] as const).map((level): ShortcutEntry => ({\n id: `heading-${level}`,\n label: labels.headingLabel(level),\n keys: ['Mod', 'Alt', String(level)],\n markdown: { marker: '#'.repeat(level), terminator: 'Space' },\n })),\n { id: 'paragraph', label: labels.paragraph, keys: ['Mod', 'Alt', '0'] },\n ],\n },\n {\n id: 'insert',\n title: labels.insertGroup,\n entries: [\n { id: 'blockquote', label: labels.blockquote, keys: ['Mod', 'Shift', 'b'], markdown: { marker: '>', terminator: 'Space' } },\n { id: 'bullet-list', label: labels.bulletList, keys: ['Mod', 'Shift', '8'], markdown: { marker: '-', terminator: 'Space' } },\n { id: 'ordered-list', label: labels.orderedList, keys: ['Mod', 'Shift', '7'], markdown: { marker: '1.', terminator: 'Space' } },\n { id: 'task-list', label: labels.taskList, markdown: { marker: '[]', terminator: 'Space' } },\n { id: 'code-block', label: labels.codeBlock, markdown: { marker: '```', terminator: 'Space' } },\n { id: 'divider', label: labels.divider, markdown: { marker: '---', terminator: 'Space' } },\n ],\n },\n {\n id: 'edit',\n title: labels.editGroup,\n entries: [\n { id: 'undo', label: labels.undo, keys: ['Mod', 'z'] },\n { id: 'redo', label: labels.redo, keys: ['Mod', 'Shift', 'z'] },\n { id: 'hard-break', label: labels.hardBreak, keys: ['Shift', 'Enter'] },\n { id: 'find-replace', label: labels.findReplace, keys: ['Mod', 'f'] },\n ],\n },\n ];\n}\n","import { useEffect, useMemo } from 'react';\nimport { defaultShortcutLabels, type ShortcutLabels } from '../labels';\nimport { XIcon } from '../icons';\nimport styles from '../styles/shortcutPanel.module.css';\nimport { buildShortcutGroups, type ShortcutGroup } from './types';\n\nexport interface ShortcutPanelProps {\n open: boolean;\n onClose: () => void;\n /** 文案覆盖,与默认英文合并。 */\n labels?: Partial<ShortcutLabels>;\n}\n\nfunction isMacPlatform(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n}\n\n/** 键帽文案:Mod/Alt 按平台落名,单字母统一大写。 */\nfunction keycapText(key: string, mac: boolean): string {\n if (key === 'Mod') return mac ? 'Cmd' : 'Ctrl';\n if (key === 'Alt') return mac ? 'Opt' : 'Alt';\n if (/^[a-z]$/.test(key)) return key.toUpperCase();\n return key;\n}\n\n/**\n * 快捷键抽屉(语雀式):右侧滑出的三列对照表——格式 / 快捷键 / Markdown。\n * 数据来自 buildShortcutGroups(键位与 input rule 均为库内真实行为)。\n * 定位 fixed 贴视口右缘;Esc 关闭。\n */\nexport function ShortcutPanel({ open, onClose, labels }: ShortcutPanelProps) {\n const t: ShortcutLabels = useMemo(\n () => ({ ...defaultShortcutLabels, ...labels }),\n [labels],\n );\n\n // 打开期间 Esc 关闭\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open, onClose]);\n\n const groups: ShortcutGroup[] = useMemo(\n () => (open ? buildShortcutGroups(t) : []),\n [open, t],\n );\n const mac = useMemo(isMacPlatform, []);\n\n if (!open) return null;\n\n return (\n <aside\n className={styles.drawer}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={t.panelTitle}\n >\n <button\n type=\"button\"\n className={styles.closeBtn}\n title={t.close}\n aria-label={t.close}\n onClick={onClose}\n >\n <XIcon size={16} />\n </button>\n <div className={styles.head}>\n <span className={styles.colFormat}>{t.colFormat}</span>\n <span className={styles.colShortcut}>{t.colShortcut}</span>\n <span className={styles.colMarkdown}>{t.colMarkdown}</span>\n </div>\n <div className={styles.body}>\n {groups.map((group) => (\n <section key={group.id} className={styles.group}>\n <h3 className={styles.groupTitle}>{group.title}</h3>\n {group.entries.map((entry) => (\n <div key={entry.id} className={styles.row}>\n <span className={styles.rowLabel}>{entry.label}</span>\n <span className={styles.rowKeys}>\n {entry.keys ? (\n entry.keys.map((key, i) => (\n <kbd key={i} className={styles.keycap}>\n {keycapText(key, mac)}\n </kbd>\n ))\n ) : (\n <span className={styles.none}>—</span>\n )}\n </span>\n <span className={styles.rowMd}>\n {entry.markdown ? (\n <>\n <kbd className={styles.keycap}>{entry.markdown.marker}</kbd>\n {entry.markdown.terminator ? (\n <kbd className={styles.keycap}>{entry.markdown.terminator}</kbd>\n ) : null}\n </>\n ) : (\n <span className={styles.none}>—</span>\n )}\n </span>\n </div>\n ))}\n </section>\n ))}\n </div>\n </aside>\n );\n}\n","// 副作用:增强 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","import { Extension } from '@tiptap/core';\nimport { skipTrailingNodeMeta } from '@tiptap/extensions';\nimport type { Node } from '@tiptap/pm/model';\nimport { Plugin, PluginKey, type EditorState } from '@tiptap/pm/state';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\nimport type { Editor } from '@tiptap/react';\n\n/**\n * 「这段正在被 AI 改写」的高亮。\n *\n * 用 **decoration** 而不是 mark:两者都不会漏进 markdown,都能盖住表格,但 decoration\n * 不需要往 schema 里加标记、也不参与 undo 历史,而且**原子节点(图表 / 图片)也能盖**\n * ——mark 只作用于行内内容,盖不住 `atom: true` 的块级节点。\n *\n * 状态由宿主通过 `pendingAnchors` 推入(提交圈选改写时给上,回填或冲突时清空)。\n * 文档被编辑时装饰会跟着映射(在原文中间插字,高亮跟着变长;在前面插,整体后移)。\n */\nexport interface PendingAnchor {\n /** 宿主自己的标识(例如一次圈选请求的 request_id)。 */\n id: string;\n /** doc 坐标区间;通常是与选区相交的顶层块的首尾(见 getMarkdownForRange)。 */\n ranges: Array<{ from: number; to: number }>;\n}\n\nexport interface PendingAnchorState {\n decorations: DecorationSet;\n}\n\n/** 用 transaction meta 推入锚点:`tr.setMeta(PENDING_ANCHOR_META, anchors)`。 */\nexport const PENDING_ANCHOR_META = 'tmr:pendingAnchor';\n\nexport const pendingAnchorPluginKey = new PluginKey<PendingAnchorState>(\n 'tmrPendingAnchor',\n);\n\n/** 装饰上的 class;点击命中时宿主用 `[data-pending-id]` 取回 id。 */\nexport const PENDING_ANCHOR_CLASS = 'tmr-pending-anchor';\n\nexport const pendingAnchorExtension = Extension.create({\n name: 'pendingAnchor',\n\n addProseMirrorPlugins() {\n return [\n new Plugin<PendingAnchorState>({\n key: pendingAnchorPluginKey,\n state: {\n init: () => ({ decorations: DecorationSet.empty }),\n apply(tr, value) {\n const next = tr.getMeta(PENDING_ANCHOR_META) as\n | PendingAnchor[]\n | undefined;\n if (next) return { decorations: buildDecorations(tr.doc, next) };\n if (tr.docChanged) {\n return { decorations: value.decorations.map(tr.mapping, tr.doc) };\n }\n return value;\n },\n },\n props: {\n decorations(state: EditorState) {\n return pendingAnchorPluginKey.getState(state)?.decorations ?? null;\n },\n },\n }),\n ];\n },\n});\n\n/** 更新待改写高亮(传空数组即清空)。不进 undo 历史。 */\nexport function setPendingAnchors(editor: Editor, anchors: PendingAnchor[]): void {\n editor.view.dispatch(\n editor.state.tr\n .setMeta(PENDING_ANCHOR_META, anchors)\n // Tiptap 的 TrailingNode(StarterKit 自带)会在「第一个 transaction」时给文档末尾补一个\n // 空段落——只要文末是图表 / 表格 / 代码块这类节点。那是它本来的行为,但**不该由一次\n // 「加个高亮」触发**:那等于用户什么都没干、正文却多了个空段落(落库就变成结尾的 \\n\\n)。\n // 用官方 meta 跳过本次。\n .setMeta(skipTrailingNodeMeta, true)\n .setMeta('addToHistory', false),\n );\n}\n\nfunction buildDecorations(doc: Node, anchors: PendingAnchor[]): DecorationSet {\n const bounds: Array<{ from: number; to: number }> = [];\n doc.forEach((child, offset) => {\n bounds.push({ from: offset, to: offset + child.nodeSize });\n });\n\n const decorations: Decoration[] = [];\n for (const anchor of anchors) {\n for (const range of anchor.ranges) {\n const from = Math.max(0, Math.min(range.from, range.to));\n const to = Math.min(doc.content.size, Math.max(range.from, range.to));\n if (from >= to) continue;\n\n for (const bound of bounds) {\n if (bound.to <= from || bound.from >= to) continue;\n const attrs = {\n class: PENDING_ANCHOR_CLASS,\n 'data-pending-id': anchor.id,\n };\n if (from <= bound.from && to >= bound.to) {\n // 整块:用 node 装饰,表格 / 图表这类块级节点才盖得住\n decorations.push(Decoration.node(bound.from, bound.to, attrs));\n } else {\n // 块内的一部分(未扩块的选区):行内高亮\n decorations.push(\n Decoration.inline(Math.max(from, bound.from), Math.min(to, bound.to), attrs),\n );\n }\n }\n }\n }\n\n return decorations.length ? DecorationSet.create(doc, decorations) : DecorationSet.empty;\n}\n","import type { Selection } from '@tiptap/pm/state';\nimport { NodeSelection, TextSelection } from '@tiptap/pm/state';\nimport { CellSelection } from '@tiptap/pm/tables';\n\n/**\n * 选区类型——给宿主判断「用户选的是什么」用。\n *\n * - `text`:普通文字选区(含 AllSelection)\n * - `cell`:表格里的单元格选区(`CellSelection`,拖过表格时就是它)\n * - `node`:整节点选区(`NodeSelection`)。图表 / 图片 / 代码块这类 `atom` 节点只能这样被选中\n * ——它们在编辑器里渲染成图或块,用户没法用拖选文字的方式选中\n */\nexport type SelectionKind = 'text' | 'cell' | 'node';\n\nexport function selectionKind(selection: Selection): SelectionKind {\n if (selection instanceof CellSelection) return 'cell';\n if (selection instanceof NodeSelection) return 'node';\n if (selection instanceof TextSelection) return 'text';\n return 'text';\n}\n","// 副作用:增强 Editor.markdown(MarkdownManager)的类型。\nimport '@tiptap/markdown';\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\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 /<!--\\s*[\\[{][\\s\\S]*?\"chartType\"[\\s\\S]*?-->/.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 // 与 insertMarkdown / 初始 content 一致:先把\n // `<!-- chartType -->` + GFM 表收成 ```tmr-chart,否则\n // TipTap 会丢掉 HTML 注释,只剩普通表格。\n const json = markdown.parse(prepareChartMarkdown(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","'use client';\n\nimport type { Chart as ChartJs } from 'chart.js';\nimport {\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type MouseEvent,\n} from 'react';\nimport { destroyChart, renderOrUpdateChart } from '../chart/renderChart';\nimport type { ChartPayload, ChartTheme } from '../chart/types';\nimport { defaultChartLabels } from '../labels';\nimport '../styles/chart.css';\n\nfunction tabLabel(\n chartType: string,\n title: string | undefined,\n index: number,\n fallback: (type: string, i: number) => string,\n): string {\n if (title?.trim()) return title;\n return fallback(chartType, index);\n}\n\n/**\n * Chart NodeView: render + NodeSelection (like Image).\n * Config editing is intentionally disabled for now (no modal).\n */\nexport function ChartView({\n node,\n editor,\n extension,\n selected,\n getPos,\n}: NodeViewProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const chartRef = useRef<ChartJs | null>(null);\n const [active, setActive] = useState(0);\n\n const payload: ChartPayload = useMemo(\n () => ({\n config: (node.attrs.config ?? []) as ChartPayload['config'],\n columns: (node.attrs.columns ?? []) as ChartPayload['columns'],\n dataSource: (node.attrs.dataSource ??\n []) as ChartPayload['dataSource'],\n }),\n [node.attrs.config, node.attrs.columns, node.attrs.dataSource],\n );\n\n const theme = (extension.options.chartTheme ?? null) as ChartTheme | null;\n const configs = payload.config;\n const safeIndex = Math.min(active, Math.max(0, configs.length - 1));\n const config = configs[safeIndex];\n const height = config?.height ?? 320;\n const canSelect = Boolean(editor?.isEditable);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !config) return;\n chartRef.current = renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart: chartRef.current,\n });\n }, [config, payload, theme]);\n\n useEffect(() => {\n return () => {\n destroyChart(chartRef.current);\n chartRef.current = null;\n };\n }, []);\n\n // When active tab changes, recreate chart (type may differ)\n useEffect(() => {\n destroyChart(chartRef.current);\n chartRef.current = null;\n const canvas = canvasRef.current;\n if (!canvas || !config) return;\n chartRef.current = renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart: null,\n });\n }, [safeIndex]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const labels = {\n ...defaultChartLabels,\n ...(extension.options.chartLabels as\n | Partial<typeof defaultChartLabels>\n | undefined),\n };\n\n const selectChart = () => {\n if (!editor || !canSelect) return;\n const pos = getPos();\n if (typeof pos !== 'number') return;\n editor.commands.setNodeSelection(pos);\n };\n\n return (\n <NodeViewWrapper\n as=\"div\"\n className={`tmr-chart${canSelect ? ' tmr-chart--interactive' : ''}${\n selected ? ' ProseMirror-selectednode' : ''\n }`}\n data-type=\"chart\"\n data-selected={selected ? 'true' : undefined}\n contentEditable={false}\n onMouseDown={(e: MouseEvent) => {\n if ((e.target as HTMLElement).closest('button')) return;\n if (e.button !== 0) return;\n // Select node but do not preventDefault — Chart.js needs hover/click.\n selectChart();\n }}\n >\n {config?.title ? (\n <div className=\"tmr-chart-title\">{config.title}</div>\n ) : null}\n {config?.dataTime ? (\n <div className=\"tmr-chart-time\">{config.dataTime}</div>\n ) : null}\n {configs.length > 1 ? (\n <div className=\"tmr-chart-tabs\" role=\"tablist\">\n {configs.map((c, i) => (\n <button\n key={`${c.chartType}-${i}`}\n type=\"button\"\n role=\"tab\"\n className=\"tmr-chart-tab\"\n data-active={i === safeIndex ? 'true' : 'false'}\n aria-selected={i === safeIndex}\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation();\n setActive(i);\n }}\n >\n {tabLabel(c.chartType, c.title, i, labels.tabLabel)}\n </button>\n ))}\n </div>\n ) : null}\n <div className=\"tmr-chart-canvas-host\" style={{ height }}>\n <canvas ref={canvasRef} />\n </div>\n </NodeViewWrapper>\n );\n}\n","import { ReactNodeViewRenderer } from '@tiptap/react';\nimport { reportChart, type ReportChartOptions } from './ChartExtension';\nimport { ChartView } from '../components/ChartView';\nimport type { ChartTheme } from './types';\nimport type { ChartLabels } from '../labels';\n\nexport interface CreateChartOptions {\n /** When true, reserved for future in-place chart editing. Currently unused (no edit UI). Default false. */\n editable?: boolean;\n chartTheme?: ChartTheme | null;\n chartLabels?: Partial<ChartLabels>;\n}\n\nexport interface InteractiveChartOptions extends ReportChartOptions {\n chartEditable: boolean;\n chartTheme: ChartTheme | null;\n chartLabels?: Partial<ChartLabels>;\n}\n\n/**\n * Client chart extension with React NodeView.\n * Server / pure HTML paths should use {@link reportChart} / {@link pureChart}.\n */\nexport function createChart(options: CreateChartOptions = {}) {\n // Chart config editing (modal) is disabled for now; keep option for later.\n const { editable = false, chartTheme = null, chartLabels } = options;\n return reportChart.extend<InteractiveChartOptions>({\n addOptions() {\n return {\n HTMLAttributes: {},\n chartEditable: editable,\n chartTheme,\n chartLabels,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(ChartView);\n },\n });\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 { useEffect, useRef, useState } from 'react';\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronsUpDownIcon,\n CopyIcon,\n TrashIcon,\n} 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 *\n * 只读态(预览 / 只读编辑器)走另一套头部:左侧语言标签,右侧复制 + 展开收起;\n * 超出 `--tmr-code-max-height`(缺省 480px)的代码块默认限高块内滚动,行号槽\n * 用 MutationObserver 跟踪 PM 管理的 code 内容保持同步(纯文本变化不触发 React\n * 重渲染,gutter 行数靠观察器自刷新)。\n */\nexport function CodeBlockView({\n node,\n updateAttributes,\n deleteNode,\n extension,\n editor,\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 const editable = editor.isEditable;\n const readonly = !editable;\n\n const [copied, setCopied] = useState(false);\n const [folded, setFolded] = useState(false);\n const [lineCount, setLineCount] = useState(() =>\n Math.max((node.textContent ?? '').split('\\n').length, 1),\n );\n const preRef = useRef<HTMLPreElement | null>(null);\n\n // 流式更新只改 code 里的文本节点,React 不重渲染;观察 pre 子树同步行数。\n useEffect(() => {\n if (!readonly) return;\n const pre = preRef.current;\n if (!pre) return;\n const update = () => {\n setLineCount(Math.max((pre.textContent ?? '').split('\\n').length, 1));\n };\n update();\n const mo = new MutationObserver(update);\n mo.observe(pre, { childList: true, subtree: true, characterData: true });\n return () => mo.disconnect();\n }, [readonly]);\n\n const handleCopy = () => {\n const text = node.textContent ?? '';\n const done = () => {\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1500);\n };\n if (navigator.clipboard?.writeText) {\n navigator.clipboard.writeText(text).then(done, () => {});\n return;\n }\n // 剪贴板 API 不可用(非安全上下文 / 旧 webview):退化为 execCommand\n const ta = document.createElement('textarea');\n ta.value = text;\n document.body.appendChild(ta);\n ta.select();\n try {\n document.execCommand('copy');\n done();\n } catch {\n // 复制失败静默\n }\n ta.remove();\n };\n\n const wrapperClass = [\n styles.wrapper,\n readonly ? styles.readonly : '',\n folded ? styles.folded : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <NodeViewWrapper className={wrapperClass}>\n {editable ? (\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 ) : (\n // 只读头部:左侧语言标签,右侧复制 + 展开收起(展开后按钮保留,供收回)\n <div className={styles.readonlyHeader} contentEditable={false}>\n <span className={styles.langBadge}>\n <span className={styles.langBraces}>{'{}'}</span>\n {currentLabel}\n </span>\n <span className={styles.readonlyActions}>\n <button\n type=\"button\"\n className={styles.actionBtn}\n onClick={handleCopy}\n aria-label={labels.copy}\n title={labels.copy}\n >\n {copied ? <CheckIcon size={14} /> : <CopyIcon size={14} />}\n </button>\n <button\n type=\"button\"\n className={styles.actionBtn}\n onClick={() => setFolded((v) => !v)}\n aria-label={folded ? labels.expand : labels.collapse}\n title={folded ? labels.expand : labels.collapse}\n aria-expanded={!folded}\n >\n <ChevronsUpDownIcon size={14} />\n </button>\n </span>\n </div>\n )}\n <pre ref={preRef} className={styles.pre}>\n {readonly ? (\n <span\n className={styles.gutter}\n contentEditable={false}\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <span key={i} className={styles.gutterLine}>\n {i + 1}\n </span>\n ))}\n </span>\n ) : null}\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 FindAndReplace from '@tiptap/extension-find-and-replace';\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 { createPortal } from 'react-dom';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from 'react';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from '../citationUtils';\nimport type { RenderCitation } from '../citationTypes';\nimport { createCitationRef } from '../createCitationRef';\nimport { CommentMark } from '../commentAnchor/CommentMark';\nimport {\n COMMENT_ACTIVE_META,\n COMMENT_CLICK_META,\n COMMENT_GUTTER_META,\n commentAnchorExtension,\n} from '../commentAnchor/commentAnchorPlugin';\nimport {\n applyCommentAnchorsToEditor,\n collectCommentIds,\n focusComment,\n nextComment,\n} from '../commentAnchor/commentAnchorController';\nimport type {\n CommentClickPayload,\n CommentRef,\n} from '../commentAnchor/commentTypes';\nimport { baseExtensions, lowlight } from '../extensions';\nimport { FindReplaceBar } from './FindReplaceBar';\nimport { ImportPlaceholder } from '../importPlaceholder';\nimport type { CodeBlockLabels, FindLabels, ShortcutLabels, SlashMenuLabels } from '../labels';\nimport { defaultShortcutLabels } from '../labels';\nimport { SlashMenu } from '../slashMenu/SlashMenuExtension';\nimport { ShortcutPanel } from '../shortcuts/ShortcutPanel';\nimport { KeyboardIcon } from '../icons';\nimport { MarkdownFileDrop } from '../markdownFileDrop';\nimport {\n pendingAnchorExtension,\n setPendingAnchors,\n type PendingAnchor,\n} from '../pendingAnchor';\nimport { selectionKind, type SelectionKind } from '../selectionKind';\nimport { MarkdownPaste } from '../markdownPaste';\nimport { parseCodeTokenAsChartOrCodeBlock } from '../chart/codeBlockChartParse';\nimport { createChart } from '../chart/createChart';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport '../styles/chart.css';\nimport '../styles/pending.css';\nimport '../styles/find.css';\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 // Built-in `code` tokens often win over chart's custom fence tokenizer;\n // upgrade ```tmr-chart here so the mid-column card editor renders ChartView.\n parseMarkdown: (token, helpers) =>\n parseCodeTokenAsChartOrCodeBlock(token, helpers, 'codeBlock'),\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\n/** 浮动条相对其定位上下文的偏移(数字按 px)。内部路径的上下文是编辑器,portal 路径是宿主容器。 */\nexport interface FindBarOffset {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n}\n\nconst DEFAULT_FIND_BAR_OFFSET: FindBarOffset = { top: 4, right: 4 };\n\nfunction findBarOffsetStyle(offset: FindBarOffset): CSSProperties {\n const px = (v: number | string | undefined) =>\n typeof v === 'number' ? `${v}px` : v;\n return {\n position: 'absolute',\n top: px(offset.top),\n right: px(offset.right),\n bottom: px(offset.bottom),\n left: px(offset.left),\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 /** 聚焦评论:设 active + 滚动 + 光标落到区间起点。找不到返回 false。 */\n focusComment: (commentId: string) => boolean;\n /** 按文档顺序跳转评论(next / prev),返回目标 commentId。 */\n nextComment: (dir?: 'next' | 'prev') => string | null;\n /** 当前 doc 内已锚定的去重 commentId 列表(文档顺序)。 */\n getCommentIds: () => string[];\n /** 打开编辑器自带的查找浮动条(宿主自己绑快捷键/按钮时用)。findBar={false} 时不生效。 */\n openFind: () => void;\n /** 收起自带浮动条,清空高亮并把焦点还给编辑器。findBar={false} 时不生效。 */\n closeFind: () => void;\n}\n\nexport interface MarkdownWysiwygEditorProps {\n /** 初始 markdown 内容。 */\n initialMarkdown?: string;\n /**\n * 是否可编辑,默认 true。false = 只读渲染,与编辑态同源同路径:\n * 同一套扩展 / NodeView / 样式,交互件(代码块语言选择、删除等)自动收起。\n * 只读态不应用评论锚定(comments 被忽略),与 MarkdownPreview 语义一致。\n */\n editable?: boolean;\n /**\n * 初始脚注来源:按 index 对齐 `[^n]`,写入 citationRef 的 url/title。\n * 仅影响初始 content;后续插入请用 `insertMarkdown(editor, md, sources)`。\n */\n sources?: SourceRef[];\n /**\n * 脚注圆标 NodeView 插槽。消费方用 Popover 包住 `defaultDom`,\n * 用 `index` 查自己的数据源。仅初始化时生效。\n */\n renderCitation?: RenderCitation;\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 /**\n * 「这段正在被 AI 改写」的高亮:宿主在提交请求时给上、回填或冲突时传空数组清空。\n * 走 decoration,**不进 markdown、不进 undo 历史**,能盖住表格与图表这类块级节点。\n */\n pendingAnchors?: PendingAnchor[];\n /** 点击待改写高亮区域时回调,给出锚点 id(宿主可用来跳回/取消)。 */\n onAnchorClick?: (id: string) => void;\n /**\n * 选区变化。宿主用它做「选中即出现引用」——塌缩成光标也会报(`empty: true`),\n * 好让引用跟着消失;`kind` 区分普通文字 / 表格单元格 / 整节点(图表)。\n */\n onSelectionChange?: (selection: {\n from: number;\n to: number;\n empty: boolean;\n kind: SelectionKind;\n }) => void;\n /** 附加到滚动容器的 class。 */\n className?: string;\n /**\n * 编辑态评论锚定:评论列表(含已解码 segments)。装载时映射为 commentAnchor\n * mark 并高亮;markdown 导出自动剥离,只读态(MarkdownPreview)不渲染评论。\n * 注意:数组引用变化会触发重新铺 mark,宿主应 memo 该数组。\n */\n comments?: CommentRef[];\n /** 受控 active 评论 id(sidebar 联动)。null = 无 active。 */\n activeCommentId?: string | null;\n /** 编辑器内点击 mark / gutter 时回调。 */\n onCommentClick?: (payload: CommentClickPayload) => void;\n /** active 变化回调(点击 mark / gutter / nextComment 时)。 */\n onActiveCommentChange?: (commentId: string | null) => void;\n /** 是否在 block 左缘渲染评论 gutter 气泡,默认 true。 */\n showCommentGutter?: boolean;\n /**\n * 编辑器内点评论 mark 是否可交互(设 active / 上报 click),默认 true。\n * 只靠侧栏单项驱动滚动定位时传 false。\n */\n commentInteractive?: boolean;\n /**\n * 启用查找替换(默认 true):注册官方 `@tiptap/extension-find-and-replace`\n * (自带命令 `setSearchTerm / replace / replaceAll / goToNextResult …` 与\n * `editor.storage.findAndReplace`)。传 false 则连扩展一起不注册——此时命令与 storage 都不存在,\n * 宿主的自绘面板也无从驱动。\n */\n findReplace?: boolean;\n /**\n * 是否由编辑器渲染浮动条(默认跟随 {@link findReplace})。传 false = **定位交给宿主**:\n * 扩展照旧注册,但编辑器不出条子,宿主自己在任意位置渲染 `<FindReplaceBar editor={…} />`\n * (与工具栏同一套分工——组件归库,摆位归宿主)。此时 {@link findShortcut} 与\n * `handle.openFind/closeFind` 一并失效,因为内部没有条子可开。\n */\n findBar?: boolean;\n /**\n * 把自带的浮动条挂到宿主的容器里(antd `getPopupContainer` 那一套):给元素或返回元素的函数\n * 即可,开合状态与 Cmd/Ctrl+F 仍归库——只换挂载点。适合条子被 `overflow: hidden` 祖先裁掉、\n * 或想让它落在自己的头部 / 侧栏里。挂进去后**定位由宿主负责**(库不再加绝对定位),\n * 且容器若在主题子树之外,记得把 `--tmr-*` 变量也带到那里。\n * 返回 null / 不传时回落到编辑器内自带的浮动条。\n */\n findBarContainer?: HTMLElement | null | (() => HTMLElement | null);\n /**\n * 浮动条相对其定位上下文的偏移,默认 `{ top: 4, right: 4 }`(右上角)。数字按 px,也收 CSS 字符串。\n * 内部路径的上下文是编辑器(粘在滚动容器顶部的那层锚点),`findBarContainer` 路径的上下文是那个容器\n * ——那条路径下库会保证容器是定位上下文(computed position 为 static 时补 `position: relative`)。\n */\n findBarOffset?: FindBarOffset;\n /**\n * 焦点在编辑器内时接管 Cmd/Ctrl+F 打开**编辑器自带的**浮动条(默认 true;`findBar={false}`\n * 时不接管,免得抢了键却不弹东西)。传 false 则只保留 `handle.openFind()`——例如宿主想\n * 保留浏览器原生查找,或自己摆入口。焦点不在编辑器内时不接管,同页多编辑器不会互相抢。\n */\n findShortcut?: boolean;\n /** 查找替换浮动条的本地化文案。 */\n findLabels?: Partial<FindLabels>;\n /**\n * 启用快捷键抽屉:编辑器右下角出现键盘悬浮按钮,点开为\n * 「格式 / 快捷键 / Markdown」三列对照抽屉(默认 true,只读态隐藏)。\n */\n shortcutPanel?: boolean;\n /** 快捷键抽屉的本地化文案。 */\n shortcutLabels?: Partial<ShortcutLabels>;\n /**\n * 把快捷键悬浮键挂到宿主的容器里(与 `findBarContainer` 同一套):\n * 给元素或返回元素的函数即可,开合状态与抽屉归库——只换按钮落点。\n * 挂进去后**定位由宿主负责**(库不再给按钮加粘性定位与右下角外边距),\n * 适合把按钮叠在宿主自己的浮层控件旁边(如「回到顶部」按钮上方)。\n * 返回 null / 不传时回落到编辑器内容右下的粘性按钮。\n */\n shortcutFabContainer?: HTMLElement | null | (() => HTMLElement | null);\n /**\n * 启用斜杠菜单:键入 `/`(行首或空白后)唤起块级插入弹窗(默认 true)。\n * 代码块内不触发,表格单元格内触发;只读态不激活。\n * 追加自定义命令项请传 `extraExtensions` 注册 `SlashMenu.configure({ items })`。\n */\n slashMenu?: boolean;\n /** 斜杠菜单的本地化文案。 */\n slashMenuLabels?: Partial<SlashMenuLabels>;\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 editable = true,\n sources,\n renderCitation,\n placeholder,\n onEditorReady,\n onTocChange,\n markdownPaste = true,\n markdownFileDrop = true,\n extraExtensions,\n codeBlockLabels,\n className,\n comments,\n activeCommentId,\n onCommentClick,\n onActiveCommentChange,\n showCommentGutter = true,\n commentInteractive = true,\n pendingAnchors,\n onAnchorClick,\n onSelectionChange,\n findReplace = true,\n findBar = findReplace,\n findBarContainer,\n findBarOffset = DEFAULT_FIND_BAR_OFFSET,\n findShortcut = true,\n findLabels,\n slashMenu = true,\n slashMenuLabels,\n shortcutPanel = true,\n shortcutLabels,\n shortcutFabContainer,\n },\n ref,\n) {\n const preparedInitial = prepareChartMarkdown(\n enrichMarkdownCitations(initialMarkdown, sources ?? []),\n );\n\n const [findOpen, setFindOpen] = useState(false);\n const [shortcutsOpen, setShortcutsOpen] = useState(false);\n const findInputRef = useRef<HTMLInputElement | null>(null);\n\n const editor = useEditor({\n extensions: [\n ...baseExtensions,\n CodeBlock.configure({ lowlight, codeBlockLabels }),\n ImageWithConfirmDelete.configure({ inline: false }),\n ImportPlaceholder,\n createChart({ editable: false }),\n createCitationRef({ renderCitation }),\n CommentMark,\n commentAnchorExtension({\n showGutter: showCommentGutter,\n interactive: commentInteractive,\n }),\n Markdown,\n pendingAnchorExtension,\n // 官方查找替换:只出命令 / storage / 装饰,UI 自绘(见 FindReplaceBar)。\n // - injectCSS 关掉:它默认会往页面插一个 <style>,绕开宿主的 --tmr-* 主题与 style.css,\n // 命中样式改由 src/styles/find.css 承担。\n // - searchDebounceMs 关掉:官方防抖走 setTimeout,抛错会落在异步回调里兜不住;\n // 防抖改由浮动条自己做(见 findReplace.ts)。\n ...(findReplace\n ? [FindAndReplace.configure({ injectCSS: false, searchDebounceMs: 0 })]\n : []),\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 // 斜杠菜单(键入 / 唤起):默认开,只读态由 suggestion 状态机自身短路\n ...(slashMenu ? [SlashMenu.configure({ labels: slashMenuLabels })] : []),\n ...(extraExtensions ?? []),\n ],\n content: preparedInitial,\n contentType: 'markdown',\n editable,\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 // 运行时切换编辑/只读(同一实例,NodeView 交互件随 editor.isEditable 收起)。\n useEffect(() => {\n editor?.setEditable(editable);\n }, [editor, editable]);\n\n const closeFind = useCallback(() => {\n setFindOpen(false);\n // 焦点归还:Tiptap 的 focus 命令内部就是 requestAnimationFrame 延后执行的\n // (`delayedFocus`),正好落在 React 卸载浮动条之后——否则被卸载的输入框会把焦点丢给 body。\n editor?.commands.focus();\n }, [editor]);\n\n // Cmd/Ctrl+F → 打开查找条。接管条件必须收得比「焦点在编辑器内」松、比「谁都能接管」紧:\n // - 焦点在本编辑器内:接管 ✓\n // - 焦点不在任何输入控件里(body)且页面上只有本编辑器:接管 ✓(单编辑器页面点完工具栏按钮能直接按)\n // - 其余情况一律不接管:同页多编辑器时不会一起弹条(文档站就是这样),宿主的其它输入框\n // 也不会被夺走原生查找。多编辑器页面上宿主可自己调 handle.openFind()。\n // 只有容器里真有那条浮动条(findBar)时才绑:否则会白抢浏览器原生查找,却什么都不弹。\n useEffect(() => {\n if (!editor || !findReplace || !findBar || !findShortcut) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey) {\n return;\n }\n if (event.key !== 'f' && event.key !== 'F') return;\n const active = document.activeElement;\n const inEditor = !!active && editor.view.dom.contains(active);\n const nothingFocused = active === null || active === document.body;\n const soleEditor = document.querySelectorAll('.ProseMirror').length <= 1;\n if (!inEditor && !editor.isFocused && !(nothingFocused && soleEditor)) {\n return;\n }\n event.preventDefault();\n setFindOpen(true);\n // 已打开时再按一次:聚焦并全选当前查询(首次打开由浮动条的 autoFocus 负责)\n requestAnimationFrame(() => findInputRef.current?.select());\n };\n document.addEventListener('keydown', onKeyDown, true);\n return () => document.removeEventListener('keydown', onKeyDown, true);\n }, [editor, findReplace, findBar, findShortcut]);\n\n // 评论列表 → 铺 mark。用 commentId 签名做防抖:宿主每次渲染传新数组引用时\n // 不会反复清/铺(清空再重铺会丢掉 mark 随编辑移动后的位置)。\n const commentsSignatureRef = useRef<string>('');\n useEffect(() => {\n // 只读态不接评论(与库的「评论锚定 = 编辑会话专属」契约一致)。\n if (!editor || !editable) return;\n const signature = (comments ?? [])\n .map((c) => `${c.commentId}:${c.segments.length}`)\n .join('|');\n if (signature === commentsSignatureRef.current) return;\n commentsSignatureRef.current = signature;\n applyCommentAnchorsToEditor(editor, comments ?? []);\n }, [editor, editable, comments]);\n\n // active 同步到插件(mark/block 高亮装饰);滚动定位走 handle.focusComment。\n useEffect(() => {\n if (!editor) return;\n editor.view.dispatch(\n editor.state.tr.setMeta(\n COMMENT_ACTIVE_META,\n activeCommentId ?? null,\n ),\n );\n }, [editor, activeCommentId]);\n\n // 待改写高亮:会话级装饰,不进 markdown / 不进 undo(宿主推入,回填或冲突时清空)。\n useEffect(() => {\n if (!editor) return;\n setPendingAnchors(editor, pendingAnchors ?? []);\n }, [editor, pendingAnchors]);\n\n // 点击待改写高亮 → 上报锚点 id。走 DOM 监听而不是插件 meta:这里只要「点了哪一段」。\n const onAnchorClickRef = useRef(onAnchorClick);\n useEffect(() => {\n onAnchorClickRef.current = onAnchorClick;\n }, [onAnchorClick]);\n useEffect(() => {\n if (!editor) return;\n const dom = editor.view.dom;\n const onClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement | null;\n const id = target?.closest?.('[data-pending-id]')?.getAttribute('data-pending-id');\n if (id) onAnchorClickRef.current?.(id);\n };\n dom.addEventListener('click', onClick);\n return () => dom.removeEventListener('click', onClick);\n }, [editor]);\n\n // 选区变化:宿主据此做「选中即出现引用 / 引用跟着选区走」。\n const onSelectionChangeRef = useRef(onSelectionChange);\n useEffect(() => {\n onSelectionChangeRef.current = onSelectionChange;\n }, [onSelectionChange]);\n useEffect(() => {\n if (!editor) return;\n const onSelectionUpdate = () => {\n const { from, to, empty } = editor.state.selection;\n onSelectionChangeRef.current?.({\n from,\n to,\n empty,\n kind: selectionKind(editor.state.selection),\n });\n };\n editor.on('selectionUpdate', onSelectionUpdate);\n return () => {\n editor.off('selectionUpdate', onSelectionUpdate);\n };\n }, [editor]);\n\n // mark / gutter 点击 → 通过 transaction meta 上报宿主(回调走 ref 防 stale)。\n const onCommentClickRef = useRef(onCommentClick);\n const onActiveCommentChangeRef = useRef(onActiveCommentChange);\n onCommentClickRef.current = onCommentClick;\n onActiveCommentChangeRef.current = onActiveCommentChange;\n useEffect(() => {\n if (!editor) return;\n const onTransaction = ({\n transaction,\n }: {\n transaction: { getMeta: (key: string) => unknown };\n }) => {\n const click = transaction.getMeta(COMMENT_CLICK_META) as\n | CommentClickPayload\n | undefined;\n if (click) {\n onCommentClickRef.current?.(click);\n onActiveCommentChangeRef.current?.(click.commentIds[0] ?? null);\n }\n const gutter = transaction.getMeta(COMMENT_GUTTER_META) as\n | { commentIds: string[]; pos: number }\n | undefined;\n if (gutter) {\n onCommentClickRef.current?.({\n commentIds: gutter.commentIds,\n anchorEl: null,\n pos: gutter.pos,\n });\n onActiveCommentChangeRef.current?.(gutter.commentIds[0] ?? null);\n }\n };\n editor.on('transaction', onTransaction);\n return () => {\n editor.off('transaction', onTransaction);\n };\n }, [editor]);\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 focusComment: (commentId: string) =>\n editor ? focusComment(editor, commentId) : false,\n nextComment: (dir?: 'next' | 'prev') =>\n editor ? nextComment(editor, dir ?? 'next') : null,\n getCommentIds: () => (editor ? collectCommentIds(editor) : []),\n openFind: () => setFindOpen(true),\n closeFind,\n }),\n [editor, closeFind],\n );\n\n // 宿主指定了容器就把条子 portal 进去;解析不到则回落到编辑器内的粘性锚点。\n const findBarTarget =\n typeof findBarContainer === 'function'\n ? findBarContainer()\n : (findBarContainer ?? null);\n\n // 条子是绝对定位的:容器得先是定位上下文。宿主容器是 static 时补一个 relative——\n // 不补的话条子会以「最近的定位祖先」为基准(可能是页面),位置会莫名其妙。\n useEffect(() => {\n if (!findBarTarget) return;\n if (getComputedStyle(findBarTarget).position === 'static') {\n findBarTarget.style.position = 'relative';\n }\n }, [findBarTarget]);\n\n const findBarNode =\n editor && findBar && findOpen ? (\n <FindReplaceBar\n editor={editor}\n labels={findLabels}\n onClose={closeFind}\n inputRef={findInputRef}\n className={styles.findBar}\n style={findBarOffsetStyle(findBarOffset)}\n />\n ) : null;\n\n const shortcutT: ShortcutLabels = useMemo(\n () => ({ ...defaultShortcutLabels, ...shortcutLabels }),\n [shortcutLabels],\n );\n\n // 宿主指定了容器就把悬浮键 portal 进去(定位归宿主),解析不到回落编辑器内粘性按钮。\n // 用 layout effect(同步于提交后、绘制前)解析:函数形式读 ref 时首渲染拿到的是\n // null,等 DOM 提交后 ref 才就绪——这里在绘制前再解析一次,避免闪一帧编辑器内按钮;\n // setState 同值会 bail out,不会死循环。\n const [shortcutFabTarget, setShortcutFabTarget] = useState<HTMLElement | null>(\n null,\n );\n const useIsoLayoutEffect =\n typeof window === 'undefined' ? useEffect : useLayoutEffect;\n useIsoLayoutEffect(() => {\n const target =\n typeof shortcutFabContainer === 'function'\n ? shortcutFabContainer()\n : (shortcutFabContainer ?? null);\n setShortcutFabTarget((prev) => (prev === target ? prev : target));\n });\n\n const shortcutFabNode =\n shortcutPanel && editable ? (\n <button\n type=\"button\"\n className={\n shortcutFabTarget\n ? `${styles.shortcutFab} ${styles.shortcutFabHosted}`\n : styles.shortcutFab\n }\n title={shortcutT.panelTitle}\n aria-label={shortcutT.panelTitle}\n aria-expanded={shortcutsOpen}\n onClick={() => setShortcutsOpen((v) => !v)}\n >\n <KeyboardIcon size={18} />\n </button>\n ) : null;\n\n return (\n <div className={styles.editorHost}>\n {/* 粘性锚点排在正文之前:浮动条跟着最近的滚动容器走,正文滚动时不会被卷上去 */}\n {findBarNode && !findBarTarget ? (\n <div className={styles.findBarAnchor}>{findBarNode}</div>\n ) : null}\n {findBarNode && findBarTarget\n ? createPortal(findBarNode, findBarTarget)\n : null}\n <EditorContent\n editor={editor}\n className={\n className ? `${styles.editorScroll} ${className}` : styles.editorScroll\n }\n />\n {/* 快捷键抽屉入口:默认 sticky-bottom 悬浮在可视区右下;\n 宿主给了 shortcutFabContainer 就 portal 进去,定位归宿主。只读态隐藏 */}\n {shortcutFabNode && shortcutFabTarget\n ? createPortal(shortcutFabNode, shortcutFabTarget)\n : shortcutFabNode}\n {shortcutPanel && editable ? (\n <ShortcutPanel\n open={shortcutsOpen}\n onClose={() => setShortcutsOpen(false)}\n labels={shortcutLabels}\n />\n ) : null}\n </div>\n );\n});\n","'use client';\n\nimport { Markdown } from '@tiptap/markdown';\nimport { EditorContent, ReactNodeViewRenderer, useEditor } from '@tiptap/react';\nimport { useEffect, useMemo } from 'react';\nimport { createChart } from '../chart/createChart';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from '../citationUtils';\nimport type { RenderCitation } from '../citationTypes';\nimport { createCitationRef } from '../createCitationRef';\nimport { baseExtensions, pureCodeBlock, pureImage } from '../extensions';\nimport { CodeBlockView } from './CodeBlockView';\nimport '../styles/chart.css';\nimport styles from '../styles/content.module.css';\n\nexport interface MarkdownPreviewProps {\n /** 要预览的 markdown 字符串。 */\n markdown: string;\n /**\n * 脚注来源列表:按 `index` 与正文 `[^n]` 对齐,写入节点的 url/title。\n * 业务数据与 Popover 仍由消费方通过 {@link renderCitation} 完成。\n */\n sources?: SourceRef[];\n /**\n * 脚注圆标 NodeView 插槽。用 Popover 等包住 `defaultDom`;\n * 用 `index` / `attrs` 查消费方自己的数据源。\n */\n renderCitation?: RenderCitation;\n className?: string;\n}\n\n/**\n * 轻量只读 markdown 预览(Tiptap + 官方 @tiptap/markdown,editable:false)。\n * 与 MarkdownWysiwygEditor 共用同一套 base 扩展与正文样式类,渲染同源——\n * 预览所见即编辑/插入后所得。用纯版 CodeBlock/Image(无 React 视图 / 删除快捷键);\n * 图表用只读 NodeView(可渲染,不可编辑弹层)。\n *\n * 这是「客户端只读预览」;若需 SEO / 无 JS 静态渲染,请改用 server 入口的\n * renderReportHtml + ReportContent / ReportContentWithCharts。\n */\nexport function MarkdownPreview({\n markdown,\n sources,\n renderCitation,\n className,\n}: MarkdownPreviewProps) {\n const prepared = useMemo(\n () =>\n prepareChartMarkdown(\n enrichMarkdownCitations(markdown, sources ?? []),\n ),\n [markdown, sources],\n );\n\n // 预览代码块挂只读 NodeView(语言标签 + 复制 + 展开收起 + 行号槽)。\n // 仅客户端入口挂;server 入口(renderReportHtml)保持纯版,静态 HTML 零 React 依赖。\n const previewCodeBlock = useMemo(\n () =>\n pureCodeBlock.extend({\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n }),\n [],\n );\n\n const extensions = useMemo(\n () => [\n ...baseExtensions,\n previewCodeBlock,\n pureImage,\n createChart({ editable: false }),\n createCitationRef({ renderCitation }),\n Markdown,\n ],\n [renderCitation],\n );\n\n const editor = useEditor(\n {\n extensions,\n content: prepared,\n contentType: 'markdown',\n editable: false,\n immediatelyRender: false,\n editorProps: {\n attributes: { class: styles.editorContent },\n },\n },\n [extensions],\n );\n\n // 文档尾随空段不在这里处理:它是 StarterKit 的 TrailingNode 补的(文末是代码块/\n // 表格/图表时),事后删节点会被它重建;改成 appendTransaction 里删则会与它互相\n // 触发形成死循环。只读预览由消费方用 CSS 隐藏该空段即可。\n\n useEffect(() => {\n if (!editor) return;\n editor.commands.setContent(prepared, { contentType: 'markdown' });\n }, [editor, prepared]);\n\n return (\n <EditorContent\n editor={editor}\n className={className ?? styles.editorScroll}\n />\n );\n}\n","import type { ToolbarLabels } from './labels';\n\n/** 包内唯一识别的扩展名:命中即本地读文本,其余一律交给宿主回调。 */\nexport const MD_FILE_RE = /\\.(md|markdown)$/i;\nexport const MD_ACCEPT = '.md,.markdown,text/markdown';\n\n/** 主栏导入下拉里的一项。`accept` 写到隐藏 file input。 */\nexport interface ImportMenuItem {\n key: string;\n label: string;\n accept: string;\n}\n\nexport function resolveImportMenuItems({\n labels,\n onImportDocument,\n importAccept,\n importMenuItems,\n}: {\n labels: ToolbarLabels;\n onImportDocument?: unknown;\n importAccept?: string;\n importMenuItems?: ImportMenuItem[];\n}): ImportMenuItem[] {\n if (importMenuItems?.length) return importMenuItems;\n const markdown: ImportMenuItem = {\n key: 'markdown',\n label: labels.importMarkdown,\n accept: MD_ACCEPT,\n };\n if (onImportDocument && importAccept) {\n return [\n markdown,\n {\n key: 'document',\n label: labels.importDocumentOther,\n accept: importAccept,\n },\n ];\n }\n return [markdown];\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from './citationUtils';\n\n/**\n * 在光标处插入 markdown 片段(封装 contentType: 'markdown')。\n * 传入 `sources` 时会先 enrich `[^n]` → 带 url 的 citation-ref,再插入。\n *\n * 整段过不了 schema(嵌套 bold、块级图进 listItem 等)时按块重试,\n * 单块仍挂则剥标记当段落。某一处脏输出不至于整次插入失败。\n */\nexport function insertMarkdown(\n editor: Editor,\n markdown: string,\n sources: SourceRef[] = [],\n): void {\n const prepared = prepareChartMarkdown(\n enrichMarkdownCitations(markdown, sources),\n );\n if (!prepared) return;\n if (tryInsertMarkdown(editor, prepared)) return;\n for (const block of splitTopLevelBlocks(prepared)) {\n if (tryInsertMarkdown(editor, block)) continue;\n insertPlainParagraph(editor, stripToPlainText(block));\n }\n}\n\nfunction tryInsertMarkdown(editor: Editor, markdown: string): boolean {\n try {\n return editor\n .chain()\n .focus()\n .insertContent(markdown, { contentType: 'markdown' })\n .run();\n } catch {\n return false;\n }\n}\n\nfunction insertPlainParagraph(editor: Editor, text: string): void {\n if (!text) return;\n editor\n .chain()\n .focus()\n .insertContent({\n type: 'paragraph',\n content: [{ type: 'text', text }],\n })\n .run();\n}\n\n/** 围栏代码整块留下,其余按空行切。 */\nexport function splitTopLevelBlocks(markdown: string): string[] {\n const out: string[] = [];\n for (const [i, part] of markdown.split(/(```[\\s\\S]*?```)/).entries()) {\n if (!part) continue;\n if (i % 2 === 1) {\n out.push(part);\n continue;\n }\n for (const block of part.split(/\\n{2,}/)) {\n if (block.trim()) out.push(block);\n }\n }\n return out;\n}\n\nexport function stripToPlainText(markdown: string): string {\n return markdown\n .replace(/!\\[[^\\]]*\\]\\([^)]+\\)/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\n .replace(/^#{1,6}\\s+/gm, '')\n .replace(/^[ \\t]*[-*+]\\s+/gm, '')\n .replace(/^[ \\t]*\\d+\\.\\s+/gm, '')\n .replace(/[*_~`]+/g, '')\n .replace(/<[^>]+>/g, '')\n .replace(/\\|/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n","import type { Editor } from '@tiptap/core';\nimport type { EditorState } from '@tiptap/pm/state';\nimport {\n CellSelection,\n isInTable,\n rowIsHeader,\n selectedRect,\n} from '@tiptap/pm/tables';\n\nexport interface TableSelectionInfo {\n rowCount: number;\n colCount: number;\n /** 选区跨越多行或多列时为 true(用于带 N 的文案)。 */\n isMultiCell: boolean;\n includesHeaderRow: boolean;\n coversAllRows: boolean;\n coversAllCols: boolean;\n}\n\n/** 当前若不在表格内返回 null。 */\nexport function getTableSelectionInfo(\n state: EditorState,\n): TableSelectionInfo | null {\n if (!isInTable(state)) return null;\n\n const rect = selectedRect(state);\n const rowCount = Math.max(1, rect.bottom - rect.top);\n const colCount = Math.max(1, rect.right - rect.left);\n\n let includesHeaderRow = false;\n for (let row = rect.top; row < rect.bottom; row++) {\n if (rowIsHeader(rect.map, rect.table, row)) {\n includesHeaderRow = true;\n break;\n }\n }\n\n return {\n rowCount,\n colCount,\n isMultiCell: rowCount > 1 || colCount > 1,\n includesHeaderRow,\n coversAllRows: rect.top === 0 && rect.bottom === rect.map.height,\n coversAllCols: rect.left === 0 && rect.right === rect.map.width,\n };\n}\n\n/** 文档坐标是否落在 CellSelection 覆盖的某个单元格内(含单元格节点本身)。 */\nexport function isPosInCellSelection(\n selection: CellSelection,\n pos: number,\n): boolean {\n let found = false;\n selection.forEachCell((node, cellPos) => {\n if (pos >= cellPos && pos <= cellPos + node.nodeSize) {\n found = true;\n }\n });\n return found;\n}\n\n/**\n * 表内右键:若点击落在已有多格选区内则保留选区;\n * 否则把光标落到点击位置(单格操作)。\n */\nexport function preserveTableSelectionOnContextMenu(\n editor: Editor,\n pos: number,\n): void {\n const { selection } = editor.state;\n if (\n selection instanceof CellSelection &&\n isPosInCellSelection(selection, pos)\n ) {\n editor.view.focus();\n return;\n }\n editor.chain().focus().setTextSelection(pos).run();\n}\n\nexport function addRowsBefore(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addRowBefore()) return false;\n }\n return true;\n}\n\nexport function addRowsAfter(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addRowAfter()) return false;\n }\n return true;\n}\n\nexport function addColumnsBefore(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addColumnBefore()) return false;\n }\n return true;\n}\n\nexport function addColumnsAfter(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addColumnAfter()) return false;\n }\n return true;\n}\n\n/** 删行:全表行被选中时改为删整表;含表头时调用方应先禁用。 */\nexport function deleteSelectedRows(editor: Editor): boolean {\n const info = getTableSelectionInfo(editor.state);\n if (!info) return false;\n if (info.coversAllRows) return editor.commands.deleteTable();\n return editor.commands.deleteRow();\n}\n\n/** 删列:选区覆盖全部列且同时覆盖全部行时删整表;仅覆盖全部列时失败(由 UI 禁用)。 */\nexport function deleteSelectedColumns(editor: Editor): boolean {\n const info = getTableSelectionInfo(editor.state);\n if (!info) return false;\n if (info.coversAllCols) {\n if (info.coversAllRows) return editor.commands.deleteTable();\n return false;\n }\n return editor.commands.deleteColumn();\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 type { Editor } from '@tiptap/react';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { renderMathInto, type MathKind } from '../math';\nimport styles from '../styles/toolbar.module.css';\n\nexport interface MathEditorPopoverProps {\n editor: Editor;\n kind: MathKind;\n mode: 'insert' | 'edit';\n pos?: number;\n latex: string;\n /** 工具栏新插入:取消时删掉占位节点 */\n isNew?: boolean;\n newLabel: string;\n placeholder: string;\n doneLabel: string;\n onConfirm: (latex: string) => void;\n onCancel: () => void;\n}\n\nfunction resolveNodeEl(editor: Editor, pos: number): HTMLElement | null {\n const dom = editor.view.nodeDOM(pos);\n if (dom instanceof HTMLElement) return dom;\n if (dom instanceof Node) return dom.parentElement;\n return null;\n}\n\nfunction mathRenderTarget(el: HTMLElement, isBlock: boolean): HTMLElement {\n if (!isBlock) return el;\n return (el.querySelector('.block-math-inner') as HTMLElement | null) ?? el;\n}\n\nfunction getMathLayerStyle(\n editor: Editor,\n kind: MathKind,\n pos?: number,\n): CSSProperties {\n const host = editor.view.dom.parentElement;\n if (!host) return {};\n const hostRect = host.getBoundingClientRect();\n const editorRect = editor.view.dom.getBoundingClientRect();\n const gap = 6;\n const blockWidth = editor.view.dom.clientWidth;\n\n if (pos != null) {\n const el = resolveNodeEl(editor, pos);\n if (el) {\n const r = el.getBoundingClientRect();\n const top = r.bottom - hostRect.top + gap;\n if (kind === 'block') {\n return {\n left: editorRect.left - hostRect.left,\n top,\n width: blockWidth,\n };\n }\n return {\n left: r.left - hostRect.left,\n top,\n };\n }\n }\n\n const coords = editor.view.coordsAtPos(editor.state.selection.from);\n if (kind === 'block') {\n return {\n left: editorRect.left - hostRect.left,\n top: coords.bottom - hostRect.top + gap,\n width: blockWidth,\n };\n }\n return {\n left: coords.left - hostRect.left,\n top: coords.bottom - hostRect.top + gap,\n };\n}\n\nexport function MathEditorPopover({\n editor,\n kind,\n mode,\n pos,\n latex,\n isNew = false,\n newLabel,\n placeholder,\n doneLabel,\n onConfirm,\n onCancel,\n}: MathEditorPopoverProps) {\n const [draft, setDraft] = useState(latex);\n const [layerStyle, setLayerStyle] = useState<CSSProperties>(() =>\n getMathLayerStyle(editor, kind, pos),\n );\n const titleId = useId();\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const isBlock = kind === 'block';\n const host = editor.view.dom.parentElement;\n\n useEffect(() => {\n setDraft(latex);\n }, [latex]);\n\n useEffect(() => {\n const update = () => setLayerStyle(getMathLayerStyle(editor, kind, pos));\n update();\n window.addEventListener('resize', update);\n return () => window.removeEventListener('resize', update);\n }, [editor, kind, pos, draft]);\n\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n useEffect(() => {\n if (pos == null) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n el.classList.add('tmr-math-editing');\n return () => {\n el.classList.remove('tmr-math-editing');\n };\n }, [editor, pos]);\n\n useEffect(() => {\n if (pos == null) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n const target = mathRenderTarget(el, isBlock);\n const src = draft.trim();\n if (src) renderMathInto(target, src, isBlock);\n else target.textContent = '';\n }, [draft, pos, editor, isBlock]);\n\n useEffect(() => {\n if (pos == null || isNew) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n const target = mathRenderTarget(el, isBlock);\n return () => {\n const restore = latex.trim();\n if (restore) renderMathInto(target, restore, isBlock);\n else target.textContent = '';\n };\n }, [pos, editor, isBlock, latex, isNew]);\n\n useEffect(() => {\n const onPtr = (e: PointerEvent) => {\n const target = e.target;\n if (!(target instanceof Node)) return;\n if (rootRef.current?.contains(target)) return;\n if (pos != null) {\n const el = resolveNodeEl(editor, pos);\n if (el?.contains(target)) return;\n }\n onCancel();\n };\n document.addEventListener('pointerdown', onPtr);\n return () => document.removeEventListener('pointerdown', onPtr);\n }, [onCancel, editor, pos]);\n\n const canSubmit = draft.trim().length > 0;\n const showHint = !canSubmit && (mode === 'insert' || isNew);\n\n const submit = () => {\n if (!canSubmit) return;\n onConfirm(draft.trim());\n };\n\n const onKeyDown = (\n e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n return;\n }\n if (e.key !== 'Enter') return;\n if (isBlock && !(e.metaKey || e.ctrlKey)) return;\n e.preventDefault();\n submit();\n };\n\n const field = isBlock ? (\n <textarea\n ref={inputRef as RefObject<HTMLTextAreaElement>}\n className={styles.mathInput}\n value={draft}\n placeholder={placeholder}\n rows={Math.max(3, draft.split('\\n').length)}\n aria-labelledby={titleId}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n />\n ) : (\n <input\n ref={inputRef as RefObject<HTMLInputElement>}\n className={styles.mathInput}\n value={draft}\n placeholder={placeholder}\n aria-labelledby={titleId}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n />\n );\n\n if (!host) return null;\n\n return createPortal(\n <div\n ref={rootRef}\n className={styles.mathLayer}\n style={layerStyle}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-labelledby={titleId}\n >\n <div\n className={\n isBlock\n ? `${styles.mathStack} ${styles.mathStackBlock}`\n : styles.mathStack\n }\n >\n {showHint ? (\n <div\n id={titleId}\n className={\n isBlock\n ? `${styles.mathHint} ${styles.mathHintBlock}`\n : styles.mathHint\n }\n >\n <span className={styles.mathHintIcon} aria-hidden>\n {isBlock ? 'TeX' : '√x'}\n </span>\n {newLabel}\n </div>\n ) : null}\n <div\n id={showHint ? undefined : titleId}\n className={\n isBlock\n ? `${styles.mathField} ${styles.mathFieldBlock}`\n : styles.mathField\n }\n >\n {field}\n <button\n type=\"button\"\n className={styles.mathDone}\n disabled={!canSubmit}\n title={\n isBlock ? `${doneLabel} (⌘/Ctrl+Enter)` : `${doneLabel} (Enter)`\n }\n onClick={submit}\n >\n {doneLabel}\n <span className={styles.mathDoneKbd} aria-hidden>\n ↵\n </span>\n </button>\n </div>\n </div>\n </div>,\n host,\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 TableDeleteIcon,\n UnderlineIcon,\n UndoIcon,\n} from '../icons';\nimport { defaultToolbarLabels, type ToolbarLabels } from '../labels';\nimport {\n MD_FILE_RE,\n resolveImportMenuItems,\n type ImportMenuItem,\n} from '../importMenu';\nimport type { SourceRef } from '../citationUtils';\nimport { insertMarkdown } from '../insertMarkdown';\nimport { subscribeMathClick, type MathKind } from '../math';\nimport {\n addColumnsAfter,\n addColumnsBefore,\n addRowsAfter,\n addRowsBefore,\n deleteSelectedColumns,\n deleteSelectedRows,\n getTableSelectionInfo,\n preserveTableSelectionOnContextMenu,\n} from '../tableSelection';\nimport styles from '../styles/toolbar.module.css';\nimport { ColorPalette } from './ColorPalette';\nimport { MathEditorPopover } from './MathEditorPopover';\n\n/** `onImportDocument` 的成功返回。给字符串等价于 `{ markdown }`。 */\nexport interface ImportDocumentResult {\n markdown: string;\n sources?: SourceRef[];\n}\n\n/** 导入进度。包用来更新光标占位文案并禁用导入按钮。 */\nexport interface ImportDocumentProgress {\n /** 0–1。通常只有上传阶段可测;转换阶段可省略。 */\n ratio?: number;\n phase: 'upload' | 'convert';\n}\n\nexport interface ImportDocumentContext {\n /** 用户点取消或组件卸载时 abort,宿主据此中断请求。 */\n signal: AbortSignal;\n onProgress?: (p: ImportDocumentProgress) => void;\n}\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(..., 'image')。\n */\n onImageUpload?: (file: File) => Promise<string>;\n /**\n * 副作用错误回调(图片上传 / Markdown 导入失败),供宿主弹自己的提示。\n * `source` 区分来源,避免一律显示「图片上传失败」。\n */\n onError?: (err: unknown, source?: 'image' | 'markdown' | 'import') => void;\n /**\n * 非 Markdown 文件的转换:收到文件,返回可插入的 Markdown。未提供则导入只吃 .md。\n * 包内不校验扩展名——格式白名单由宿主的 `importAccept` 与本回调自己负责。\n * 抛错转交 onError(..., 'import');`AbortError` 视为用户取消,不报错。\n */\n onImportDocument?: (\n file: File,\n ctx: ImportDocumentContext,\n ) => Promise<ImportDocumentResult | string>;\n /**\n * 追加到导入 input 的 accept(默认已含 `.md,.markdown,text/markdown`)。\n * 例:`.doc,.docx,.csv,.pdf`。未传 `importMenuItems` 且传了 `onImportDocument` 时,\n * 下拉会多一项「Document」。\n */\n importAccept?: string;\n /**\n * 主栏导入下拉的选项。不传则 Markdown;再加 `onImportDocument` + `importAccept`\n * 时多一项 Document。宿主要拆成 Word / PDF 时自己传入。\n */\n importMenuItems?: ImportMenuItem[];\n /** 是否显示导入下拉,默认 `true`。卡片等场景可关掉。 */\n showImport?: boolean;\n labels?: Partial<ToolbarLabels>;\n /** 追加到 More 菜单末尾的自定义项。 */\n extraToolbarItems?: ExtraToolbarItem[];\n className?: string;\n}\n\nexport type { ImportMenuItem };\n\n/** 单个工具栏按钮:激活态高亮,disabled 时灰显。 */\nfunction ToolbarButton({\n title,\n active,\n disabled,\n busy,\n onClick,\n children,\n}: {\n title: string;\n active?: boolean;\n disabled?: boolean;\n busy?: 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 aria-busy={busy}\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\nfunction TableMenuItem({\n label,\n disabled,\n onClick,\n children,\n}: {\n label: string;\n disabled?: boolean;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n className={styles.tableMenuItem}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onClick}\n >\n <span className={styles.tableMenuItemIcon} aria-hidden>\n {children}\n </span>\n <span className={styles.tableMenuItemLabel}>{label}</span>\n </button>\n );\n}\n\nfunction TableMenuDivider() {\n return <div className={styles.tableMenuDivider} 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\nconst TABLE_PICKER_COLS = 10;\nconst TABLE_PICKER_ROWS = 8;\n\n/**\n * More 菜单里的「插入表格」:二级面板用网格悬停选行列,点击插入。\n * 保持 Popover(不夺编辑器焦点),与 MenuItem 一致。\n */\nfunction TableInsertItem({\n disabled,\n labels,\n onInsert,\n}: {\n disabled?: boolean;\n labels: Pick<ToolbarLabels, 'tableInsert' | 'tableSizeSelected'>;\n onInsert: (rows: number, cols: number) => void;\n}) {\n const closeMenu = useContext(MenuCloseCtx);\n const [open, setOpen] = useState(false);\n const [hover, setHover] = useState({ cols: 0, rows: 0 });\n\n const resetHover = useCallback(() => setHover({ cols: 0, rows: 0 }), []);\n\n return (\n <Popover.Root\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) resetHover();\n }}\n >\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n disabled={disabled}\n className={`${styles.menuItem} ${open ? styles.menuItemSelected : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>⊞</span>\n {labels.tableInsert}\n </span>\n <ChevronDownIcon size={12} className={styles.tableInsertCaret} />\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.tableSizePicker}\n side=\"right\"\n align=\"start\"\n sideOffset={6}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <div\n className={styles.tableSizeGrid}\n style={{\n gridTemplateColumns: `repeat(${TABLE_PICKER_COLS}, 1fr)`,\n }}\n onMouseLeave={resetHover}\n >\n {Array.from({ length: TABLE_PICKER_ROWS * TABLE_PICKER_COLS }, (_, i) => {\n const col = (i % TABLE_PICKER_COLS) + 1;\n const row = Math.floor(i / TABLE_PICKER_COLS) + 1;\n const active = hover.cols > 0 && col <= hover.cols && row <= hover.rows;\n return (\n <button\n key={i}\n type=\"button\"\n aria-label={labels.tableSizeSelected(col, row)}\n className={`${styles.tableSizeCell} ${active ? styles.tableSizeCellActive : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n onMouseEnter={() => setHover({ cols: col, rows: row })}\n onClick={() => {\n onInsert(row, col);\n setOpen(false);\n resetHover();\n closeMenu();\n }}\n />\n );\n })}\n </div>\n <div className={styles.tableSizeLabel}>\n {hover.cols > 0\n ? labels.tableSizeSelected(hover.cols, hover.rows)\n : labels.tableInsert}\n </div>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\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 onImportDocument,\n importAccept,\n importMenuItems,\n showImport = true,\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 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 // 多格选区内右键:保留 CellSelection;选区外才落到点击位\n preserveTableSelectionOnContextMenu(editor, coords.pos);\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 const tableSel = tableMenu ? getTableSelectionInfo(editor.state) : null;\n const tableRowN = tableSel?.rowCount ?? 1;\n const tableColN = tableSel?.colCount ?? 1;\n const tableMulti = tableSel?.isMultiCell ?? false;\n const disableAddRowBefore = !!tableSel?.includesHeaderRow;\n const disableDeleteRow = !!tableSel?.includesHeaderRow;\n const disableDeleteColumn =\n !!tableSel?.coversAllCols && !tableSel?.coversAllRows;\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, 'image');\n }\n };\n\n // ── 导入:.md 包内读文本插入;其余原样交给宿主 onImportDocument ──\n const importInputRef = useRef<HTMLInputElement>(null);\n const [importing, setImporting] = useState<ImportDocumentProgress | null>(\n null,\n );\n const importAbortRef = useRef<AbortController | null>(null);\n\n // 卸载(如切路由)中断在飞的导入,避免请求泄漏与卸载后 setState\n useEffect(() => () => importAbortRef.current?.abort(), []);\n\n const handleImportChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file) return;\n\n if (MD_FILE_RE.test(file.name)) {\n try {\n insertMarkdown(editor, await file.text());\n } catch (err) {\n console.error('markdown import failed:', err);\n onError?.(err, 'markdown');\n }\n return;\n }\n\n if (!onImportDocument) {\n onError?.(new Error(`unsupported file: ${file.name}`), 'import');\n return;\n }\n\n const ctrl = new AbortController();\n importAbortRef.current = ctrl;\n setImporting({ phase: 'upload', ratio: 0 });\n const labelOf = (p: ImportDocumentProgress) =>\n p.phase === 'convert'\n ? t.importDocumentConverting\n : t.importDocumentUploading(Math.round((p.ratio ?? 0) * 100));\n editor.commands.insertImportPlaceholder(labelOf({ phase: 'upload', ratio: 0 }));\n try {\n const raw = await onImportDocument(file, {\n signal: ctrl.signal,\n onProgress: (p) => {\n if (ctrl.signal.aborted) return;\n setImporting(p);\n editor.commands.updateImportPlaceholder(labelOf(p));\n },\n });\n editor.commands.removeImportPlaceholder();\n const md = typeof raw === 'string' ? raw : raw.markdown;\n const sources = typeof raw === 'string' ? [] : raw.sources ?? [];\n insertMarkdown(editor, md, sources);\n } catch (err) {\n editor.commands.removeImportPlaceholder();\n // 卸载 abort 不算错误\n if (!ctrl.signal.aborted) {\n console.error('document import failed:', err);\n onError?.(err, 'import');\n }\n } finally {\n if (importAbortRef.current === ctrl) importAbortRef.current = null;\n setImporting(null);\n }\n };\n\n const importItems = resolveImportMenuItems({\n labels: t,\n onImportDocument,\n importAccept,\n importMenuItems,\n });\n\n const pickImport = (accept: string) => {\n const input = importInputRef.current;\n if (!input) return;\n input.accept = accept;\n input.value = '';\n input.click();\n };\n\n // 进度写在光标占位上;按钮只区分空闲 / 忙碌。\n const importTitle = importing ? t.importDocumentBusy : t.importDocumentHint;\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 [mathEdit, setMathEdit] = useState<{\n kind: MathKind;\n mode: 'insert' | 'edit';\n pos?: number;\n latex: string;\n isNew?: boolean;\n } | null>(null);\n\n useEffect(() => subscribeMathClick((payload) => {\n setMathEdit({\n kind: payload.kind,\n mode: 'edit',\n pos: payload.pos,\n latex: payload.latex,\n });\n }), []);\n\n const openInsertMath = (kind: MathKind) => {\n const { from, to } = editor.state.selection;\n const selected =\n from === to ? '' : editor.state.doc.textBetween(from, to, ' ');\n const type = kind === 'inline' ? 'inlineMath' : 'blockMath';\n const searchFrom = from;\n chain().insertContent({ type, attrs: { latex: selected } }).run();\n let pos: number | null = null;\n editor.state.doc.nodesBetween(\n searchFrom,\n editor.state.doc.content.size,\n (node, nodePos) => {\n if (pos != null) return false;\n if (\n node.type.name === type &&\n String(node.attrs.latex ?? '') === selected\n ) {\n pos = nodePos;\n return false;\n }\n },\n );\n if (pos == null) {\n setMathEdit({ kind, mode: 'insert', latex: selected, isNew: true });\n return;\n }\n setMathEdit({\n kind,\n mode: 'edit',\n pos,\n latex: selected,\n isNew: true,\n });\n };\n\n const applyMath = (latex: string) => {\n if (!mathEdit) return;\n const { kind, mode, pos } = mathEdit;\n setMathEdit(null);\n if (mode === 'edit' && pos != null) {\n if (kind === 'inline') {\n chain().updateInlineMath({ latex, pos }).run();\n } else {\n chain().updateBlockMath({ latex, pos }).run();\n }\n return;\n }\n if (kind === 'inline') {\n chain().insertContent({ type: 'inlineMath', attrs: { latex } }).run();\n } else {\n chain().insertContent({ type: 'blockMath', attrs: { latex } }).run();\n }\n };\n\n const cancelMath = () => {\n if (!mathEdit) return;\n const { isNew, pos } = mathEdit;\n if (isNew && pos != null) {\n const node = editor.state.doc.nodeAt(pos);\n if (\n node &&\n (node.type.name === 'inlineMath' || node.type.name === 'blockMath')\n ) {\n editor\n .chain()\n .focus()\n .deleteRange({ from: pos, to: pos + node.nodeSize })\n .run();\n }\n }\n setMathEdit(null);\n };\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 {showImport ? (\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={importTitle}\n aria-label={importTitle}\n aria-busy={!!importing}\n disabled={!!importing}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>\n {t.importDocument}\n </span>\n <ChevronDownIcon\n size={12}\n className={styles.styleTriggerCaret}\n />\n </button>\n }\n >\n {importItems.map((item) => (\n <MenuItem\n key={item.key}\n onSelect={() => pickImport(item.accept)}\n >\n {item.label}\n </MenuItem>\n ))}\n </MenuPopover>\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={() => openInsertMath('inline')}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>√x</span>\n {t.inlineMath}\n </span>\n </MenuItem>\n <MenuItem onSelect={() => openInsertMath('block')}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>∑</span>\n {t.blockMath}\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 <TableInsertItem\n disabled={state.inTable}\n labels={t}\n onInsert={(rows, cols) =>\n chain()\n .insertTable({ rows, cols, withHeaderRow: true })\n .run()\n }\n />\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 {/* 导入的隐藏文件选择器:accept 由下拉选项写入 */}\n {showImport ? (\n <input\n ref={importInputRef}\n type=\"file\"\n hidden\n onChange={handleImportChange}\n />\n ) : null}\n\n {mathEdit ? (\n <MathEditorPopover\n editor={editor}\n kind={mathEdit.kind}\n mode={mathEdit.mode}\n pos={mathEdit.pos}\n latex={mathEdit.latex}\n isNew={mathEdit.isNew}\n newLabel={\n mathEdit.kind === 'inline' ? t.mathNewInline : t.mathNewBlock\n }\n placeholder={t.mathPlaceholder}\n doneLabel={t.mathDone}\n onConfirm={applyMath}\n onCancel={cancelMath}\n />\n ) : null}\n\n {/* 表格右键菜单:纵向,图标 + 文案,分组分隔 */}\n {tableMenu &&\n createPortal(\n <div\n className={styles.tableBubble}\n style={{ position: 'fixed', left: tableMenu.x, top: tableMenu.y }}\n role=\"menu\"\n onMouseDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.preventDefault()}\n >\n <TableMenuItem\n label={\n tableMulti\n ? t.tableAddColumnBeforeN(tableColN)\n : t.tableAddColumnBefore\n }\n onClick={() =>\n runTable(() => addColumnsBefore(editor, tableColN))\n }\n >\n <ColumnBeforeIcon />\n </TableMenuItem>\n <TableMenuItem\n label={\n tableMulti\n ? t.tableAddColumnAfterN(tableColN)\n : t.tableAddColumnAfter\n }\n onClick={() =>\n runTable(() => addColumnsAfter(editor, tableColN))\n }\n >\n <ColumnAfterIcon />\n </TableMenuItem>\n <TableMenuItem\n label={\n tableMulti\n ? t.tableDeleteColumnN(tableColN)\n : t.tableDeleteColumn\n }\n disabled={disableDeleteColumn}\n onClick={() =>\n runTable(() => {\n deleteSelectedColumns(editor);\n })\n }\n >\n <ColumnDeleteIcon />\n </TableMenuItem>\n <TableMenuDivider />\n <TableMenuItem\n label={\n tableMulti\n ? t.tableAddRowBeforeN(tableRowN)\n : t.tableAddRowBefore\n }\n disabled={disableAddRowBefore}\n onClick={() =>\n runTable(() => addRowsBefore(editor, tableRowN))\n }\n >\n <RowBeforeIcon />\n </TableMenuItem>\n <TableMenuItem\n label={\n tableMulti ? t.tableAddRowAfterN(tableRowN) : t.tableAddRowAfter\n }\n onClick={() => runTable(() => addRowsAfter(editor, tableRowN))}\n >\n <RowAfterIcon />\n </TableMenuItem>\n <TableMenuItem\n label={\n tableMulti ? t.tableDeleteRowN(tableRowN) : t.tableDeleteRow\n }\n disabled={disableDeleteRow}\n onClick={() =>\n runTable(() => {\n deleteSelectedRows(editor);\n })\n }\n >\n <RowDeleteIcon />\n </TableMenuItem>\n <TableMenuDivider />\n <TableMenuItem\n label={t.tableDeleteTable}\n onClick={() =>\n runTable(() => {\n editor.commands.deleteTable();\n })\n }\n >\n <TableDeleteIcon />\n </TableMenuItem>\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","'use client';\n\nimport * as Popover from '@radix-ui/react-popover';\nimport type { ReactNode } from 'react';\nimport styles from '../styles/comment.module.css';\n\nexport interface CommentPopoverProps {\n open: boolean;\n onOpenChange?: (open: boolean) => void;\n /** 被点击的 mark 元素(from onCommentClick 的 anchorEl)。 */\n anchorEl: HTMLElement | null;\n children: ReactNode;\n side?: 'top' | 'bottom' | 'left' | 'right';\n align?: 'start' | 'center' | 'end';\n sideOffset?: number;\n}\n\n/**\n * 评论浮层(Radix)。库只负责锚定与外观,内容由宿主通过 children 提供\n * (典型:评论正文 + Resolve/Dismiss/Reopen 操作)。\n * 锚点是点击 mark 的动态元素:渲染一个 fixed 1x1 span 挂在 anchorEl 的\n * getBoundingClientRect 位置,Radix 以它为锚。\n */\nexport function CommentPopover({\n open,\n onOpenChange,\n anchorEl,\n children,\n side = 'top',\n align = 'start',\n sideOffset = 6,\n}: CommentPopoverProps) {\n const rect = open && anchorEl ? anchorEl.getBoundingClientRect() : null;\n return (\n <Popover.Root open={open} onOpenChange={onOpenChange}>\n {rect && (\n <Popover.Anchor asChild>\n <span\n className={styles.popoverAnchor}\n style={{ left: rect.left, top: rect.top }}\n />\n </Popover.Anchor>\n )}\n <Popover.Portal>\n <Popover.Content\n className={styles.popoverContent}\n side={side}\n align={align}\n sideOffset={sideOffset}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n {children}\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n","import type { Editor } from '@tiptap/react';\nimport {\n mapCommentAnchors,\n type CommentAnchorStatus,\n type CommentSegment,\n} from './commentAnchor/commentMapper';\n\n/**\n * 内容锚点 → 当前文档里的区间。\n *\n * 用途:宿主在提交一次「圈选改写」时记下选区的内容锚点(`prefix` / `exact` / `suffix`,\n * `blockHash` 可选),等 AI 改完、推送回来时再用它把那段区间找回来——**不能用位置**,\n * 因为编辑器在这期间可能整体重建过(保存、切卡、SWR 刷新都会重挂),位置活不过重建。\n *\n * 锚点类型直接复用评论锚定那套(`commentMapper`),匹配走同一条 fallback 链:\n * `blockHash` → 前后文 → `exact` → 前缀降级(前 20 字)。**这条链是会降级的**,所以:\n *\n * > 调用方必须自己比对返回的 `text` 是否仍等于提交时那一段。本函数只回答「在哪」,\n * > 不回答「还算不算同一段」——后者决定了是原地回填还是弹冲突。\n */\nexport interface AnchorRange {\n /** doc 坐标 */\n from: number;\n to: number;\n /**\n * 区间当前的纯文本。**按匹配器的口径**给出:`commentMapper` 把区间内的 text 节点\n * 直接拼起来(块之间**没有分隔符**),所以这里也是 `textBetween(from, to)`(不传\n * blockSeparator)。调用方拿它跟「建锚点时用的那段文本」比对——两边必须同一口径,\n * 否则多块区间(表格 / 列表)会永远对不上。\n */\n text: string;\n status: CommentAnchorStatus;\n}\n\n/** 探针 id:借 commentMapper 的匹配链路,但我们只要区间,不要评论语义。 */\nconst PROBE_ID = '__anchor-range-probe__';\n\nexport function findRangeByAnchor(\n editor: Editor,\n anchor: CommentSegment | null | undefined,\n): AnchorRange | null {\n if (!anchor || !anchor.exact) return null;\n\n const [result] = mapCommentAnchors(editor.state.doc, [\n { commentId: PROBE_ID, segments: [anchor] },\n ]);\n const range = result?.ranges[0];\n if (!range) return null;\n\n return {\n from: range.from,\n to: range.to,\n // 无 blockSeparator:与 commentMapper 的 `collectText`(text 节点直接拼接)同一口径\n text: editor.state.doc.textBetween(range.from, range.to),\n status: result.status,\n };\n}\n","import '@tiptap/markdown';\nimport type { JSONContent } from '@tiptap/core';\nimport type { Editor } from '@tiptap/react';\n\n/**\n * 取区间对应的 markdown,并给出它在 `editor.getMarkdown()` 输出里的精确偏移。\n *\n * 为什么需要它:后端改卡走的是「在正文里逐字找到这段,替换」(`replace_in_text` +\n * `count=1`),所以发过去的那段必须是**存库正文的逐字子串**;调用方还要知道它在整篇里\n * 的偏移,才能从存库正文取前后文(`ref`)并界定「这次改了哪一段」。官方 OSS 只有整篇\n * `Editor.getMarkdown()`;官方 Pro 的 `getMarkdownRange` 只返回字符串、不给偏移,也不做\n * 块扩展。\n *\n * **默认扩块**(`expandToBlocks: true`):把区间扩展到与它相交的顶层块的首尾。一是序列化\n * 稳定(半句话里跨着加粗,片段序列化会在断口插入多余的 `**`),二是**只有块对齐时偏移才是\n * 算出来的,而不是猜出来的**。\n *\n * 偏移怎么来的:把 doc 的顶层块逐个序列化、用 `\\n\\n` 拼起来,等于整篇序列化(有测试钉住\n * 这条不变量),于是「前 i 块拼接的长度」就是第 i 块的起点偏移。这条不变量若在某篇文档上\n * 不成立,退回按内容在整篇里定位;定位不到或出现多处就返回 `null`——宁可让调用方知道\n * 拿不到偏移,也不要给一个错的。\n */\nexport interface MarkdownRange {\n /** 区间对应的 markdown 片段(扩块后)。 */\n markdown: string;\n /** 片段在 `editor.getMarkdown()` 输出里的起始偏移。 */\n from: number;\n /** 结束偏移(不含)。恒有 `to - from === markdown.length`。 */\n to: number;\n /**\n * **同一段**在 doc 坐标里的范围(扩块之后)。\n *\n * 宿主需要它把「读」和「写」对齐:`from/to` 是 markdown 偏移,而编辑器里的替换要按\n * doc 坐标做。少了它,宿主只能自己拿原始选区去定位,于是「用来定位的那段」和\n * 「按 markdown 偏移算出来的那段」不是同一段——把 A 段写进 B 区间,内容就会重复。\n */\n docFrom: number;\n docTo: number;\n}\n\nexport interface GetMarkdownForRangeOptions {\n /**\n * 是否把区间扩展到与它相交的顶层块(段落 / 表格 / 列表 / 图表 …)的首尾。\n * 默认 `true`:调用方要「存库正文的逐字子串 + 精确偏移」时应该保持默认。\n * 设 `false` 按原区间取,此时偏移依赖内容定位,可能返回 `null`。\n */\n expandToBlocks?: boolean;\n}\n\n/** 顶层块之间的分隔符——与 MarkdownManager 的 doc 级拼接一致。 */\nconst BLOCK_SEPARATOR = '\\n\\n';\n\ninterface TopLevelBlock {\n json: JSONContent;\n /** doc 坐标 */\n from: number;\n to: number;\n}\n\nfunction topLevelBlocks(editor: Editor): TopLevelBlock[] {\n const blocks: TopLevelBlock[] = [];\n editor.state.doc.forEach((node, offset) => {\n blocks.push({\n json: node.toJSON() as JSONContent,\n from: offset,\n to: offset + node.nodeSize,\n });\n });\n return blocks;\n}\n\nexport function getMarkdownForRange(\n editor: Editor,\n from: number,\n to: number,\n options: GetMarkdownForRangeOptions = {},\n): MarkdownRange | null {\n const manager = editor.markdown;\n if (!manager) return null;\n\n const size = editor.state.doc.content.size;\n let start = Math.max(0, Math.min(from, to));\n let end = Math.min(size, Math.max(from, to));\n if (start >= end) return null;\n\n const blocks = topLevelBlocks(editor);\n if (blocks.length === 0) return null;\n\n const expand = options.expandToBlocks !== false;\n\n // 与 [start, end) 相交的顶层块:第一个末端越过 start 的、到最后一个起点早于 end 的。\n // 单元格内、列表项内的选区都会扩到它们所属的顶层块(表格 / 列表整体)。\n let first = 0;\n let last = blocks.length - 1;\n if (expand) {\n first = blocks.findIndex((b) => b.to > start);\n if (first < 0) return null;\n for (let i = blocks.length - 1; i >= first; i -= 1) {\n if (blocks[i].from < end) {\n last = i;\n break;\n }\n }\n start = blocks[first].from;\n end = blocks[last].to;\n }\n\n const parts = blocks.map((b) => manager.serialize({ type: 'doc', content: [b.json] }));\n const full = editor.getMarkdown();\n\n if (expand && parts.join(BLOCK_SEPARATOR) === full) {\n const markdown = parts.slice(first, last + 1).join(BLOCK_SEPARATOR);\n // 空段落拼出来是空串:语义上等于「这段没内容」,交给调用方去判空不如这里就返回 null\n if (!markdown) return null;\n const at =\n first === 0\n ? 0\n : parts.slice(0, first).join(BLOCK_SEPARATOR).length + BLOCK_SEPARATOR.length;\n return { markdown, from: at, to: at + markdown.length, docFrom: start, docTo: end };\n }\n\n // 非块对齐,或整篇拼接与 getMarkdown() 不一致:只能按内容定位,且必须唯一\n const markdown = manager.serialize(\n editor.state.doc.cut(start, end).toJSON() as JSONContent,\n );\n if (!markdown) return null;\n const at = full.indexOf(markdown);\n if (at < 0 || full.indexOf(markdown, at + 1) >= 0) return null;\n return { markdown, from: at, to: at + markdown.length, docFrom: start, docTo: end };\n}\n","import { MarkdownManager } from '@tiptap/markdown';\nimport { CitationRef } from './CitationRef';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport { baseExtensions, pureChart, pureCodeBlock, pureImage } from './extensions';\n\n/**\n * 把一段正文规范成「编辑器读进来再吐出去」的那种写法。\n *\n * **为什么需要它**:编辑器加载 markdown 时要先解析成文档结构,而 markdown 里有些东西是\n * 排版装饰、解析时就丢了(表格列宽的空格、注释 JSON 里的空格、数值尾零 …)。所以\n * 「存库正文」和「编辑器序列化结果」常常**逐字不同**——这与用户改没改无关,加载那一刻就\n * 发生了。而后端改卡走的是「在正文里逐字找到这段再替换」,两边写法不一致就会搜不到。\n * 宿主在要动正文之前(例如圈选改写提交前)先用本函数比对/对齐一次即可。\n *\n * **已知会被规范化的结构**(都是排版层面,内容语义不变):\n *\n * | 结构 | 存库可能是 | 规范化后 |\n * |------|-----------|---------|\n * | GFM 表格 | `\\| 收入 \\| 100 \\|` | 按列内容宽度重排对齐(多/少空格) |\n * | 图表注释 JSON | `<!-- {\"chartType\": \"column\"} -->` | `<!-- {\"chartType\":\"column\"} -->`(去空格,键序按解析结果) |\n * | **图表区**的数值 | `132.0` | `132`(图表把表解析成 payload,数值走 number 再写回) |\n * | 纯空白的正文 | `\" \\n \"` | `\"\"` |\n *\n * 注意第三行**只作用于图表区**:普通 GFM 表格走 marked 的表格解析,单元格是文本,\n * `1,234.50` 这种写法会原样保留(有测试钉住)。\n *\n * 反过来,这些**不该**被改动,同样有测试钉住:标题/段落/加粗斜体/列表/引用、代码块、\n * 公式、图片、脚注 `[^n]`、图表仍是「注释 + 表」的作者形态(不会变成 ```tmr-chart 围栏)。\n *\n * 注意它**不使用** `enrichMarkdownCitations`:脚注的 `[^n]` 由 CitationRef 自带的\n * tokenizer 解析,url/title 只存在于节点属性里、不进 markdown,所以规范化不需要 sources。\n */\nexport function normalizeMarkdown(markdown: string): string {\n if (!markdown) return markdown;\n const manager = getManager();\n return manager.serialize(manager.parse(prepareChartMarkdown(markdown)));\n}\n\n// [perf] 与 renderReportHtml 同样的理由:每次 new MarkdownManager 都会让底层 marked 全局\n// 累积 tokenizer,parse 逐次变慢。这里只做「解析 → 序列化」,无状态,模块级复用即可。\nlet sharedManager: MarkdownManager | null = null;\n\nfunction getManager(): MarkdownManager {\n sharedManager ??= new MarkdownManager({\n extensions: [...baseExtensions, pureCodeBlock, pureImage, pureChart, CitationRef],\n });\n return sharedManager;\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport { enrichMarkdownCitations, type SourceRef } from './citationUtils';\nimport { splitTopLevelBlocks, stripToPlainText } from './insertMarkdown';\n\nexport interface ReplaceRangeOptions {\n /** 脚注来源:把 `[^n]` enrich 成带 url/title 的 citation-ref(与 `insertMarkdown` 同一套)。 */\n sources?: SourceRef[];\n}\n\n/**\n * 用一段 markdown **替换**一个区间。给「后台回填」用——AI 在别处改完,把结果写回编辑器。\n *\n * 与 `insertMarkdown` 的三处刻意差异(都在注释里点明,改的时候别抹平):\n *\n * 1. **不抢焦点**。`insertMarkdown` 是「用户主动插入」,链式带了 `.focus()`;后台回填时\n * 用户可能正在别处打字,抢焦点等于打断他。所以这里直接调 `insertContentAt`。\n * 2. **按区间替换**,不是往光标处插(`insertContentAt` 收 `{from,to}` 时后者即替换)。\n * 3. **进 undo 历史**。`insertContentAt` 本身是一个 transaction,撤销一步就回去;\n * 与评论锚定的 `addToHistory: false` 相反——正文改动必须能撤。\n *\n * 解析失败(AI 的脏输出过不了 schema:嵌套 bold、块级图进 listItem …)时按块降级,\n * 与 `insertMarkdown` 同一套策略。注意降级路径是**逐块多次 transaction**,撤销要多按几下;\n * 只在整段失败时才走。\n *\n * @returns 是否改动了文档。空 markdown 返回 `false`(不静默删掉用户的内容)。\n */\nexport function replaceRangeWithMarkdown(\n editor: Editor,\n range: { from: number; to: number },\n markdown: string,\n options: ReplaceRangeOptions = {},\n): boolean {\n const prepared = prepareChartMarkdown(\n enrichMarkdownCitations(markdown ?? '', options.sources ?? []),\n );\n if (!prepared.trim()) return false;\n\n let from = Math.max(0, Math.min(range.from, range.to));\n let to = Math.max(range.from, range.to);\n if (from === to) return false;\n\n // ① 整段替换:一个 transaction,撤销一步到位\n if (tryInsertMarkdownAt(editor, from, to, prepared)) return true;\n\n // ② 降级:逐块替换。块插完要往后挪插入点,否则每块都往同一个区间插、只剩最后一块\n for (const block of splitTopLevelBlocks(prepared)) {\n const before = editor.state.doc.content.size;\n const changed =\n tryInsertMarkdownAt(editor, from, to, block) ||\n insertPlainParagraphAt(editor, from, to, stripToPlainText(block));\n if (!changed) continue;\n // 插入内容的 doc 尺寸 = 文档增量 + 被替换掉的宽度\n const inserted = editor.state.doc.content.size - before + (to - from);\n from += inserted;\n to = from;\n }\n return true;\n}\n\n/** 注意:不带 `.focus()`——后台回填不能抢用户的焦点。 */\nfunction tryInsertMarkdownAt(\n editor: Editor,\n from: number,\n to: number,\n markdown: string,\n): boolean {\n try {\n return editor\n .chain()\n .insertContentAt({ from, to }, markdown, { contentType: 'markdown' })\n .run();\n } catch {\n return false;\n }\n}\n\nfunction insertPlainParagraphAt(\n editor: Editor,\n from: number,\n to: number,\n text: string,\n): boolean {\n try {\n return editor\n .chain()\n .insertContentAt(\n { from, to },\n { type: 'paragraph', content: text ? [{ type: 'text', text }] : [] },\n )\n .run();\n } catch {\n return false;\n }\n}\n","import type { Editor, Range } from '@tiptap/core';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport { insertMarkdown } from '../insertMarkdown';\n\n/**\n * 斜杠命令项插入 markdown 的共享原语:同一条 chain 内先删触发词再插内容,\n * 撤销是一步。整段过不了 schema 时降级为「按块重试 + 剥标记当段落」\n * (复用 insertMarkdown 的降级路径)——那条路径里删除已单独成事务,\n * 撤销会是多步,但注册表项是受控 markdown,正常不会走到。\n */\nexport function insertSlashMarkdown(\n editor: Editor,\n range: Range,\n markdown: string,\n): void {\n const prepared = prepareChartMarkdown(markdown);\n if (!prepared) return;\n try {\n const ok = editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent(prepared, { contentType: 'markdown' })\n .run();\n if (ok) return;\n } catch {\n // 整段过不了 schema:走降级\n }\n editor.chain().focus().deleteRange(range).run();\n insertMarkdown(editor, prepared);\n}\n"],"names":["m","r","e","active","b","counter","toggle","styles","Node","item","SlashMenuPopup","header","Fragment","group","MD_FILE_RE","f","input","setActive","readonly","folded","pre","_a","MarkdownWysiwygEditor","a","gutter","row","field","bar","list","markdown","at"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/components/CitationRefView.tsx","../src/createCitationRef.ts","../src/commentAnchor/commentAnchorPlugin.ts","../src/commentAnchor/commentAnchorController.ts","../src/findReplace.ts","../src/icons/index.tsx","../src/labels.ts","../src/components/FindReplaceBar.tsx","../src/importPlaceholder.ts","../src/slashMenu/items.ts","../src/slashMenu/SlashMenuPopup.tsx","../src/slashMenu/SlashMenuExtension.ts","../src/shortcuts/types.ts","../src/shortcuts/ShortcutPanel.tsx","../src/markdownFileDrop.ts","../src/pendingAnchor.ts","../src/selectionKind.ts","../src/markdownPaste.ts","../src/components/ChartView.tsx","../src/chart/createChart.ts","../src/components/CodeBlockView.tsx","../src/components/MarkdownWysiwygEditor.tsx","../src/components/MarkdownPreview.tsx","../src/importMenu.ts","../src/insertMarkdown.ts","../src/components/ColorPalette.tsx","../src/linkEditing.ts","../src/components/LinkPopover.tsx","../src/tableSelection.ts","../src/components/TableHandles.tsx","../src/components/MathEditorPopover.tsx","../src/components/EditorToolbar.tsx","../src/hooks/useIsMobile.ts","../src/components/TocPanel.tsx","../src/commentAnchor/CommentPopover.tsx","../src/anchorRange.ts","../src/markdownRange.ts","../src/normalizeMarkdown.ts","../src/replaceRange.ts","../src/slashMenu/insertSlashMarkdown.ts"],"sourcesContent":["'use client';\n\nimport {\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport type { RenderCitation } from '../citationTypes';\n\n/**\n * 脚注圆标 React NodeView。\n * 无 `renderCitation` 时渲默认 pill(有 url 则可点);有插槽时把 defaultDom 交给消费方。\n */\nexport function CitationRefView({ node, extension }: NodeViewProps) {\n const index = String(node.attrs.index ?? '');\n const url = (node.attrs.url as string | null) || null;\n const title = (node.attrs.title as string | null) || '';\n const renderCitation = extension.options.renderCitation as\n | RenderCitation\n | undefined;\n\n const pill = (\n <span\n className=\"citation-ref\"\n data-index={index}\n {...(url ? { 'data-url': url } : {})}\n {...(title ? { 'data-title': title } : {})}\n >\n {!renderCitation && url ? (\n <a\n href={url}\n title={title}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {index}\n </a>\n ) : (\n index\n )}\n </span>\n );\n\n const content = renderCitation\n ? renderCitation({\n index,\n attrs: { index, url, title: title || null },\n defaultDom: pill,\n })\n : pill;\n\n return (\n <NodeViewWrapper\n as=\"span\"\n data-citation-ref=\"\"\n style={{ display: 'inline' }}\n >\n {content}\n </NodeViewWrapper>\n );\n}\n","'use client';\n\nimport { ReactNodeViewRenderer } from '@tiptap/react';\nimport { CitationRef, type CitationRefOptions } from './CitationRef';\nimport type { RenderCitation } from './citationTypes';\nimport { CitationRefView } from './components/CitationRefView';\n\nexport type CitationRefViewOptions = CitationRefOptions & {\n renderCitation?: RenderCitation;\n};\n\n/**\n * 客户端增强版 CitationRef:挂 React NodeView,支持 `renderCitation` 插槽。\n * server / SSR 请继续用纯 {@link CitationRef}(无 React)。\n */\nexport function createCitationRef(\n options: { renderCitation?: RenderCitation } = {},\n) {\n return CitationRef.extend<CitationRefViewOptions>({\n addOptions() {\n return {\n HTMLAttributes: {},\n ...this.parent?.(),\n renderCitation: options.renderCitation,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(CitationRefView);\n },\n }).configure({\n renderCitation: options.renderCitation,\n });\n}\n","/**\n * 评论锚定客户端插件:\n * - 装饰:block 左缘 gutter 气泡(showGutter)、active 评论的 mark/block 高亮;\n * - 交互:点击 mark / gutter 通过 transaction meta 上报(宿主经 editor.on('transaction')\n * 接收,规避扩展创建时闭包 stale 的问题);\n * - 守卫:粘贴 / 拖拽的 slice 剥离 commentAnchor mark,防止幽灵高亮。\n *\n * 只读态(MarkdownPreview)不注入本插件、不接评论 —— 评论是编辑会话专属。\n */\n\nimport {\n Fragment,\n Slice,\n type MarkType,\n type Node as PMNode,\n} from '@tiptap/pm/model';\nimport { Extension } from '@tiptap/core';\nimport {\n Plugin,\n PluginKey,\n type EditorState,\n} from '@tiptap/pm/state';\nimport {\n Decoration,\n DecorationSet,\n type EditorView,\n} from '@tiptap/pm/view';\nimport type { CommentClickPayload } from './commentTypes';\n\nexport const COMMENT_ACTIVE_META = 'tmr:comment:active';\nexport const COMMENT_CLICK_META = 'tmr:comment:click';\nexport const COMMENT_GUTTER_META = 'tmr:comment:gutter';\n\nexport interface CommentGutterPayload {\n commentIds: string[];\n pos: number;\n}\n\nexport interface CommentAnchorPluginOptions {\n /** 是否在 block 左缘渲染评论 gutter 气泡,默认 true。 */\n showGutter?: boolean;\n /**\n * 编辑器内点 mark 是否参与交互(默认 true:设 active + 上报 click meta)。\n * 设 false 后点击 mark 完全惰性(不设 active、不上报),适合「只靠侧栏单项\n * 驱动滚动定位」的宿主。\n */\n interactive?: boolean;\n}\n\nexport interface CommentAnchorPluginState {\n activeCommentId: string | null;\n}\n\nexport const commentAnchorPluginKey = new PluginKey<CommentAnchorPluginState>(\n 'tmrCommentAnchor',\n);\n\n/** 从 Slice 中剔除 commentAnchor mark(粘贴/拖拽守卫)。 */\nexport function stripCommentAnchorMarks(\n slice: Slice,\n markType: MarkType,\n): Slice {\n const strip = (fragment: Fragment): Fragment => {\n const children: PMNode[] = [];\n fragment.forEach((child) => {\n if (child.isText && child.marks.some((m) => m.type === markType)) {\n children.push(\n child.mark(child.marks.filter((m) => m.type !== markType)),\n );\n } else if (child.content.size > 0) {\n children.push(child.copy(strip(child.content)));\n } else {\n children.push(child);\n }\n });\n return Fragment.fromArray(children);\n };\n return new Slice(strip(slice.content), slice.openStart, slice.openEnd);\n}\n\nfunction sliceHasCommentMarks(slice: Slice, markType: MarkType): boolean {\n let found = false;\n slice.content.descendants((node) => {\n if (node.isText && node.marks.some((m) => m.type === markType)) {\n found = true;\n return false;\n }\n return true;\n });\n return found;\n}\n\n/** 顶层 block 边界。 */\nfunction blockBounds(doc: PMNode): Array<{ start: number; end: number }> {\n const bounds: Array<{ start: number; end: number }> = [];\n doc.forEach((child, offset) => {\n bounds.push({ start: offset, end: offset + child.nodeSize });\n });\n return bounds;\n}\n\n/** commentId → 文本区间(从 doc 内 commentAnchor mark 收集)。 */\nfunction collectCommentRanges(\n doc: PMNode,\n): Map<string, Array<{ from: number; to: number }>> {\n const byId = new Map<string, Array<{ from: number; to: number }>>();\n doc.descendants((node, pos) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n const ids = (m.attrs.commentIds as string[]) ?? [];\n for (const id of ids) {\n const arr = byId.get(id) ?? [];\n arr.push({ from: pos, to: pos + node.nodeSize });\n byId.set(id, arr);\n }\n }\n return true;\n });\n return byId;\n}\n\nfunction rangesIntersectBlock(\n ranges: Array<{ from: number; to: number }>,\n start: number,\n end: number,\n): boolean {\n return ranges.some((r) => r.from < end && r.to > start);\n}\n\nfunction gutterDom(\n commentIds: string[],\n view: EditorView,\n blockPos: number,\n): HTMLElement {\n const el = document.createElement('span');\n el.className = 'tmr-comment-gutter';\n el.setAttribute('data-comment-ids', commentIds.join(' '));\n el.textContent = String(commentIds.length);\n el.title = `${commentIds.length}`;\n // 不抢编辑器焦点/选区\n el.addEventListener('mousedown', (e) => {\n e.preventDefault();\n e.stopPropagation();\n });\n el.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n view.dispatch(\n view.state.tr\n .setMeta(COMMENT_ACTIVE_META, commentIds[0] ?? null)\n .setMeta(COMMENT_GUTTER_META, {\n commentIds,\n pos: blockPos,\n } satisfies CommentGutterPayload),\n );\n });\n return el;\n}\n\nexport function commentAnchorPlugin(\n options: CommentAnchorPluginOptions = {},\n): Plugin<CommentAnchorPluginState> {\n const showGutter = options.showGutter !== false;\n const interactive = options.interactive !== false;\n\n return new Plugin<CommentAnchorPluginState>({\n key: commentAnchorPluginKey,\n state: {\n init: () => ({ activeCommentId: null }),\n apply: (tr, value) => {\n const active = tr.getMeta(COMMENT_ACTIVE_META);\n return active !== undefined\n ? { activeCommentId: active as string | null }\n : value;\n },\n },\n props: {\n decorations(state: EditorState) {\n const byId = collectCommentRanges(state.doc);\n if (byId.size === 0) return DecorationSet.empty;\n\n const decos: Decoration[] = [];\n const bounds = blockBounds(state.doc);\n\n if (showGutter) {\n for (const b of bounds) {\n const idsInBlock: string[] = [];\n for (const [id, ranges] of byId) {\n if (rangesIntersectBlock(ranges, b.start, b.end)) {\n idsInBlock.push(id);\n }\n }\n if (idsInBlock.length > 0) {\n decos.push(\n Decoration.widget(\n b.start,\n (view) => gutterDom(idsInBlock, view, b.start),\n { side: -1, key: `tmr-gutter:${b.start}` },\n ),\n );\n }\n }\n }\n\n const activeId =\n commentAnchorPluginKey.getState(state)?.activeCommentId ?? null;\n if (activeId) {\n const ranges = byId.get(activeId) ?? [];\n for (const r of ranges) {\n decos.push(\n Decoration.inline(r.from, r.to, { class: 'tmr-comment-active' }),\n );\n }\n for (const b of bounds) {\n if (rangesIntersectBlock(ranges, b.start, b.end)) {\n decos.push(\n Decoration.node(b.start, b.end, {\n class: 'tmr-comment-block-active',\n }),\n );\n }\n }\n }\n\n return DecorationSet.create(state.doc, decos);\n },\n\n handleClick(view: EditorView, pos: number, event: MouseEvent) {\n // 惰性模式:编辑器内点击 mark 不产生任何交互(侧栏单项驱动)。\n if (!interactive) return false;\n const target = event.target as Element | null;\n const el = target?.closest?.(\n 'mark.tmr-comment[data-comment-ids]',\n ) as HTMLElement | null;\n if (!el) return false;\n const commentIds = (el.getAttribute('data-comment-ids') ?? '')\n .split(' ')\n .filter(Boolean);\n if (commentIds.length === 0) return false;\n view.dispatch(\n view.state.tr\n .setMeta(COMMENT_ACTIVE_META, commentIds[0] ?? null)\n .setMeta(COMMENT_CLICK_META, {\n commentIds,\n anchorEl: el,\n pos,\n } satisfies CommentClickPayload),\n );\n return true;\n },\n\n // 粘贴 / 拖拽 / 编辑器内拖动的 slice 统一走这里:剥离评论 mark,\n // 防止复制粘贴产生幽灵高亮。正文内容不变,只是丢掉会话级元数据。\n transformPasted(slice: Slice, view: EditorView) {\n const markType = view.state.schema.marks.commentAnchor;\n if (!markType || !sliceHasCommentMarks(slice, markType)) return slice;\n return stripCommentAnchorMarks(slice, markType);\n },\n },\n });\n}\n\n/**\n * Tiptap Extension 包装:把评论锚定 Plugin 挂进 useEditor / Editor 的 extensions。\n * 只读态(MarkdownPreview)不要注入本扩展 —— 评论是编辑会话专属。\n */\nexport function commentAnchorExtension(\n options: CommentAnchorPluginOptions = {},\n) {\n return Extension.create({\n name: 'tmrCommentAnchor',\n addProseMirrorPlugins() {\n return [commentAnchorPlugin(options)];\n },\n });\n}\n","/**\n * 编辑会话内的评论锚定控制器(纯函数,供宿主 / 组件 handle 复用)。\n *\n * 职责:\n * - applyCommentAnchorsToEditor:comments 装载时把 segments 映射成 mark 铺入 doc;\n * - focusComment / nextComment:active 状态 + 滚动 + 选区;\n * - collectCommentIds / commentRangesById:供宿主查询。\n */\n\nimport type { Editor } from '@tiptap/core';\nimport {\n COMMENT_ACTIVE_META,\n commentAnchorPluginKey,\n} from './commentAnchorPlugin';\nimport {\n mapCommentAnchors,\n mergeCommentIntervals,\n type CommentRange,\n} from './commentMapper';\nimport type { CommentRef } from './commentTypes';\n\n/** 先清后铺,幂等;无评论时清空全部 mark。 */\nexport function applyCommentAnchorsToEditor(\n editor: Editor,\n comments: CommentRef[],\n): void {\n // 只读态不接评论(库契约:评论锚定 = 编辑会话专属)。\n if (!editor.isEditable) return;\n const intervals =\n comments.length > 0\n ? mergeCommentIntervals(\n mapCommentAnchors(\n editor.state.doc,\n comments.map((c) => ({ commentId: c.commentId, segments: c.segments })),\n ).map((r) => ({ commentId: r.commentId, ranges: r.ranges })),\n )\n : [];\n const chain = editor.chain().clearCommentAnchors();\n if (intervals.length > 0) chain.applyCommentAnchors(intervals);\n chain.run();\n}\n\n/** 文档顺序去重的 commentId 列表(gutter / 导航顺序)。 */\nexport function collectCommentIds(editor: Editor): string[] {\n const ids: string[] = [];\n editor.state.doc.descendants((node) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n for (const id of (m.attrs.commentIds as string[]) ?? []) {\n if (!ids.includes(id)) ids.push(id);\n }\n }\n return true;\n });\n return ids;\n}\n\nexport function commentRangesById(\n editor: Editor,\n commentId: string,\n): CommentRange[] {\n const ranges: CommentRange[] = [];\n editor.state.doc.descendants((node, pos) => {\n if (!node.isText) return true;\n for (const m of node.marks) {\n if (m.type.name !== 'commentAnchor') continue;\n const ids = (m.attrs.commentIds as string[]) ?? [];\n if (ids.includes(commentId)) {\n ranges.push({ from: pos, to: pos + node.nodeSize });\n }\n }\n return true;\n });\n return ranges;\n}\n\nfunction setActive(editor: Editor, commentId: string | null): void {\n editor.view.dispatch(\n editor.state.tr.setMeta(COMMENT_ACTIVE_META, commentId),\n );\n}\n\nfunction getActive(editor: Editor): string | null {\n return commentAnchorPluginKey.getState(editor.state)?.activeCommentId ?? null;\n}\n\n/**\n * 聚焦某条评论:设置 active(mark/block 高亮)+ 滚动到第一个 mark + 光标落到\n * 区间起点。找不到(outdated)时清空 active 并返回 false。\n */\nexport function focusComment(editor: Editor, commentId: string): boolean {\n const ranges = commentRangesById(editor, commentId);\n if (ranges.length === 0) {\n setActive(editor, null);\n return false;\n }\n setActive(editor, commentId);\n const markEl = editor.view.dom.querySelector<HTMLElement>(\n `mark.tmr-comment[data-comment-ids~=\"${CSS.escape(commentId)}\"]`,\n );\n markEl?.scrollIntoView?.({ block: 'center', behavior: 'smooth' });\n editor.chain().setTextSelection(ranges[0].from).run();\n return true;\n}\n\n/** 按文档顺序在评论间循环跳转(dir: next / prev)。 */\nexport function nextComment(\n editor: Editor,\n dir: 'next' | 'prev' = 'next',\n): string | null {\n const ids = collectCommentIds(editor);\n if (ids.length === 0) return null;\n const active = getActive(editor);\n const current = active ? ids.indexOf(active) : -1;\n const nextIdx =\n dir === 'next'\n ? (current + 1) % ids.length\n : (current - 1 + ids.length) % ids.length;\n const target = ids[nextIdx];\n focusComment(editor, target);\n return target;\n}\n","/**\n * 查找替换的适配层。\n *\n * 匹配 / 高亮 / 替换全部由官方 `@tiptap/extension-find-and-replace` 承担(命令 + storage +\n * decoration),宿主与 AI 侧可以直接用 `editor.commands.setSearchTerm / replaceAll …`。\n * 这个文件只收拾 Tiptap 3.31.3 上的一个坑,以及库内的默认防抖。\n */\n\nimport type { Editor } from '@tiptap/react';\n\n/** 官方扩展在 `extensionManager` 里的注册名(与官方 UI Components 同款判据)。 */\nexport const FIND_EXTENSION_NAME = 'findAndReplace';\n\n/**\n * 输入法组合中的这次按键要不要放行。\n *\n * 中文 / 日文输入法里 Enter 是「提交候选词」、Escape 是「取消候选」,都不是「执行」:不拦的话,\n * 每次确认候选词都会触发一次跳转(替换框则直接替换一处),而按 Esc 想取消候选反而把浮动条关掉。\n * 判据取两路——`isComposing` 覆盖常规路径,`keyCode === 229` 兜住 Safari 在组合收尾时的 keydown\n * (与 slashMenu/SlashMenuExtension.ts 的 isComposing() 同一套;那边还多一路 ProseMirror 的\n * `view.composing`,React 事件里拿不到,调用方传 `event.nativeEvent` 即可)。\n */\nexport function isComposingKeyEvent(\n event: Pick<KeyboardEvent, 'isComposing' | 'keyCode'>,\n): boolean {\n return event.isComposing || event.keyCode === 229;\n}\n\n/**\n * 查找替换扩展是否已注册。\n *\n * 按 `extensionManager.extensions` 里的注册名查,而不是探 `editor.commands.setSearchTerm`\n * 在不在——命令探测分不清「扩展根本没装」和「命令被别的同名扩展覆盖」,也判不出已销毁的实例。\n * 官方 UI Components 的 `isFindAndReplaceAvailable` 用的是同一条判据。\n */\nexport function hasFindReplaceExtension(\n editor: Editor | null | undefined,\n): boolean {\n if (!editor || editor.isDestroyed) return false;\n return (\n editor.extensionManager?.extensions.some(\n (extension) => extension.name === FIND_EXTENSION_NAME,\n ) ?? false\n );\n}\n\n/**\n * 输入防抖(毫秒)。\n *\n * 注意:注册扩展时必须把官方选项 `searchDebounceMs` 设为 **0**。官方防抖走 `setTimeout`,\n * 真正的 dispatch 发生在异步回调里,下面 `runFindCommand` 的守卫就兜不住那次抛错。\n * 防抖改由调用方(浮动条)自己做,语义一样但全程同步。\n */\nexport const FIND_DEBOUNCE_MS = 120;\n\nconst MISMATCH_RE = /Applying a mismatched transaction/;\n\n/**\n * 跑一条官方查找替换命令,兜掉 Tiptap 3.31.3 的一处事务错配。\n *\n * 成因:官方扩展的 `setSearchTerm` 不走 CommandManager 给的 dispatch,而是自己\n * `editor.state.tr` + `view.dispatch`(见扩展 dist 的 `applySearchTerm`)。CommandManager\n * 在命令结束后仍会派发它「命令开始时创建」的那个 tr。若这次派发触发了 TrailingNode 的\n * appendTransaction(**文末是代码块 / 表格 / 图表**时它会补一个空段落,starter-kit 自带),\n * doc 已经前进,那个旧 tr 的 `before` 就对不上当前 doc → `RangeError: Applying a mismatched\n * transaction`。\n *\n * 此时查询其实已经生效(扩展自己那次 dispatch 成功了、尾段落也补上了),只是紧随其后的\n * 第二次派发炸掉。所以捕获这一种错并重试一次即可收敛——重试时文末空段落已在,TrailingNode\n * 不再插手。其它错误照抛,不吞。\n */\nexport function runFindCommand(run: () => void): void {\n try {\n run();\n } catch (error) {\n if (error instanceof RangeError && MISMATCH_RE.test(error.message)) {\n run();\n return;\n }\n throw error;\n }\n}\n","import type { SVGProps } from 'react';\n\n/**\n * 内联 SVG 图标集(0 运行时依赖)。stroke 走 currentColor,尺寸默认 1em 跟随字号,\n * 故颜色/大小随文本与主题自动变化。\n *\n * 通用图标(粗体/斜体/下划线/列表/撤销/查找等,本文件表格图标之前的部分)的 path 取自\n * Lucide,其许可证为 ISC,其中部分图形源自 Feather 的 MIT——完整版权声明见\n * 仓库根目录 THIRD_PARTY_LICENSES.md。表格行列操作图标(Column / Row / TableDelete 系列)为自绘。\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\n/** 橡皮擦:表格菜单的「清空内容」。 */\nexport const EraserIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\" />\n <path d=\"M22 21H7\" />\n <path d=\"m5 11 9 9\" />\n </Svg>\n);\n\n/** 逆时针回转:表格菜单的「重置单元格样式」。 */\nexport const RotateCcwIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\n <path d=\"M3 3v5h5\" />\n </Svg>\n);\n\n/** 在新窗口打开(链接浮层的「打开」按钮)。 */\nexport const ExternalLinkIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M15 3h6v6\" />\n <path d=\"M10 14 21 3\" />\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\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 ImportIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M12 3v12\" />\n <path d=\"m8 11 4 4 4-4\" />\n <path d=\"M8 5H4a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-4\" />\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\nexport const SearchIcon = (p: IconProps) => (\n <Svg {...p}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </Svg>\n);\n\nexport const XIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Svg>\n);\n\nexport const ChevronUpIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m18 15-6-6-6 6\" />\n </Svg>\n);\n\nexport const ReplaceIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 4a1 1 0 0 1 1-1\" />\n <path d=\"M15 10a1 1 0 0 1-1-1\" />\n <path d=\"M21 4a1 1 0 0 0-1-1\" />\n <path d=\"M21 9a1 1 0 0 1-1 1\" />\n <path d=\"m3 7 3 3 3-3\" />\n <path d=\"M6 10V5a2 2 0 0 1 2-2h2\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\n </Svg>\n);\n\nexport const ReplaceAllIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"M14 14a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1\" />\n <path d=\"M14 4a1 1 0 0 1 1-1\" />\n <path d=\"M15 10a1 1 0 0 1-1-1\" />\n <path d=\"M19 14a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1\" />\n <path d=\"M21 4a1 1 0 0 0-1-1\" />\n <path d=\"M21 9a1 1 0 0 1-1 1\" />\n <path d=\"m3 7 3 3 3-3\" />\n <path d=\"M6 10V5a2 2 0 0 1 2-2h2\" />\n <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\" />\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\nexport const TableDeleteIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect x=\"3\" y=\"5\" width=\"18\" height=\"14\" rx=\"1\" />\n <path d=\"M3 9h18\" />\n <path d=\"M9 5v14\" />\n <path d=\"M15 5v14\" />\n <path d=\"m7 2 10 20\" />\n </Svg>\n);\n\nexport const CopyIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\n </Svg>\n);\n\nexport const ChevronsUpDownIcon = (p: IconProps) => (\n <Svg {...p}>\n <path d=\"m7 15 5 5 5-5\" />\n <path d=\"m7 9 5-5 5 5\" />\n </Svg>\n);\n\nexport const KeyboardIcon = (p: IconProps) => (\n <Svg {...p}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"M6 8h.01\" />\n <path d=\"M10 8h.01\" />\n <path d=\"M14 8h.01\" />\n <path d=\"M18 8h.01\" />\n <path d=\"M6 12h.01\" />\n <path d=\"M10 12h.01\" />\n <path d=\"M14 12h.01\" />\n <path d=\"M18 12h.01\" />\n <path d=\"M7 16h10\" />\n </Svg>\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 /**\n * 链接浮层输入框的占位与无障碍名(原 `window.prompt` 的提示语,现在落到输入框上)。\n */\n linkPrompt: string;\n /** 链接浮层「应用」按钮的 title / aria-label。 */\n linkApply: string;\n /** 链接浮层「在新窗口打开」按钮的 title / aria-label。 */\n linkOpen: string;\n /** 链接浮层「移除链接」按钮的 title / aria-label。 */\n linkRemove: string;\n /** 链接浮层:地址被编辑器拒绝时的提示(落在输入框 title 上)。 */\n linkInvalid: string;\n image: string;\n imageUploadFailed: string;\n /** Markdown 文件导入失败(与图片上传共用 onError 回调时,便于宿主区分文案)。 */\n importMarkdownFailed: string;\n /** 主栏导入下拉触发器上的短文案(对齐 style / fontSize)。 */\n importDocument: string;\n /** 导入触发器 title / aria-label。 */\n importDocumentHint: string;\n /** 未传 importMenuItems、但传了 onImportDocument + importAccept 时的第二项。 */\n importDocumentOther: string;\n /** 导入进行中的按钮 title。 */\n importDocumentBusy: string;\n /** 光标占位:上传阶段,传入 0–100。 */\n importDocumentUploading: (percent: number) => string;\n /** 光标占位:转换阶段,不要百分比。 */\n importDocumentConverting: string;\n /** 非 Markdown 文件导入失败(onError 的 source === 'import')。 */\n importDocumentFailed: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n more: string;\n /**\n * 工具栏的搜索入口(放大镜按钮,落在 More 之后):title 与 aria-label。\n * 只在宿主传了 `onSearch` 时才渲染——它只是入口,条子本身归编辑器\n * (`<MarkdownWysiwygEditor>`),点击后由宿主调 `handle.openFind()`。\n */\n search: string;\n codeBlock: string;\n hr: string;\n /** 导入下拉里的 Markdown 项。 */\n importMarkdown: string;\n tableInsert: string;\n /** 行手柄的 title / aria-label(鼠标悬停单元格时出现在行的左缘)。 */\n tableRowMenu: string;\n /** 列手柄的 title / aria-label(悬停时出现在表格上方、对齐该列)。 */\n tableColumnMenu: string;\n /** 表格菜单:清空选中行 / 列 / 单元格矩形里的内容(保留单元格与表头)。 */\n tableClearContent: string;\n /** 表格菜单:把选中单元格的样式属性复位(列宽、对齐等;不动合并结构)。 */\n tableResetCellStyles: string;\n /** 表格底边 `+` 手柄(末尾追加一行)的 title / aria-label。 */\n tableAppendRow: string;\n /** 表格右边 `+` 手柄(末尾追加一列)的 title / aria-label。 */\n tableAppendColumn: string;\n /** 网格选择器底部尺寸文案,如 \"3 × 4\"。参数顺序:列、行。 */\n tableSizeSelected: (cols: number, rows: number) => string;\n tableAddColumnBefore: string;\n tableAddColumnAfter: string;\n tableDeleteColumn: string;\n tableAddRowBefore: string;\n tableAddRowAfter: string;\n tableDeleteRow: string;\n /** 多格选区:在左侧插入 N 列。 */\n tableAddColumnBeforeN: (n: number) => string;\n /** 多格选区:在右侧插入 N 列。 */\n tableAddColumnAfterN: (n: number) => string;\n /** 多格选区:删除 N 列。 */\n tableDeleteColumnN: (n: number) => string;\n /** 多格选区:在上方插入 N 行。 */\n tableAddRowBeforeN: (n: number) => string;\n /** 多格选区:在下方插入 N 行。 */\n tableAddRowAfterN: (n: number) => string;\n /** 多格选区:删除 N 行。 */\n tableDeleteRowN: (n: number) => string;\n tableDeleteTable: string;\n inlineMath: string;\n blockMath: string;\n mathPlaceholder: string;\n mathDone: string;\n mathCancel: string;\n mathNewInline: string;\n mathNewBlock: string;\n}\n\n/** 斜杠菜单(键入 / 唤起的块级插入弹窗)文案。 */\nexport interface SlashMenuLabels {\n /** 弹窗 aria-label。 */\n menuLabel: string;\n /** 分组标题:文本块。 */\n groupText: string;\n /** 分组标题:列表。 */\n groupList: string;\n /** 分组标题:结构 / 高级块。 */\n groupAdvanced: string;\n normalText: string;\n headingLabel: (level: number) => string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n blockquote: string;\n codeBlock: string;\n divider: string;\n table: string;\n inlineMath: string;\n blockMath: string;\n}\n\nexport interface ChartLabels {\n /** Tab label when config has no title. */\n tabLabel: (chartType: string, index: number) => string;\n done: string;\n cancel: string;\n configLabel: string;\n tableLabel: string;\n /** Modal dialog title. */\n editTitle: string;\n}\n\nexport const defaultChartLabels: ChartLabels = {\n tabLabel: (chartType, index) => `${chartType} ${index + 1}`,\n done: 'Done',\n cancel: 'Cancel',\n configLabel: 'Chart config (JSON)',\n tableLabel: 'Data table (Markdown)',\n editTitle: 'Edit chart',\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 linkApply: 'Apply link',\n linkOpen: 'Open in new window',\n linkRemove: 'Remove link',\n linkInvalid: 'The editor rejected this address',\n image: 'Image',\n imageUploadFailed: 'Image upload failed',\n importMarkdownFailed: 'Markdown import failed',\n importDocument: 'Import',\n importDocumentHint: 'Import a file',\n importDocumentOther: 'Document',\n importDocumentBusy: 'Importing…',\n importDocumentUploading: (percent) => `Uploading ${percent}%`,\n importDocumentConverting: 'Converting…',\n importDocumentFailed: 'Import failed',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n more: 'More',\n search: 'Find & replace',\n codeBlock: 'Code block',\n hr: 'Divider',\n importMarkdown: 'Markdown',\n tableInsert: 'Insert table',\n tableRowMenu: 'Row actions',\n tableColumnMenu: 'Column actions',\n tableClearContent: 'Clear content',\n tableResetCellStyles: 'Reset cell styles',\n tableAppendRow: 'Add row',\n tableAppendColumn: 'Add column',\n tableSizeSelected: (cols, rows) => `${cols} × ${rows}`,\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 tableAddColumnBeforeN: (n) => `Add ${n} columns before`,\n tableAddColumnAfterN: (n) => `Add ${n} columns after`,\n tableDeleteColumnN: (n) => `Delete ${n} columns`,\n tableAddRowBeforeN: (n) => `Add ${n} rows before`,\n tableAddRowAfterN: (n) => `Add ${n} rows after`,\n tableDeleteRowN: (n) => `Delete ${n} rows`,\n tableDeleteTable: 'Delete table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n mathPlaceholder: 'E = mc^2',\n mathDone: 'Done',\n mathCancel: 'Cancel',\n mathNewInline: 'New equation',\n mathNewBlock: 'Add a TeX equation',\n};\n\nexport const defaultSlashMenuLabels: SlashMenuLabels = {\n menuLabel: 'Insert block',\n groupText: 'Text',\n groupList: 'Lists',\n groupAdvanced: 'Advanced',\n normalText: 'Normal text',\n headingLabel: (level) => `Heading ${level}`,\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n blockquote: 'Blockquote',\n codeBlock: 'Code block',\n divider: 'Divider',\n table: 'Table',\n inlineMath: 'Inline equation',\n blockMath: 'Block equation',\n};\n\n/** 快捷键抽屉面板(键位 + Markdown 触发写法对照)文案。 */\nexport interface ShortcutLabels {\n /** 抽屉标题。 */\n panelTitle: string;\n /** 关闭按钮 aria / title。 */\n close: string;\n /** 三列表头:格式 / 快捷键 / Markdown。 */\n colFormat: string;\n colShortcut: string;\n colMarkdown: string;\n /** 分组标题。 */\n formatGroup: string;\n insertGroup: string;\n editGroup: string;\n bold: string;\n italic: string;\n strike: string;\n underline: string;\n inlineCode: string;\n highlight: string;\n headingLabel: (level: number) => string;\n paragraph: string;\n blockquote: string;\n bulletList: string;\n orderedList: string;\n taskList: string;\n codeBlock: string;\n divider: string;\n undo: string;\n redo: string;\n hardBreak: string;\n findReplace: string;\n}\n\nexport const defaultShortcutLabels: ShortcutLabels = {\n panelTitle: 'Shortcuts',\n close: 'Close',\n colFormat: 'Format',\n colShortcut: 'Shortcut',\n colMarkdown: 'Markdown',\n formatGroup: 'Formatting',\n insertGroup: 'Insert',\n editGroup: 'Editing',\n bold: 'Bold',\n italic: 'Italic',\n strike: 'Strikethrough',\n underline: 'Underline',\n inlineCode: 'Inline code',\n highlight: 'Highlight',\n headingLabel: (level) => `Heading ${level}`,\n paragraph: 'Normal text',\n blockquote: 'Blockquote',\n bulletList: 'Bullet list',\n orderedList: 'Ordered list',\n taskList: 'Task list',\n codeBlock: 'Code block',\n divider: 'Divider',\n undo: 'Undo',\n redo: 'Redo',\n hardBreak: 'Hard break',\n findReplace: 'Find & replace',\n};\n\n/** 链接编辑浮层(`<LinkPopover>`)文案。 */\nexport interface LinkPopoverLabels {\n /** 输入框占位与无障碍名,也是浮层的 aria-label。 */\n field: string;\n apply: string;\n open: string;\n remove: string;\n /** 地址被编辑器拒绝时的提示(落在输入框 title 上)。 */\n invalid: string;\n}\n\nexport const defaultLinkPopoverLabels: LinkPopoverLabels = {\n field: 'Enter URL',\n apply: 'Apply link',\n open: 'Open in new window',\n remove: 'Remove link',\n invalid: 'The editor rejected this address',\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 copy: string;\n /** 只读态:展开超出限高的代码块。 */\n expand: string;\n /** 只读态:收起已展开的代码块。 */\n collapse: string;\n}\n\nexport const defaultCodeBlockLabels: CodeBlockLabels = {\n autoDetect: 'Auto-detect',\n delete: 'Delete code block',\n copy: 'Copy code',\n expand: 'Expand code',\n collapse: 'Collapse code',\n};\n\nexport interface CommentLabels {\n open: string;\n resolved: string;\n dismissed: string;\n outdated: string;\n ambiguous: string;\n partial: string;\n gutterTitle: string;\n}\n\nexport const defaultCommentLabels: CommentLabels = {\n open: 'Open',\n resolved: 'Resolved',\n dismissed: 'Dismissed',\n outdated: 'Outdated',\n ambiguous: 'Ambiguous',\n partial: 'Partially matched',\n gutterTitle: 'Comment',\n};\n\nexport interface FindLabels {\n /** 查找输入框的占位与无障碍名,也用作浮动条的 aria-label。 */\n find: string;\n /** 替换输入框的占位与无障碍名。 */\n replace: string;\n next: string;\n previous: string;\n replaceOne: string;\n replaceAll: string;\n close: string;\n caseSensitive: string;\n wholeWord: string;\n useRegex: string;\n /** 计数文案。无结果时 current 传 0;有结果但还没定位到某一条(currentIndex 为 null)时也是 0。 */\n counter: (current: number, total: number) => string;\n /** 正则模式下模式非法(RE2 不支持 lookaround / backreference 等,见官方扩展)。 */\n invalidRegex: string;\n /** 只读态提示:可查不可换。 */\n readOnly: string;\n}\n\nexport const defaultFindLabels: FindLabels = {\n find: 'Find',\n replace: 'Replace with',\n next: 'Next match',\n previous: 'Previous match',\n replaceOne: 'Replace',\n replaceAll: 'Replace all',\n close: 'Close',\n caseSensitive: 'Match case',\n wholeWord: 'Whole word',\n useRegex: 'Use regular expression',\n counter: (current, total) => `${current} / ${total}`,\n invalidRegex: 'Invalid pattern',\n readOnly: 'Read-only',\n};\n","'use client';\n\nimport {\n createSearchRegex,\n FindAndReplacePluginKey,\n} from '@tiptap/extension-find-and-replace';\nimport { useEditorState, type Editor } from '@tiptap/react';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type RefObject,\n} from 'react';\nimport {\n FIND_DEBOUNCE_MS,\n hasFindReplaceExtension,\n isComposingKeyEvent,\n runFindCommand,\n} from '../findReplace';\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ReplaceAllIcon,\n ReplaceIcon,\n SearchIcon,\n XIcon,\n} from '../icons';\nimport { defaultFindLabels, type FindLabels } from '../labels';\nimport styles from '../styles/findBar.module.css';\n\nexport interface FindReplaceBarProps {\n /** 编辑器实例(由 `<MarkdownWysiwygEditor>` 提供,浮动条不自行创建编辑器)。 */\n editor: Editor;\n /** 关闭(Esc / ×):宿主负责收起浮动条并把焦点还给编辑器。 */\n onClose: () => void;\n labels?: Partial<FindLabels>;\n /**\n * 查找输入框 ref。宿主拿它实现「再按一次 Mod+F 聚焦并全选当前查询」。\n * 也用于浮动条打开时自动聚焦。\n */\n inputRef?: RefObject<HTMLInputElement | null>;\n /** 定位 / 层级 class,由宿主给(浮动条自身只负责内部布局)。 */\n className?: string;\n /** 根节点内联样式(编辑器用它落 findBarOffset;宿主自绘时也可用)。 */\n style?: CSSProperties;\n}\n\n/**\n * 查找替换浮动条。匹配、高亮、替换全部由官方\n * `@tiptap/extension-find-and-replace` 承担(含 RE2 安全正则、跨标记匹配、单事务全部替换),\n * 这里只做输入、计数、开关与键位。\n *\n * 打开即把查询推给编辑器,关闭时 `clearSearch()`——高亮是会话级的,不留残影。\n *\n * 给宿主的稳定选择器(内部 class 是 CSS Modules 哈希过的,宿主够不着):根节点\n * `data-find-bar`、两个输入框 `data-find-field=\"search|replace\"`、计数 `data-find-counter`、\n * 两个开关 `data-find-option=\"match-case|whole-words\"`、按钮\n * `data-find-action=\"previous|next|close|replace|replace-all\"`。\n */\n\n/** 「扩展没注册」的警告只发一次(模块级):同页多实例、或条子被反复开关时,重复同一句没有信息量。 */\nlet warnedMissingExtension = false;\nfunction warnMissingExtensionOnce(): void {\n if (warnedMissingExtension) return;\n warnedMissingExtension = true;\n console.warn(\n '[tiptap-markdown-react] FindReplaceBar 需要官方 find 扩展:' +\n '请让 <MarkdownWysiwygEditor findReplace> 保持开启(默认 true),' +\n '否则 setSearchTerm / replaceAll 等命令不存在。',\n );\n}\n\nexport function FindReplaceBar({\n editor,\n onClose,\n labels,\n inputRef,\n className,\n style,\n}: FindReplaceBarProps) {\n const t: FindLabels = { ...defaultFindLabels, ...labels };\n const [term, setTerm] = useState('');\n const [replaceTerm, setReplaceTerm] = useState('');\n\n // 宿主自己摆条子时可能把 findReplace 关了——那时扩展没注册,命令与插件 state 都不存在。\n // 不拦住的话下面每个 effect 都会 TypeError 把宿主的树带崩;这里退化为不渲染并留一句提示。\n const hasExtension = hasFindReplaceExtension(editor);\n useEffect(() => {\n if (!hasExtension) warnMissingExtensionOnce();\n }, [hasExtension]);\n\n const state = useEditorState({\n editor,\n selector: ({ editor: instance }) => {\n const plugin = FindAndReplacePluginKey.getState(instance.state);\n return {\n currentIndex: plugin?.currentIndex ?? null,\n total: plugin?.results.length ?? 0,\n caseSensitive: plugin?.caseSensitive ?? false,\n wholeWord: plugin?.wholeWord ?? false,\n useRegex: plugin?.useRegex ?? false,\n };\n },\n });\n\n /** 所有命令都从这里走:扩展缺席时直接跳过(见上面 hasExtension)。 */\n const runCommand = useCallback(\n (run: () => void) => {\n if (!hasExtension) return;\n runFindCommand(run);\n },\n [hasExtension],\n );\n\n // 查询词防抖由这里做(扩展注册时 searchDebounceMs: 0,原因见 findReplace.ts):\n // 输入时延迟推给编辑器,回车 / 替换等动作前先 flush,否则会拿着旧查询执行。\n const appliedTermRef = useRef<string | null>(null);\n const pushTerm = useCallback(\n (value: string) => {\n appliedTermRef.current = value;\n runCommand(() => editor.commands.setSearchTerm(value));\n },\n [editor, runCommand],\n );\n const flushTerm = useCallback(() => {\n if (appliedTermRef.current !== term) pushTerm(term);\n }, [pushTerm, term]);\n\n useEffect(() => {\n if (appliedTermRef.current === term) return;\n const timer = setTimeout(() => pushTerm(term), FIND_DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [term, pushTerm]);\n\n useEffect(() => {\n runCommand(() => editor.commands.setReplaceTerm(replaceTerm));\n }, [editor, replaceTerm, runCommand]);\n\n // 关闭 / 卸载时清空查询与高亮。\n useEffect(() => {\n return () => {\n if (!editor.isDestroyed) runCommand(() => editor.commands.clearSearch());\n };\n }, [editor, runCommand]);\n\n /** 动作类命令(导航 / 替换):先落定查询词,再执行。 */\n const runAction = useCallback(\n (action: () => void) => {\n flushTerm();\n runCommand(action);\n },\n [flushTerm, runCommand],\n );\n\n // RE2 模式非法(lookaround / backreference 等):官方返回零结果不报错,这里给个提示,\n // 否则「输入了正则却一直 0 / 0」没有解释。\n const invalidPattern = useMemo(\n () =>\n term !== '' &&\n state.useRegex &&\n createSearchRegex(term, {\n caseSensitive: state.caseSensitive,\n useRegex: true,\n wholeWord: false,\n }) === null,\n [term, state.useRegex, state.caseSensitive],\n );\n\n // currentIndex 为 null = 有结果、但还没定位到某一条(官方 `formatResultCount` 同款语义:\n // 那一条分支返回 `0 / total`)。不这样判的话第 1 条会被冒充成「当前」。\n const current =\n state.total === 0 || state.currentIndex === null\n ? 0\n : state.currentIndex + 1;\n const counter = t.counter(current, state.total);\n\n const keepFocus = (e: ReactMouseEvent) => e.preventDefault();\n\n const onFindKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (isComposingKeyEvent(e.nativeEvent)) return;\n if (e.key === 'Enter') {\n e.preventDefault();\n runAction(() => {\n if (e.shiftKey) editor.commands.goToPreviousResult();\n else editor.commands.goToNextResult();\n });\n }\n };\n\n const onReplaceKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n if (isComposingKeyEvent(e.nativeEvent)) return;\n if (e.key === 'Enter') {\n e.preventDefault();\n runAction(() => editor.commands.replace());\n }\n };\n\n const toggle = (key: 'caseSensitive' | 'wholeWord', value: boolean) => {\n runCommand(() => {\n if (key === 'caseSensitive') editor.commands.setCaseSensitive(value);\n else editor.commands.setWholeWord(value);\n });\n };\n\n if (!hasExtension) return null;\n\n const toggleClass = (on: boolean) =>\n `${styles.btn} ${styles.toggle}${on ? ` ${styles.toggleOn}` : ''}`;\n\n return (\n <div\n className={className ? `${styles.bar} ${className}` : styles.bar}\n style={style}\n data-find-bar=\"\"\n role=\"dialog\"\n aria-label={t.find}\n onKeyDown={(e) => {\n // 输入法组合中的 Esc 是「取消候选词」,放行。其余吃到 Esc 就自己收掉并**消费掉**这次\n // 按键(stopPropagation)——宿主按文档把条子放进自己的弹窗 / 抽屉时,那一层的 Esc\n // 处理不该被同一次按键带着一起关。\n if (isComposingKeyEvent(e.nativeEvent)) return;\n if (e.key !== 'Escape') return;\n e.preventDefault();\n e.stopPropagation();\n onClose();\n }}\n >\n <div className={styles.row}>\n <span className={styles.field}>\n <SearchIcon size={14} className={styles.fieldIcon} />\n <input\n ref={inputRef}\n className={styles.input}\n data-find-field=\"search\"\n value={term}\n onChange={(e) => setTerm(e.target.value)}\n onKeyDown={onFindKeyDown}\n placeholder={t.find}\n aria-label={t.find}\n autoFocus\n spellCheck={false}\n />\n <span\n className={`${styles.counter}${invalidPattern ? ` ${styles.counterInvalid}` : ''}`}\n data-find-counter=\"\"\n aria-live=\"polite\"\n title={invalidPattern ? t.invalidRegex : undefined}\n >\n {invalidPattern ? t.invalidRegex : counter}\n </span>\n </span>\n <button\n type=\"button\"\n className={toggleClass(state.caseSensitive)}\n data-find-option=\"match-case\"\n title={t.caseSensitive}\n aria-label={t.caseSensitive}\n aria-pressed={state.caseSensitive}\n onMouseDown={keepFocus}\n onClick={() => toggle('caseSensitive', !state.caseSensitive)}\n >\n Aa\n </button>\n <button\n type=\"button\"\n className={toggleClass(state.wholeWord)}\n data-find-option=\"whole-words\"\n title={t.wholeWord}\n aria-label={t.wholeWord}\n aria-pressed={state.wholeWord}\n onMouseDown={keepFocus}\n onClick={() => toggle('wholeWord', !state.wholeWord)}\n >\n ab\n </button>\n\n <span className={styles.spacer} />\n <span className={styles.iconGroup}>\n <button\n type=\"button\"\n className={styles.btn}\n data-find-action=\"previous\"\n title={t.previous}\n aria-label={t.previous}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.goToPreviousResult())}\n >\n <ChevronUpIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n data-find-action=\"next\"\n title={t.next}\n aria-label={t.next}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.goToNextResult())}\n >\n <ChevronDownIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n data-find-action=\"close\"\n title={t.close}\n aria-label={t.close}\n onClick={onClose}\n >\n <XIcon size={16} />\n </button>\n </span>\n </div>\n\n {editor.isEditable ? (\n <div className={styles.row}>\n <span className={styles.field}>\n <input\n className={styles.input}\n data-find-field=\"replace\"\n value={replaceTerm}\n onChange={(e) => setReplaceTerm(e.target.value)}\n onKeyDown={onReplaceKeyDown}\n placeholder={t.replace}\n aria-label={t.replace}\n spellCheck={false}\n />\n </span>\n <span className={styles.spacer} />\n <button\n type=\"button\"\n className={styles.btn}\n data-find-action=\"replace\"\n title={t.replaceOne}\n aria-label={t.replaceOne}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.replace())}\n >\n <ReplaceIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n data-find-action=\"replace-all\"\n title={t.replaceAll}\n aria-label={t.replaceAll}\n disabled={state.total === 0}\n onMouseDown={keepFocus}\n onClick={() => runAction(() => editor.commands.replaceAll())}\n >\n <ReplaceAllIcon size={16} />\n </button>\n </div>\n ) : (\n <div className={styles.row}>\n <span className={styles.readOnly}>{t.readOnly}</span>\n </div>\n )}\n </div>\n );\n}\n","import { Node } from '@tiptap/core';\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n importPlaceholder: {\n insertImportPlaceholder: (label: string) => ReturnType;\n updateImportPlaceholder: (label: string) => ReturnType;\n removeImportPlaceholder: () => ReturnType;\n };\n }\n}\n\nfunction findPlaceholderPos(doc: {\n descendants: (\n f: (node: { type: { name: string } }, pos: number) => boolean | void,\n ) => void;\n}): number | null {\n let found: number | null = null;\n doc.descendants((node, pos) => {\n if (node.type.name === 'importPlaceholder') {\n found = pos;\n return false;\n }\n });\n return found;\n}\n\n/** 导入进行中插在光标处的占位块。不进 Markdown,autosave 不会把进度文案落库。 */\nexport const ImportPlaceholder = Node.create({\n name: 'importPlaceholder',\n group: 'block',\n atom: true,\n selectable: false,\n draggable: false,\n\n addAttributes() {\n return {\n label: {\n default: '',\n parseHTML: (el) => el.getAttribute('data-label') ?? '',\n renderHTML: (attrs) =>\n attrs.label ? { 'data-label': attrs.label } : {},\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'div[data-type=\"import-placeholder\"]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const label = String(node.attrs.label ?? '');\n return [\n 'div',\n {\n ...HTMLAttributes,\n 'data-type': 'import-placeholder',\n class: 'tmr-import-placeholder',\n contenteditable: 'false',\n 'aria-live': 'polite',\n 'aria-busy': 'true',\n },\n ['span', { class: 'tmr-import-placeholder-spin', 'aria-hidden': 'true' }],\n ['span', { class: 'tmr-import-placeholder-label' }, label],\n ];\n },\n\n renderMarkdown() {\n return '';\n },\n\n addCommands() {\n return {\n insertImportPlaceholder:\n (label) =>\n ({ chain }) =>\n chain()\n .focus()\n .insertContent({\n type: this.name,\n attrs: { label },\n })\n .command(({ tr }) => {\n tr.setMeta('addToHistory', false);\n tr.setMeta('preventUpdate', true);\n return true;\n })\n .run(),\n updateImportPlaceholder:\n (label) =>\n ({ tr, dispatch, state }) => {\n const pos = findPlaceholderPos(state.doc);\n if (pos == null) return false;\n if (dispatch) {\n dispatch(\n tr\n .setNodeMarkup(pos, undefined, { label })\n .setMeta('addToHistory', false)\n .setMeta('preventUpdate', true),\n );\n }\n return true;\n },\n removeImportPlaceholder:\n () =>\n ({ tr, dispatch, state }) => {\n const pos = findPlaceholderPos(state.doc);\n if (pos == null) return false;\n const node = state.doc.nodeAt(pos);\n if (!node) return false;\n if (dispatch) {\n dispatch(\n tr\n .delete(pos, pos + node.nodeSize)\n .setMeta('addToHistory', false)\n .setMeta('preventUpdate', true),\n );\n }\n return true;\n },\n };\n },\n});\n","import type { Editor } from '@tiptap/core';\nimport {\n defaultSlashMenuLabels,\n type SlashMenuLabels,\n} from '../labels';\nimport type { SlashMenuItem } from './types';\n\n/**\n * 默认斜杠命令项:全部是「可序列化为 markdown」的块级操作。\n * 图片、附件、AI、二级子菜单、最近使用不在 v1 范围。\n *\n * 图标沿用工具栏下拉菜单的文字字形语言(`{ }` / `√x` / `∑` / `—` / `❝`),\n * 三组(文本 / 列表 / 高级)在弹窗里分节展示。\n */\nexport function createDefaultSlashMenuItems(\n labels: SlashMenuLabels = defaultSlashMenuLabels,\n): SlashMenuItem[] {\n return [\n {\n id: 'normal-text',\n title: labels.normalText,\n group: labels.groupText,\n icon: '¶',\n aliases: ['zhengwen', '正文', 'paragraph', 'text'],\n order: 0,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).setParagraph().run();\n },\n },\n ...([1, 2, 3] as const).map((level): SlashMenuItem => ({\n id: `heading-${level}`,\n title: labels.headingLabel(level),\n group: labels.groupText,\n icon: `H${level}`,\n aliases: [`h${level}`, 'biaoti', '标题', 'heading'],\n order: level,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setHeading({ level })\n .run();\n },\n })),\n {\n id: 'bullet-list',\n title: labels.bulletList,\n group: labels.groupList,\n icon: '•',\n aliases: ['wuxu', '无序', '列表', 'bullet', 'ul'],\n order: 4,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleBulletList().run();\n },\n },\n {\n id: 'ordered-list',\n title: labels.orderedList,\n group: labels.groupList,\n icon: '1.',\n aliases: ['youxu', '有序', '列表', 'ordered', 'ol'],\n order: 5,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleOrderedList().run();\n },\n },\n {\n id: 'task-list',\n title: labels.taskList,\n group: labels.groupList,\n icon: '✓',\n aliases: ['renwu', '任务', '待办', 'task', 'todo', 'checklist'],\n order: 6,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleTaskList().run();\n },\n },\n {\n id: 'blockquote',\n title: labels.blockquote,\n group: labels.groupAdvanced,\n icon: '❝',\n aliases: ['yinyong', '引用', 'quote', 'blockquote'],\n order: 7,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleBlockquote().run();\n },\n },\n {\n id: 'code-block',\n title: labels.codeBlock,\n group: labels.groupAdvanced,\n icon: '{ }',\n aliases: ['daima', '代码', 'code', 'fence'],\n order: 8,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).toggleCodeBlock().run();\n },\n },\n {\n id: 'divider',\n title: labels.divider,\n group: labels.groupAdvanced,\n icon: '—',\n aliases: ['fenge', '分割线', '分隔线', 'hr', 'divider'],\n order: 9,\n apply: (editor, range) => {\n editor.chain().focus().deleteRange(range).setHorizontalRule().run();\n },\n },\n {\n id: 'table',\n title: labels.table,\n group: labels.groupAdvanced,\n icon: '▦',\n aliases: ['biaoge', '表格', 'table'],\n order: 10,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertTable({ rows: 3, cols: 3, withHeaderRow: true })\n .run();\n },\n },\n {\n id: 'inline-math',\n title: labels.inlineMath,\n group: labels.groupAdvanced,\n icon: '√x',\n aliases: ['gongshi', '公式', '行内公式', 'math', 'latex'],\n order: 11,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({ type: 'inlineMath', attrs: { latex: 'E=mc^2' } })\n .run();\n },\n },\n {\n id: 'block-math',\n title: labels.blockMath,\n group: labels.groupAdvanced,\n icon: '∑',\n aliases: ['gongshi', '公式', '块级公式', 'mathblock', 'latex'],\n order: 12,\n apply: (editor, range) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent({ type: 'blockMath', attrs: { latex: 'E=mc^2' } })\n .run();\n },\n },\n ];\n}\n\n/** 按 title / aliases 做小写 includes 过滤;空 query 返回全部。 */\nexport function filterSlashItems(\n items: SlashMenuItem[],\n query: string,\n): SlashMenuItem[] {\n const q = query.trim().toLowerCase();\n if (!q) return items;\n return items.filter(\n (item) =>\n item.title.toLowerCase().includes(q) ||\n item.aliases?.some((alias) => alias.toLowerCase().includes(q)),\n );\n}\n","import {\n Fragment,\n forwardRef,\n useEffect,\n useImperativeHandle,\n useState,\n type ReactNode,\n} from 'react';\nimport styles from '../styles/slashMenu.module.css';\nimport type { SlashMenuItem } from './types';\n\nexport interface SlashMenuPopupHandle {\n /** 编辑器键盘事件经 IME 守卫后委托进来;返回 true 表示已消费。 */\n onKeyDown: (event: KeyboardEvent) => boolean;\n}\n\nexport interface SlashMenuPopupProps {\n items: SlashMenuItem[];\n query: string;\n menuLabel: string;\n command: (item: SlashMenuItem) => void;\n}\n\n/**\n * 把有序列表切成「相邻同名组」的节:返回 [组名 | null, 项][]。\n * 组首项的行携带组名(渲染为节标题 + 该项),其余行组名为 null。\n */\nfunction withGroupHeaders(\n items: SlashMenuItem[],\n): Array<[ReactNode, SlashMenuItem]> {\n const rows: Array<[ReactNode, SlashMenuItem]> = [];\n let lastGroup: string | undefined;\n for (const item of items) {\n if (item.group && item.group !== lastGroup) {\n rows.push([item.group, item]);\n lastGroup = item.group;\n } else {\n if (!item.group) lastGroup = undefined;\n rows.push([null, item]);\n }\n }\n return rows;\n}\n\n/**\n * 斜杠菜单弹层。样式对齐工具栏下拉菜单(radix 面板 + 文字字形图标 +\n * 品牌色高亮);定位由 @tiptap/suggestion 的 mount(floating-ui)接管。\n * 零匹配时渲染 null:弹层隐藏但 suggestion 保持激活,query 恢复命中时\n * 重新出现。\n */\nexport const SlashMenuPopup = forwardRef<\n SlashMenuPopupHandle,\n SlashMenuPopupProps\n>(function SlashMenuPopup({ items, query, menuLabel, command }, ref) {\n const [index, setIndex] = useState(0);\n\n // query 变化(过滤)后选区回到第一项\n useEffect(() => {\n setIndex(0);\n }, [query]);\n\n useImperativeHandle(\n ref,\n () => ({\n onKeyDown(event) {\n if (!items.length) return false;\n if (event.key === 'ArrowDown' || (event.key === 'Tab' && !event.shiftKey)) {\n setIndex((i) => (i + 1) % items.length);\n return true;\n }\n if (event.key === 'ArrowUp' || (event.key === 'Tab' && event.shiftKey)) {\n setIndex((i) => (i - 1 + items.length) % items.length);\n return true;\n }\n if (event.key === 'Enter') {\n const item = items[index];\n if (!item) return false;\n command(item);\n return true;\n }\n return false;\n },\n }),\n [items, index, command],\n );\n\n if (!items.length) return null;\n\n // 键盘索引按「可选项」计;分组头不占位\n let optionIndex = -1;\n\n return (\n <div className={styles.menu} role=\"listbox\" aria-label={menuLabel}>\n {withGroupHeaders(items).map(([header, item]) => {\n optionIndex += 1;\n const i = optionIndex;\n return (\n <Fragment key={item.id}>\n {header !== null ? (\n <div className={styles.groupLabel} aria-hidden=\"true\">\n {header}\n </div>\n ) : null}\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={i === index}\n title={item.title}\n className={i === index ? styles.itemActive : styles.item}\n // 键盘焦点留在编辑器里,↑↓/Enter 才能继续驱动弹层\n tabIndex={-1}\n onMouseEnter={() => setIndex(i)}\n onMouseDown={(e) => {\n // 用 mousedown 抢在编辑器 blur 之前执行,避免选区先被抖掉\n e.preventDefault();\n command(item);\n }}\n >\n {item.icon != null ? (\n <span className={styles.itemIcon} aria-hidden=\"true\">\n {item.icon}\n </span>\n ) : (\n <span className={styles.itemIcon} aria-hidden=\"true\" />\n )}\n <span className={styles.itemTitle}>{item.title}</span>\n </button>\n </Fragment>\n );\n })}\n </div>\n );\n});\n","import { Extension } from '@tiptap/core';\nimport { ReactRenderer } from '@tiptap/react';\nimport Suggestion, {\n type SuggestionKeyDownProps,\n type SuggestionProps,\n} from '@tiptap/suggestion';\nimport { PluginKey } from '@tiptap/pm/state';\nimport {\n defaultSlashMenuLabels,\n type SlashMenuLabels,\n} from '../labels';\nimport styles from '../styles/slashMenu.module.css';\nimport { createDefaultSlashMenuItems, filterSlashItems } from './items';\nimport { SlashMenuPopup, type SlashMenuPopupHandle } from './SlashMenuPopup';\nimport type { SlashMenuItem } from './types';\n\nexport interface SlashMenuOptions {\n /** 追加的宿主自定义命令项(排在默认项之后)。 */\n items?: SlashMenuItem[];\n /** 弹窗文案,与默认英文文案合并。 */\n labels?: Partial<SlashMenuLabels>;\n}\n\n/** 输入法组合态下的按键交给 IME 自己处理(上游 suggestion 不查 composing)。 */\nfunction isComposing(event: KeyboardEvent, view: { composing: boolean }): boolean {\n return view.composing || event.isComposing || event.keyCode === 229;\n}\n\n/**\n * 斜杠菜单:键入 `/` 唤起块级插入弹窗。\n *\n * - 触发规则:行首或空白后(`allowedPrefixes`,空白含全角 U+3000);\n * 正文里「和/或」这类合法斜杠不会触发。\n * - 代码块内不触发;表格单元格内触发(见 allow)。\n * - 定位/滚动跟随/点外关闭全走官方 `props.mount`(floating-ui),\n * 弹层挂 document.body(逃出宿主 overflow 裁剪),`--tmr-*` 主题\n * 变量从编辑器解析后复制到弹层宿主。\n * - 只读态由 suggestion 状态机自身拦截(isEditable 短路)。\n */\nexport const SlashMenu = Extension.create<SlashMenuOptions>({\n name: 'slashMenu',\n\n addOptions() {\n return { items: undefined, labels: undefined };\n },\n\n addProseMirrorPlugins() {\n const { items: extraItems, labels } = this.options;\n const allItems = [\n ...createDefaultSlashMenuItems({ ...defaultSlashMenuLabels, ...labels }),\n ...(extraItems ?? []),\n ];\n\n let renderer: ReactRenderer<SlashMenuPopupHandle> | null = null;\n let unmountPopup: (() => void) | null = null;\n\n return [\n Suggestion<SlashMenuItem>({\n editor: this.editor,\n pluginKey: new PluginKey('tmrSlashMenu'),\n char: '/',\n // 行首(节点内起始,空 prefix 天然放行)或空白后触发\n allowedPrefixes: [' ', '\\t', '\\u3000'],\n allowSpaces: false,\n decorationClass: 'tmr-slash-suggestion',\n decorationEmptyClass: 'tmr-slash-suggestion-empty',\n items: ({ query }) => filterSlashItems(allItems, query),\n command: ({ editor, range, props: item }) => {\n item.apply(editor, range);\n },\n allow: ({ editor }) => editor.isEditable && !editor.isActive('codeBlock'),\n render: () => ({\n onStart: (props: SuggestionProps<SlashMenuItem>) => {\n renderer = new ReactRenderer(\n SlashMenuPopup,\n {\n editor: props.editor,\n props: {\n items: props.items,\n query: props.query,\n menuLabel:\n this.options.labels?.menuLabel ?? defaultSlashMenuLabels.menuLabel,\n command: props.command,\n },\n className: styles.popupHost,\n },\n );\n // 挂到 body(suggestion 默认容器):弹层要能浮出编辑器,宿主在\n // 编辑器外层套 overflow:hidden(圆角窗口/滚动容器)时不会被裁。\n // 主题变量随行:编辑器子树上的 --tmr-* 解析值复制到弹层宿主,\n // 宿主把变量定义在任意深度的子树里也能保持配色一致。\n const pmStyle = getComputedStyle(props.editor.view.dom);\n for (const name of [\n '--tmr-text',\n '--tmr-accent',\n '--tmr-toolbar-border',\n '--tmr-toolbar-muted',\n ]) {\n const value = pmStyle.getPropertyValue(name);\n if (value) renderer.element.style.setProperty(name, value);\n }\n unmountPopup = props.mount(renderer.element);\n },\n onUpdate: (props: SuggestionProps<SlashMenuItem>) => {\n renderer?.updateProps({\n items: props.items,\n query: props.query,\n command: props.command,\n });\n },\n onKeyDown: (props: SuggestionKeyDownProps) => {\n if (!renderer || isComposing(props.event, props.view)) return false;\n return renderer.ref?.onKeyDown(props.event) ?? false;\n },\n onExit: () => {\n unmountPopup?.();\n unmountPopup = null;\n renderer?.destroy();\n renderer = null;\n },\n }),\n }),\n ];\n },\n});\n","import type { ShortcutLabels } from '../labels';\n\n/**\n * 快捷键面板数据模型。keys 里的 'Mod' / 'Alt' 按平台渲染\n * (macOS: Cmd / Opt;其他: Ctrl / Alt)。\n * markdown.terminator 为触发终止键;无 terminator 的包裹型语法\n * (如 **x**)在键入收尾字符时即触发。\n */\nexport interface ShortcutEntry {\n id: string;\n /** 展示名(已本地化)。 */\n label: string;\n /** 键帽序列;不传表示无默认键位。 */\n keys?: string[];\n /** Markdown 触发写法;不传表示无对应 input rule。 */\n markdown?: {\n /** 触发片段,如 '**x**' 或 '#'。 */\n marker: string;\n /** 终止键(如 Space / Enter)。 */\n terminator?: string;\n };\n}\n\nexport interface ShortcutGroup {\n id: string;\n title: string;\n entries: ShortcutEntry[];\n}\n\n/**\n * 快捷键注册表。**每一条都必须真实**:键位来自所装 Tiptap 扩展的\n * addKeyboardShortcuts 默认值,markdown 触发来自对应 input rule\n * (上标/下标/链接在本库无默认键位与 input rule,故不列)。\n */\nexport function buildShortcutGroups(labels: ShortcutLabels): ShortcutGroup[] {\n return [\n {\n id: 'format',\n title: labels.formatGroup,\n entries: [\n { id: 'bold', label: labels.bold, keys: ['Mod', 'b'], markdown: { marker: '**x**' } },\n { id: 'italic', label: labels.italic, keys: ['Mod', 'i'], markdown: { marker: '*x*' } },\n { id: 'strike', label: labels.strike, keys: ['Mod', 'Shift', 's'], markdown: { marker: '~~x~~' } },\n { id: 'underline', label: labels.underline, keys: ['Mod', 'u'] },\n { id: 'inline-code', label: labels.inlineCode, keys: ['Mod', 'e'], markdown: { marker: '`x`' } },\n { id: 'highlight', label: labels.highlight, keys: ['Mod', 'Shift', 'h'], markdown: { marker: '==x==' } },\n ...([1, 2, 3, 4, 5, 6] as const).map((level): ShortcutEntry => ({\n id: `heading-${level}`,\n label: labels.headingLabel(level),\n keys: ['Mod', 'Alt', String(level)],\n markdown: { marker: '#'.repeat(level), terminator: 'Space' },\n })),\n { id: 'paragraph', label: labels.paragraph, keys: ['Mod', 'Alt', '0'] },\n ],\n },\n {\n id: 'insert',\n title: labels.insertGroup,\n entries: [\n { id: 'blockquote', label: labels.blockquote, keys: ['Mod', 'Shift', 'b'], markdown: { marker: '>', terminator: 'Space' } },\n { id: 'bullet-list', label: labels.bulletList, keys: ['Mod', 'Shift', '8'], markdown: { marker: '-', terminator: 'Space' } },\n { id: 'ordered-list', label: labels.orderedList, keys: ['Mod', 'Shift', '7'], markdown: { marker: '1.', terminator: 'Space' } },\n { id: 'task-list', label: labels.taskList, markdown: { marker: '[]', terminator: 'Space' } },\n { id: 'code-block', label: labels.codeBlock, markdown: { marker: '```', terminator: 'Space' } },\n { id: 'divider', label: labels.divider, markdown: { marker: '---', terminator: 'Space' } },\n ],\n },\n {\n id: 'edit',\n title: labels.editGroup,\n entries: [\n { id: 'undo', label: labels.undo, keys: ['Mod', 'z'] },\n { id: 'redo', label: labels.redo, keys: ['Mod', 'Shift', 'z'] },\n { id: 'hard-break', label: labels.hardBreak, keys: ['Shift', 'Enter'] },\n { id: 'find-replace', label: labels.findReplace, keys: ['Mod', 'f'] },\n ],\n },\n ];\n}\n","import { useEffect, useMemo } from 'react';\nimport { defaultShortcutLabels, type ShortcutLabels } from '../labels';\nimport { XIcon } from '../icons';\nimport styles from '../styles/shortcutPanel.module.css';\nimport { buildShortcutGroups, type ShortcutGroup } from './types';\n\nexport interface ShortcutPanelProps {\n open: boolean;\n onClose: () => void;\n /** 文案覆盖,与默认英文合并。 */\n labels?: Partial<ShortcutLabels>;\n}\n\nfunction isMacPlatform(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);\n}\n\n/** 键帽文案:Mod/Alt 按平台落名,单字母统一大写。 */\nfunction keycapText(key: string, mac: boolean): string {\n if (key === 'Mod') return mac ? 'Cmd' : 'Ctrl';\n if (key === 'Alt') return mac ? 'Opt' : 'Alt';\n if (/^[a-z]$/.test(key)) return key.toUpperCase();\n return key;\n}\n\n/**\n * 快捷键抽屉(语雀式):右侧滑出的三列对照表——格式 / 快捷键 / Markdown。\n * 数据来自 buildShortcutGroups(键位与 input rule 均为库内真实行为)。\n * 定位 fixed 贴视口右缘;Esc 关闭。\n */\nexport function ShortcutPanel({ open, onClose, labels }: ShortcutPanelProps) {\n const t: ShortcutLabels = useMemo(\n () => ({ ...defaultShortcutLabels, ...labels }),\n [labels],\n );\n\n // 打开期间 Esc 关闭\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, [open, onClose]);\n\n const groups: ShortcutGroup[] = useMemo(\n () => (open ? buildShortcutGroups(t) : []),\n [open, t],\n );\n const mac = useMemo(isMacPlatform, []);\n\n if (!open) return null;\n\n return (\n <aside\n className={styles.drawer}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={t.panelTitle}\n >\n <button\n type=\"button\"\n className={styles.closeBtn}\n title={t.close}\n aria-label={t.close}\n onClick={onClose}\n >\n <XIcon size={16} />\n </button>\n <div className={styles.head}>\n <span className={styles.colFormat}>{t.colFormat}</span>\n <span className={styles.colShortcut}>{t.colShortcut}</span>\n <span className={styles.colMarkdown}>{t.colMarkdown}</span>\n </div>\n <div className={styles.body}>\n {groups.map((group) => (\n <section key={group.id} className={styles.group}>\n <h3 className={styles.groupTitle}>{group.title}</h3>\n {group.entries.map((entry) => (\n <div key={entry.id} className={styles.row}>\n <span className={styles.rowLabel}>{entry.label}</span>\n <span className={styles.rowKeys}>\n {entry.keys ? (\n entry.keys.map((key, i) => (\n <kbd key={i} className={styles.keycap}>\n {keycapText(key, mac)}\n </kbd>\n ))\n ) : (\n <span className={styles.none}>—</span>\n )}\n </span>\n <span className={styles.rowMd}>\n {entry.markdown ? (\n <>\n <kbd className={styles.keycap}>{entry.markdown.marker}</kbd>\n {entry.markdown.terminator ? (\n <kbd className={styles.keycap}>{entry.markdown.terminator}</kbd>\n ) : null}\n </>\n ) : (\n <span className={styles.none}>—</span>\n )}\n </span>\n </div>\n ))}\n </section>\n ))}\n </div>\n </aside>\n );\n}\n","// 副作用:增强 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","import { Extension } from '@tiptap/core';\nimport { skipTrailingNodeMeta } from '@tiptap/extensions';\nimport type { Node } from '@tiptap/pm/model';\nimport { Plugin, PluginKey, type EditorState } from '@tiptap/pm/state';\nimport { Decoration, DecorationSet } from '@tiptap/pm/view';\nimport type { Editor } from '@tiptap/react';\n\n/**\n * 「这段正在被 AI 改写」的高亮。\n *\n * 用 **decoration** 而不是 mark:两者都不会漏进 markdown,都能盖住表格,但 decoration\n * 不需要往 schema 里加标记、也不参与 undo 历史,而且**原子节点(图表 / 图片)也能盖**\n * ——mark 只作用于行内内容,盖不住 `atom: true` 的块级节点。\n *\n * 状态由宿主通过 `pendingAnchors` 推入(提交圈选改写时给上,回填或冲突时清空)。\n * 文档被编辑时装饰会跟着映射(在原文中间插字,高亮跟着变长;在前面插,整体后移)。\n */\nexport interface PendingAnchor {\n /** 宿主自己的标识(例如一次圈选请求的 request_id)。 */\n id: string;\n /** doc 坐标区间;通常是与选区相交的顶层块的首尾(见 getMarkdownForRange)。 */\n ranges: Array<{ from: number; to: number }>;\n}\n\nexport interface PendingAnchorState {\n decorations: DecorationSet;\n}\n\n/** 用 transaction meta 推入锚点:`tr.setMeta(PENDING_ANCHOR_META, anchors)`。 */\nexport const PENDING_ANCHOR_META = 'tmr:pendingAnchor';\n\nexport const pendingAnchorPluginKey = new PluginKey<PendingAnchorState>(\n 'tmrPendingAnchor',\n);\n\n/** 装饰上的 class;点击命中时宿主用 `[data-pending-id]` 取回 id。 */\nexport const PENDING_ANCHOR_CLASS = 'tmr-pending-anchor';\n\nexport const pendingAnchorExtension = Extension.create({\n name: 'pendingAnchor',\n\n addProseMirrorPlugins() {\n return [\n new Plugin<PendingAnchorState>({\n key: pendingAnchorPluginKey,\n state: {\n init: () => ({ decorations: DecorationSet.empty }),\n apply(tr, value) {\n const next = tr.getMeta(PENDING_ANCHOR_META) as\n | PendingAnchor[]\n | undefined;\n if (next) return { decorations: buildDecorations(tr.doc, next) };\n if (tr.docChanged) {\n return { decorations: value.decorations.map(tr.mapping, tr.doc) };\n }\n return value;\n },\n },\n props: {\n decorations(state: EditorState) {\n return pendingAnchorPluginKey.getState(state)?.decorations ?? null;\n },\n },\n }),\n ];\n },\n});\n\n/** 更新待改写高亮(传空数组即清空)。不进 undo 历史。 */\nexport function setPendingAnchors(editor: Editor, anchors: PendingAnchor[]): void {\n editor.view.dispatch(\n editor.state.tr\n .setMeta(PENDING_ANCHOR_META, anchors)\n // Tiptap 的 TrailingNode(StarterKit 自带)会在「第一个 transaction」时给文档末尾补一个\n // 空段落——只要文末是图表 / 表格 / 代码块这类节点。那是它本来的行为,但**不该由一次\n // 「加个高亮」触发**:那等于用户什么都没干、正文却多了个空段落(落库就变成结尾的 \\n\\n)。\n // 用官方 meta 跳过本次。\n .setMeta(skipTrailingNodeMeta, true)\n .setMeta('addToHistory', false),\n );\n}\n\nfunction buildDecorations(doc: Node, anchors: PendingAnchor[]): DecorationSet {\n const bounds: Array<{ from: number; to: number }> = [];\n doc.forEach((child, offset) => {\n bounds.push({ from: offset, to: offset + child.nodeSize });\n });\n\n const decorations: Decoration[] = [];\n for (const anchor of anchors) {\n for (const range of anchor.ranges) {\n const from = Math.max(0, Math.min(range.from, range.to));\n const to = Math.min(doc.content.size, Math.max(range.from, range.to));\n if (from >= to) continue;\n\n for (const bound of bounds) {\n if (bound.to <= from || bound.from >= to) continue;\n const attrs = {\n class: PENDING_ANCHOR_CLASS,\n 'data-pending-id': anchor.id,\n };\n if (from <= bound.from && to >= bound.to) {\n // 整块:用 node 装饰,表格 / 图表这类块级节点才盖得住\n decorations.push(Decoration.node(bound.from, bound.to, attrs));\n } else {\n // 块内的一部分(未扩块的选区):行内高亮\n decorations.push(\n Decoration.inline(Math.max(from, bound.from), Math.min(to, bound.to), attrs),\n );\n }\n }\n }\n }\n\n return decorations.length ? DecorationSet.create(doc, decorations) : DecorationSet.empty;\n}\n","import type { Selection } from '@tiptap/pm/state';\nimport { NodeSelection, TextSelection } from '@tiptap/pm/state';\nimport { CellSelection } from '@tiptap/pm/tables';\n\n/**\n * 选区类型——给宿主判断「用户选的是什么」用。\n *\n * - `text`:普通文字选区(含 AllSelection)\n * - `cell`:表格里的单元格选区(`CellSelection`,拖过表格时就是它)\n * - `node`:整节点选区(`NodeSelection`)。图表 / 图片 / 代码块这类 `atom` 节点只能这样被选中\n * ——它们在编辑器里渲染成图或块,用户没法用拖选文字的方式选中\n */\nexport type SelectionKind = 'text' | 'cell' | 'node';\n\nexport function selectionKind(selection: Selection): SelectionKind {\n if (selection instanceof CellSelection) return 'cell';\n if (selection instanceof NodeSelection) return 'node';\n if (selection instanceof TextSelection) return 'text';\n return 'text';\n}\n","// 副作用:增强 Editor.markdown(MarkdownManager)的类型。\nimport '@tiptap/markdown';\nimport { Extension } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\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 /<!--\\s*[\\[{][\\s\\S]*?\"chartType\"[\\s\\S]*?-->/.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 // 与 insertMarkdown / 初始 content 一致:先把\n // `<!-- chartType -->` + GFM 表收成 ```tmr-chart,否则\n // TipTap 会丢掉 HTML 注释,只剩普通表格。\n const json = markdown.parse(prepareChartMarkdown(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","'use client';\n\nimport type { Chart as ChartJs } from 'chart.js';\nimport {\n NodeViewWrapper,\n type NodeViewProps,\n} from '@tiptap/react';\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type MouseEvent,\n} from 'react';\nimport { destroyChart, renderOrUpdateChart } from '../chart/renderChart';\nimport type { ChartPayload, ChartTheme } from '../chart/types';\nimport { defaultChartLabels } from '../labels';\nimport '../styles/chart.css';\n\nfunction tabLabel(\n chartType: string,\n title: string | undefined,\n index: number,\n fallback: (type: string, i: number) => string,\n): string {\n if (title?.trim()) return title;\n return fallback(chartType, index);\n}\n\n/**\n * Chart NodeView: render + NodeSelection (like Image).\n * Config editing is intentionally disabled for now (no modal).\n */\nexport function ChartView({\n node,\n editor,\n extension,\n selected,\n getPos,\n}: NodeViewProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const chartRef = useRef<ChartJs | null>(null);\n const [active, setActive] = useState(0);\n\n const payload: ChartPayload = useMemo(\n () => ({\n config: (node.attrs.config ?? []) as ChartPayload['config'],\n columns: (node.attrs.columns ?? []) as ChartPayload['columns'],\n dataSource: (node.attrs.dataSource ??\n []) as ChartPayload['dataSource'],\n }),\n [node.attrs.config, node.attrs.columns, node.attrs.dataSource],\n );\n\n const theme = (extension.options.chartTheme ?? null) as ChartTheme | null;\n const configs = payload.config;\n const safeIndex = Math.min(active, Math.max(0, configs.length - 1));\n const config = configs[safeIndex];\n const height = config?.height ?? 320;\n const canSelect = Boolean(editor?.isEditable);\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !config) return;\n chartRef.current = renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart: chartRef.current,\n });\n }, [config, payload, theme]);\n\n useEffect(() => {\n return () => {\n destroyChart(chartRef.current);\n chartRef.current = null;\n };\n }, []);\n\n // When active tab changes, recreate chart (type may differ)\n useEffect(() => {\n destroyChart(chartRef.current);\n chartRef.current = null;\n const canvas = canvasRef.current;\n if (!canvas || !config) return;\n chartRef.current = renderOrUpdateChart({\n canvas,\n config,\n payload,\n theme,\n chart: null,\n });\n }, [safeIndex]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const labels = {\n ...defaultChartLabels,\n ...(extension.options.chartLabels as\n | Partial<typeof defaultChartLabels>\n | undefined),\n };\n\n const selectChart = () => {\n if (!editor || !canSelect) return;\n const pos = getPos();\n if (typeof pos !== 'number') return;\n editor.commands.setNodeSelection(pos);\n };\n\n return (\n <NodeViewWrapper\n as=\"div\"\n className={`tmr-chart${canSelect ? ' tmr-chart--interactive' : ''}${\n selected ? ' ProseMirror-selectednode' : ''\n }`}\n data-type=\"chart\"\n data-selected={selected ? 'true' : undefined}\n contentEditable={false}\n onMouseDown={(e: MouseEvent) => {\n if ((e.target as HTMLElement).closest('button')) return;\n if (e.button !== 0) return;\n // Select node but do not preventDefault — Chart.js needs hover/click.\n selectChart();\n }}\n >\n {config?.title ? (\n <div className=\"tmr-chart-title\">{config.title}</div>\n ) : null}\n {config?.dataTime ? (\n <div className=\"tmr-chart-time\">{config.dataTime}</div>\n ) : null}\n {configs.length > 1 ? (\n <div className=\"tmr-chart-tabs\" role=\"tablist\">\n {configs.map((c, i) => (\n <button\n key={`${c.chartType}-${i}`}\n type=\"button\"\n role=\"tab\"\n className=\"tmr-chart-tab\"\n data-active={i === safeIndex ? 'true' : 'false'}\n aria-selected={i === safeIndex}\n onMouseDown={(e) => e.stopPropagation()}\n onClick={(e) => {\n e.stopPropagation();\n setActive(i);\n }}\n >\n {tabLabel(c.chartType, c.title, i, labels.tabLabel)}\n </button>\n ))}\n </div>\n ) : null}\n <div className=\"tmr-chart-canvas-host\" style={{ height }}>\n <canvas ref={canvasRef} />\n </div>\n </NodeViewWrapper>\n );\n}\n","import { ReactNodeViewRenderer } from '@tiptap/react';\nimport { reportChart, type ReportChartOptions } from './ChartExtension';\nimport { ChartView } from '../components/ChartView';\nimport type { ChartTheme } from './types';\nimport type { ChartLabels } from '../labels';\n\nexport interface CreateChartOptions {\n /** When true, reserved for future in-place chart editing. Currently unused (no edit UI). Default false. */\n editable?: boolean;\n chartTheme?: ChartTheme | null;\n chartLabels?: Partial<ChartLabels>;\n}\n\nexport interface InteractiveChartOptions extends ReportChartOptions {\n chartEditable: boolean;\n chartTheme: ChartTheme | null;\n chartLabels?: Partial<ChartLabels>;\n}\n\n/**\n * Client chart extension with React NodeView.\n * Server / pure HTML paths should use {@link reportChart} / {@link pureChart}.\n */\nexport function createChart(options: CreateChartOptions = {}) {\n // Chart config editing (modal) is disabled for now; keep option for later.\n const { editable = false, chartTheme = null, chartLabels } = options;\n return reportChart.extend<InteractiveChartOptions>({\n addOptions() {\n return {\n HTMLAttributes: {},\n chartEditable: editable,\n chartTheme,\n chartLabels,\n };\n },\n addNodeView() {\n return ReactNodeViewRenderer(ChartView);\n },\n });\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 { useEffect, useRef, useState } from 'react';\nimport {\n CheckIcon,\n ChevronDownIcon,\n ChevronsUpDownIcon,\n CopyIcon,\n TrashIcon,\n} 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 *\n * 只读态(预览 / 只读编辑器)走另一套头部:左侧语言标签,右侧复制 + 展开收起;\n * 超出 `--tmr-code-max-height`(缺省 480px)的代码块默认限高块内滚动,行号槽\n * 用 MutationObserver 跟踪 PM 管理的 code 内容保持同步(纯文本变化不触发 React\n * 重渲染,gutter 行数靠观察器自刷新)。\n */\nexport function CodeBlockView({\n node,\n updateAttributes,\n deleteNode,\n extension,\n editor,\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 const editable = editor.isEditable;\n const readonly = !editable;\n\n const [copied, setCopied] = useState(false);\n const [folded, setFolded] = useState(false);\n const [lineCount, setLineCount] = useState(() =>\n Math.max((node.textContent ?? '').split('\\n').length, 1),\n );\n const preRef = useRef<HTMLPreElement | null>(null);\n\n // 流式更新只改 code 里的文本节点,React 不重渲染;观察 pre 子树同步行数。\n useEffect(() => {\n if (!readonly) return;\n const pre = preRef.current;\n if (!pre) return;\n const update = () => {\n setLineCount(Math.max((pre.textContent ?? '').split('\\n').length, 1));\n };\n update();\n const mo = new MutationObserver(update);\n mo.observe(pre, { childList: true, subtree: true, characterData: true });\n return () => mo.disconnect();\n }, [readonly]);\n\n const handleCopy = () => {\n const text = node.textContent ?? '';\n const done = () => {\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1500);\n };\n if (navigator.clipboard?.writeText) {\n navigator.clipboard.writeText(text).then(done, () => {});\n return;\n }\n // 剪贴板 API 不可用(非安全上下文 / 旧 webview):退化为 execCommand\n const ta = document.createElement('textarea');\n ta.value = text;\n document.body.appendChild(ta);\n ta.select();\n try {\n document.execCommand('copy');\n done();\n } catch {\n // 复制失败静默\n }\n ta.remove();\n };\n\n const wrapperClass = [\n styles.wrapper,\n readonly ? styles.readonly : '',\n folded ? styles.folded : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <NodeViewWrapper className={wrapperClass}>\n {editable ? (\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 ) : (\n // 只读头部:左侧语言标签,右侧复制 + 展开收起(展开后按钮保留,供收回)\n <div className={styles.readonlyHeader} contentEditable={false}>\n <span className={styles.langBadge}>\n <span className={styles.langBraces}>{'{}'}</span>\n {currentLabel}\n </span>\n <span className={styles.readonlyActions}>\n <button\n type=\"button\"\n className={styles.actionBtn}\n onClick={handleCopy}\n aria-label={labels.copy}\n title={labels.copy}\n >\n {copied ? <CheckIcon size={14} /> : <CopyIcon size={14} />}\n </button>\n <button\n type=\"button\"\n className={styles.actionBtn}\n onClick={() => setFolded((v) => !v)}\n aria-label={folded ? labels.expand : labels.collapse}\n title={folded ? labels.expand : labels.collapse}\n aria-expanded={!folded}\n >\n <ChevronsUpDownIcon size={14} />\n </button>\n </span>\n </div>\n )}\n <pre ref={preRef} className={styles.pre}>\n {readonly ? (\n <span\n className={styles.gutter}\n contentEditable={false}\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <span key={i} className={styles.gutterLine}>\n {i + 1}\n </span>\n ))}\n </span>\n ) : null}\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 FindAndReplace from '@tiptap/extension-find-and-replace';\nimport Image from '@tiptap/extension-image';\nimport { TableOfContents } from '@tiptap/extension-table-of-contents';\nimport { Placeholder } from '@tiptap/extensions';\nimport { Markdown } from '@tiptap/markdown';\nimport {\n EditorContent,\n ReactNodeViewRenderer,\n useEditor,\n type AnyExtension,\n type Editor,\n} from '@tiptap/react';\nimport { createPortal } from 'react-dom';\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from 'react';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from '../citationUtils';\nimport type { RenderCitation } from '../citationTypes';\nimport { createCitationRef } from '../createCitationRef';\nimport { CommentMark } from '../commentAnchor/CommentMark';\nimport {\n COMMENT_ACTIVE_META,\n COMMENT_CLICK_META,\n COMMENT_GUTTER_META,\n commentAnchorExtension,\n} from '../commentAnchor/commentAnchorPlugin';\nimport {\n applyCommentAnchorsToEditor,\n collectCommentIds,\n focusComment,\n nextComment,\n} from '../commentAnchor/commentAnchorController';\nimport type {\n CommentClickPayload,\n CommentRef,\n} from '../commentAnchor/commentTypes';\nimport { baseExtensions, lowlight } from '../extensions';\nimport { isComposingKeyEvent } from '../findReplace';\nimport { FindReplaceBar } from './FindReplaceBar';\nimport { ImportPlaceholder } from '../importPlaceholder';\nimport type { CodeBlockLabels, FindLabels, ShortcutLabels, SlashMenuLabels } from '../labels';\nimport { defaultShortcutLabels } from '../labels';\nimport { SlashMenu } from '../slashMenu/SlashMenuExtension';\nimport { ShortcutPanel } from '../shortcuts/ShortcutPanel';\nimport { KeyboardIcon } from '../icons';\nimport { MarkdownFileDrop } from '../markdownFileDrop';\nimport {\n pendingAnchorExtension,\n setPendingAnchors,\n type PendingAnchor,\n} from '../pendingAnchor';\nimport { selectionKind, type SelectionKind } from '../selectionKind';\nimport { MarkdownPaste } from '../markdownPaste';\nimport { parseCodeTokenAsChartOrCodeBlock } from '../chart/codeBlockChartParse';\nimport { createChart } from '../chart/createChart';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport '../styles/chart.css';\nimport '../styles/pending.css';\nimport '../styles/find.css';\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 // Built-in `code` tokens often win over chart's custom fence tokenizer;\n // upgrade ```tmr-chart here so the mid-column card editor renders ChartView.\n parseMarkdown: (token, helpers) =>\n parseCodeTokenAsChartOrCodeBlock(token, helpers, 'codeBlock'),\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\n/** 浮动条相对其定位上下文的偏移(数字按 px)。内部路径的上下文是编辑器,portal 路径是宿主容器。 */\nexport interface FindBarOffset {\n top?: number | string;\n right?: number | string;\n bottom?: number | string;\n left?: number | string;\n}\n\nconst DEFAULT_FIND_BAR_OFFSET: FindBarOffset = { top: 4, right: 4 };\n\nfunction findBarOffsetStyle(offset: FindBarOffset): CSSProperties {\n const px = (v: number | string | undefined) =>\n typeof v === 'number' ? `${v}px` : v;\n return {\n position: 'absolute',\n top: px(offset.top),\n right: px(offset.right),\n bottom: px(offset.bottom),\n left: px(offset.left),\n };\n}\n\n/**\n * 这次按键归本编辑器管吗。Cmd/Ctrl+F 与 Esc 共用同一套边界:\n * - 焦点在本编辑器内 → 管\n * - 焦点不在任何输入控件里(body)且页面上只有本编辑器 → 也管(单编辑器页面点完工具栏能直接按)\n * - 其余一律不管:同页多编辑器不会一起抢键,宿主的输入框与其它浮层也不会被夺走按键。\n */\nfunction editorOwnsKeyboard(editor: Editor): boolean {\n const active = document.activeElement;\n const inEditor = !!active && editor.view.dom.contains(active);\n if (inEditor || editor.isFocused) return true;\n const nothingFocused = active === null || active === document.body;\n return nothingFocused && document.querySelectorAll('.ProseMirror').length <= 1;\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 /** 聚焦评论:设 active + 滚动 + 光标落到区间起点。找不到返回 false。 */\n focusComment: (commentId: string) => boolean;\n /** 按文档顺序跳转评论(next / prev),返回目标 commentId。 */\n nextComment: (dir?: 'next' | 'prev') => string | null;\n /** 当前 doc 内已锚定的去重 commentId 列表(文档顺序)。 */\n getCommentIds: () => string[];\n /** 打开编辑器自带的查找浮动条(宿主自己绑快捷键/按钮时用)。findBar={false} 时不生效。 */\n openFind: () => void;\n /** 收起自带浮动条,清空高亮并把焦点还给编辑器。findBar={false} 时不生效。 */\n closeFind: () => void;\n /**\n * 反转自带浮动条:关着就开、开着就关。工具栏那个带 active 态的放大镜接它\n * (`onSearch={() => handle.current?.toggleFind()}`)。findBar={false} 时不生效。\n */\n toggleFind: () => void;\n}\n\nexport interface MarkdownWysiwygEditorProps {\n /** 初始 markdown 内容。 */\n initialMarkdown?: string;\n /**\n * 是否可编辑,默认 true。false = 只读渲染,与编辑态同源同路径:\n * 同一套扩展 / NodeView / 样式,交互件(代码块语言选择、删除等)自动收起。\n * 只读态不应用评论锚定(comments 被忽略),与 MarkdownPreview 语义一致。\n */\n editable?: boolean;\n /**\n * 初始脚注来源:按 index 对齐 `[^n]`,写入 citationRef 的 url/title。\n * 仅影响初始 content;后续插入请用 `insertMarkdown(editor, md, sources)`。\n */\n sources?: SourceRef[];\n /**\n * 脚注圆标 NodeView 插槽。消费方用 Popover 包住 `defaultDom`,\n * 用 `index` 查自己的数据源。仅初始化时生效。\n */\n renderCitation?: RenderCitation;\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 /**\n * 「这段正在被 AI 改写」的高亮:宿主在提交请求时给上、回填或冲突时传空数组清空。\n * 走 decoration,**不进 markdown、不进 undo 历史**,能盖住表格与图表这类块级节点。\n */\n pendingAnchors?: PendingAnchor[];\n /** 点击待改写高亮区域时回调,给出锚点 id(宿主可用来跳回/取消)。 */\n onAnchorClick?: (id: string) => void;\n /**\n * 选区变化。宿主用它做「选中即出现引用」——塌缩成光标也会报(`empty: true`),\n * 好让引用跟着消失;`kind` 区分普通文字 / 表格单元格 / 整节点(图表)。\n */\n onSelectionChange?: (selection: {\n from: number;\n to: number;\n empty: boolean;\n kind: SelectionKind;\n }) => void;\n /** 附加到滚动容器的 class。 */\n className?: string;\n /**\n * 编辑态评论锚定:评论列表(含已解码 segments)。装载时映射为 commentAnchor\n * mark 并高亮;markdown 导出自动剥离,只读态(MarkdownPreview)不渲染评论。\n * 注意:数组引用变化会触发重新铺 mark,宿主应 memo 该数组。\n */\n comments?: CommentRef[];\n /** 受控 active 评论 id(sidebar 联动)。null = 无 active。 */\n activeCommentId?: string | null;\n /** 编辑器内点击 mark / gutter 时回调。 */\n onCommentClick?: (payload: CommentClickPayload) => void;\n /** active 变化回调(点击 mark / gutter / nextComment 时)。 */\n onActiveCommentChange?: (commentId: string | null) => void;\n /** 是否在 block 左缘渲染评论 gutter 气泡,默认 true。 */\n showCommentGutter?: boolean;\n /**\n * 编辑器内点评论 mark 是否可交互(设 active / 上报 click),默认 true。\n * 只靠侧栏单项驱动滚动定位时传 false。\n */\n commentInteractive?: boolean;\n /**\n * 启用查找替换(默认 true):注册官方 `@tiptap/extension-find-and-replace`\n * (自带命令 `setSearchTerm / replace / replaceAll / goToNextResult …` 与\n * `editor.storage.findAndReplace`)。传 false 则连扩展一起不注册——此时命令与 storage 都不存在,\n * 宿主的自绘面板也无从驱动。\n */\n findReplace?: boolean;\n /**\n * 是否由编辑器渲染浮动条(默认跟随 {@link findReplace})。传 false = **定位交给宿主**:\n * 扩展照旧注册,但编辑器不出条子,宿主自己在任意位置渲染 `<FindReplaceBar editor={…} />`\n * (与工具栏同一套分工——组件归库,摆位归宿主)。此时 {@link findShortcut} 与\n * `handle.openFind/closeFind` 一并失效,因为内部没有条子可开。\n */\n findBar?: boolean;\n /**\n * 把自带的浮动条挂到宿主的容器里(antd `getPopupContainer` 那一套):给元素或返回元素的函数\n * 即可,开合状态与 Cmd/Ctrl+F 仍归库——只换挂载点。适合条子被 `overflow: hidden` 祖先裁掉、\n * 或想让它落在自己的头部 / 侧栏里。挂进去后**定位由宿主负责**(库不再加绝对定位),\n * 且容器若在主题子树之外,记得把 `--tmr-*` 变量也带到那里。\n * 返回 null / 不传时回落到编辑器内自带的浮动条。\n */\n findBarContainer?: HTMLElement | null | (() => HTMLElement | null);\n /**\n * 浮动条相对其定位上下文的偏移,默认 `{ top: 4, right: 4 }`(右上角)。数字按 px,也收 CSS 字符串。\n * 内部路径的上下文是编辑器(粘在滚动容器顶部的那层锚点),`findBarContainer` 路径的上下文是那个容器\n * ——那条路径下库会保证容器是定位上下文(computed position 为 static 时补 `position: relative`)。\n */\n findBarOffset?: FindBarOffset;\n /**\n * 焦点在编辑器内时接管 Cmd/Ctrl+F 打开**编辑器自带的**浮动条(默认 true;`findBar={false}`\n * 时不接管,免得抢了键却不弹东西)。传 false 则只保留 `handle.openFind()`——例如宿主想\n * 保留浏览器原生查找,或自己摆入口。焦点不在编辑器内时不接管,同页多编辑器不会互相抢。\n */\n findShortcut?: boolean;\n /** 查找替换浮动条的本地化文案。 */\n findLabels?: Partial<FindLabels>;\n /**\n * 浮动条开合状态变化的通知(条子开着时 `handle.openFind()`、Esc / × 关掉都会触发)。\n * 典型用法是驱动别处的入口按钮:`<EditorToolbar onSearch={open} searchActive={isOpen} />`。\n * 只在真正变化时回调,挂载时不会先报一次 `false`;报的是「条子真的在屏幕上」——\n * `findBar={false}`(宿主自己摆条子)时恒为 `false`,不会因为 `openFind()` 空转就亮起入口。\n */\n onFindOpenChange?: (open: boolean) => void;\n /**\n * 启用快捷键抽屉:编辑器右下角出现键盘悬浮按钮,点开为\n * 「格式 / 快捷键 / Markdown」三列对照抽屉(默认 true,只读态隐藏)。\n */\n shortcutPanel?: boolean;\n /** 快捷键抽屉的本地化文案。 */\n shortcutLabels?: Partial<ShortcutLabels>;\n /**\n * 把快捷键悬浮键挂到宿主的容器里(与 `findBarContainer` 同一套):\n * 给元素或返回元素的函数即可,开合状态与抽屉归库——只换按钮落点。\n * 挂进去后**定位由宿主负责**(库不再给按钮加粘性定位与右下角外边距),\n * 适合把按钮叠在宿主自己的浮层控件旁边(如「回到顶部」按钮上方)。\n * 返回 null / 不传时回落到编辑器内容右下的粘性按钮。\n */\n shortcutFabContainer?: HTMLElement | null | (() => HTMLElement | null);\n /**\n * 启用斜杠菜单:键入 `/`(行首或空白后)唤起块级插入弹窗(默认 true)。\n * 代码块内不触发,表格单元格内触发;只读态不激活。\n * 追加自定义命令项请传 `extraExtensions` 注册 `SlashMenu.configure({ items })`。\n */\n slashMenu?: boolean;\n /** 斜杠菜单的本地化文案。 */\n slashMenuLabels?: Partial<SlashMenuLabels>;\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 editable = true,\n sources,\n renderCitation,\n placeholder,\n onEditorReady,\n onTocChange,\n markdownPaste = true,\n markdownFileDrop = true,\n extraExtensions,\n codeBlockLabels,\n className,\n comments,\n activeCommentId,\n onCommentClick,\n onActiveCommentChange,\n showCommentGutter = true,\n commentInteractive = true,\n pendingAnchors,\n onAnchorClick,\n onSelectionChange,\n findReplace = true,\n findBar = findReplace,\n findBarContainer,\n findBarOffset = DEFAULT_FIND_BAR_OFFSET,\n findShortcut = true,\n findLabels,\n onFindOpenChange,\n slashMenu = true,\n slashMenuLabels,\n shortcutPanel = true,\n shortcutLabels,\n shortcutFabContainer,\n },\n ref,\n) {\n const preparedInitial = prepareChartMarkdown(\n enrichMarkdownCitations(initialMarkdown, sources ?? []),\n );\n\n const [findOpen, setFindOpen] = useState(false);\n const [shortcutsOpen, setShortcutsOpen] = useState(false);\n const findInputRef = useRef<HTMLInputElement | null>(null);\n\n const editor = useEditor({\n extensions: [\n ...baseExtensions,\n CodeBlock.configure({ lowlight, codeBlockLabels }),\n ImageWithConfirmDelete.configure({ inline: false }),\n ImportPlaceholder,\n // 空文档占位符:官方 Placeholder 把 data-placeholder 属性与\n // is-empty / is-editor-empty 类打在**空文本块节点**上——CSS\n // (styles/content.module.css)正是在节点上 attr(data-placeholder)\n // 取值。早先只把属性挂在根 div 上,选择器永远匹配不到,占位符从没显示过。\n // showOnlyWhenEditable 默认 true,只读态自动不显示。\n ...(placeholder ? [Placeholder.configure({ placeholder })] : []),\n createChart({ editable: false }),\n createCitationRef({ renderCitation }),\n CommentMark,\n commentAnchorExtension({\n showGutter: showCommentGutter,\n interactive: commentInteractive,\n }),\n Markdown,\n pendingAnchorExtension,\n // 官方查找替换:只出命令 / storage / 装饰,UI 自绘(见 FindReplaceBar)。\n // - injectCSS 关掉:它默认会往页面插一个 <style>,绕开宿主的 --tmr-* 主题与 style.css,\n // 命中样式改由 src/styles/find.css 承担。\n // - searchDebounceMs 关掉:官方防抖走 setTimeout,抛错会落在异步回调里兜不住;\n // 防抖改由浮动条自己做(见 findReplace.ts)。\n ...(findReplace\n ? [FindAndReplace.configure({ injectCSS: false, searchDebounceMs: 0 })]\n : []),\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 // 斜杠菜单(键入 / 唤起):默认开,只读态由 suggestion 状态机自身短路\n ...(slashMenu ? [SlashMenu.configure({ labels: slashMenuLabels })] : []),\n ...(extraExtensions ?? []),\n ],\n content: preparedInitial,\n contentType: 'markdown',\n editable,\n // Next.js SSR:服务端不立即渲染,避免 hydration 不一致\n immediatelyRender: false,\n editorProps: {\n attributes: {\n class: styles.editorContent,\n },\n },\n });\n\n useEffect(() => {\n onEditorReady?.(editor);\n return () => onEditorReady?.(null);\n }, [editor, onEditorReady]);\n\n // 运行时切换编辑/只读(同一实例,NodeView 交互件随 editor.isEditable 收起)。\n useEffect(() => {\n editor?.setEditable(editable);\n }, [editor, editable]);\n\n /**\n * 打开查找条。带着「再按一次」的语义:已经开着时聚焦并全选当前查询(首次打开由条子自己的\n * autoFocus 负责,此时查询多半是空串,`select()` 是空操作)。\n */\n const openFind = useCallback(() => {\n setFindOpen(true);\n requestAnimationFrame(() => findInputRef.current?.select());\n }, []);\n\n const closeFind = useCallback(() => {\n setFindOpen(false);\n // 焦点归还:Tiptap 的 focus 命令内部就是 requestAnimationFrame 延后执行的\n // (`delayedFocus`),正好落在 React 卸载浮动条之后——否则被卸载的输入框会把焦点丢给 body。\n editor?.commands.focus();\n }, [editor]);\n\n /**\n * 反转查找条:关着就开、开着就关。工具栏那个放大镜接的是它——带 active 态的按钮点一下得能灭。\n * `openFind()` 保持「已开着时重聚焦并全选查询」的语义,和 Cmd/Ctrl+F(同一个手势)一致。\n */\n const toggleFind = useCallback(() => {\n if (findOpen) closeFind();\n else openFind();\n }, [findOpen, closeFind, openFind]);\n\n // 开合状态上报宿主(回调走 ref 防 stale)。报的是「条子真的在屏幕上」——`findBar={false}`\n // 时宿主自己摆条子,`findOpen` 翻起来也不该点亮别处的入口。只在真正变化时回调,\n // 挂载时不先报一次 false。\n const findBarOpen = findOpen && findBar && findReplace;\n const onFindOpenChangeRef = useRef(onFindOpenChange);\n onFindOpenChangeRef.current = onFindOpenChange;\n // 初值取 `false`(`findOpen` 的初值):挂载那次比较相等,不会回调一次「本来就是 false」。\n const notifiedFindOpenRef = useRef(false);\n useEffect(() => {\n if (notifiedFindOpenRef.current === findBarOpen) return;\n notifiedFindOpenRef.current = findBarOpen;\n onFindOpenChangeRef.current?.(findBarOpen);\n }, [findBarOpen]);\n\n // 条子随本实例一起消失时(换 key、换文档、切路由),宿主的入口不该继续亮着——新实例的\n // `notifiedFindOpenRef` 初值是 false、`findBarOpen` 也是 false,两者相等就不会回调,于是\n // 上一实例报过的那个 `true` 没人撤销。所以卸载时补发一次。StrictMode 的模拟卸载不会误报\n // (那时条子并没开着,值就是 false)。\n const findBarOpenRef = useRef(findBarOpen);\n findBarOpenRef.current = findBarOpen;\n useEffect(\n () => () => {\n if (findBarOpenRef.current) onFindOpenChangeRef.current?.(false);\n },\n [],\n );\n\n // Cmd/Ctrl+F → 打开查找条。接管边界见 editorOwnsKeyboard()。\n // 只有容器里真有那条浮动条(findBar)时才绑:否则会白抢浏览器原生查找,却什么都不弹。\n useEffect(() => {\n if (!editor || !findReplace || !findBar || !findShortcut) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey) {\n return;\n }\n if (event.key !== 'f' && event.key !== 'F') return;\n if (!editorOwnsKeyboard(editor)) return;\n event.preventDefault();\n openFind();\n };\n document.addEventListener('keydown', onKeyDown, true);\n return () => document.removeEventListener('keydown', onKeyDown, true);\n }, [editor, findReplace, findBar, findShortcut, openFind]);\n\n // Esc → 关掉查找条。条子自己那份 onKeyDown 只在焦点位于条子内时才收得到,用户点回正文继续\n // 编辑后想收条子就只能去点 ×;这里按同一套边界(editorOwnsKeyboard)补上「焦点在正文 /\n // 页面只有本编辑器且焦点在 body」的情况。消费掉这次 Esc(preventDefault + stopPropagation),\n // 免得宿主的浮动层跟着一起关;输入法组合中的 Esc 是「取消候选词」,放行。\n //\n // 注意**不要**用 `event.defaultPrevented` 判断「内层已经处理过、让给它」:实测在真实编辑器里\n // Escape 一定已被 preventDefault——prosemirror-view 的 keydown 一旦有 handleKeyDown 返回 true\n // 就 preventDefault(`node_modules/prosemirror-view/src/input.ts:136`),斜杠菜单等就在这条路上。\n // 那样写这条分支永远不会走。边界交给 editorOwnsKeyboard:焦点在别的浮层 / 宿主的输入框里时\n // 它本来就是 false,不会去抢。\n useEffect(() => {\n if (!editor || !findBarOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return;\n if (isComposingKeyEvent(event)) return;\n if (!editorOwnsKeyboard(editor)) return;\n event.preventDefault();\n event.stopPropagation();\n closeFind();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [editor, findBarOpen, closeFind]);\n\n // 评论列表 → 铺 mark。用 commentId 签名做防抖:宿主每次渲染传新数组引用时\n // 不会反复清/铺(清空再重铺会丢掉 mark 随编辑移动后的位置)。\n const commentsSignatureRef = useRef<string>('');\n useEffect(() => {\n // 只读态不接评论(与库的「评论锚定 = 编辑会话专属」契约一致)。\n if (!editor || !editable) return;\n const signature = (comments ?? [])\n .map((c) => `${c.commentId}:${c.segments.length}`)\n .join('|');\n if (signature === commentsSignatureRef.current) return;\n commentsSignatureRef.current = signature;\n applyCommentAnchorsToEditor(editor, comments ?? []);\n }, [editor, editable, comments]);\n\n // active 同步到插件(mark/block 高亮装饰);滚动定位走 handle.focusComment。\n useEffect(() => {\n if (!editor) return;\n editor.view.dispatch(\n editor.state.tr.setMeta(\n COMMENT_ACTIVE_META,\n activeCommentId ?? null,\n ),\n );\n }, [editor, activeCommentId]);\n\n // 待改写高亮:会话级装饰,不进 markdown / 不进 undo(宿主推入,回填或冲突时清空)。\n useEffect(() => {\n if (!editor) return;\n setPendingAnchors(editor, pendingAnchors ?? []);\n }, [editor, pendingAnchors]);\n\n // 点击待改写高亮 → 上报锚点 id。走 DOM 监听而不是插件 meta:这里只要「点了哪一段」。\n const onAnchorClickRef = useRef(onAnchorClick);\n useEffect(() => {\n onAnchorClickRef.current = onAnchorClick;\n }, [onAnchorClick]);\n useEffect(() => {\n if (!editor) return;\n const dom = editor.view.dom;\n const onClick = (event: MouseEvent) => {\n const target = event.target as HTMLElement | null;\n const id = target?.closest?.('[data-pending-id]')?.getAttribute('data-pending-id');\n if (id) onAnchorClickRef.current?.(id);\n };\n dom.addEventListener('click', onClick);\n return () => dom.removeEventListener('click', onClick);\n }, [editor]);\n\n // 选区变化:宿主据此做「选中即出现引用 / 引用跟着选区走」。\n const onSelectionChangeRef = useRef(onSelectionChange);\n useEffect(() => {\n onSelectionChangeRef.current = onSelectionChange;\n }, [onSelectionChange]);\n useEffect(() => {\n if (!editor) return;\n const onSelectionUpdate = () => {\n const { from, to, empty } = editor.state.selection;\n onSelectionChangeRef.current?.({\n from,\n to,\n empty,\n kind: selectionKind(editor.state.selection),\n });\n };\n editor.on('selectionUpdate', onSelectionUpdate);\n return () => {\n editor.off('selectionUpdate', onSelectionUpdate);\n };\n }, [editor]);\n\n // mark / gutter 点击 → 通过 transaction meta 上报宿主(回调走 ref 防 stale)。\n const onCommentClickRef = useRef(onCommentClick);\n const onActiveCommentChangeRef = useRef(onActiveCommentChange);\n onCommentClickRef.current = onCommentClick;\n onActiveCommentChangeRef.current = onActiveCommentChange;\n useEffect(() => {\n if (!editor) return;\n const onTransaction = ({\n transaction,\n }: {\n transaction: { getMeta: (key: string) => unknown };\n }) => {\n const click = transaction.getMeta(COMMENT_CLICK_META) as\n | CommentClickPayload\n | undefined;\n if (click) {\n onCommentClickRef.current?.(click);\n onActiveCommentChangeRef.current?.(click.commentIds[0] ?? null);\n }\n const gutter = transaction.getMeta(COMMENT_GUTTER_META) as\n | { commentIds: string[]; pos: number }\n | undefined;\n if (gutter) {\n onCommentClickRef.current?.({\n commentIds: gutter.commentIds,\n anchorEl: null,\n pos: gutter.pos,\n });\n onActiveCommentChangeRef.current?.(gutter.commentIds[0] ?? null);\n }\n };\n editor.on('transaction', onTransaction);\n return () => {\n editor.off('transaction', onTransaction);\n };\n }, [editor]);\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 focusComment: (commentId: string) =>\n editor ? focusComment(editor, commentId) : false,\n nextComment: (dir?: 'next' | 'prev') =>\n editor ? nextComment(editor, dir ?? 'next') : null,\n getCommentIds: () => (editor ? collectCommentIds(editor) : []),\n openFind: () => openFind(),\n closeFind,\n toggleFind: () => toggleFind(),\n }),\n [editor, closeFind, openFind, toggleFind],\n );\n\n // 宿主指定了容器就把条子 portal 进去;解析不到则回落到编辑器内的粘性锚点。\n const findBarTarget =\n typeof findBarContainer === 'function'\n ? findBarContainer()\n : (findBarContainer ?? null);\n\n // 条子是绝对定位的:容器得先是定位上下文。宿主容器是 static 时补一个 relative——\n // 不补的话条子会以「最近的定位祖先」为基准(可能是页面),位置会莫名其妙。\n useEffect(() => {\n if (!findBarTarget) return;\n if (getComputedStyle(findBarTarget).position === 'static') {\n findBarTarget.style.position = 'relative';\n }\n }, [findBarTarget]);\n\n const findBarNode =\n editor && findBar && findOpen ? (\n <FindReplaceBar\n editor={editor}\n labels={findLabels}\n onClose={closeFind}\n inputRef={findInputRef}\n className={styles.findBar}\n style={findBarOffsetStyle(findBarOffset)}\n />\n ) : null;\n\n const shortcutT: ShortcutLabels = useMemo(\n () => ({ ...defaultShortcutLabels, ...shortcutLabels }),\n [shortcutLabels],\n );\n\n // 宿主指定了容器就把悬浮键 portal 进去(定位归宿主),解析不到回落编辑器内粘性按钮。\n // 用 layout effect(同步于提交后、绘制前)解析:函数形式读 ref 时首渲染拿到的是\n // null,等 DOM 提交后 ref 才就绪——这里在绘制前再解析一次,避免闪一帧编辑器内按钮;\n // setState 同值会 bail out,不会死循环。\n const [shortcutFabTarget, setShortcutFabTarget] = useState<HTMLElement | null>(\n null,\n );\n const useIsoLayoutEffect =\n typeof window === 'undefined' ? useEffect : useLayoutEffect;\n useIsoLayoutEffect(() => {\n const target =\n typeof shortcutFabContainer === 'function'\n ? shortcutFabContainer()\n : (shortcutFabContainer ?? null);\n setShortcutFabTarget((prev) => (prev === target ? prev : target));\n });\n\n const shortcutFabNode =\n shortcutPanel && editable ? (\n <button\n type=\"button\"\n className={\n shortcutFabTarget\n ? `${styles.shortcutFab} ${styles.shortcutFabHosted}`\n : styles.shortcutFab\n }\n title={shortcutT.panelTitle}\n aria-label={shortcutT.panelTitle}\n aria-expanded={shortcutsOpen}\n onClick={() => setShortcutsOpen((v) => !v)}\n >\n <KeyboardIcon size={18} />\n </button>\n ) : null;\n\n return (\n <div className={styles.editorHost}>\n {/* 粘性锚点排在正文之前:浮动条跟着最近的滚动容器走,正文滚动时不会被卷上去 */}\n {findBarNode && !findBarTarget ? (\n <div className={styles.findBarAnchor}>{findBarNode}</div>\n ) : null}\n {findBarNode && findBarTarget\n ? createPortal(findBarNode, findBarTarget)\n : null}\n <EditorContent\n editor={editor}\n className={\n className ? `${styles.editorScroll} ${className}` : styles.editorScroll\n }\n />\n {/* 快捷键抽屉入口:默认 sticky-bottom 悬浮在可视区右下;\n 宿主给了 shortcutFabContainer 就 portal 进去,定位归宿主。只读态隐藏 */}\n {shortcutFabNode && shortcutFabTarget\n ? createPortal(shortcutFabNode, shortcutFabTarget)\n : shortcutFabNode}\n {shortcutPanel && editable ? (\n <ShortcutPanel\n open={shortcutsOpen}\n onClose={() => setShortcutsOpen(false)}\n labels={shortcutLabels}\n />\n ) : null}\n </div>\n );\n});\n","'use client';\n\nimport { Markdown } from '@tiptap/markdown';\nimport { EditorContent, ReactNodeViewRenderer, useEditor } from '@tiptap/react';\nimport { useEffect, useMemo } from 'react';\nimport { createChart } from '../chart/createChart';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from '../citationUtils';\nimport type { RenderCitation } from '../citationTypes';\nimport { createCitationRef } from '../createCitationRef';\nimport { baseExtensions, pureCodeBlock, pureImage } from '../extensions';\nimport { CodeBlockView } from './CodeBlockView';\nimport '../styles/chart.css';\nimport styles from '../styles/content.module.css';\n\nexport interface MarkdownPreviewProps {\n /** 要预览的 markdown 字符串。 */\n markdown: string;\n /**\n * 脚注来源列表:按 `index` 与正文 `[^n]` 对齐,写入节点的 url/title。\n * 业务数据与 Popover 仍由消费方通过 {@link renderCitation} 完成。\n */\n sources?: SourceRef[];\n /**\n * 脚注圆标 NodeView 插槽。用 Popover 等包住 `defaultDom`;\n * 用 `index` / `attrs` 查消费方自己的数据源。\n */\n renderCitation?: RenderCitation;\n className?: string;\n}\n\n/**\n * 轻量只读 markdown 预览(Tiptap + 官方 @tiptap/markdown,editable:false)。\n * 与 MarkdownWysiwygEditor 共用同一套 base 扩展与正文样式类,渲染同源——\n * 预览所见即编辑/插入后所得。用纯版 CodeBlock/Image(无 React 视图 / 删除快捷键);\n * 图表用只读 NodeView(可渲染,不可编辑弹层)。\n *\n * 这是「客户端只读预览」;若需 SEO / 无 JS 静态渲染,请改用 server 入口的\n * renderReportHtml + ReportContent / ReportContentWithCharts。\n */\nexport function MarkdownPreview({\n markdown,\n sources,\n renderCitation,\n className,\n}: MarkdownPreviewProps) {\n const prepared = useMemo(\n () =>\n prepareChartMarkdown(\n enrichMarkdownCitations(markdown, sources ?? []),\n ),\n [markdown, sources],\n );\n\n // 预览代码块挂只读 NodeView(语言标签 + 复制 + 展开收起 + 行号槽)。\n // 仅客户端入口挂;server 入口(renderReportHtml)保持纯版,静态 HTML 零 React 依赖。\n const previewCodeBlock = useMemo(\n () =>\n pureCodeBlock.extend({\n addNodeView() {\n return ReactNodeViewRenderer(CodeBlockView);\n },\n }),\n [],\n );\n\n const extensions = useMemo(\n () => [\n ...baseExtensions,\n previewCodeBlock,\n pureImage,\n createChart({ editable: false }),\n createCitationRef({ renderCitation }),\n Markdown,\n ],\n [renderCitation],\n );\n\n const editor = useEditor(\n {\n extensions,\n content: prepared,\n contentType: 'markdown',\n editable: false,\n immediatelyRender: false,\n editorProps: {\n attributes: { class: styles.editorContent },\n },\n },\n [extensions],\n );\n\n // 文档尾随空段不在这里处理:它是 StarterKit 的 TrailingNode 补的(文末是代码块/\n // 表格/图表时),事后删节点会被它重建;改成 appendTransaction 里删则会与它互相\n // 触发形成死循环。只读预览由消费方用 CSS 隐藏该空段即可。\n\n useEffect(() => {\n if (!editor) return;\n editor.commands.setContent(prepared, { contentType: 'markdown' });\n }, [editor, prepared]);\n\n return (\n <EditorContent\n editor={editor}\n className={className ?? styles.editorScroll}\n />\n );\n}\n","import type { ToolbarLabels } from './labels';\n\n/** 包内唯一识别的扩展名:命中即本地读文本,其余一律交给宿主回调。 */\nexport const MD_FILE_RE = /\\.(md|markdown)$/i;\nexport const MD_ACCEPT = '.md,.markdown,text/markdown';\n\n/** 主栏导入下拉里的一项。`accept` 写到隐藏 file input。 */\nexport interface ImportMenuItem {\n key: string;\n label: string;\n accept: string;\n}\n\nexport function resolveImportMenuItems({\n labels,\n onImportDocument,\n importAccept,\n importMenuItems,\n}: {\n labels: ToolbarLabels;\n onImportDocument?: unknown;\n importAccept?: string;\n importMenuItems?: ImportMenuItem[];\n}): ImportMenuItem[] {\n if (importMenuItems?.length) return importMenuItems;\n const markdown: ImportMenuItem = {\n key: 'markdown',\n label: labels.importMarkdown,\n accept: MD_ACCEPT,\n };\n if (onImportDocument && importAccept) {\n return [\n markdown,\n {\n key: 'document',\n label: labels.importDocumentOther,\n accept: importAccept,\n },\n ];\n }\n return [markdown];\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport {\n enrichMarkdownCitations,\n type SourceRef,\n} from './citationUtils';\n\n/**\n * 在光标处插入 markdown 片段(封装 contentType: 'markdown')。\n * 传入 `sources` 时会先 enrich `[^n]` → 带 url 的 citation-ref,再插入。\n *\n * 整段过不了 schema(嵌套 bold、块级图进 listItem 等)时按块重试,\n * 单块仍挂则剥标记当段落。某一处脏输出不至于整次插入失败。\n */\nexport function insertMarkdown(\n editor: Editor,\n markdown: string,\n sources: SourceRef[] = [],\n): void {\n const prepared = prepareChartMarkdown(\n enrichMarkdownCitations(markdown, sources),\n );\n if (!prepared) return;\n if (tryInsertMarkdown(editor, prepared)) return;\n for (const block of splitTopLevelBlocks(prepared)) {\n if (tryInsertMarkdown(editor, block)) continue;\n insertPlainParagraph(editor, stripToPlainText(block));\n }\n}\n\nfunction tryInsertMarkdown(editor: Editor, markdown: string): boolean {\n try {\n return editor\n .chain()\n .focus()\n .insertContent(markdown, { contentType: 'markdown' })\n .run();\n } catch {\n return false;\n }\n}\n\nfunction insertPlainParagraph(editor: Editor, text: string): void {\n if (!text) return;\n editor\n .chain()\n .focus()\n .insertContent({\n type: 'paragraph',\n content: [{ type: 'text', text }],\n })\n .run();\n}\n\n/** 围栏代码整块留下,其余按空行切。 */\nexport function splitTopLevelBlocks(markdown: string): string[] {\n const out: string[] = [];\n for (const [i, part] of markdown.split(/(```[\\s\\S]*?```)/).entries()) {\n if (!part) continue;\n if (i % 2 === 1) {\n out.push(part);\n continue;\n }\n for (const block of part.split(/\\n{2,}/)) {\n if (block.trim()) out.push(block);\n }\n }\n return out;\n}\n\nexport function stripToPlainText(markdown: string): string {\n return markdown\n .replace(/!\\[[^\\]]*\\]\\([^)]+\\)/g, '')\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1')\n .replace(/^#{1,6}\\s+/gm, '')\n .replace(/^[ \\t]*[-*+]\\s+/gm, '')\n .replace(/^[ \\t]*\\d+\\.\\s+/gm, '')\n .replace(/[*_~`]+/g, '')\n .replace(/<[^>]+>/g, '')\n .replace(/\\|/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\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","/**\n * 链接编辑的适配层。\n *\n * 逻辑按官方 UI Components 的 `useLinkPopover` 搬(MIT),外壳自绘。相对原来的\n * `window.prompt` 增量也都在这里:\n *\n * - 改地址时把范围扩到**整条链接**(`extendMarkRange`),而不是只作用于光标那一段;\n * - 选区为空时把地址本身当文本插进去(空选区上没有文字可以套 mark);\n * - 移除时带上 `preventAutolink` 元数据(与官方同款),免得自动链接插件把它加回来;\n * - 「在新窗口打开」前过一遍协议白名单,`javascript:` 之类直接拒掉;\n * - 裸域名补协议。官方面板不补,但 Tiptap 的 `setLink` 是把值**原样**存下来的,而它自己的\n * 自动链接(linkify)会按 `defaultProtocol` 补——两边不一致的结果是:手打 `example.com`\n * 存成相对链接,markdown 导出的就是 `[x](example.com)`。这里按扩展配的 `defaultProtocol`\n * 补齐,让「打字」和「粘贴」落到同一个地址上。\n *\n * 放在这里而不是组件里,是为了能脱离 DOM 直接跑单测(同 replaceRange / insertMarkdown)。\n */\n\nimport type { Editor } from '@tiptap/react';\n\nimport { isComposingKeyEvent } from './findReplace';\n\n/** 「在新窗口打开」允许的协议(对齐官方 `sanitizeUrl` / Tiptap Link 的默认允准集)。 */\nconst OPENABLE_PROTOCOLS = new Set([\n 'http:',\n 'https:',\n 'ftp:',\n 'ftps:',\n 'mailto:',\n 'tel:',\n 'callto:',\n 'sms:',\n 'cid:',\n 'xmpp:',\n]);\n\n/** 已经有协议了(`https:` / `mailto:` …),或者是个站内相对地址(`/x`、`#x`、`?x`)。 */\nconst HAS_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;\nconst SITE_RELATIVE_RE = /^[/#?]/;\n/**\n * 主机:端口 形态(`localhost:3000`、`127.0.0.1:8080`、`[::1]:3000`)。它们**看着像协议**\n * (`localhost:` 也满足 `HAS_SCHEME_RE`),但显然是主机,要按主机补协议——否则会被当成\n * 未知协议,Tiptap 的 `isAllowedUri` 也会直接拒掉。\n */\nconst HOST_PORT_RE = /^(localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0|\\[[0-9a-f:]+\\]):\\d+($|[/#?])/i;\n/** 第一段里带点的裸域名(`example.com/path`)。 */\nconst BARE_HOST_RE = /^[^/?#]*\\.[^/?#]*/;\n\n/** 链接可编辑吗:只读态、或当前选区不允许套 link mark(例如整块选中)时为 false。 */\nexport function canSetLink(editor: Editor | null | undefined): boolean {\n if (!editor || editor.isEditable === false) return false;\n try {\n return editor.can().setMark('link');\n } catch {\n return false;\n }\n}\n\n/** 光标 / 选区是否落在链接里。 */\nexport function isLinkActive(editor: Editor | null | undefined): boolean {\n if (!editor) return false;\n return editor.isActive('link');\n}\n\n/** 读当前链接的 href(不在链接里时是空串)。 */\nexport function readLinkHref(editor: Editor | null | undefined): string {\n if (!editor) return '';\n const { href } = editor.getAttributes('link');\n return typeof href === 'string' ? href : '';\n}\n\n/** 扩展上配的默认协议(`StarterKit` 里是 `http`),读不到就按 http 算。 */\nfunction defaultProtocol(editor: Editor): string {\n const link = editor.extensionManager?.extensions.find(\n (extension) => extension.name === 'link',\n );\n const configured = (link?.options as { defaultProtocol?: string } | undefined)\n ?.defaultProtocol;\n return configured || 'http';\n}\n\n/**\n * 把用户输入整理成要存进 href 的值。\n *\n * 原样保留:空、站内相对地址(`/docs`、`#sec`、`?q=1`)、已带协议的(`https:`、`mailto:`)。\n * 补协议:裸域名(`example.com`、`example.com/a`)与主机:端口(`localhost:3000`)——补的是\n * 扩展配置的 `defaultProtocol`,与 Tiptap 自动链接同一套,避免手打和粘贴落到不同地址。\n */\nexport function normalizeLinkHref(editor: Editor, raw: string): string {\n const value = raw.trim();\n if (!value) return '';\n if (SITE_RELATIVE_RE.test(value)) return value;\n if (HOST_PORT_RE.test(value)) return `${defaultProtocol(editor)}://${value}`;\n if (HAS_SCHEME_RE.test(value)) return value;\n if (!BARE_HOST_RE.test(value)) return value;\n return `${defaultProtocol(editor)}://${value}`;\n}\n\n/**\n * 应用链接:把地址套到**整条**链接(或选区)上;选区为空且原本不在链接里时,把地址当文本插进去。\n * 返回扩展是否接受了这个地址——`setLink` 会走 Tiptap 的 `isAllowedUri`。\n *\n * 两处与官方那版不同,都是单测逼出来的:\n * 1. 先 `can().setLink()` 干跑一遍。官方把 `insertContent` 挂在失败的 `setLink` 后面直接\n * `run()`,结果是地址被拒时正文仍被改(链接文字被换成那个地址)。\n * 2. 「当文本插入」的判据是「选区为空**且光标不在已有链接里**」。官方只看选区是否为空,\n * 于是「光标在链接里、改一个地址」会把整条链接的文字替换成地址——而这正是这个浮层的主用途。\n */\nexport function applyLink(editor: Editor | null | undefined, raw: string): boolean {\n if (!editor) return false;\n const href = normalizeLinkHref(editor, raw);\n if (!href) return false;\n if (!editor.can().setLink({ href })) return false;\n\n const isEmpty = editor.state.selection.empty;\n const insideLink = isLinkActive(editor);\n const chain = editor\n .chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href });\n\n if (isEmpty && !insideLink) chain.insertContent({ type: 'text', text: href });\n\n return chain.run();\n}\n\n/** 移除链接:范围同样扩到整条,并挡住自动链接立刻加回来。 */\nexport function removeLink(editor: Editor | null | undefined): boolean {\n if (!editor) return false;\n return editor\n .chain()\n .focus()\n .extendMarkRange('link')\n .unsetLink()\n .setMeta('preventAutolink', true)\n .run();\n}\n\n/**\n * 把待打开的地址解析成绝对地址;解析不了、或协议不在白名单里时返回 `'#'` 表示「别打开」。\n *\n * 与官方 `sanitizeUrl(inputUrl, baseUrl)` 同语义:先按 base 解析成绝对地址(相对地址因此也\n * 能用),再查协议白名单。调用方拿到 `'#'` 就不开新窗口。\n */\nexport function sanitizeLinkUrl(input: string, baseUrl: string): string {\n try {\n const url = new URL(input, baseUrl);\n if (OPENABLE_PROTOCOLS.has(url.protocol)) return url.href;\n } catch {\n // 解析失败 = 非法地址\n }\n return '#';\n}\n\n/**\n * 打开地址(新窗口 + `noopener,noreferrer`)。空输入或非法地址都不开窗——调用方在此之前\n * 已经用 `sanitizeLinkUrl` 判过一次,这里再判一次是为了让这个入口单独用也安全。\n */\nexport function openLinkUrl(input: string, baseUrl: string): boolean {\n if (!input.trim()) return false;\n const safe = sanitizeLinkUrl(input, baseUrl);\n if (safe === '#') return false;\n window.open(safe, '_blank', 'noopener,noreferrer');\n return true;\n}\n\n/** 输入框的回车是否该当作「应用」(输入法组合中的回车是提交候选词,放行)。 */\nexport function isApplyKey(event: {\n key: string;\n nativeEvent: Pick<KeyboardEvent, 'isComposing' | 'keyCode'>;\n}): boolean {\n if (event.key !== 'Enter') return false;\n return !isComposingKeyEvent(event.nativeEvent);\n}\n","'use client';\n\nimport * as Popover from '@radix-ui/react-popover';\nimport type { Editor } from '@tiptap/react';\nimport {\n useState,\n type CSSProperties,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { CheckIcon, ExternalLinkIcon, TrashIcon } from '../icons';\nimport { defaultLinkPopoverLabels, type LinkPopoverLabels } from '../labels';\nimport {\n applyLink,\n canSetLink,\n isApplyKey,\n normalizeLinkHref,\n openLinkUrl,\n readLinkHref,\n removeLink,\n} from '../linkEditing';\nimport styles from '../styles/linkPopover.module.css';\n\nexport interface LinkPopoverProps {\n /** 编辑器实例。 */\n editor: Editor;\n /**\n * 触发器:传宿主自己的按钮元素。Radix 的 `asChild` 要接管它的点击 / ref / aria——\n * 传函数组件时得先 `forwardRef`(本库的 `<EditorToolbar>` 就是这么接的)。\n */\n trigger: ReactNode;\n labels?: Partial<LinkPopoverLabels>;\n /** 挂到浮层根节点上的 class / 内联样式(定位与层级归宿主,Radix 只管浮层方向)。 */\n className?: string;\n style?: CSSProperties;\n}\n\n/**\n * 链接编辑浮层:输入地址 + 应用 / 在新窗口打开 / 移除。\n *\n * 逻辑全在 `linkEditing.ts`(从官方 UI Components 的 `useLinkPopover` 搬的),这里只负责输入、\n * 按钮与状态。取代表驱动器的 `window.prompt`:能**编辑已有链接**(打开即预填当前地址,\n * 而旧实现是「在链接里点一下就删除」)、能打开、能移除,且 `window.prompt` 在 Electron /\n * 部分 WebView 里根本不可用。\n *\n * 地址被编辑器拒掉时(Tiptap 的 `isAllowedUri`)浮层不关,输入框转成危险色并带上 title,\n * 让用户改——静默什么都不发生是最难查的。\n */\nexport function LinkPopover({\n editor,\n trigger,\n labels,\n className,\n style,\n}: LinkPopoverProps) {\n const [open, setOpen] = useState(false);\n\n return (\n <Popover.Root open={open} onOpenChange={setOpen}>\n <Popover.Trigger asChild>{trigger}</Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n sideOffset={4}\n align=\"start\"\n // 关闭后不要把焦点夺回触发器:应用后该留在编辑器里(applyLink 里已经 focus 过)\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <LinkPanel\n editor={editor}\n labels={labels}\n className={className}\n style={style}\n onClose={() => setOpen(false)}\n />\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n\nfunction LinkPanel({\n editor,\n labels,\n className,\n style,\n onClose,\n}: {\n editor: Editor;\n labels?: Partial<LinkPopoverLabels>;\n className?: string;\n style?: CSSProperties;\n onClose: () => void;\n}) {\n const t: LinkPopoverLabels = { ...defaultLinkPopoverLabels, ...labels };\n // Radix 关闭时会卸载内容,所以这里的初值就是「每次打开读一次当前地址」——光标在链接里\n // 打开时预填它的 href,便于改地址而不是先删再加。\n const [url, setUrl] = useState(() => readLinkHref(editor));\n const [invalid, setInvalid] = useState(false);\n\n const canEdit = canSetLink(editor);\n const hasUrl = url.trim().length > 0;\n const keepFocus = (e: ReactMouseEvent) => e.preventDefault();\n\n const apply = () => {\n if (!applyLink(editor, url)) {\n setInvalid(true);\n return;\n }\n setInvalid(false);\n onClose();\n };\n\n const openInNewWindow = () => {\n // 先补协议再交给白名单:裸域名不该按「相对本页」打开\n openLinkUrl(normalizeLinkHref(editor, url), window.location.href);\n };\n\n const remove = () => {\n removeLink(editor);\n onClose();\n };\n\n const onInputKeyDown = (e: ReactKeyboardEvent<HTMLInputElement>) => {\n // 输入法组合中的回车是「提交候选词」,放行(isApplyKey 里判)\n if (!isApplyKey(e)) return;\n e.preventDefault();\n apply();\n };\n\n return (\n <div\n className={className ? `${styles.panel} ${className}` : styles.panel}\n style={style}\n data-link-popover=\"\"\n role=\"dialog\"\n aria-label={t.field}\n >\n <span className={`${styles.field}${invalid ? ` ${styles.fieldInvalid}` : ''}`}>\n <input\n className={styles.input}\n data-link-field=\"\"\n data-link-invalid={invalid ? '' : undefined}\n type=\"url\"\n value={url}\n onChange={(e) => {\n setUrl(e.target.value);\n setInvalid(false);\n }}\n onKeyDown={onInputKeyDown}\n placeholder={t.field}\n aria-label={t.field}\n aria-invalid={invalid || undefined}\n title={invalid ? t.invalid : undefined}\n autoFocus\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n />\n </span>\n\n <button\n type=\"button\"\n className={`${styles.btn} ${styles.apply}`}\n data-link-action=\"apply\"\n title={t.apply}\n aria-label={t.apply}\n disabled={!canEdit || !hasUrl}\n onMouseDown={keepFocus}\n onClick={apply}\n >\n <CheckIcon size={16} />\n </button>\n\n <span className={styles.divider} aria-hidden=\"true\" />\n\n <button\n type=\"button\"\n className={styles.btn}\n data-link-action=\"open\"\n title={t.open}\n aria-label={t.open}\n disabled={!hasUrl}\n onMouseDown={keepFocus}\n onClick={openInNewWindow}\n >\n <ExternalLinkIcon size={16} />\n </button>\n <button\n type=\"button\"\n className={styles.btn}\n data-link-action=\"remove\"\n title={t.remove}\n aria-label={t.remove}\n disabled={!canEdit}\n onMouseDown={keepFocus}\n onClick={remove}\n >\n <TrashIcon size={16} />\n </button>\n </div>\n );\n}\n","import type { Editor } from '@tiptap/core';\nimport type { Node as PMNode } from '@tiptap/pm/model';\nimport type { EditorState } from '@tiptap/pm/state';\nimport {\n cellAround,\n CellSelection,\n isInTable,\n rowIsHeader,\n selectedRect,\n TableMap,\n} from '@tiptap/pm/tables';\n\nexport interface TableSelectionInfo {\n rowCount: number;\n colCount: number;\n /** 选区跨越多行或多列时为 true(用于带 N 的文案)。 */\n isMultiCell: boolean;\n includesHeaderRow: boolean;\n coversAllRows: boolean;\n coversAllCols: boolean;\n}\n\n/** 当前若不在表格内返回 null。 */\nexport function getTableSelectionInfo(\n state: EditorState,\n): TableSelectionInfo | null {\n if (!isInTable(state)) return null;\n\n const rect = selectedRect(state);\n const rowCount = Math.max(1, rect.bottom - rect.top);\n const colCount = Math.max(1, rect.right - rect.left);\n\n let includesHeaderRow = false;\n for (let row = rect.top; row < rect.bottom; row++) {\n if (rowIsHeader(rect.map, rect.table, row)) {\n includesHeaderRow = true;\n break;\n }\n }\n\n return {\n rowCount,\n colCount,\n isMultiCell: rowCount > 1 || colCount > 1,\n includesHeaderRow,\n coversAllRows: rect.top === 0 && rect.bottom === rect.map.height,\n coversAllCols: rect.left === 0 && rect.right === rect.map.width,\n };\n}\n\n/** 文档坐标是否落在 CellSelection 覆盖的某个单元格内(含单元格节点本身)。 */\nexport function isPosInCellSelection(\n selection: CellSelection,\n pos: number,\n): boolean {\n let found = false;\n selection.forEachCell((node, cellPos) => {\n if (pos >= cellPos && pos <= cellPos + node.nodeSize) {\n found = true;\n }\n });\n return found;\n}\n\n\nexport function addRowsBefore(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addRowBefore()) return false;\n }\n return true;\n}\n\nexport function addRowsAfter(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addRowAfter()) return false;\n }\n return true;\n}\n\nexport function addColumnsBefore(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addColumnBefore()) return false;\n }\n return true;\n}\n\nexport function addColumnsAfter(editor: Editor, count: number): boolean {\n const n = Math.max(1, count);\n for (let i = 0; i < n; i++) {\n if (!editor.commands.addColumnAfter()) return false;\n }\n return true;\n}\n\n/** 删行:全表行被选中时改为删整表;含表头时调用方应先禁用。 */\nexport function deleteSelectedRows(editor: Editor): boolean {\n const info = getTableSelectionInfo(editor.state);\n if (!info) return false;\n if (info.coversAllRows) return editor.commands.deleteTable();\n return editor.commands.deleteRow();\n}\n\n/** 删列:选区覆盖全部列且同时覆盖全部行时删整表;仅覆盖全部列时失败(由 UI 禁用)。 */\nexport function deleteSelectedColumns(editor: Editor): boolean {\n const info = getTableSelectionInfo(editor.state);\n if (!info) return false;\n if (info.coversAllCols) {\n if (info.coversAllRows) return editor.commands.deleteTable();\n return false;\n }\n return editor.commands.deleteColumn();\n}\n\n/** 结构属性:改它们等于改变表格形状,合并 / 拆分有专门的命令,重置样式时不碰。 */\nconst STRUCTURAL_CELL_ATTRS = new Set(['colspan', 'rowspan']);\n\n/**\n * 选区覆盖到的单元格:CellSelection 的全部单元格;若只是个文本光标,就取它所在的那一格。\n * (菜单里永远是 CellSelection;带光标这条是为了让命令单独用也说得通。)\n */\nfunction selectedCellEntries(\n editor: Editor,\n): Array<{ pos: number; node: PMNode }> {\n const { selection } = editor.state;\n const entries: Array<{ pos: number; node: PMNode }> = [];\n\n if (selection instanceof CellSelection) {\n selection.forEachCell((node, pos) => {\n entries.push({ pos, node });\n });\n return entries;\n }\n\n const $cell = cellAround(selection.$from);\n if (!$cell) return entries;\n const pos = $cell.before($cell.depth);\n const node = editor.state.doc.nodeAt(pos);\n if (node) entries.push({ pos, node });\n return entries;\n}\n\n/**\n * 清空选中单元格的**内容**,保留单元格本身与它的属性(表头行因此不会被降级)。\n *\n * 单元格必须至少留一个块,所以内容替换成一个空段落。已经空的单元格跳过——不改动、\n * 也不产生多余的撤销步。返回是否真的改了文档。\n */\nexport function clearSelectedCellContents(editor: Editor): boolean {\n const entries = selectedCellEntries(editor);\n if (!entries.length) return false;\n const paragraph = editor.state.schema.nodes.paragraph;\n if (!paragraph) return false;\n\n const tr = editor.state.tr;\n // 从后往前改:替换内容会改变 nodeSize,先算好后面的位置才不会位移串味\n for (const { pos, node } of [...entries].sort((a, b) => b.pos - a.pos)) {\n const isEmpty =\n node.childCount === 1 &&\n !!node.firstChild?.isTextblock &&\n node.firstChild.content.size === 0;\n if (isEmpty) continue;\n tr.replaceWith(pos + 1, pos + node.nodeSize - 1, paragraph.createAndFill()!);\n }\n\n if (!tr.docChanged) return false;\n editor.view.dispatch(tr.scrollIntoView());\n return true;\n}\n\n/**\n * 把选中单元格的**样式属性**复位(列宽、对齐等,按各属性的 schema 默认值)。\n *\n * 不动 `colspan` / `rowspan`:那是结构,复位它们会让表格形状不合法(缺格)。\n * (扩展有 `mergeCells` / `splitCell`,但本库不暴露入口——GFM 没有 colspan,合并导出成\n * `| 1<br>2 | |` 且回不去,见 README。)\n */\nexport function resetSelectedCellStyles(editor: Editor): boolean {\n const entries = selectedCellEntries(editor);\n if (!entries.length) return false;\n\n const tr = editor.state.tr;\n for (const { pos, node } of entries) {\n const attrs = (node.type.spec.attrs ?? {}) as Record<\n string,\n { default?: unknown }\n >;\n const next: Record<string, unknown> = { ...node.attrs };\n let changed = false;\n for (const [key, spec] of Object.entries(attrs)) {\n if (STRUCTURAL_CELL_ATTRS.has(key)) continue;\n const fallback = spec?.default ?? null;\n if (next[key] !== fallback) {\n next[key] = fallback;\n changed = true;\n }\n }\n if (changed) tr.setNodeMarkup(pos, undefined, next);\n }\n\n if (!tr.docChanged) return false;\n editor.view.dispatch(tr);\n return true;\n}\n\n/** 找当前要操作的那张表:优先用光标 / 选区所在的那张(同页多表时才不会改错),否则文档里的第一张。 */\nfunction findTable(editor: Editor): { pos: number; node: PMNode } | null {\n const $from = editor.state.selection.$from;\n for (let d = $from.depth; d > 0; d -= 1) {\n if ($from.node(d).type.name === 'table') {\n return { pos: $from.before(d), node: $from.node(d) };\n }\n }\n\n let found: { pos: number; node: PMNode } | null = null;\n editor.state.doc.descendants((node, pos) => {\n if (found !== null) return false;\n if (node.type.name === 'table') {\n found = { pos, node };\n return false;\n }\n return true;\n });\n return found;\n}\n\n/** 把第 index 行 / 列整体选成 CellSelection(末尾追加这类操作要先「瞄准」)。 */\nfunction selectLineAt(\n editor: Editor,\n table: { pos: number; node: PMNode },\n kind: 'row' | 'col',\n index: number,\n): void {\n const map = TableMap.get(table.node);\n const start = table.pos + 1;\n const anchorCell = start + map.positionAt(kind === 'row' ? index : 0, kind === 'col' ? index : 0, table.node);\n const headCell =\n start +\n map.positionAt(\n kind === 'row' ? index : map.height - 1,\n kind === 'col' ? index : map.width - 1,\n table.node,\n );\n editor.view.dispatch(\n editor.state.tr.setSelection(\n new CellSelection(\n editor.state.doc.resolve(anchorCell),\n editor.state.doc.resolve(headCell),\n ),\n ),\n );\n}\n\n/**\n * 在表格末尾追加一行(表底那个 `+`)。\n * 先把最后一行选成 CellSelection——扩展的 `addRowAfter` 是按选区办事的。\n */\nexport function appendRowToTable(editor: Editor): boolean {\n const table = findTable(editor);\n if (!table) return false;\n selectLineAt(editor, table, 'row', TableMap.get(table.node).height - 1);\n return addRowsAfter(editor, 1);\n}\n\n/**\n * 在表格末尾追加一列(表格右侧那个 `+`)。\n * 同理先把最后一列选成 CellSelection。\n */\nexport function appendColumnToTable(editor: Editor): boolean {\n const table = findTable(editor);\n if (!table) return false;\n selectLineAt(editor, table, 'col', TableMap.get(table.node).width - 1);\n return addColumnsAfter(editor, 1);\n}\n","'use client';\n\nimport type { Editor } from '@tiptap/core';\nimport { CellSelection, cellAround, TableMap } from '@tiptap/pm/tables';\nimport {\n Fragment,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ColumnAfterIcon,\n ColumnBeforeIcon,\n ColumnDeleteIcon,\n EraserIcon,\n RotateCcwIcon,\n RowAfterIcon,\n RowBeforeIcon,\n RowDeleteIcon,\n TableDeleteIcon,\n} from '../icons';\nimport type { ToolbarLabels } from '../labels';\nimport {\n addColumnsAfter,\n addColumnsBefore,\n appendColumnToTable,\n appendRowToTable,\n addRowsAfter,\n addRowsBefore,\n clearSelectedCellContents,\n deleteSelectedColumns,\n deleteSelectedRows,\n resetSelectedCellStyles,\n getTableSelectionInfo,\n isPosInCellSelection,\n} from '../tableSelection';\nimport styles from '../styles/tableHandles.module.css';\n\nexport interface TableHandlesProps {\n /** 编辑器实例。只读态不出手柄。 */\n editor: Editor;\n /** 已合并默认值的工具栏文案(行列菜单项与两个手柄的 aria-label 都取自它)。 */\n labels: ToolbarLabels;\n}\n\n/** 悬停到某个单元格时量出来的几何:手柄贴边 + 建 CellSelection 用。 */\ninterface HoverGeom {\n /** 当前悬停的单元格元素(用来跳过同一格的重复测量)。 */\n cell: HTMLElement;\n rowTop: number;\n rowHeight: number;\n colLeft: number;\n colWidth: number;\n tableLeft: number;\n tableTop: number;\n /** 表格右缘 / 下缘:末尾追加行列的两个 `+` 手柄贴在它们外侧。 */\n tableRight: number;\n tableBottom: number;\n /** 悬停的这格是不是表格的最后一行 / 最后一列——决定要不要出对应的 `+`。 */\n onLastRow: boolean;\n onLastCol: boolean;\n}\n\n/**\n * 悬停的这格落在表格的最后一行 / 最后一列吗(按 TableMap 算,colspan 也算得对)。\n * 末尾追加的 `+` 只在贴着那两行/列时才出现,否则鼠标停在表格中间也会冒出两个加号。\n */\nfunction edgeFlags(\n editor: Editor,\n cell: HTMLElement,\n): { onLastRow: boolean; onLastCol: boolean } {\n try {\n const $cell = cellAround(editor.state.doc.resolve(editor.view.posAtDOM(cell, 0)));\n if (!$cell) return { onLastRow: false, onLastCol: false };\n // 官方(prosemirror-tables)自己的换算写法:findCell($pos.pos - $pos.start(-1))。\n // 注意别用 $pos.before($pos.depth)——cellAround 给的是「行层」的 ResolvedPos,\n // before(depth) 拿到的是行首的位置,不是这一格的。\n const map = TableMap.get($cell.node(-1));\n const rect = map.findCell($cell.pos - $cell.start(-1));\n return {\n onLastRow: rect.bottom === map.height,\n onLastCol: rect.right === map.width,\n };\n } catch {\n return { onLastRow: false, onLastCol: false };\n }\n}\n\n/** 菜单挂在哪个手柄(multi = 右键多格选区)上。 */\ninterface HandleMenu {\n kind: 'row' | 'col' | 'multi';\n x: number;\n y: number;\n}\n\n/** 手柄相对单元格边缘的间距(列手柄在表格上方,行手柄在表格左侧)。 */\nconst COL_HANDLE_GAP = 22;\nconst ROW_HANDLE_GAP = 26;\n/** 末尾追加行列的 `+` 手柄贴在表格右缘 / 下缘外侧的间距。 */\nconst EXTEND_GAP = 6;\n/** `+` 手柄的粗细(长度由表格尺寸决定)。 */\nconst EXTEND_THICKNESS = 16;\n/**\n * 指针离开单元格后手柄再活一会儿(毫秒):走向手柄的路上有一段「既非单元格也非手柄」的空隙,\n * 立刻收起就会点不到。见下面悬停追踪那段注释。\n */\nconst HOVER_KEEP_MS = 160;\n\n/** 量单元格与它所在行 / 表格的视口矩形(手柄是 fixed 定位,直接用视口坐标)。 */\nfunction measureCell(editor: Editor, cell: HTMLElement): HoverGeom | null {\n const table = cell.closest('table');\n const row = cell.closest('tr');\n if (!table || !row) return null;\n // 校验这个 DOM 还对应文档里的位置(视图可能刚重建过)\n try {\n editor.view.posAtDOM(cell, 0);\n } catch {\n return null;\n }\n const cellRect = cell.getBoundingClientRect();\n const rowRect = row.getBoundingClientRect();\n const tableRect = table.getBoundingClientRect();\n const edges = edgeFlags(editor, cell);\n return {\n cell,\n ...edges,\n rowTop: rowRect.top,\n rowHeight: rowRect.height,\n colLeft: cellRect.left,\n colWidth: cellRect.width,\n tableLeft: tableRect.left,\n tableTop: tableRect.top,\n tableRight: tableRect.right,\n tableBottom: tableRect.bottom,\n };\n}\n\n/** 把整行 / 整列选成 CellSelection:菜单里的命令都按选区办事,选中即「瞄准」。 */\nfunction selectRowOrColumn(\n editor: Editor,\n cell: HTMLElement,\n kind: 'row' | 'col',\n): boolean {\n let pos: number;\n try {\n pos = editor.view.posAtDOM(cell, 0);\n } catch {\n return false;\n }\n const $cell = cellAround(editor.state.doc.resolve(pos));\n if (!$cell) return false;\n const selection =\n kind === 'row'\n ? CellSelection.rowSelection($cell)\n : CellSelection.colSelection($cell);\n editor.view.dispatch(editor.state.tr.setSelection(selection));\n return true;\n}\n\ninterface MenuItemSpec {\n key: string;\n label: string;\n icon: ReactNode;\n /** 分组:组变了就插一条分隔线(列操作 / 行操作 / 单元格操作 / 删除表格)。 */\n group: 'col' | 'row' | 'cells';\n disabled?: boolean;\n run: () => void;\n}\n\n/** 按手柄种类组装菜单项:行手柄只管行、列手柄只管列,右键多格选区两样都给。 */\nfunction menuItemsFor(\n editor: Editor,\n labels: ToolbarLabels,\n kind: HandleMenu['kind'],\n): MenuItemSpec[] {\n const info = getTableSelectionInfo(editor.state);\n const rowN = info?.rowCount ?? 1;\n const colN = info?.colCount ?? 1;\n // 「几行几列」的文案**只**给多格选区用:点行手柄时选区是「整行 × 全部列」,\n // 按 isMultiCell 判会得到「插入 1 行」这种拗口文案(而且列数会被算进去)。\n const multi = kind === 'multi';\n const items: MenuItemSpec[] = [];\n\n if (kind === 'col' || kind === 'multi') {\n items.push(\n {\n key: 'col-before',\n group: 'col',\n label: multi ? labels.tableAddColumnBeforeN(colN) : labels.tableAddColumnBefore,\n icon: <ColumnBeforeIcon />,\n run: () => addColumnsBefore(editor, colN),\n },\n {\n key: 'col-after',\n group: 'col',\n label: multi ? labels.tableAddColumnAfterN(colN) : labels.tableAddColumnAfter,\n icon: <ColumnAfterIcon />,\n run: () => addColumnsAfter(editor, colN),\n },\n {\n key: 'col-delete',\n group: 'col',\n label: multi ? labels.tableDeleteColumnN(colN) : labels.tableDeleteColumn,\n icon: <ColumnDeleteIcon />,\n // 只选了全部列、却没选全部行:删列会把表格删没,禁掉\n disabled: !!info?.coversAllCols && !info?.coversAllRows,\n run: () => deleteSelectedColumns(editor),\n },\n );\n }\n\n if (kind === 'row' || kind === 'multi') {\n items.push(\n {\n key: 'row-before',\n group: 'row',\n label: multi ? labels.tableAddRowBeforeN(rowN) : labels.tableAddRowBefore,\n icon: <RowBeforeIcon />,\n // 上方是表头行时插行没意义\n disabled: !!info?.includesHeaderRow,\n run: () => addRowsBefore(editor, rowN),\n },\n {\n key: 'row-after',\n group: 'row',\n label: multi ? labels.tableAddRowAfterN(rowN) : labels.tableAddRowAfter,\n icon: <RowAfterIcon />,\n run: () => addRowsAfter(editor, rowN),\n },\n {\n key: 'row-delete',\n group: 'row',\n label: multi ? labels.tableDeleteRowN(rowN) : labels.tableDeleteRow,\n icon: <RowDeleteIcon />,\n disabled: !!info?.includesHeaderRow,\n run: () => deleteSelectedRows(editor),\n },\n );\n }\n\n // 单元格级操作:清空内容、重置样式。两者都不改变表格形状,所以行 / 列 / 多格选区都给。\n items.push(\n {\n key: 'cells-clear',\n group: 'cells',\n label: labels.tableClearContent,\n icon: <EraserIcon />,\n run: () => clearSelectedCellContents(editor),\n },\n {\n key: 'cells-reset',\n group: 'cells',\n label: labels.tableResetCellStyles,\n icon: <RotateCcwIcon />,\n run: () => resetSelectedCellStyles(editor),\n },\n );\n\n return items;\n}\n\n/**\n * 表格的悬停手柄(Notion 式):鼠标落在单元格上时,行左缘出一条竖胶囊(⋮)、表格上方出一条\n * 横胶囊(⋯),点开就是该行 / 该列的操作菜单。\n *\n * 这是原来「表内右键出菜单」的替代——右键只保留**多格选区**的批量增删(手柄只覆盖单行单列,\n * 那个场景手柄表达不了)。命令全部复用 `tableSelection.ts`,与工具栏的「插入表格」共用一套。\n *\n * 手柄是 fixed 定位、渲染在 body 的 portal 里:它要贴着单元格边缘,而工具栏并不在编辑器 DOM\n * 内。滚动 / 缩放时重新量一遍悬停的那颗单元格,让手柄跟着走。\n */\nexport function TableHandles({ editor, labels }: TableHandlesProps) {\n const [hover, setHover] = useState<HoverGeom | null>(null);\n const [menu, setMenu] = useState<HandleMenu | null>(null);\n\n const hoverRef = useRef<HoverGeom | null>(null);\n const menuRef = useRef<HandleMenu | null>(null);\n menuRef.current = menu;\n\n const clearHover = useCallback(() => {\n if (!hoverRef.current) return;\n hoverRef.current = null;\n setHover(null);\n }, []);\n\n const closeMenu = useCallback(() => setMenu(null), []);\n\n /** 重新量一遍悬停的那颗单元格(滚动 / 缩放 / 追加行列后手柄要跟着走)。 */\n const remeasureHover = useCallback(() => {\n const cell = hoverRef.current?.cell;\n if (!cell) return;\n const next = cell.isConnected ? measureCell(editor, cell) : null;\n hoverRef.current = next;\n setHover(next);\n }, [editor]);\n /** 离开后的收起定时器(悬停意图,见下面的注释)。 */\n const clearTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const cancelPendingClear = useCallback(() => {\n if (clearTimerRef.current === null) return;\n clearTimeout(clearTimerRef.current);\n clearTimerRef.current = null;\n }, []);\n\n // 悬停追踪挂在 document 上。\n //\n // 关键点:**离开单元格 ≠ 离开**。指针从单元格走向手柄时,中间必然经过一小段既不是单元格、\n // 也不在手柄上的地方(手柄贴在表格外侧,本身只有 28px 高,斜着移动更是会绕过它),\n // 那一刻若立刻收起,手柄就在你点到之前消失了。所以这里用「悬停意图」:不在单元格 / 手柄上时\n // 只挂一个 ~160ms 的收起定时器,指针在这段时间内碰到手柄或单元格就取消。\n useEffect(() => {\n const onMove = (event: MouseEvent) => {\n if (!editor.isEditable || menuRef.current) return;\n const target = event.target as HTMLElement | null;\n\n // 指针已经到手柄上:留着,并取消待收起\n if (target?.closest?.('[data-table-handle], [data-table-extend]')) {\n cancelPendingClear();\n return;\n }\n\n const cell =\n target && editor.view.dom.contains(target)\n ? (target.closest('td, th') as HTMLElement | null)\n : null;\n\n if (!cell) {\n // 既不在单元格也不在手柄上:宽限一段再收(指针可能正走向手柄)\n if (hoverRef.current && clearTimerRef.current === null) {\n clearTimerRef.current = setTimeout(() => {\n clearTimerRef.current = null;\n clearHover();\n }, HOVER_KEEP_MS);\n }\n return;\n }\n\n cancelPendingClear();\n if (hoverRef.current?.cell === cell) return;\n const next = measureCell(editor, cell);\n hoverRef.current = next;\n setHover(next);\n };\n const onBlurWindow = () => {\n cancelPendingClear();\n clearHover();\n };\n // 滚动 / 缩放后手柄的 fixed 坐标会失真:重新量那颗单元格让手柄跟着走,而不是直接收起\n // (窗口一动手柄就没了很烦)。单元格已经不在文档里了才收起。\n document.addEventListener('mousemove', onMove);\n document.addEventListener('mouseleave', onBlurWindow);\n window.addEventListener('scroll', remeasureHover, true);\n window.addEventListener('resize', remeasureHover);\n return () => {\n cancelPendingClear();\n document.removeEventListener('mousemove', onMove);\n document.removeEventListener('mouseleave', onBlurWindow);\n window.removeEventListener('scroll', remeasureHover, true);\n window.removeEventListener('resize', remeasureHover);\n };\n }, [editor, clearHover, cancelPendingClear, remeasureHover]);\n\n // 右键:只服务多格选区(单行 / 单列交给手柄)\n useEffect(() => {\n const dom = editor.view.dom;\n const onContextMenu = (event: MouseEvent) => {\n const info = getTableSelectionInfo(editor.state);\n const { selection } = editor.state;\n if (!info?.isMultiCell || !(selection instanceof CellSelection)) return;\n const coords = editor.view.posAtCoords({\n left: event.clientX,\n top: event.clientY,\n });\n if (!coords || !isPosInCellSelection(selection, coords.pos)) return;\n event.preventDefault();\n hoverRef.current = null;\n setHover(null);\n setMenu({ kind: 'multi', x: event.clientX, y: event.clientY });\n };\n dom.addEventListener('contextmenu', onContextMenu);\n return () => dom.removeEventListener('contextmenu', onContextMenu);\n }, [editor]);\n\n // 菜单开着时:点外面 / Esc 收起(菜内点击不关,交给菜单项自己收)\n useEffect(() => {\n if (!menu) return;\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') closeMenu();\n };\n const onDown = (event: MouseEvent) => {\n const target = event.target as HTMLElement | null;\n if (target?.closest?.('[data-table-menu]')) return;\n closeMenu();\n };\n document.addEventListener('keydown', onKey, true);\n document.addEventListener('mousedown', onDown);\n return () => {\n document.removeEventListener('keydown', onKey, true);\n document.removeEventListener('mousedown', onDown);\n };\n }, [menu, closeMenu]);\n\n if (typeof document === 'undefined') return null;\n\n const openHandleMenu = (kind: 'row' | 'col') => {\n if (!hover) return;\n if (!selectRowOrColumn(editor, hover.cell, kind)) return;\n setHover(null);\n hoverRef.current = null;\n setMenu(\n kind === 'row'\n ? { kind, x: hover.tableLeft + 6, y: hover.rowTop }\n : { kind, x: hover.colLeft, y: hover.tableTop + 6 },\n );\n };\n\n const items = menu ? menuItemsFor(editor, labels, menu.kind) : [];\n const showHandles = !!hover && !menu && editor.isEditable;\n\n return createPortal(\n <>\n {showHandles && hover ? (\n <>\n <button\n type=\"button\"\n data-table-handle=\"row\"\n className={`${styles.handle} ${styles.handleRow}`}\n style={{\n left: hover.tableLeft - ROW_HANDLE_GAP,\n // 长度跟着行高走(原来固定 28px 居中,行高时就显得太短)\n top: hover.rowTop,\n height: hover.rowHeight,\n }}\n title={labels.tableRowMenu}\n aria-label={labels.tableRowMenu}\n // 保住编辑器选区:点手柄不该先把光标丢掉\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => openHandleMenu('row')}\n >\n <span aria-hidden>⋮</span>\n </button>\n <button\n type=\"button\"\n data-table-handle=\"col\"\n className={`${styles.handle} ${styles.handleCol}`}\n style={{\n // 长度跟着列宽走,两端与单元格对齐\n left: hover.colLeft,\n top: hover.tableTop - COL_HANDLE_GAP,\n width: hover.colWidth,\n }}\n title={labels.tableColumnMenu}\n aria-label={labels.tableColumnMenu}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => openHandleMenu('col')}\n >\n <span aria-hidden>⋯</span>\n </button>\n\n {/* 末尾追加:只有悬停贴着最后一列 / 最后一行时才出现对应的一条 `+`\n (鼠标停在表格中间不该冒加号)。长度跟着表格尺寸走,点完重新量一次。 */}\n {hover.onLastCol ? (\n <button\n type=\"button\"\n data-table-extend=\"col\"\n className={styles.extend}\n style={{\n left: hover.tableRight + EXTEND_GAP,\n top: hover.tableTop,\n width: EXTEND_THICKNESS,\n height: Math.max(EXTEND_THICKNESS, hover.tableBottom - hover.tableTop),\n }}\n title={labels.tableAppendColumn}\n aria-label={labels.tableAppendColumn}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n appendColumnToTable(editor);\n remeasureHover();\n }}\n >\n <span aria-hidden>+</span>\n </button>\n ) : null}\n {hover.onLastRow ? (\n <button\n type=\"button\"\n data-table-extend=\"row\"\n className={styles.extend}\n style={{\n left: hover.tableLeft,\n top: hover.tableBottom + EXTEND_GAP,\n width: Math.max(EXTEND_THICKNESS, hover.tableRight - hover.tableLeft),\n height: EXTEND_THICKNESS,\n }}\n title={labels.tableAppendRow}\n aria-label={labels.tableAppendRow}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n appendRowToTable(editor);\n remeasureHover();\n }}\n >\n <span aria-hidden>+</span>\n </button>\n ) : null}\n </>\n ) : null}\n\n {menu ? (\n <div\n className={styles.tableBubble}\n data-table-menu=\"\"\n style={{ left: menu.x, top: menu.y }}\n role=\"menu\"\n onMouseDown={(e) => e.stopPropagation()}\n onContextMenu={(e) => e.preventDefault()}\n >\n {items.map((item, index) => (\n <Fragment key={item.key}>\n {index > 0 && item.group !== items[index - 1].group ? (\n <span className={styles.tableMenuDivider} aria-hidden />\n ) : null}\n <button\n type=\"button\"\n role=\"menuitem\"\n className={styles.tableMenuItem}\n disabled={item.disabled}\n onClick={() => {\n item.run();\n closeMenu();\n }}\n >\n <span className={styles.tableMenuItemIcon} aria-hidden>\n {item.icon}\n </span>\n <span className={styles.tableMenuItemLabel}>{item.label}</span>\n </button>\n </Fragment>\n ))}\n <span className={styles.tableMenuDivider} aria-hidden />\n <button\n type=\"button\"\n role=\"menuitem\"\n className={styles.tableMenuItem}\n onClick={() => {\n editor.commands.deleteTable();\n closeMenu();\n }}\n >\n <span className={styles.tableMenuItemIcon} aria-hidden>\n <TableDeleteIcon />\n </span>\n <span className={styles.tableMenuItemLabel}>\n {labels.tableDeleteTable}\n </span>\n </button>\n </div>\n ) : null}\n </>,\n document.body,\n );\n}\n","'use client';\n\nimport type { Editor } from '@tiptap/react';\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { renderMathInto, type MathKind } from '../math';\nimport styles from '../styles/toolbar.module.css';\n\nexport interface MathEditorPopoverProps {\n editor: Editor;\n kind: MathKind;\n mode: 'insert' | 'edit';\n pos?: number;\n latex: string;\n /** 工具栏新插入:取消时删掉占位节点 */\n isNew?: boolean;\n newLabel: string;\n placeholder: string;\n doneLabel: string;\n onConfirm: (latex: string) => void;\n onCancel: () => void;\n}\n\nfunction resolveNodeEl(editor: Editor, pos: number): HTMLElement | null {\n const dom = editor.view.nodeDOM(pos);\n if (dom instanceof HTMLElement) return dom;\n if (dom instanceof Node) return dom.parentElement;\n return null;\n}\n\nfunction mathRenderTarget(el: HTMLElement, isBlock: boolean): HTMLElement {\n if (!isBlock) return el;\n return (el.querySelector('.block-math-inner') as HTMLElement | null) ?? el;\n}\n\nfunction getMathLayerStyle(\n editor: Editor,\n kind: MathKind,\n pos?: number,\n): CSSProperties {\n const host = editor.view.dom.parentElement;\n if (!host) return {};\n const hostRect = host.getBoundingClientRect();\n const editorRect = editor.view.dom.getBoundingClientRect();\n const gap = 6;\n const blockWidth = editor.view.dom.clientWidth;\n\n if (pos != null) {\n const el = resolveNodeEl(editor, pos);\n if (el) {\n const r = el.getBoundingClientRect();\n const top = r.bottom - hostRect.top + gap;\n if (kind === 'block') {\n return {\n left: editorRect.left - hostRect.left,\n top,\n width: blockWidth,\n };\n }\n return {\n left: r.left - hostRect.left,\n top,\n };\n }\n }\n\n const coords = editor.view.coordsAtPos(editor.state.selection.from);\n if (kind === 'block') {\n return {\n left: editorRect.left - hostRect.left,\n top: coords.bottom - hostRect.top + gap,\n width: blockWidth,\n };\n }\n return {\n left: coords.left - hostRect.left,\n top: coords.bottom - hostRect.top + gap,\n };\n}\n\nexport function MathEditorPopover({\n editor,\n kind,\n mode,\n pos,\n latex,\n isNew = false,\n newLabel,\n placeholder,\n doneLabel,\n onConfirm,\n onCancel,\n}: MathEditorPopoverProps) {\n const [draft, setDraft] = useState(latex);\n const [layerStyle, setLayerStyle] = useState<CSSProperties>(() =>\n getMathLayerStyle(editor, kind, pos),\n );\n const titleId = useId();\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const isBlock = kind === 'block';\n const host = editor.view.dom.parentElement;\n\n useEffect(() => {\n setDraft(latex);\n }, [latex]);\n\n useEffect(() => {\n const update = () => setLayerStyle(getMathLayerStyle(editor, kind, pos));\n update();\n window.addEventListener('resize', update);\n return () => window.removeEventListener('resize', update);\n }, [editor, kind, pos, draft]);\n\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n useEffect(() => {\n if (pos == null) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n el.classList.add('tmr-math-editing');\n return () => {\n el.classList.remove('tmr-math-editing');\n };\n }, [editor, pos]);\n\n useEffect(() => {\n if (pos == null) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n const target = mathRenderTarget(el, isBlock);\n const src = draft.trim();\n if (src) renderMathInto(target, src, isBlock);\n else target.textContent = '';\n }, [draft, pos, editor, isBlock]);\n\n useEffect(() => {\n if (pos == null || isNew) return;\n const el = resolveNodeEl(editor, pos);\n if (!el) return;\n const target = mathRenderTarget(el, isBlock);\n return () => {\n const restore = latex.trim();\n if (restore) renderMathInto(target, restore, isBlock);\n else target.textContent = '';\n };\n }, [pos, editor, isBlock, latex, isNew]);\n\n useEffect(() => {\n const onPtr = (e: PointerEvent) => {\n const target = e.target;\n if (!(target instanceof Node)) return;\n if (rootRef.current?.contains(target)) return;\n if (pos != null) {\n const el = resolveNodeEl(editor, pos);\n if (el?.contains(target)) return;\n }\n onCancel();\n };\n document.addEventListener('pointerdown', onPtr);\n return () => document.removeEventListener('pointerdown', onPtr);\n }, [onCancel, editor, pos]);\n\n const canSubmit = draft.trim().length > 0;\n const showHint = !canSubmit && (mode === 'insert' || isNew);\n\n const submit = () => {\n if (!canSubmit) return;\n onConfirm(draft.trim());\n };\n\n const onKeyDown = (\n e: KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onCancel();\n return;\n }\n if (e.key !== 'Enter') return;\n if (isBlock && !(e.metaKey || e.ctrlKey)) return;\n e.preventDefault();\n submit();\n };\n\n const field = isBlock ? (\n <textarea\n ref={inputRef as RefObject<HTMLTextAreaElement>}\n className={styles.mathInput}\n value={draft}\n placeholder={placeholder}\n rows={Math.max(3, draft.split('\\n').length)}\n aria-labelledby={titleId}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n />\n ) : (\n <input\n ref={inputRef as RefObject<HTMLInputElement>}\n className={styles.mathInput}\n value={draft}\n placeholder={placeholder}\n aria-labelledby={titleId}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n />\n );\n\n if (!host) return null;\n\n return createPortal(\n <div\n ref={rootRef}\n className={styles.mathLayer}\n style={layerStyle}\n role=\"dialog\"\n aria-modal=\"false\"\n aria-labelledby={titleId}\n >\n <div\n className={\n isBlock\n ? `${styles.mathStack} ${styles.mathStackBlock}`\n : styles.mathStack\n }\n >\n {showHint ? (\n <div\n id={titleId}\n className={\n isBlock\n ? `${styles.mathHint} ${styles.mathHintBlock}`\n : styles.mathHint\n }\n >\n <span className={styles.mathHintIcon} aria-hidden>\n {isBlock ? 'TeX' : '√x'}\n </span>\n {newLabel}\n </div>\n ) : null}\n <div\n id={showHint ? undefined : titleId}\n className={\n isBlock\n ? `${styles.mathField} ${styles.mathFieldBlock}`\n : styles.mathField\n }\n >\n {field}\n <button\n type=\"button\"\n className={styles.mathDone}\n disabled={!canSubmit}\n title={\n isBlock ? `${doneLabel} (⌘/Ctrl+Enter)` : `${doneLabel} (Enter)`\n }\n onClick={submit}\n >\n {doneLabel}\n <span className={styles.mathDoneKbd} aria-hidden>\n ↵\n </span>\n </button>\n </div>\n </div>\n </div>,\n host,\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 forwardRef,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n type ButtonHTMLAttributes,\n type ReactNode,\n} from 'react';\nimport {\n BoldIcon,\n ChevronDownIcon,\n CodeIcon,\n ImageIcon,\n ItalicIcon,\n LinkIcon,\n ListChecksIcon,\n ListOrderedIcon,\n ListUnorderedIcon,\n RedoIcon,\n SearchIcon,\n StrikethroughIcon,\n UnderlineIcon,\n UndoIcon,\n} from '../icons';\nimport { defaultToolbarLabels, type ToolbarLabels } from '../labels';\nimport {\n MD_FILE_RE,\n resolveImportMenuItems,\n type ImportMenuItem,\n} from '../importMenu';\nimport type { SourceRef } from '../citationUtils';\nimport { insertMarkdown } from '../insertMarkdown';\nimport { subscribeMathClick, type MathKind } from '../math';\nimport styles from '../styles/toolbar.module.css';\nimport { ColorPalette } from './ColorPalette';\nimport { LinkPopover } from './LinkPopover';\nimport { TableHandles } from './TableHandles';\nimport { MathEditorPopover } from './MathEditorPopover';\n\n/** `onImportDocument` 的成功返回。给字符串等价于 `{ markdown }`。 */\nexport interface ImportDocumentResult {\n markdown: string;\n sources?: SourceRef[];\n}\n\n/** 导入进度。包用来更新光标占位文案并禁用导入按钮。 */\nexport interface ImportDocumentProgress {\n /** 0–1。通常只有上传阶段可测;转换阶段可省略。 */\n ratio?: number;\n phase: 'upload' | 'convert';\n}\n\nexport interface ImportDocumentContext {\n /** 用户点取消或组件卸载时 abort,宿主据此中断请求。 */\n signal: AbortSignal;\n onProgress?: (p: ImportDocumentProgress) => void;\n}\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(..., 'image')。\n */\n onImageUpload?: (file: File) => Promise<string>;\n /**\n * 副作用错误回调(图片上传 / Markdown 导入失败),供宿主弹自己的提示。\n * `source` 区分来源,避免一律显示「图片上传失败」。\n */\n onError?: (err: unknown, source?: 'image' | 'markdown' | 'import') => void;\n /**\n * 非 Markdown 文件的转换:收到文件,返回可插入的 Markdown。未提供则导入只吃 .md。\n * 包内不校验扩展名——格式白名单由宿主的 `importAccept` 与本回调自己负责。\n * 抛错转交 onError(..., 'import');`AbortError` 视为用户取消,不报错。\n */\n onImportDocument?: (\n file: File,\n ctx: ImportDocumentContext,\n ) => Promise<ImportDocumentResult | string>;\n /**\n * 追加到导入 input 的 accept(默认已含 `.md,.markdown,text/markdown`)。\n * 例:`.doc,.docx,.csv,.pdf`。未传 `importMenuItems` 且传了 `onImportDocument` 时,\n * 下拉会多一项「Document」。\n */\n importAccept?: string;\n /**\n * 主栏导入下拉的选项。不传则 Markdown;再加 `onImportDocument` + `importAccept`\n * 时多一项 Document。宿主要拆成 Word / PDF 时自己传入。\n */\n importMenuItems?: ImportMenuItem[];\n /** 是否显示导入下拉,默认 `true`。卡片等场景可关掉。 */\n showImport?: boolean;\n labels?: Partial<ToolbarLabels>;\n /**\n * 工具栏最右端的搜索入口(放大镜)。**不传就不渲染**——条子本身归\n * `<MarkdownWysiwygEditor>`,这里只给一个入口,宿主接上自己的编辑器句柄即可:\n * `onSearch={() => handle.current?.openFind()}`。\n *\n * 条子归编辑器渲染(`findBar` 开)时才接;`findBar={false}` 的宿主自己摆条子,\n * 这个入口点了也不会弹东西。只读态照样可查,所以不随 `editable` 灰显。\n */\n onSearch?: () => void;\n /** 条子当前是否开着(驱动按钮的 aria-pressed / 高亮)。不传恒为未激活。 */\n searchActive?: boolean;\n /** 追加到 More 菜单末尾的自定义项。 */\n extraToolbarItems?: ExtraToolbarItem[];\n className?: string;\n}\n\nexport type { ImportMenuItem };\n\n/**\n * 单个工具栏按钮:激活态高亮,disabled 时灰显。\n *\n * forwardRef + 透传其余属性,是为了让它能当 Radix 的触发器(`<LinkPopover>` 的 `asChild`\n * 要挂 ref,并把 `aria-expanded` / `data-state` 传下来)。\n */\nconst ToolbarButton = forwardRef<\n HTMLButtonElement,\n {\n title: string;\n active?: boolean;\n disabled?: boolean;\n busy?: boolean;\n onClick?: () => void;\n children: ReactNode;\n } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title' | 'onClick' | 'children'>\n>(function ToolbarButton(\n { title, active, disabled, busy, onClick, children, className, ...rest },\n ref,\n) {\n return (\n <button\n {...rest}\n ref={ref}\n type=\"button\"\n title={title}\n aria-label={title}\n aria-pressed={active}\n aria-busy={busy}\n disabled={disabled}\n className={`${styles.btn} ${active ? styles.btnActive : ''}${className ? ` ${className}` : ''}`}\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\nconst TABLE_PICKER_COLS = 10;\nconst TABLE_PICKER_ROWS = 8;\n\n/**\n * More 菜单里的「插入表格」:二级面板用网格悬停选行列,点击插入。\n * 保持 Popover(不夺编辑器焦点),与 MenuItem 一致。\n */\nfunction TableInsertItem({\n disabled,\n labels,\n onInsert,\n}: {\n disabled?: boolean;\n labels: Pick<ToolbarLabels, 'tableInsert' | 'tableSizeSelected'>;\n onInsert: (rows: number, cols: number) => void;\n}) {\n const closeMenu = useContext(MenuCloseCtx);\n const [open, setOpen] = useState(false);\n const [hover, setHover] = useState({ cols: 0, rows: 0 });\n\n const resetHover = useCallback(() => setHover({ cols: 0, rows: 0 }), []);\n\n return (\n <Popover.Root\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) resetHover();\n }}\n >\n <Popover.Trigger asChild>\n <button\n type=\"button\"\n disabled={disabled}\n className={`${styles.menuItem} ${open ? styles.menuItemSelected : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>⊞</span>\n {labels.tableInsert}\n </span>\n <ChevronDownIcon size={12} className={styles.tableInsertCaret} />\n </button>\n </Popover.Trigger>\n <Popover.Portal>\n <Popover.Content\n className={styles.tableSizePicker}\n side=\"right\"\n align=\"start\"\n sideOffset={6}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <div\n className={styles.tableSizeGrid}\n style={{\n gridTemplateColumns: `repeat(${TABLE_PICKER_COLS}, 1fr)`,\n }}\n onMouseLeave={resetHover}\n >\n {Array.from({ length: TABLE_PICKER_ROWS * TABLE_PICKER_COLS }, (_, i) => {\n const col = (i % TABLE_PICKER_COLS) + 1;\n const row = Math.floor(i / TABLE_PICKER_COLS) + 1;\n const active = hover.cols > 0 && col <= hover.cols && row <= hover.rows;\n return (\n <button\n key={i}\n type=\"button\"\n aria-label={labels.tableSizeSelected(col, row)}\n className={`${styles.tableSizeCell} ${active ? styles.tableSizeCellActive : ''}`}\n onMouseDown={(e) => e.preventDefault()}\n onMouseEnter={() => setHover({ cols: col, rows: row })}\n onClick={() => {\n onInsert(row, col);\n setOpen(false);\n resetHover();\n closeMenu();\n }}\n />\n );\n })}\n </div>\n <div className={styles.tableSizeLabel}>\n {hover.cols > 0\n ? labels.tableSizeSelected(hover.cols, hover.rows)\n : labels.tableInsert}\n </div>\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\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 onImportDocument,\n importAccept,\n importMenuItems,\n showImport = true,\n labels,\n onSearch,\n searchActive = false,\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 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 // ── 图片:选图 → 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, 'image');\n }\n };\n\n // ── 导入:.md 包内读文本插入;其余原样交给宿主 onImportDocument ──\n const importInputRef = useRef<HTMLInputElement>(null);\n const [importing, setImporting] = useState<ImportDocumentProgress | null>(\n null,\n );\n const importAbortRef = useRef<AbortController | null>(null);\n\n // 卸载(如切路由)中断在飞的导入,避免请求泄漏与卸载后 setState\n useEffect(() => () => importAbortRef.current?.abort(), []);\n\n const handleImportChange = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (!file) return;\n\n if (MD_FILE_RE.test(file.name)) {\n try {\n insertMarkdown(editor, await file.text());\n } catch (err) {\n console.error('markdown import failed:', err);\n onError?.(err, 'markdown');\n }\n return;\n }\n\n if (!onImportDocument) {\n onError?.(new Error(`unsupported file: ${file.name}`), 'import');\n return;\n }\n\n const ctrl = new AbortController();\n importAbortRef.current = ctrl;\n setImporting({ phase: 'upload', ratio: 0 });\n const labelOf = (p: ImportDocumentProgress) =>\n p.phase === 'convert'\n ? t.importDocumentConverting\n : t.importDocumentUploading(Math.round((p.ratio ?? 0) * 100));\n editor.commands.insertImportPlaceholder(labelOf({ phase: 'upload', ratio: 0 }));\n try {\n const raw = await onImportDocument(file, {\n signal: ctrl.signal,\n onProgress: (p) => {\n if (ctrl.signal.aborted) return;\n setImporting(p);\n editor.commands.updateImportPlaceholder(labelOf(p));\n },\n });\n editor.commands.removeImportPlaceholder();\n const md = typeof raw === 'string' ? raw : raw.markdown;\n const sources = typeof raw === 'string' ? [] : raw.sources ?? [];\n insertMarkdown(editor, md, sources);\n } catch (err) {\n editor.commands.removeImportPlaceholder();\n // 卸载 abort 不算错误\n if (!ctrl.signal.aborted) {\n console.error('document import failed:', err);\n onError?.(err, 'import');\n }\n } finally {\n if (importAbortRef.current === ctrl) importAbortRef.current = null;\n setImporting(null);\n }\n };\n\n const importItems = resolveImportMenuItems({\n labels: t,\n onImportDocument,\n importAccept,\n importMenuItems,\n });\n\n const pickImport = (accept: string) => {\n const input = importInputRef.current;\n if (!input) return;\n input.accept = accept;\n input.value = '';\n input.click();\n };\n\n // 进度写在光标占位上;按钮只区分空闲 / 忙碌。\n const importTitle = importing ? t.importDocumentBusy : t.importDocumentHint;\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 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 [mathEdit, setMathEdit] = useState<{\n kind: MathKind;\n mode: 'insert' | 'edit';\n pos?: number;\n latex: string;\n isNew?: boolean;\n } | null>(null);\n\n useEffect(() => subscribeMathClick((payload) => {\n setMathEdit({\n kind: payload.kind,\n mode: 'edit',\n pos: payload.pos,\n latex: payload.latex,\n });\n }), []);\n\n const openInsertMath = (kind: MathKind) => {\n const { from, to } = editor.state.selection;\n const selected =\n from === to ? '' : editor.state.doc.textBetween(from, to, ' ');\n const type = kind === 'inline' ? 'inlineMath' : 'blockMath';\n const searchFrom = from;\n chain().insertContent({ type, attrs: { latex: selected } }).run();\n let pos: number | null = null;\n editor.state.doc.nodesBetween(\n searchFrom,\n editor.state.doc.content.size,\n (node, nodePos) => {\n if (pos != null) return false;\n if (\n node.type.name === type &&\n String(node.attrs.latex ?? '') === selected\n ) {\n pos = nodePos;\n return false;\n }\n },\n );\n if (pos == null) {\n setMathEdit({ kind, mode: 'insert', latex: selected, isNew: true });\n return;\n }\n setMathEdit({\n kind,\n mode: 'edit',\n pos,\n latex: selected,\n isNew: true,\n });\n };\n\n const applyMath = (latex: string) => {\n if (!mathEdit) return;\n const { kind, mode, pos } = mathEdit;\n setMathEdit(null);\n if (mode === 'edit' && pos != null) {\n if (kind === 'inline') {\n chain().updateInlineMath({ latex, pos }).run();\n } else {\n chain().updateBlockMath({ latex, pos }).run();\n }\n return;\n }\n if (kind === 'inline') {\n chain().insertContent({ type: 'inlineMath', attrs: { latex } }).run();\n } else {\n chain().insertContent({ type: 'blockMath', attrs: { latex } }).run();\n }\n };\n\n const cancelMath = () => {\n if (!mathEdit) return;\n const { isNew, pos } = mathEdit;\n if (isNew && pos != null) {\n const node = editor.state.doc.nodeAt(pos);\n if (\n node &&\n (node.type.name === 'inlineMath' || node.type.name === 'blockMath')\n ) {\n editor\n .chain()\n .focus()\n .deleteRange({ from: pos, to: pos + node.nodeSize })\n .run();\n }\n }\n setMathEdit(null);\n };\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 光标在链接里打开时预填它的 href(旧实现是 window.prompt,在链接里点一下就删)。 */}\n <LinkPopover\n editor={editor}\n labels={{\n field: t.linkPrompt,\n apply: t.linkApply,\n open: t.linkOpen,\n remove: t.linkRemove,\n invalid: t.linkInvalid,\n }}\n trigger={\n <ToolbarButton title={t.link} active={state.link}>\n <LinkIcon />\n </ToolbarButton>\n }\n />\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 {showImport ? (\n <MenuPopover\n trigger={\n <button\n type=\"button\"\n className={styles.styleTrigger}\n title={importTitle}\n aria-label={importTitle}\n aria-busy={!!importing}\n disabled={!!importing}\n onMouseDown={(e) => e.preventDefault()}\n >\n <span className={styles.styleTriggerLabel}>\n {t.importDocument}\n </span>\n <ChevronDownIcon\n size={12}\n className={styles.styleTriggerCaret}\n />\n </button>\n }\n >\n {importItems.map((item) => (\n <MenuItem\n key={item.key}\n onSelect={() => pickImport(item.accept)}\n >\n {item.label}\n </MenuItem>\n ))}\n </MenuPopover>\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 {/* 查找替换入口:条子归编辑器,这里只开一道门。宿主接 onSearch 时才出现。\n 位置在 More 左侧——More 是「其余都以它收口」的兜底菜单,惯例留在最右;\n 而且行内本来就排满,谁在最后谁就先被挤到下一行。 */}\n {onSearch ? (\n <ToolbarButton\n title={t.search}\n active={searchActive}\n onClick={onSearch}\n >\n <SearchIcon />\n </ToolbarButton>\n ) : null}\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={() => openInsertMath('inline')}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>√x</span>\n {t.inlineMath}\n </span>\n </MenuItem>\n <MenuItem onSelect={() => openInsertMath('block')}>\n <span className={styles.styleItem}>\n <span className={styles.styleIcon}>∑</span>\n {t.blockMath}\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 <TableInsertItem\n disabled={state.inTable}\n labels={t}\n onInsert={(rows, cols) =>\n chain()\n .insertTable({ rows, cols, withHeaderRow: true })\n .run()\n }\n />\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 {/* 导入的隐藏文件选择器:accept 由下拉选项写入 */}\n {showImport ? (\n <input\n ref={importInputRef}\n type=\"file\"\n hidden\n onChange={handleImportChange}\n />\n ) : null}\n\n {mathEdit ? (\n <MathEditorPopover\n editor={editor}\n kind={mathEdit.kind}\n mode={mathEdit.mode}\n pos={mathEdit.pos}\n latex={mathEdit.latex}\n isNew={mathEdit.isNew}\n newLabel={\n mathEdit.kind === 'inline' ? t.mathNewInline : t.mathNewBlock\n }\n placeholder={t.mathPlaceholder}\n doneLabel={t.mathDone}\n onConfirm={applyMath}\n onCancel={cancelMath}\n />\n ) : null}\n\n {/* 表格悬停手柄(行左缘 ⋮ / 表格上方 ⋯)+ 它的操作菜单;\n 原来那套「表内右键出菜单」只剩多格选区的批量增删,由这个组件自己接管 */}\n <TableHandles editor={editor} labels={t} />\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","'use client';\n\nimport * as Popover from '@radix-ui/react-popover';\nimport type { ReactNode } from 'react';\nimport styles from '../styles/comment.module.css';\n\nexport interface CommentPopoverProps {\n open: boolean;\n onOpenChange?: (open: boolean) => void;\n /** 被点击的 mark 元素(from onCommentClick 的 anchorEl)。 */\n anchorEl: HTMLElement | null;\n children: ReactNode;\n side?: 'top' | 'bottom' | 'left' | 'right';\n align?: 'start' | 'center' | 'end';\n sideOffset?: number;\n}\n\n/**\n * 评论浮层(Radix)。库只负责锚定与外观,内容由宿主通过 children 提供\n * (典型:评论正文 + Resolve/Dismiss/Reopen 操作)。\n * 锚点是点击 mark 的动态元素:渲染一个 fixed 1x1 span 挂在 anchorEl 的\n * getBoundingClientRect 位置,Radix 以它为锚。\n */\nexport function CommentPopover({\n open,\n onOpenChange,\n anchorEl,\n children,\n side = 'top',\n align = 'start',\n sideOffset = 6,\n}: CommentPopoverProps) {\n const rect = open && anchorEl ? anchorEl.getBoundingClientRect() : null;\n return (\n <Popover.Root open={open} onOpenChange={onOpenChange}>\n {rect && (\n <Popover.Anchor asChild>\n <span\n className={styles.popoverAnchor}\n style={{ left: rect.left, top: rect.top }}\n />\n </Popover.Anchor>\n )}\n <Popover.Portal>\n <Popover.Content\n className={styles.popoverContent}\n side={side}\n align={align}\n sideOffset={sideOffset}\n onOpenAutoFocus={(e) => e.preventDefault()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n {children}\n </Popover.Content>\n </Popover.Portal>\n </Popover.Root>\n );\n}\n","import type { Editor } from '@tiptap/react';\nimport {\n mapCommentAnchors,\n type CommentAnchorStatus,\n type CommentSegment,\n} from './commentAnchor/commentMapper';\n\n/**\n * 内容锚点 → 当前文档里的区间。\n *\n * 用途:宿主在提交一次「圈选改写」时记下选区的内容锚点(`prefix` / `exact` / `suffix`,\n * `blockHash` 可选),等 AI 改完、推送回来时再用它把那段区间找回来——**不能用位置**,\n * 因为编辑器在这期间可能整体重建过(保存、切卡、SWR 刷新都会重挂),位置活不过重建。\n *\n * 锚点类型直接复用评论锚定那套(`commentMapper`),匹配走同一条 fallback 链:\n * `blockHash` → 前后文 → `exact` → 前缀降级(前 20 字)。**这条链是会降级的**,所以:\n *\n * > 调用方必须自己比对返回的 `text` 是否仍等于提交时那一段。本函数只回答「在哪」,\n * > 不回答「还算不算同一段」——后者决定了是原地回填还是弹冲突。\n */\nexport interface AnchorRange {\n /** doc 坐标 */\n from: number;\n to: number;\n /**\n * 区间当前的纯文本。**按匹配器的口径**给出:`commentMapper` 把区间内的 text 节点\n * 直接拼起来(块之间**没有分隔符**),所以这里也是 `textBetween(from, to)`(不传\n * blockSeparator)。调用方拿它跟「建锚点时用的那段文本」比对——两边必须同一口径,\n * 否则多块区间(表格 / 列表)会永远对不上。\n */\n text: string;\n status: CommentAnchorStatus;\n}\n\n/** 探针 id:借 commentMapper 的匹配链路,但我们只要区间,不要评论语义。 */\nconst PROBE_ID = '__anchor-range-probe__';\n\nexport function findRangeByAnchor(\n editor: Editor,\n anchor: CommentSegment | null | undefined,\n): AnchorRange | null {\n if (!anchor || !anchor.exact) return null;\n\n const [result] = mapCommentAnchors(editor.state.doc, [\n { commentId: PROBE_ID, segments: [anchor] },\n ]);\n const range = result?.ranges[0];\n if (!range) return null;\n\n return {\n from: range.from,\n to: range.to,\n // 无 blockSeparator:与 commentMapper 的 `collectText`(text 节点直接拼接)同一口径\n text: editor.state.doc.textBetween(range.from, range.to),\n status: result.status,\n };\n}\n","import '@tiptap/markdown';\nimport type { JSONContent } from '@tiptap/core';\nimport type { Editor } from '@tiptap/react';\n\n/**\n * 取区间对应的 markdown,并给出它在 `editor.getMarkdown()` 输出里的精确偏移。\n *\n * 为什么需要它:后端改卡走的是「在正文里逐字找到这段,替换」(`replace_in_text` +\n * `count=1`),所以发过去的那段必须是**存库正文的逐字子串**;调用方还要知道它在整篇里\n * 的偏移,才能从存库正文取前后文(`ref`)并界定「这次改了哪一段」。官方 OSS 只有整篇\n * `Editor.getMarkdown()`;官方 Pro 的 `getMarkdownRange` 只返回字符串、不给偏移,也不做\n * 块扩展。\n *\n * **默认扩块**(`expandToBlocks: true`):把区间扩展到与它相交的顶层块的首尾。一是序列化\n * 稳定(半句话里跨着加粗,片段序列化会在断口插入多余的 `**`),二是**只有块对齐时偏移才是\n * 算出来的,而不是猜出来的**。\n *\n * 偏移怎么来的:把 doc 的顶层块逐个序列化、用 `\\n\\n` 拼起来,等于整篇序列化(有测试钉住\n * 这条不变量),于是「前 i 块拼接的长度」就是第 i 块的起点偏移。这条不变量若在某篇文档上\n * 不成立,退回按内容在整篇里定位;定位不到或出现多处就返回 `null`——宁可让调用方知道\n * 拿不到偏移,也不要给一个错的。\n */\nexport interface MarkdownRange {\n /** 区间对应的 markdown 片段(扩块后)。 */\n markdown: string;\n /** 片段在 `editor.getMarkdown()` 输出里的起始偏移。 */\n from: number;\n /** 结束偏移(不含)。恒有 `to - from === markdown.length`。 */\n to: number;\n /**\n * **同一段**在 doc 坐标里的范围(扩块之后)。\n *\n * 宿主需要它把「读」和「写」对齐:`from/to` 是 markdown 偏移,而编辑器里的替换要按\n * doc 坐标做。少了它,宿主只能自己拿原始选区去定位,于是「用来定位的那段」和\n * 「按 markdown 偏移算出来的那段」不是同一段——把 A 段写进 B 区间,内容就会重复。\n */\n docFrom: number;\n docTo: number;\n}\n\nexport interface GetMarkdownForRangeOptions {\n /**\n * 是否把区间扩展到与它相交的顶层块(段落 / 表格 / 列表 / 图表 …)的首尾。\n * 默认 `true`:调用方要「存库正文的逐字子串 + 精确偏移」时应该保持默认。\n * 设 `false` 按原区间取,此时偏移依赖内容定位,可能返回 `null`。\n */\n expandToBlocks?: boolean;\n}\n\n/** 顶层块之间的分隔符——与 MarkdownManager 的 doc 级拼接一致。 */\nconst BLOCK_SEPARATOR = '\\n\\n';\n\ninterface TopLevelBlock {\n json: JSONContent;\n /** doc 坐标 */\n from: number;\n to: number;\n}\n\nfunction topLevelBlocks(editor: Editor): TopLevelBlock[] {\n const blocks: TopLevelBlock[] = [];\n editor.state.doc.forEach((node, offset) => {\n blocks.push({\n json: node.toJSON() as JSONContent,\n from: offset,\n to: offset + node.nodeSize,\n });\n });\n return blocks;\n}\n\nexport function getMarkdownForRange(\n editor: Editor,\n from: number,\n to: number,\n options: GetMarkdownForRangeOptions = {},\n): MarkdownRange | null {\n const manager = editor.markdown;\n if (!manager) return null;\n\n const size = editor.state.doc.content.size;\n let start = Math.max(0, Math.min(from, to));\n let end = Math.min(size, Math.max(from, to));\n if (start >= end) return null;\n\n const blocks = topLevelBlocks(editor);\n if (blocks.length === 0) return null;\n\n const expand = options.expandToBlocks !== false;\n\n // 与 [start, end) 相交的顶层块:第一个末端越过 start 的、到最后一个起点早于 end 的。\n // 单元格内、列表项内的选区都会扩到它们所属的顶层块(表格 / 列表整体)。\n let first = 0;\n let last = blocks.length - 1;\n if (expand) {\n first = blocks.findIndex((b) => b.to > start);\n if (first < 0) return null;\n for (let i = blocks.length - 1; i >= first; i -= 1) {\n if (blocks[i].from < end) {\n last = i;\n break;\n }\n }\n start = blocks[first].from;\n end = blocks[last].to;\n }\n\n const parts = blocks.map((b) => manager.serialize({ type: 'doc', content: [b.json] }));\n const full = editor.getMarkdown();\n\n if (expand && parts.join(BLOCK_SEPARATOR) === full) {\n const markdown = parts.slice(first, last + 1).join(BLOCK_SEPARATOR);\n // 空段落拼出来是空串:语义上等于「这段没内容」,交给调用方去判空不如这里就返回 null\n if (!markdown) return null;\n const at =\n first === 0\n ? 0\n : parts.slice(0, first).join(BLOCK_SEPARATOR).length + BLOCK_SEPARATOR.length;\n return { markdown, from: at, to: at + markdown.length, docFrom: start, docTo: end };\n }\n\n // 非块对齐,或整篇拼接与 getMarkdown() 不一致:只能按内容定位,且必须唯一\n const markdown = manager.serialize(\n editor.state.doc.cut(start, end).toJSON() as JSONContent,\n );\n if (!markdown) return null;\n const at = full.indexOf(markdown);\n if (at < 0 || full.indexOf(markdown, at + 1) >= 0) return null;\n return { markdown, from: at, to: at + markdown.length, docFrom: start, docTo: end };\n}\n","import { MarkdownManager } from '@tiptap/markdown';\nimport { CitationRef } from './CitationRef';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport { baseExtensions, pureChart, pureCodeBlock, pureImage } from './extensions';\n\n/**\n * 把一段正文规范成「编辑器读进来再吐出去」的那种写法。\n *\n * **为什么需要它**:编辑器加载 markdown 时要先解析成文档结构,而 markdown 里有些东西是\n * 排版装饰、解析时就丢了(表格列宽的空格、注释 JSON 里的空格、数值尾零 …)。所以\n * 「存库正文」和「编辑器序列化结果」常常**逐字不同**——这与用户改没改无关,加载那一刻就\n * 发生了。而后端改卡走的是「在正文里逐字找到这段再替换」,两边写法不一致就会搜不到。\n * 宿主在要动正文之前(例如圈选改写提交前)先用本函数比对/对齐一次即可。\n *\n * **已知会被规范化的结构**(都是排版层面,内容语义不变):\n *\n * | 结构 | 存库可能是 | 规范化后 |\n * |------|-----------|---------|\n * | GFM 表格 | `\\| 收入 \\| 100 \\|` | 按列内容宽度重排对齐(多/少空格) |\n * | 图表注释 JSON | `<!-- {\"chartType\": \"column\"} -->` | `<!-- {\"chartType\":\"column\"} -->`(去空格,键序按解析结果) |\n * | **图表区**的数值 | `132.0` | `132`(图表把表解析成 payload,数值走 number 再写回) |\n * | 纯空白的正文 | `\" \\n \"` | `\"\"` |\n *\n * 注意第三行**只作用于图表区**:普通 GFM 表格走 marked 的表格解析,单元格是文本,\n * `1,234.50` 这种写法会原样保留(有测试钉住)。\n *\n * 反过来,这些**不该**被改动,同样有测试钉住:标题/段落/加粗斜体/列表/引用、代码块、\n * 公式、图片、脚注 `[^n]`、图表仍是「注释 + 表」的作者形态(不会变成 ```tmr-chart 围栏)。\n *\n * 注意它**不使用** `enrichMarkdownCitations`:脚注的 `[^n]` 由 CitationRef 自带的\n * tokenizer 解析,url/title 只存在于节点属性里、不进 markdown,所以规范化不需要 sources。\n */\nexport function normalizeMarkdown(markdown: string): string {\n if (!markdown) return markdown;\n const manager = getManager();\n return manager.serialize(manager.parse(prepareChartMarkdown(markdown)));\n}\n\n// [perf] 与 renderReportHtml 同样的理由:每次 new MarkdownManager 都会让底层 marked 全局\n// 累积 tokenizer,parse 逐次变慢。这里只做「解析 → 序列化」,无状态,模块级复用即可。\nlet sharedManager: MarkdownManager | null = null;\n\nfunction getManager(): MarkdownManager {\n sharedManager ??= new MarkdownManager({\n extensions: [...baseExtensions, pureCodeBlock, pureImage, pureChart, CitationRef],\n });\n return sharedManager;\n}\n","import '@tiptap/markdown';\nimport type { Editor } from '@tiptap/react';\nimport { prepareChartMarkdown } from './chart/prepareChartMarkdown';\nimport { enrichMarkdownCitations, type SourceRef } from './citationUtils';\nimport { splitTopLevelBlocks, stripToPlainText } from './insertMarkdown';\n\nexport interface ReplaceRangeOptions {\n /** 脚注来源:把 `[^n]` enrich 成带 url/title 的 citation-ref(与 `insertMarkdown` 同一套)。 */\n sources?: SourceRef[];\n}\n\n/**\n * 用一段 markdown **替换**一个区间。给「后台回填」用——AI 在别处改完,把结果写回编辑器。\n *\n * 与 `insertMarkdown` 的三处刻意差异(都在注释里点明,改的时候别抹平):\n *\n * 1. **不抢焦点**。`insertMarkdown` 是「用户主动插入」,链式带了 `.focus()`;后台回填时\n * 用户可能正在别处打字,抢焦点等于打断他。所以这里直接调 `insertContentAt`。\n * 2. **按区间替换**,不是往光标处插(`insertContentAt` 收 `{from,to}` 时后者即替换)。\n * 3. **进 undo 历史**。`insertContentAt` 本身是一个 transaction,撤销一步就回去;\n * 与评论锚定的 `addToHistory: false` 相反——正文改动必须能撤。\n *\n * 解析失败(AI 的脏输出过不了 schema:嵌套 bold、块级图进 listItem …)时按块降级,\n * 与 `insertMarkdown` 同一套策略。注意降级路径是**逐块多次 transaction**,撤销要多按几下;\n * 只在整段失败时才走。\n *\n * @returns 是否改动了文档。空 markdown 返回 `false`(不静默删掉用户的内容)。\n */\nexport function replaceRangeWithMarkdown(\n editor: Editor,\n range: { from: number; to: number },\n markdown: string,\n options: ReplaceRangeOptions = {},\n): boolean {\n const prepared = prepareChartMarkdown(\n enrichMarkdownCitations(markdown ?? '', options.sources ?? []),\n );\n if (!prepared.trim()) return false;\n\n let from = Math.max(0, Math.min(range.from, range.to));\n let to = Math.max(range.from, range.to);\n if (from === to) return false;\n\n // ① 整段替换:一个 transaction,撤销一步到位\n if (tryInsertMarkdownAt(editor, from, to, prepared)) return true;\n\n // ② 降级:逐块替换。块插完要往后挪插入点,否则每块都往同一个区间插、只剩最后一块\n for (const block of splitTopLevelBlocks(prepared)) {\n const before = editor.state.doc.content.size;\n const changed =\n tryInsertMarkdownAt(editor, from, to, block) ||\n insertPlainParagraphAt(editor, from, to, stripToPlainText(block));\n if (!changed) continue;\n // 插入内容的 doc 尺寸 = 文档增量 + 被替换掉的宽度\n const inserted = editor.state.doc.content.size - before + (to - from);\n from += inserted;\n to = from;\n }\n return true;\n}\n\n/** 注意:不带 `.focus()`——后台回填不能抢用户的焦点。 */\nfunction tryInsertMarkdownAt(\n editor: Editor,\n from: number,\n to: number,\n markdown: string,\n): boolean {\n try {\n return editor\n .chain()\n .insertContentAt({ from, to }, markdown, { contentType: 'markdown' })\n .run();\n } catch {\n return false;\n }\n}\n\nfunction insertPlainParagraphAt(\n editor: Editor,\n from: number,\n to: number,\n text: string,\n): boolean {\n try {\n return editor\n .chain()\n .insertContentAt(\n { from, to },\n { type: 'paragraph', content: text ? [{ type: 'text', text }] : [] },\n )\n .run();\n } catch {\n return false;\n }\n}\n","import type { Editor, Range } from '@tiptap/core';\nimport { prepareChartMarkdown } from '../chart/prepareChartMarkdown';\nimport { insertMarkdown } from '../insertMarkdown';\n\n/**\n * 斜杠命令项插入 markdown 的共享原语:同一条 chain 内先删触发词再插内容,\n * 撤销是一步。整段过不了 schema 时降级为「按块重试 + 剥标记当段落」\n * (复用 insertMarkdown 的降级路径)——那条路径里删除已单独成事务,\n * 撤销会是多步,但注册表项是受控 markdown,正常不会走到。\n */\nexport function insertSlashMarkdown(\n editor: Editor,\n range: Range,\n markdown: string,\n): void {\n const prepared = prepareChartMarkdown(markdown);\n if (!prepared) return;\n try {\n const ok = editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent(prepared, { contentType: 'markdown' })\n .run();\n if (ok) return;\n } catch {\n // 整段过不了 schema:走降级\n }\n editor.chain().focus().deleteRange(range).run();\n insertMarkdown(editor, prepared);\n}\n"],"names":["m","r","e","active","b","counter","toggle","styles","Node","item","SlashMenuPopup","header","Fragment","group","MD_FILE_RE","f","input","setActive","readonly","folded","pre","_a","MarkdownWysiwygEditor","a","gutter","apply","row","node","pos","menu","field","ToolbarButton","bar","list","markdown","at"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAYO,SAAS,gBAAgB,EAAE,MAAM,aAA4B;AAClE,QAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,EAAE;AAC3C,QAAM,MAAO,KAAK,MAAM,OAAyB;AACjD,QAAM,QAAS,KAAK,MAAM,SAA2B;AACrD,QAAM,iBAAiB,UAAU,QAAQ;AAIzC,QAAM,OACJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,cAAY;AAAA,MACX,GAAI,MAAM,EAAE,YAAY,IAAA,IAAQ,CAAA;AAAA,MAChC,GAAI,QAAQ,EAAE,cAAc,MAAA,IAAU,CAAA;AAAA,MAEtC,UAAA,CAAC,kBAAkB,MAClB;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM;AAAA,UACN;AAAA,UACA,QAAO;AAAA,UACP,KAAI;AAAA,UAEH,UAAA;AAAA,QAAA;AAAA,MAAA,IAGH;AAAA,IAAA;AAAA,EAAA;AAKN,QAAM,UAAU,iBACZ,eAAe;AAAA,IACb;AAAA,IACA,OAAO,EAAE,OAAO,KAAK,OAAO,SAAS,KAAA;AAAA,IACrC,YAAY;AAAA,EAAA,CACb,IACD;AAEJ,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAG;AAAA,MACH,qBAAkB;AAAA,MAClB,OAAO,EAAE,SAAS,SAAA;AAAA,MAEjB,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AC5CO,SAAS,kBACd,UAA+C,IAC/C;AACA,SAAO,YAAY,OAA+B;AAAA,IAChD,aAAa;;AACX,aAAO;AAAA,QACL,gBAAgB,CAAA;AAAA,QAChB,IAAG,UAAK,WAAL;AAAA,QACH,gBAAgB,QAAQ;AAAA,MAAA;AAAA,IAE5B;AAAA,IACA,cAAc;AACZ,aAAO,sBAAsB,eAAe;AAAA,IAC9C;AAAA,EAAA,CACD,EAAE,UAAU;AAAA,IACX,gBAAgB,QAAQ;AAAA,EAAA,CACzB;AACH;ACHO,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAsB5B,MAAM,yBAAyB,IAAI;AAAA,EACxC;AACF;AAGO,SAAS,wBACd,OACA,UACO;AACP,QAAM,QAAQ,CAAC,aAAiC;AAC9C,UAAM,WAAqB,CAAA;AAC3B,aAAS,QAAQ,CAAC,UAAU;AAC1B,UAAI,MAAM,UAAU,MAAM,MAAM,KAAK,CAACA,OAAMA,GAAE,SAAS,QAAQ,GAAG;AAChE,iBAAS;AAAA,UACP,MAAM,KAAK,MAAM,MAAM,OAAO,CAACA,OAAMA,GAAE,SAAS,QAAQ,CAAC;AAAA,QAAA;AAAA,MAE7D,WAAW,MAAM,QAAQ,OAAO,GAAG;AACjC,iBAAS,KAAK,MAAM,KAAK,MAAM,MAAM,OAAO,CAAC,CAAC;AAAA,MAChD,OAAO;AACL,iBAAS,KAAK,KAAK;AAAA,MACrB;AAAA,IACF,CAAC;AACD,WAAO,SAAS,UAAU,QAAQ;AAAA,EACpC;AACA,SAAO,IAAI,MAAM,MAAM,MAAM,OAAO,GAAG,MAAM,WAAW,MAAM,OAAO;AACvE;AAEA,SAAS,qBAAqB,OAAc,UAA6B;AACvE,MAAI,QAAQ;AACZ,QAAM,QAAQ,YAAY,CAAC,SAAS;AAClC,QAAI,KAAK,UAAU,KAAK,MAAM,KAAK,CAACA,OAAMA,GAAE,SAAS,QAAQ,GAAG;AAC9D,cAAQ;AACR,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAGA,SAAS,YAAY,KAAoD;AACvE,QAAM,SAAgD,CAAA;AACtD,MAAI,QAAQ,CAAC,OAAO,WAAW;AAC7B,WAAO,KAAK,EAAE,OAAO,QAAQ,KAAK,SAAS,MAAM,UAAU;AAAA,EAC7D,CAAC;AACD,SAAO;AACT;AAGA,SAAS,qBACP,KACkD;AAClD,QAAM,2BAAW,IAAA;AACjB,MAAI,YAAY,CAAC,MAAM,QAAQ;AAC7B,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,eAAWA,MAAK,KAAK,OAAO;AAC1B,UAAIA,GAAE,KAAK,SAAS,gBAAiB;AACrC,YAAM,MAAOA,GAAE,MAAM,cAA2B,CAAA;AAChD,iBAAW,MAAM,KAAK;AACpB,cAAM,MAAM,KAAK,IAAI,EAAE,KAAK,CAAA;AAC5B,YAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,UAAU;AAC/C,aAAK,IAAI,IAAI,GAAG;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAEA,SAAS,qBACP,QACA,OACA,KACS;AACT,SAAO,OAAO,KAAK,CAACC,OAAMA,GAAE,OAAO,OAAOA,GAAE,KAAK,KAAK;AACxD;AAEA,SAAS,UACP,YACA,MACA,UACa;AACb,QAAM,KAAK,SAAS,cAAc,MAAM;AACxC,KAAG,YAAY;AACf,KAAG,aAAa,oBAAoB,WAAW,KAAK,GAAG,CAAC;AACxD,KAAG,cAAc,OAAO,WAAW,MAAM;AACzC,KAAG,QAAQ,GAAG,WAAW,MAAM;AAE/B,KAAG,iBAAiB,aAAa,CAACC,OAAM;AACtC,IAAAA,GAAE,eAAA;AACF,IAAAA,GAAE,gBAAA;AAAA,EACJ,CAAC;AACD,KAAG,iBAAiB,SAAS,CAACA,OAAM;AAClC,IAAAA,GAAE,eAAA;AACF,IAAAA,GAAE,gBAAA;AACF,SAAK;AAAA,MACH,KAAK,MAAM,GACR,QAAQ,qBAAqB,WAAW,CAAC,KAAK,IAAI,EAClD,QAAQ,qBAAqB;AAAA,QAC5B;AAAA,QACA,KAAK;AAAA,MAAA,CACyB;AAAA,IAAA;AAAA,EAEtC,CAAC;AACD,SAAO;AACT;AAEO,SAAS,oBACd,UAAsC,IACJ;AAClC,QAAM,aAAa,QAAQ,eAAe;AAC1C,QAAM,cAAc,QAAQ,gBAAgB;AAE5C,SAAO,IAAI,OAAiC;AAAA,IAC1C,KAAK;AAAA,IACL,OAAO;AAAA,MACL,MAAM,OAAO,EAAE,iBAAiB;MAChC,OAAO,CAAC,IAAI,UAAU;AACpB,cAAMC,UAAS,GAAG,QAAQ,mBAAmB;AAC7C,eAAOA,YAAW,SACd,EAAE,iBAAiBA,YACnB;AAAA,MACN;AAAA,IAAA;AAAA,IAEF,OAAO;AAAA,MACL,YAAY,OAAoB;;AAC9B,cAAM,OAAO,qBAAqB,MAAM,GAAG;AAC3C,YAAI,KAAK,SAAS,EAAG,QAAO,cAAc;AAE1C,cAAM,QAAsB,CAAA;AAC5B,cAAM,SAAS,YAAY,MAAM,GAAG;AAEpC,YAAI,YAAY;AACd,qBAAWC,MAAK,QAAQ;AACtB,kBAAM,aAAuB,CAAA;AAC7B,uBAAW,CAAC,IAAI,MAAM,KAAK,MAAM;AAC/B,kBAAI,qBAAqB,QAAQA,GAAE,OAAOA,GAAE,GAAG,GAAG;AAChD,2BAAW,KAAK,EAAE;AAAA,cACpB;AAAA,YACF;AACA,gBAAI,WAAW,SAAS,GAAG;AACzB,oBAAM;AAAA,gBACJ,WAAW;AAAA,kBACTA,GAAE;AAAA,kBACF,CAAC,SAAS,UAAU,YAAY,MAAMA,GAAE,KAAK;AAAA,kBAC7C,EAAE,MAAM,IAAI,KAAK,cAAcA,GAAE,KAAK,GAAA;AAAA,gBAAG;AAAA,cAC3C;AAAA,YAEJ;AAAA,UACF;AAAA,QACF;AAEA,cAAM,aACJ,4BAAuB,SAAS,KAAK,MAArC,mBAAwC,oBAAmB;AAC7D,YAAI,UAAU;AACZ,gBAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,CAAA;AACrC,qBAAWH,MAAK,QAAQ;AACtB,kBAAM;AAAA,cACJ,WAAW,OAAOA,GAAE,MAAMA,GAAE,IAAI,EAAE,OAAO,qBAAA,CAAsB;AAAA,YAAA;AAAA,UAEnE;AACA,qBAAWG,MAAK,QAAQ;AACtB,gBAAI,qBAAqB,QAAQA,GAAE,OAAOA,GAAE,GAAG,GAAG;AAChD,oBAAM;AAAA,gBACJ,WAAW,KAAKA,GAAE,OAAOA,GAAE,KAAK;AAAA,kBAC9B,OAAO;AAAA,gBAAA,CACR;AAAA,cAAA;AAAA,YAEL;AAAA,UACF;AAAA,QACF;AAEA,eAAO,cAAc,OAAO,MAAM,KAAK,KAAK;AAAA,MAC9C;AAAA,MAEA,YAAY,MAAkB,KAAa,OAAmB;;AAE5D,YAAI,CAAC,YAAa,QAAO;AACzB,cAAM,SAAS,MAAM;AACrB,cAAM,MAAK,sCAAQ,YAAR;AAAA;AAAA,UACT;AAAA;AAEF,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,cAAc,GAAG,aAAa,kBAAkB,KAAK,IACxD,MAAM,GAAG,EACT,OAAO,OAAO;AACjB,YAAI,WAAW,WAAW,EAAG,QAAO;AACpC,aAAK;AAAA,UACH,KAAK,MAAM,GACR,QAAQ,qBAAqB,WAAW,CAAC,KAAK,IAAI,EAClD,QAAQ,oBAAoB;AAAA,YAC3B;AAAA,YACA,UAAU;AAAA,YACV;AAAA,UAAA,CAC6B;AAAA,QAAA;AAEnC,eAAO;AAAA,MACT;AAAA;AAAA;AAAA,MAIA,gBAAgB,OAAc,MAAkB;AAC9C,cAAM,WAAW,KAAK,MAAM,OAAO,MAAM;AACzC,YAAI,CAAC,YAAY,CAAC,qBAAqB,OAAO,QAAQ,EAAG,QAAO;AAChE,eAAO,wBAAwB,OAAO,QAAQ;AAAA,MAChD;AAAA,IAAA;AAAA,EACF,CACD;AACH;AAMO,SAAS,uBACd,UAAsC,IACtC;AACA,SAAO,UAAU,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,wBAAwB;AACtB,aAAO,CAAC,oBAAoB,OAAO,CAAC;AAAA,IACtC;AAAA,EAAA,CACD;AACH;AC9PO,SAAS,4BACd,QACA,UACM;AAEN,MAAI,CAAC,OAAO,WAAY;AACxB,QAAM,YACJ,SAAS,SAAS,IACd;AAAA,IACE;AAAA,MACE,OAAO,MAAM;AAAA,MACb,SAAS,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,WAAW,UAAU,EAAE,WAAW;AAAA,IAAA,EACtE,IAAI,CAACH,QAAO,EAAE,WAAWA,GAAE,WAAW,QAAQA,GAAE,SAAS;AAAA,EAAA,IAE7D,CAAA;AACN,QAAM,QAAQ,OAAO,MAAA,EAAQ,oBAAA;AAC7B,MAAI,UAAU,SAAS,EAAG,OAAM,oBAAoB,SAAS;AAC7D,QAAM,IAAA;AACR;AAGO,SAAS,kBAAkB,QAA0B;AAC1D,QAAM,MAAgB,CAAA;AACtB,SAAO,MAAM,IAAI,YAAY,CAAC,SAAS;AACrC,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,eAAWD,MAAK,KAAK,OAAO;AAC1B,UAAIA,GAAE,KAAK,SAAS,gBAAiB;AACrC,iBAAW,MAAOA,GAAE,MAAM,cAA2B,CAAA,GAAI;AACvD,YAAI,CAAC,IAAI,SAAS,EAAE,EAAG,KAAI,KAAK,EAAE;AAAA,MACpC;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAEO,SAAS,kBACd,QACA,WACgB;AAChB,QAAM,SAAyB,CAAA;AAC/B,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AAC1C,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,eAAWA,MAAK,KAAK,OAAO;AAC1B,UAAIA,GAAE,KAAK,SAAS,gBAAiB;AACrC,YAAM,MAAOA,GAAE,MAAM,cAA2B,CAAA;AAChD,UAAI,IAAI,SAAS,SAAS,GAAG;AAC3B,eAAO,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,UAAU;AAAA,MACpD;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAEA,SAAS,UAAU,QAAgB,WAAgC;AACjE,SAAO,KAAK;AAAA,IACV,OAAO,MAAM,GAAG,QAAQ,qBAAqB,SAAS;AAAA,EAAA;AAE1D;AAEA,SAAS,UAAU,QAA+B;;AAChD,WAAO,4BAAuB,SAAS,OAAO,KAAK,MAA5C,mBAA+C,oBAAmB;AAC3E;AAMO,SAAS,aAAa,QAAgB,WAA4B;;AACvE,QAAM,SAAS,kBAAkB,QAAQ,SAAS;AAClD,MAAI,OAAO,WAAW,GAAG;AACvB,cAAU,QAAQ,IAAI;AACtB,WAAO;AAAA,EACT;AACA,YAAU,QAAQ,SAAS;AAC3B,QAAM,SAAS,OAAO,KAAK,IAAI;AAAA,IAC7B,uCAAuC,IAAI,OAAO,SAAS,CAAC;AAAA,EAAA;AAE9D,yCAAQ,mBAAR,gCAAyB,EAAE,OAAO,UAAU,UAAU;AACtD,SAAO,MAAA,EAAQ,iBAAiB,OAAO,CAAC,EAAE,IAAI,EAAE,IAAA;AAChD,SAAO;AACT;AAGO,SAAS,YACd,QACA,MAAuB,QACR;AACf,QAAM,MAAM,kBAAkB,MAAM;AACpC,MAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,QAAMG,UAAS,UAAU,MAAM;AAC/B,QAAM,UAAUA,UAAS,IAAI,QAAQA,OAAM,IAAI;AAC/C,QAAM,UACJ,QAAQ,UACH,UAAU,KAAK,IAAI,UACnB,UAAU,IAAI,IAAI,UAAU,IAAI;AACvC,QAAM,SAAS,IAAI,OAAO;AAC1B,eAAa,QAAQ,MAAM;AAC3B,SAAO;AACT;AC/GO,MAAM,sBAAsB;AAW5B,SAAS,oBACd,OACS;AACT,SAAO,MAAM,eAAe,MAAM,YAAY;AAChD;AASO,SAAS,wBACd,QACS;;AACT,MAAI,CAAC,UAAU,OAAO,YAAa,QAAO;AAC1C,WACE,YAAO,qBAAP,mBAAyB,WAAW;AAAA,IAClC,CAAC,cAAc,UAAU,SAAS;AAAA,QAC/B;AAET;AASO,MAAM,mBAAmB;AAEhC,MAAM,cAAc;AAgBb,SAAS,eAAe,KAAuB;AACpD,MAAI;AACF,QAAA;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,cAAc,YAAY,KAAK,MAAM,OAAO,GAAG;AAClE,UAAA;AACA;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;ACnEA,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;AAIK,MAAM,aAAa,CAAC,MACzB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,uFAAA,CAAuF;AAAA,EAC/F,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EAAA,CACtB;AAIK,MAAM,gBAAgB,CAAC,MAC5B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,oDAAA,CAAoD;AAAA,EAC5D,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EAAA,CACrB;AAIK,MAAM,mBAAmB,CAAC,MAC/B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EACpB,oBAAC,QAAA,EAAK,GAAE,cAAA,CAAc;AAAA,EACtB,oBAAC,QAAA,EAAK,GAAE,2DAAA,CAA2D;AAAA,EAAA,CACrE;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,aAAa,CAAC,MACzB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EACxB,oBAAC,QAAA,EAAK,GAAE,4EAAA,CAA4E;AAAA,EAAA,CACtF;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;AAGK,MAAM,aAAa,CAAC,MACzB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,YAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,iBAAA,CAAiB;AAAA,EAAA,CAC3B;AAGK,MAAM,QAAQ,CAAC,MACpB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EACrB,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EAAA,CACvB;AAGK,MAAM,gBAAgB,CAAC,MAC5B,oBAAC,KAAA,EAAK,GAAG,GACP,UAAA,oBAAC,QAAA,EAAK,GAAE,iBAAA,CAAiB,EAAA,CAC3B;AAGK,MAAM,cAAc,CAAC,MAC1B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,uBAAA,CAAuB;AAAA,EAC/B,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,eAAA,CAAe;AAAA,EACvB,oBAAC,QAAA,EAAK,GAAE,0BAAA,CAA0B;AAAA,EAClC,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,MAAK,OAAM,KAAI,QAAO,KAAI,IAAG,IAAA,CAAI;AAAA,EAAA,CACjD;AAGK,MAAM,iBAAiB,CAAC,MAC7B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,uCAAA,CAAuC;AAAA,EAC/C,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,uBAAA,CAAuB;AAAA,EAC/B,oBAAC,QAAA,EAAK,GAAE,uCAAA,CAAuC;AAAA,EAC/C,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,sBAAA,CAAsB;AAAA,EAC9B,oBAAC,QAAA,EAAK,GAAE,eAAA,CAAe;AAAA,EACvB,oBAAC,QAAA,EAAK,GAAE,0BAAA,CAA0B;AAAA,EAClC,oBAAC,QAAA,EAAK,GAAE,KAAI,GAAE,MAAK,OAAM,KAAI,QAAO,KAAI,IAAG,IAAA,CAAI;AAAA,EAAA,CACjD;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;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,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,UAAA,CAAU;AAAA,EAClB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EAAA,CACvB;AAGK,MAAM,WAAW,CAAC,MACvB,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,OAAM,MAAK,QAAO,MAAK,GAAE,KAAI,GAAE,KAAI,IAAG,KAAI,IAAG,KAAI;AAAA,EACvD,oBAAC,QAAA,EAAK,GAAE,0DAAA,CAA0D;AAAA,EAAA,CACpE;AAGK,MAAM,qBAAqB,CAAC,MACjC,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,GAAE,gBAAA,CAAgB;AAAA,EACxB,oBAAC,QAAA,EAAK,GAAE,eAAA,CAAe;AAAA,EAAA,CACzB;AAGK,MAAM,eAAe,CAAC,MAC3B,qBAAC,KAAA,EAAK,GAAG,GACP,UAAA;AAAA,EAAA,oBAAC,QAAA,EAAK,OAAM,MAAK,QAAO,MAAK,GAAE,KAAI,GAAE,KAAI,IAAG,IAAA,CAAI;AAAA,EAChD,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EACnB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EACpB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EACpB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EACpB,oBAAC,QAAA,EAAK,GAAE,YAAA,CAAY;AAAA,EACpB,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EACrB,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EACrB,oBAAC,QAAA,EAAK,GAAE,aAAA,CAAa;AAAA,EACrB,oBAAC,QAAA,EAAK,GAAE,WAAA,CAAW;AAAA,EAAA,CACrB;AChMK,MAAM,qBAAkC;AAAA,EAC7C,UAAU,CAAC,WAAW,UAAU,GAAG,SAAS,IAAI,QAAQ,CAAC;AAAA,EACzD,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,WAAW;AACb;AAEO,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,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,OAAO;AAAA,EACP,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,yBAAyB,CAAC,YAAY,aAAa,OAAO;AAAA,EAC1D,0BAA0B;AAAA,EAC1B,sBAAsB;AAAA,EACtB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,IAAI;AAAA,EACJ,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,mBAAmB,CAAC,MAAM,SAAS,GAAG,IAAI,MAAM,IAAI;AAAA,EACpD,sBAAsB;AAAA,EACtB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,uBAAuB,CAAC,MAAM,OAAO,CAAC;AAAA,EACtC,sBAAsB,CAAC,MAAM,OAAO,CAAC;AAAA,EACrC,oBAAoB,CAAC,MAAM,UAAU,CAAC;AAAA,EACtC,oBAAoB,CAAC,MAAM,OAAO,CAAC;AAAA,EACnC,mBAAmB,CAAC,MAAM,OAAO,CAAC;AAAA,EAClC,iBAAiB,CAAC,MAAM,UAAU,CAAC;AAAA,EACnC,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,cAAc;AAChB;AAEO,MAAM,yBAA0C;AAAA,EACrD,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,cAAc,CAAC,UAAU,WAAW,KAAK;AAAA,EACzC,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,WAAW;AACb;AAoCO,MAAM,wBAAwC;AAAA,EACnD,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,cAAc,CAAC,UAAU,WAAW,KAAK;AAAA,EACzC,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,aAAa;AACf;AAaO,MAAM,2BAA8C;AAAA,EACzD,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,SAAS;AACX;AAOO,MAAM,4BAAgD;AAAA,EAC3D,MAAM;AAAA,EACN,OAAO;AACT;AAQO,MAAM,mBAA8B;AAAA,EACzC,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AACZ;AAaO,MAAM,yBAA0C;AAAA,EACrD,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AACZ;AAYO,MAAM,uBAAsC;AAAA,EACjD,MAAM;AAAA,EACN,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AACf;AAuBO,MAAM,oBAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,eAAe;AAAA,EACf,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS,CAAC,SAAS,UAAU,GAAG,OAAO,MAAM,KAAK;AAAA,EAClD,cAAc;AAAA,EACd,UAAU;AACZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7WA,IAAI,yBAAyB;AAC7B,SAAS,2BAAiC;AACxC,MAAI,uBAAwB;AAC5B,2BAAyB;AACzB,UAAQ;AAAA,IACN;AAAA,EAAA;AAIJ;AAEO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAwB;AACtB,QAAM,IAAgB,EAAE,GAAG,mBAAmB,GAAG,OAAA;AACjD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,EAAE;AAIjD,QAAM,eAAe,wBAAwB,MAAM;AACnD,YAAU,MAAM;AACd,QAAI,CAAC,aAAc,0BAAA;AAAA,EACrB,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,QAAQ,eAAe;AAAA,IAC3B;AAAA,IACA,UAAU,CAAC,EAAE,QAAQ,eAAe;AAClC,YAAM,SAAS,wBAAwB,SAAS,SAAS,KAAK;AAC9D,aAAO;AAAA,QACL,eAAc,iCAAQ,iBAAgB;AAAA,QACtC,QAAO,iCAAQ,QAAQ,WAAU;AAAA,QACjC,gBAAe,iCAAQ,kBAAiB;AAAA,QACxC,YAAW,iCAAQ,cAAa;AAAA,QAChC,WAAU,iCAAQ,aAAY;AAAA,MAAA;AAAA,IAElC;AAAA,EAAA,CACD;AAGD,QAAM,aAAa;AAAA,IACjB,CAAC,QAAoB;AACnB,UAAI,CAAC,aAAc;AACnB,qBAAe,GAAG;AAAA,IACpB;AAAA,IACA,CAAC,YAAY;AAAA,EAAA;AAKf,QAAM,iBAAiB,OAAsB,IAAI;AACjD,QAAM,WAAW;AAAA,IACf,CAAC,UAAkB;AACjB,qBAAe,UAAU;AACzB,iBAAW,MAAM,OAAO,SAAS,cAAc,KAAK,CAAC;AAAA,IACvD;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EAAA;AAErB,QAAM,YAAY,YAAY,MAAM;AAClC,QAAI,eAAe,YAAY,KAAM,UAAS,IAAI;AAAA,EACpD,GAAG,CAAC,UAAU,IAAI,CAAC;AAEnB,YAAU,MAAM;AACd,QAAI,eAAe,YAAY,KAAM;AACrC,UAAM,QAAQ,WAAW,MAAM,SAAS,IAAI,GAAG,gBAAgB;AAC/D,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,YAAU,MAAM;AACd,eAAW,MAAM,OAAO,SAAS,eAAe,WAAW,CAAC;AAAA,EAC9D,GAAG,CAAC,QAAQ,aAAa,UAAU,CAAC;AAGpC,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,CAAC,OAAO,YAAa,YAAW,MAAM,OAAO,SAAS,aAAa;AAAA,IACzE;AAAA,EACF,GAAG,CAAC,QAAQ,UAAU,CAAC;AAGvB,QAAM,YAAY;AAAA,IAChB,CAAC,WAAuB;AACtB,gBAAA;AACA,iBAAW,MAAM;AAAA,IACnB;AAAA,IACA,CAAC,WAAW,UAAU;AAAA,EAAA;AAKxB,QAAM,iBAAiB;AAAA,IACrB,MACE,SAAS,MACT,MAAM,YACN,kBAAkB,MAAM;AAAA,MACtB,eAAe,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,IAAA,CACZ,MAAM;AAAA,IACT,CAAC,MAAM,MAAM,UAAU,MAAM,aAAa;AAAA,EAAA;AAK5C,QAAM,UACJ,MAAM,UAAU,KAAK,MAAM,iBAAiB,OACxC,IACA,MAAM,eAAe;AAC3B,QAAME,WAAU,EAAE,QAAQ,SAAS,MAAM,KAAK;AAE9C,QAAM,YAAY,CAACH,OAAuBA,GAAE,eAAA;AAE5C,QAAM,gBAAgB,CAACA,OAA4C;AACjE,QAAI,oBAAoBA,GAAE,WAAW,EAAG;AACxC,QAAIA,GAAE,QAAQ,SAAS;AACrB,MAAAA,GAAE,eAAA;AACF,gBAAU,MAAM;AACd,YAAIA,GAAE,SAAU,QAAO,SAAS,mBAAA;AAAA,YAC3B,QAAO,SAAS,eAAA;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,mBAAmB,CAACA,OAA4C;AACpE,QAAI,oBAAoBA,GAAE,WAAW,EAAG;AACxC,QAAIA,GAAE,QAAQ,SAAS;AACrB,MAAAA,GAAE,eAAA;AACF,gBAAU,MAAM,OAAO,SAAS,QAAA,CAAS;AAAA,IAC3C;AAAA,EACF;AAEA,QAAMI,UAAS,CAAC,KAAoC,UAAmB;AACrE,eAAW,MAAM;AACf,UAAI,QAAQ,gBAAiB,QAAO,SAAS,iBAAiB,KAAK;AAAA,UAC9D,QAAO,SAAS,aAAa,KAAK;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,aAAc,QAAO;AAE1B,QAAM,cAAc,CAAC,OACnB,GAAGC,SAAO,GAAG,IAAIA,SAAO,MAAM,GAAG,KAAK,IAAIA,SAAO,QAAQ,KAAK,EAAE;AAElE,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,YAAY,GAAGA,SAAO,GAAG,IAAI,SAAS,KAAKA,SAAO;AAAA,MAC7D;AAAA,MACA,iBAAc;AAAA,MACd,MAAK;AAAA,MACL,cAAY,EAAE;AAAA,MACd,WAAW,CAACL,OAAM;AAIhB,YAAI,oBAAoBA,GAAE,WAAW,EAAG;AACxC,YAAIA,GAAE,QAAQ,SAAU;AACxB,QAAAA,GAAE,eAAA;AACF,QAAAA,GAAE,gBAAA;AACF,gBAAA;AAAA,MACF;AAAA,MAEA,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAWK,SAAO,KACrB,UAAA;AAAA,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,OACtB,UAAA;AAAA,YAAA,oBAAC,YAAA,EAAW,MAAM,IAAI,WAAWA,SAAO,WAAW;AAAA,YACnD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,KAAK;AAAA,gBACL,WAAWA,SAAO;AAAA,gBAClB,mBAAgB;AAAA,gBAChB,OAAO;AAAA,gBACP,UAAU,CAACL,OAAM,QAAQA,GAAE,OAAO,KAAK;AAAA,gBACvC,WAAW;AAAA,gBACX,aAAa,EAAE;AAAA,gBACf,cAAY,EAAE;AAAA,gBACd,WAAS;AAAA,gBACT,YAAY;AAAA,cAAA;AAAA,YAAA;AAAA,YAEd;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW,GAAGK,SAAO,OAAO,GAAG,iBAAiB,IAAIA,SAAO,cAAc,KAAK,EAAE;AAAA,gBAChF,qBAAkB;AAAA,gBAClB,aAAU;AAAA,gBACV,OAAO,iBAAiB,EAAE,eAAe;AAAA,gBAExC,UAAA,iBAAiB,EAAE,eAAeF;AAAA,cAAA;AAAA,YAAA;AAAA,UACrC,GACF;AAAA,UACE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAW,YAAY,MAAM,aAAa;AAAA,cAC1C,oBAAiB;AAAA,cACjB,OAAO,EAAE;AAAA,cACT,cAAY,EAAE;AAAA,cACd,gBAAc,MAAM;AAAA,cACpB,aAAa;AAAA,cACb,SAAS,MAAMC,QAAO,iBAAiB,CAAC,MAAM,aAAa;AAAA,cAC5D,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAW,YAAY,MAAM,SAAS;AAAA,cACtC,oBAAiB;AAAA,cACjB,OAAO,EAAE;AAAA,cACT,cAAY,EAAE;AAAA,cACd,gBAAc,MAAM;AAAA,cACpB,aAAa;AAAA,cACb,SAAS,MAAMA,QAAO,aAAa,CAAC,MAAM,SAAS;AAAA,cACpD,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAIH,oBAAC,QAAA,EAAK,WAAWC,SAAO,OAAA,CAAQ;AAAA,UAChC,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAWA,SAAO;AAAA,gBAClB,oBAAiB;AAAA,gBACjB,OAAO,EAAE;AAAA,gBACT,cAAY,EAAE;AAAA,gBACd,UAAU,MAAM,UAAU;AAAA,gBAC1B,aAAa;AAAA,gBACb,SAAS,MAAM,UAAU,MAAM,OAAO,SAAS,oBAAoB;AAAA,gBAEnE,UAAA,oBAAC,eAAA,EAAc,MAAM,GAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,YAE3B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAWA,SAAO;AAAA,gBAClB,oBAAiB;AAAA,gBACjB,OAAO,EAAE;AAAA,gBACT,cAAY,EAAE;AAAA,gBACd,UAAU,MAAM,UAAU;AAAA,gBAC1B,aAAa;AAAA,gBACb,SAAS,MAAM,UAAU,MAAM,OAAO,SAAS,gBAAgB;AAAA,gBAE/D,UAAA,oBAAC,iBAAA,EAAgB,MAAM,GAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,YAE7B;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAWA,SAAO;AAAA,gBAClB,oBAAiB;AAAA,gBACjB,OAAO,EAAE;AAAA,gBACT,cAAY,EAAE;AAAA,gBACd,SAAS;AAAA,gBAET,UAAA,oBAAC,OAAA,EAAM,MAAM,GAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UACnB,EAAA,CACF;AAAA,QAAA,GACF;AAAA,QAEC,OAAO,aACN,qBAAC,OAAA,EAAI,WAAWA,SAAO,KACrB,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,OACtB,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWA,SAAO;AAAA,cAClB,mBAAgB;AAAA,cAChB,OAAO;AAAA,cACP,UAAU,CAACL,OAAM,eAAeA,GAAE,OAAO,KAAK;AAAA,cAC9C,WAAW;AAAA,cACX,aAAa,EAAE;AAAA,cACf,cAAY,EAAE;AAAA,cACd,YAAY;AAAA,YAAA;AAAA,UAAA,GAEhB;AAAA,UACA,oBAAC,QAAA,EAAK,WAAWK,SAAO,OAAA,CAAQ;AAAA,UAChC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAWA,SAAO;AAAA,cAClB,oBAAiB;AAAA,cACjB,OAAO,EAAE;AAAA,cACT,cAAY,EAAE;AAAA,cACd,UAAU,MAAM,UAAU;AAAA,cAC1B,aAAa;AAAA,cACb,SAAS,MAAM,UAAU,MAAM,OAAO,SAAS,SAAS;AAAA,cAExD,UAAA,oBAAC,aAAA,EAAY,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAEzB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAWA,SAAO;AAAA,cAClB,oBAAiB;AAAA,cACjB,OAAO,EAAE;AAAA,cACT,cAAY,EAAE;AAAA,cACd,UAAU,MAAM,UAAU;AAAA,cAC1B,aAAa;AAAA,cACb,SAAS,MAAM,UAAU,MAAM,OAAO,SAAS,YAAY;AAAA,cAE3D,UAAA,oBAAC,gBAAA,EAAe,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,QAC5B,EAAA,CACF,IAEA,oBAAC,OAAA,EAAI,WAAWA,SAAO,KACrB,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,UAAW,UAAA,EAAE,UAAS,EAAA,CAChD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;ACnWA,SAAS,mBAAmB,KAIV;AAChB,MAAI,QAAuB;AAC3B,MAAI,YAAY,CAAC,MAAM,QAAQ;AAC7B,QAAI,KAAK,KAAK,SAAS,qBAAqB;AAC1C,cAAQ;AACR,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,MAAM,oBAAoBC,OAAK,OAAO;AAAA,EAC3C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,WAAW;AAAA,EAEX,gBAAgB;AACd,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS;AAAA,QACT,WAAW,CAAC,OAAO,GAAG,aAAa,YAAY,KAAK;AAAA,QACpD,YAAY,CAAC,UACX,MAAM,QAAQ,EAAE,cAAc,MAAM,UAAU,CAAA;AAAA,MAAC;AAAA,IACnD;AAAA,EAEJ;AAAA,EAEA,YAAY;AACV,WAAO,CAAC,EAAE,KAAK,uCAAuC;AAAA,EACxD;AAAA,EAEA,WAAW,EAAE,MAAM,kBAAkB;AACnC,UAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,EAAE;AAC3C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,GAAG;AAAA,QACH,aAAa;AAAA,QACb,OAAO;AAAA,QACP,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,aAAa;AAAA,MAAA;AAAA,MAEf,CAAC,QAAQ,EAAE,OAAO,+BAA+B,eAAe,QAAQ;AAAA,MACxE,CAAC,QAAQ,EAAE,OAAO,+BAAA,GAAkC,KAAK;AAAA,IAAA;AAAA,EAE7D;AAAA,EAEA,iBAAiB;AACf,WAAO;AAAA,EACT;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL,yBACE,CAAC,UACD,CAAC,EAAE,MAAA,MACD,MAAA,EACG,MAAA,EACA,cAAc;AAAA,QACb,MAAM,KAAK;AAAA,QACX,OAAO,EAAE,MAAA;AAAA,MAAM,CAChB,EACA,QAAQ,CAAC,EAAE,SAAS;AACnB,WAAG,QAAQ,gBAAgB,KAAK;AAChC,WAAG,QAAQ,iBAAiB,IAAI;AAChC,eAAO;AAAA,MACT,CAAC,EACA,IAAA;AAAA,MACP,yBACE,CAAC,UACD,CAAC,EAAE,IAAI,UAAU,YAAY;AAC3B,cAAM,MAAM,mBAAmB,MAAM,GAAG;AACxC,YAAI,OAAO,KAAM,QAAO;AACxB,YAAI,UAAU;AACZ;AAAA,YACE,GACG,cAAc,KAAK,QAAW,EAAE,MAAA,CAAO,EACvC,QAAQ,gBAAgB,KAAK,EAC7B,QAAQ,iBAAiB,IAAI;AAAA,UAAA;AAAA,QAEpC;AACA,eAAO;AAAA,MACT;AAAA,MACF,yBACE,MACA,CAAC,EAAE,IAAI,UAAU,YAAY;AAC3B,cAAM,MAAM,mBAAmB,MAAM,GAAG;AACxC,YAAI,OAAO,KAAM,QAAO;AACxB,cAAM,OAAO,MAAM,IAAI,OAAO,GAAG;AACjC,YAAI,CAAC,KAAM,QAAO;AAClB,YAAI,UAAU;AACZ;AAAA,YACE,GACG,OAAO,KAAK,MAAM,KAAK,QAAQ,EAC/B,QAAQ,gBAAgB,KAAK,EAC7B,QAAQ,iBAAiB,IAAI;AAAA,UAAA;AAAA,QAEpC;AACA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,EAEN;AACF,CAAC;;;;;;;;;;;;;;;;;AC5GM,SAAS,4BACd,SAA0B,wBACT;AACjB,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,YAAY,MAAM,aAAa,MAAM;AAAA,MAC/C,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,aAAA,EAAe,IAAA;AAAA,MAC3D;AAAA,IAAA;AAAA,IAEF,GAAI,CAAC,GAAG,GAAG,CAAC,EAAY,IAAI,CAAC,WAA0B;AAAA,MACrD,IAAI,WAAW,KAAK;AAAA,MACpB,OAAO,OAAO,aAAa,KAAK;AAAA,MAChC,OAAO,OAAO;AAAA,MACd,MAAM,IAAI,KAAK;AAAA,MACf,SAAS,CAAC,IAAI,KAAK,IAAI,UAAU,MAAM,SAAS;AAAA,MAChD,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eACG,MAAA,EACA,MAAA,EACA,YAAY,KAAK,EACjB,WAAW,EAAE,MAAA,CAAO,EACpB,IAAA;AAAA,MACL;AAAA,IAAA,EACA;AAAA,IACF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,QAAQ,MAAM,MAAM,UAAU,IAAI;AAAA,MAC5C,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,iBAAA,EAAmB,IAAA;AAAA,MAC/D;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,SAAS,MAAM,MAAM,WAAW,IAAI;AAAA,MAC9C,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,kBAAA,EAAoB,IAAA;AAAA,MAChE;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,SAAS,MAAM,MAAM,QAAQ,QAAQ,WAAW;AAAA,MAC1D,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,eAAA,EAAiB,IAAA;AAAA,MAC7D;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,WAAW,MAAM,SAAS,YAAY;AAAA,MAChD,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,iBAAA,EAAmB,IAAA;AAAA,MAC/D;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,SAAS,MAAM,QAAQ,OAAO;AAAA,MACxC,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,gBAAA,EAAkB,IAAA;AAAA,MAC9D;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,SAAS,OAAO,OAAO,MAAM,SAAS;AAAA,MAChD,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eAAO,MAAA,EAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,kBAAA,EAAoB,IAAA;AAAA,MAChE;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,UAAU,MAAM,OAAO;AAAA,MACjC,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eACG,QACA,MAAA,EACA,YAAY,KAAK,EACjB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,eAAe,KAAA,CAAM,EACrD,IAAA;AAAA,MACL;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,WAAW,MAAM,QAAQ,QAAQ,OAAO;AAAA,MAClD,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eACG,QACA,MAAA,EACA,YAAY,KAAK,EACjB,cAAc,EAAE,MAAM,cAAc,OAAO,EAAE,OAAO,WAAS,CAAG,EAChE,IAAA;AAAA,MACL;AAAA,IAAA;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,OAAO,OAAO;AAAA,MACd,MAAM;AAAA,MACN,SAAS,CAAC,WAAW,MAAM,QAAQ,aAAa,OAAO;AAAA,MACvD,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ,UAAU;AACxB,eACG,QACA,MAAA,EACA,YAAY,KAAK,EACjB,cAAc,EAAE,MAAM,aAAa,OAAO,EAAE,OAAO,WAAS,CAAG,EAC/D,IAAA;AAAA,MACL;AAAA,IAAA;AAAA,EACF;AAEJ;AAGO,SAAS,iBACd,OACA,OACiB;AACjB,QAAM,IAAI,MAAM,KAAA,EAAO,YAAA;AACvB,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,MAAM;AAAA,IACX,CAACC,UAAA;;AACC,aAAAA,MAAK,MAAM,YAAA,EAAc,SAAS,CAAC,OACnC,KAAAA,MAAK,YAAL,mBAAc,KAAK,CAAC,UAAU,MAAM,cAAc,SAAS,CAAC;AAAA;AAAA,EAAC;AAEnE;ACnJA,SAAS,iBACP,OACmC;AACnC,QAAM,OAA0C,CAAA;AAChD,MAAI;AACJ,aAAWA,SAAQ,OAAO;AACxB,QAAIA,MAAK,SAASA,MAAK,UAAU,WAAW;AAC1C,WAAK,KAAK,CAACA,MAAK,OAAOA,KAAI,CAAC;AAC5B,kBAAYA,MAAK;AAAA,IACnB,OAAO;AACL,UAAI,CAACA,MAAK,MAAO,aAAY;AAC7B,WAAK,KAAK,CAAC,MAAMA,KAAI,CAAC;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAQO,MAAM,iBAAiB,WAG5B,SAASC,gBAAe,EAAE,OAAO,OAAO,WAAW,QAAA,GAAW,KAAK;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AAGpC,YAAU,MAAM;AACd,aAAS,CAAC;AAAA,EACZ,GAAG,CAAC,KAAK,CAAC;AAEV;AAAA,IACE;AAAA,IACA,OAAO;AAAA,MACL,UAAU,OAAO;AACf,YAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,YAAI,MAAM,QAAQ,eAAgB,MAAM,QAAQ,SAAS,CAAC,MAAM,UAAW;AACzE,mBAAS,CAAC,OAAO,IAAI,KAAK,MAAM,MAAM;AACtC,iBAAO;AAAA,QACT;AACA,YAAI,MAAM,QAAQ,aAAc,MAAM,QAAQ,SAAS,MAAM,UAAW;AACtE,mBAAS,CAAC,OAAO,IAAI,IAAI,MAAM,UAAU,MAAM,MAAM;AACrD,iBAAO;AAAA,QACT;AACA,YAAI,MAAM,QAAQ,SAAS;AACzB,gBAAMD,QAAO,MAAM,KAAK;AACxB,cAAI,CAACA,MAAM,QAAO;AAClB,kBAAQA,KAAI;AACZ,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,CAAC,OAAO,OAAO,OAAO;AAAA,EAAA;AAGxB,MAAI,CAAC,MAAM,OAAQ,QAAO;AAG1B,MAAI,cAAc;AAElB,6BACG,OAAA,EAAI,WAAWF,SAAO,MAAM,MAAK,WAAU,cAAY,WACrD,UAAA,iBAAiB,KAAK,EAAE,IAAI,CAAC,CAACI,SAAQF,KAAI,MAAM;AAC/C,mBAAe;AACf,UAAM,IAAI;AACV,gCACGG,YAAA,EACE,UAAA;AAAA,MAAAD,YAAW,2BACT,OAAA,EAAI,WAAWJ,SAAO,YAAY,eAAY,QAC5C,UAAAI,QAAA,CACH,IACE;AAAA,MACJ;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,iBAAe,MAAM;AAAA,UACrB,OAAOF,MAAK;AAAA,UACZ,WAAW,MAAM,QAAQF,SAAO,aAAaA,SAAO;AAAA,UAEpD,UAAU;AAAA,UACV,cAAc,MAAM,SAAS,CAAC;AAAA,UAC9B,aAAa,CAACL,OAAM;AAElB,YAAAA,GAAE,eAAA;AACF,oBAAQO,KAAI;AAAA,UACd;AAAA,UAEC,UAAA;AAAA,YAAAA,MAAK,QAAQ,OACZ,oBAAC,UAAK,WAAWF,SAAO,UAAU,eAAY,QAC3C,UAAAE,MAAK,KAAA,CACR,IAEA,oBAAC,QAAA,EAAK,WAAWF,SAAO,UAAU,eAAY,QAAO;AAAA,gCAEtD,QAAA,EAAK,WAAWA,SAAO,WAAY,gBAAK,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IACjD,EAAA,GA7BaE,MAAK,EA8BpB;AAAA,EAEJ,CAAC,EAAA,CACH;AAEJ,CAAC;AC5GD,SAAS,YAAY,OAAsB,MAAuC;AAChF,SAAO,KAAK,aAAa,MAAM,eAAe,MAAM,YAAY;AAClE;AAaO,MAAM,YAAY,UAAU,OAAyB;AAAA,EAC1D,MAAM;AAAA,EAEN,aAAa;AACX,WAAO,EAAE,OAAO,QAAW,QAAQ,OAAA;AAAA,EACrC;AAAA,EAEA,wBAAwB;AACtB,UAAM,EAAE,OAAO,YAAY,OAAA,IAAW,KAAK;AAC3C,UAAM,WAAW;AAAA,MACf,GAAG,4BAA4B,EAAE,GAAG,wBAAwB,GAAG,QAAQ;AAAA,MACvE,GAAI,cAAc,CAAA;AAAA,IAAC;AAGrB,QAAI,WAAuD;AAC3D,QAAI,eAAoC;AAExC,WAAO;AAAA,MACL,WAA0B;AAAA,QACxB,QAAQ,KAAK;AAAA,QACb,WAAW,IAAI,UAAU,cAAc;AAAA,QACvC,MAAM;AAAA;AAAA,QAEN,iBAAiB,CAAC,KAAK,KAAM,GAAQ;AAAA,QACrC,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,sBAAsB;AAAA,QACtB,OAAO,CAAC,EAAE,YAAY,iBAAiB,UAAU,KAAK;AAAA,QACtD,SAAS,CAAC,EAAE,QAAQ,OAAO,OAAOA,YAAW;AAC3C,UAAAA,MAAK,MAAM,QAAQ,KAAK;AAAA,QAC1B;AAAA,QACA,OAAO,CAAC,EAAE,aAAa,OAAO,cAAc,CAAC,OAAO,SAAS,WAAW;AAAA,QACxE,QAAQ,OAAO;AAAA,UACb,SAAS,CAAC,UAA0C;;AAClD,uBAAW,IAAI;AAAA,cACb;AAAA,cACA;AAAA,gBACE,QAAQ,MAAM;AAAA,gBACd,OAAO;AAAA,kBACL,OAAO,MAAM;AAAA,kBACb,OAAO,MAAM;AAAA,kBACb,aACE,UAAK,QAAQ,WAAb,mBAAqB,cAAa,uBAAuB;AAAA,kBAC3D,SAAS,MAAM;AAAA,gBAAA;AAAA,gBAEjB,WAAWF,SAAO;AAAA,cAAA;AAAA,YACpB;AAMF,kBAAM,UAAU,iBAAiB,MAAM,OAAO,KAAK,GAAG;AACtD,uBAAW,QAAQ;AAAA,cACjB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA,GACC;AACD,oBAAM,QAAQ,QAAQ,iBAAiB,IAAI;AAC3C,kBAAI,MAAO,UAAS,QAAQ,MAAM,YAAY,MAAM,KAAK;AAAA,YAC3D;AACA,2BAAe,MAAM,MAAM,SAAS,OAAO;AAAA,UAC7C;AAAA,UACA,UAAU,CAAC,UAA0C;AACnD,iDAAU,YAAY;AAAA,cACpB,OAAO,MAAM;AAAA,cACb,OAAO,MAAM;AAAA,cACb,SAAS,MAAM;AAAA,YAAA;AAAA,UAEnB;AAAA,UACA,WAAW,CAAC,UAAkC;;AAC5C,gBAAI,CAAC,YAAY,YAAY,MAAM,OAAO,MAAM,IAAI,EAAG,QAAO;AAC9D,qBAAO,cAAS,QAAT,mBAAc,UAAU,MAAM,WAAU;AAAA,UACjD;AAAA,UACA,QAAQ,MAAM;AACZ;AACA,2BAAe;AACf,iDAAU;AACV,uBAAW;AAAA,UACb;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA;AAAA,EAEL;AACF,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1FM,SAAS,oBAAoB,QAAyC;AAC3E,SAAO;AAAA,IACL;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,SAAS;AAAA,QACP,EAAE,IAAI,QAAQ,OAAO,OAAO,MAAM,MAAM,CAAC,OAAO,GAAG,GAAG,UAAU,EAAE,QAAQ,UAAQ;AAAA,QAClF,EAAE,IAAI,UAAU,OAAO,OAAO,QAAQ,MAAM,CAAC,OAAO,GAAG,GAAG,UAAU,EAAE,QAAQ,QAAM;AAAA,QACpF,EAAE,IAAI,UAAU,OAAO,OAAO,QAAQ,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,UAAU,EAAE,QAAQ,UAAQ;AAAA,QAC/F,EAAE,IAAI,aAAa,OAAO,OAAO,WAAW,MAAM,CAAC,OAAO,GAAG,EAAA;AAAA,QAC7D,EAAE,IAAI,eAAe,OAAO,OAAO,YAAY,MAAM,CAAC,OAAO,GAAG,GAAG,UAAU,EAAE,QAAQ,QAAM;AAAA,QAC7F,EAAE,IAAI,aAAa,OAAO,OAAO,WAAW,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,UAAU,EAAE,QAAQ,UAAQ;AAAA,QACrG,GAAI,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,EAAY,IAAI,CAAC,WAA0B;AAAA,UAC9D,IAAI,WAAW,KAAK;AAAA,UACpB,OAAO,OAAO,aAAa,KAAK;AAAA,UAChC,MAAM,CAAC,OAAO,OAAO,OAAO,KAAK,CAAC;AAAA,UAClC,UAAU,EAAE,QAAQ,IAAI,OAAO,KAAK,GAAG,YAAY,QAAA;AAAA,QAAQ,EAC3D;AAAA,QACF,EAAE,IAAI,aAAa,OAAO,OAAO,WAAW,MAAM,CAAC,OAAO,OAAO,GAAG,EAAA;AAAA,MAAE;AAAA,IACxE;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,SAAS;AAAA,QACP,EAAE,IAAI,cAAc,OAAO,OAAO,YAAY,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,UAAU,EAAE,QAAQ,KAAK,YAAY,UAAQ;AAAA,QACxH,EAAE,IAAI,eAAe,OAAO,OAAO,YAAY,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,UAAU,EAAE,QAAQ,KAAK,YAAY,UAAQ;AAAA,QACzH,EAAE,IAAI,gBAAgB,OAAO,OAAO,aAAa,MAAM,CAAC,OAAO,SAAS,GAAG,GAAG,UAAU,EAAE,QAAQ,MAAM,YAAY,UAAQ;AAAA,QAC5H,EAAE,IAAI,aAAa,OAAO,OAAO,UAAU,UAAU,EAAE,QAAQ,MAAM,YAAY,QAAA,EAAQ;AAAA,QACzF,EAAE,IAAI,cAAc,OAAO,OAAO,WAAW,UAAU,EAAE,QAAQ,OAAO,YAAY,QAAA,EAAQ;AAAA,QAC5F,EAAE,IAAI,WAAW,OAAO,OAAO,SAAS,UAAU,EAAE,QAAQ,OAAO,YAAY,QAAA,EAAQ;AAAA,MAAE;AAAA,IAC3F;AAAA,IAEF;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO;AAAA,MACd,SAAS;AAAA,QACP,EAAE,IAAI,QAAQ,OAAO,OAAO,MAAM,MAAM,CAAC,OAAO,GAAG,EAAA;AAAA,QACnD,EAAE,IAAI,QAAQ,OAAO,OAAO,MAAM,MAAM,CAAC,OAAO,SAAS,GAAG,EAAA;AAAA,QAC5D,EAAE,IAAI,cAAc,OAAO,OAAO,WAAW,MAAM,CAAC,SAAS,OAAO,EAAA;AAAA,QACpE,EAAE,IAAI,gBAAgB,OAAO,OAAO,aAAa,MAAM,CAAC,OAAO,GAAG,EAAA;AAAA,MAAE;AAAA,IACtE;AAAA,EACF;AAEJ;ACjEA,SAAS,gBAAyB;AAChC,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,SAAO,kBAAkB,KAAK,UAAU,YAAY,UAAU,SAAS;AACzE;AAGA,SAAS,WAAW,KAAa,KAAsB;AACrD,MAAI,QAAQ,MAAO,QAAO,MAAM,QAAQ;AACxC,MAAI,QAAQ,MAAO,QAAO,MAAM,QAAQ;AACxC,MAAI,UAAU,KAAK,GAAG,EAAG,QAAO,IAAI,YAAA;AACpC,SAAO;AACT;AAOO,SAAS,cAAc,EAAE,MAAM,SAAS,UAA8B;AAC3E,QAAM,IAAoB;AAAA,IACxB,OAAO,EAAE,GAAG,uBAAuB,GAAG;IACtC,CAAC,MAAM;AAAA,EAAA;AAIT,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,CAACL,OAAqB;AAClC,UAAIA,GAAE,QAAQ,SAAU,SAAA;AAAA,IAC1B;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,WAAO,MAAM,SAAS,oBAAoB,WAAW,KAAK;AAAA,EAC5D,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,QAAM,SAA0B;AAAA,IAC9B,MAAO,OAAO,oBAAoB,CAAC,IAAI,CAAA;AAAA,IACvC,CAAC,MAAM,CAAC;AAAA,EAAA;AAEV,QAAM,MAAM,QAAQ,eAAe,EAAE;AAErC,MAAI,CAAC,KAAM,QAAO;AAElB,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWK,SAAO;AAAA,MAClB,MAAK;AAAA,MACL,cAAW;AAAA,MACX,cAAY,EAAE;AAAA,MAEd,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAWA,SAAO;AAAA,YAClB,OAAO,EAAE;AAAA,YACT,cAAY,EAAE;AAAA,YACd,SAAS;AAAA,YAET,UAAA,oBAAC,OAAA,EAAM,MAAM,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA;AAAA,QAEnB,qBAAC,OAAA,EAAI,WAAWA,SAAO,MACrB,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAY,YAAE,WAAU;AAAA,8BAC/C,QAAA,EAAK,WAAWA,SAAO,aAAc,YAAE,aAAY;AAAA,8BACnD,QAAA,EAAK,WAAWA,SAAO,aAAc,YAAE,YAAA,CAAY;AAAA,QAAA,GACtD;AAAA,QACA,oBAAC,OAAA,EAAI,WAAWA,SAAO,MACpB,UAAA,OAAO,IAAI,CAACM,WACX,qBAAC,WAAA,EAAuB,WAAWN,SAAO,OACxC,UAAA;AAAA,UAAA,oBAAC,MAAA,EAAG,WAAWA,SAAO,YAAa,iBAAM,OAAM;AAAA,UAC9CM,OAAM,QAAQ,IAAI,CAAC,UAClB,qBAAC,OAAA,EAAmB,WAAWN,SAAO,KACpC,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,UAAW,gBAAM,OAAM;AAAA,YAC/C,oBAAC,QAAA,EAAK,WAAWA,SAAO,SACrB,UAAA,MAAM,OACL,MAAM,KAAK,IAAI,CAAC,KAAK,MACnB,oBAAC,OAAA,EAAY,WAAWA,SAAO,QAC5B,UAAA,WAAW,KAAK,GAAG,KADZ,CAEV,CACD,IAED,oBAAC,QAAA,EAAK,WAAWA,SAAO,MAAM,eAAC,GAEnC;AAAA,gCACC,QAAA,EAAK,WAAWA,SAAO,OACrB,UAAA,MAAM,WACL,qBAAAK,YAAA,EACE,UAAA;AAAA,cAAA,oBAAC,SAAI,WAAWL,SAAO,QAAS,UAAA,MAAM,SAAS,QAAO;AAAA,cACrD,MAAM,SAAS,aACd,oBAAC,OAAA,EAAI,WAAWA,SAAO,QAAS,UAAA,MAAM,SAAS,WAAA,CAAW,IACxD;AAAA,YAAA,GACN,IAEA,oBAAC,QAAA,EAAK,WAAWA,SAAO,MAAM,eAAC,EAAA,CAEnC;AAAA,UAAA,EAAA,GAxBQ,MAAM,EAyBhB,CACD;AAAA,QAAA,KA7BWM,OAAM,EA8BpB,CACD,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AC1GA,MAAMC,eAAa;AASnB,MAAM,gBAAgB,CAAC,iBAAiB,mBAAmB,EAAE;AAG7D,eAAe,oBACb,QACA,OACA,KACe;AACf,QAAM,UAAU,MAAM,OAAO,CAACC,OAAMD,aAAW,KAAKC,GAAE,IAAI,CAAC;AAC3D,MAAI,QAAQ,WAAW,EAAG;AAE1B,QAAM,WAAW,OAAO;AACxB,MAAI,CAAC,SAAU;AACf,QAAM,QAAQ,MAAM,QAAQ,IAAI,QAAQ,IAAI,CAACA,OAAMA,GAAE,KAAA,CAAM,CAAC;AAC5D,QAAM,OAAO,SAAS,MAAM,MAAM,KAAK,MAAM,CAAC;AAC9C,MAAI,OAAO,MAAM;AACf,WAAO,MAAA,EAAQ,MAAA,EAAQ,gBAAgB,KAAK,IAAI,EAAE,IAAA;AAAA,EACpD,OAAO;AACL,WAAO,QAAQ,MAAA,EAAQ,cAAc,IAAI,EAAE,IAAA;AAAA,EAC7C;AACF;AAQO,MAAM,mBAAmB,UAAU,OAAO;AAAA,EAC/C,MAAM;AAAA,EAEN,wBAAwB;AACtB,UAAM,EAAE,WAAW;AACnB,WAAO;AAAA,MACL,iBAAiB;AAAA,QACf,KAAK,IAAI,UAAU,kBAAkB;AAAA,QACrC;AAAA,QACA,kBAAkB;AAAA,QAClB,QAAQ,CAAC,IAAI,OAAO,QAAQ;AAC1B,8BAAoB,IAAI,OAAO,GAAG,EAAE,MAAM,CAAC,QAAQ;AACjD,oBAAQ,MAAM,8BAA8B,GAAG;AAAA,UACjD,CAAC;AAAA,QACH;AAAA,QACA,SAAS,CAAC,IAAI,UAAU;AACtB,8BAAoB,IAAI,KAAK,EAAE,MAAM,CAAC,QAAQ;AAC5C,oBAAQ,MAAM,+BAA+B,GAAG;AAAA,UAClD,CAAC;AAAA,QACH;AAAA,MAAA,CACD;AAAA,IAAA;AAAA,EAEL;AACF,CAAC;ACtCM,MAAM,sBAAsB;AAE5B,MAAM,yBAAyB,IAAI;AAAA,EACxC;AACF;AAGO,MAAM,uBAAuB;AAE7B,MAAM,yBAAyB,UAAU,OAAO;AAAA,EACrD,MAAM;AAAA,EAEN,wBAAwB;AACtB,WAAO;AAAA,MACL,IAAI,OAA2B;AAAA,QAC7B,KAAK;AAAA,QACL,OAAO;AAAA,UACL,MAAM,OAAO,EAAE,aAAa,cAAc,MAAA;AAAA,UAC1C,MAAM,IAAI,OAAO;AACf,kBAAM,OAAO,GAAG,QAAQ,mBAAmB;AAG3C,gBAAI,aAAa,EAAE,aAAa,iBAAiB,GAAG,KAAK,IAAI,EAAA;AAC7D,gBAAI,GAAG,YAAY;AACjB,qBAAO,EAAE,aAAa,MAAM,YAAY,IAAI,GAAG,SAAS,GAAG,GAAG,EAAA;AAAA,YAChE;AACA,mBAAO;AAAA,UACT;AAAA,QAAA;AAAA,QAEF,OAAO;AAAA,UACL,YAAY,OAAoB;;AAC9B,qBAAO,4BAAuB,SAAS,KAAK,MAArC,mBAAwC,gBAAe;AAAA,UAChE;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA;AAAA,EAEL;AACF,CAAC;AAGM,SAAS,kBAAkB,QAAgB,SAAgC;AAChF,SAAO,KAAK;AAAA,IACV,OAAO,MAAM,GACV,QAAQ,qBAAqB,OAAO,EAKpC,QAAQ,sBAAsB,IAAI,EAClC,QAAQ,gBAAgB,KAAK;AAAA,EAAA;AAEpC;AAEA,SAAS,iBAAiB,KAAW,SAAyC;AAC5E,QAAM,SAA8C,CAAA;AACpD,MAAI,QAAQ,CAAC,OAAO,WAAW;AAC7B,WAAO,KAAK,EAAE,MAAM,QAAQ,IAAI,SAAS,MAAM,UAAU;AAAA,EAC3D,CAAC;AAED,QAAM,cAA4B,CAAA;AAClC,aAAW,UAAU,SAAS;AAC5B,eAAW,SAAS,OAAO,QAAQ;AACjC,YAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,EAAE,CAAC;AACvD,YAAM,KAAK,KAAK,IAAI,IAAI,QAAQ,MAAM,KAAK,IAAI,MAAM,MAAM,MAAM,EAAE,CAAC;AACpE,UAAI,QAAQ,GAAI;AAEhB,iBAAW,SAAS,QAAQ;AAC1B,YAAI,MAAM,MAAM,QAAQ,MAAM,QAAQ,GAAI;AAC1C,cAAM,QAAQ;AAAA,UACZ,OAAO;AAAA,UACP,mBAAmB,OAAO;AAAA,QAAA;AAE5B,YAAI,QAAQ,MAAM,QAAQ,MAAM,MAAM,IAAI;AAExC,sBAAY,KAAK,WAAW,KAAK,MAAM,MAAM,MAAM,IAAI,KAAK,CAAC;AAAA,QAC/D,OAAO;AAEL,sBAAY;AAAA,YACV,WAAW,OAAO,KAAK,IAAI,MAAM,MAAM,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,EAAE,GAAG,KAAK;AAAA,UAAA;AAAA,QAE/E;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,YAAY,SAAS,cAAc,OAAO,KAAK,WAAW,IAAI,cAAc;AACrF;ACrGO,SAAS,cAAc,WAAqC;AACjE,MAAI,qBAAqB,cAAe,QAAO;AAC/C,MAAI,qBAAqB,cAAe,QAAO;AAC/C,MAAI,qBAAqB,cAAe,QAAO;AAC/C,SAAO;AACT;ACRO,SAAS,kBAAkB,MAAuB;AACvD,SACE,aAAa,KAAK,IAAI;AAAA,EACtB,kBAAkB,KAAK,IAAI;AAAA,EAC3B,kCAAkC,KAAK,IAAI;AAAA,EAC3C,2BAA2B,KAAK,IAAI;AAAA,EACpC,eAAe,KAAK,IAAI;AAAA,EACxB,eAAe,KAAK,IAAI;AAAA,EACxB,QAAQ,KAAK,IAAI;AAAA,EACjB,QAAQ,KAAK,IAAI;AAAA,EACjB,eAAe,KAAK,IAAI;AAAA,EACxB,uBAAuB,KAAK,IAAI;AAAA,EAChC,6CAA6C,KAAK,IAAI;AAE1D;AAiBO,MAAM,gBAAgB,UAAU,OAAO;AAAA,EAC5C,MAAM;AAAA,EAEN,wBAAwB;AACtB,UAAM,EAAE,WAAW;AACnB,WAAO;AAAA,MACL,IAAI,OAAO;AAAA,QACT,KAAK,IAAI,UAAU,eAAe;AAAA,QAClC,OAAO;AAAA,UACL,YAAY,MAAM,OAAO;AACvB,kBAAM,YAAY,MAAM;AACxB,gBAAI,CAAC,UAAW,QAAO;AACvB,kBAAM,OAAO,UAAU,QAAQ,YAAY;AAC3C,gBAAI,CAAC,KAAM,QAAO;AAGlB,kBAAMC,SAAS,KACZ;AACH,gBAAIA,UAAA,gBAAAA,OAAO,SAAU,QAAO;AAE5B,gBAAI,KAAK,MAAM,UAAU,MAAM,OAAO,KAAK,KAAK,KAAM,QAAO;AAC7D,gBAAI,CAAC,kBAAkB,IAAI,EAAG,QAAO;AAErC,kBAAM,WAAW,OAAO;AACxB,gBAAI,CAAC,SAAU,QAAO;AACtB,gBAAI;AAIF,oBAAM,OAAO,SAAS,MAAM,qBAAqB,IAAI,CAAC;AACtD,qBAAO,SAAS,cAAc,IAAI;AAClC,qBAAO;AAAA,YACT,SAAS,KAAK;AACZ,sBAAQ,MAAM,gCAAgC,GAAG;AACjD,qBAAO;AAAA,YACT;AAAA,UACF;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA;AAAA,EAEL;AACF,CAAC;AChED,SAAS,SACP,WACA,OACA,OACA,UACQ;AACR,MAAI,+BAAO,OAAQ,QAAO;AAC1B,SAAO,SAAS,WAAW,KAAK;AAClC;AAMO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAkB;AAChB,QAAM,YAAY,OAA0B,IAAI;AAChD,QAAM,WAAW,OAAuB,IAAI;AAC5C,QAAM,CAACb,SAAQc,UAAS,IAAI,SAAS,CAAC;AAEtC,QAAM,UAAwB;AAAA,IAC5B,OAAO;AAAA,MACL,QAAS,KAAK,MAAM,UAAU,CAAA;AAAA,MAC9B,SAAU,KAAK,MAAM,WAAW,CAAA;AAAA,MAChC,YAAa,KAAK,MAAM,cACtB,CAAA;AAAA,IAAC;AAAA,IAEL,CAAC,KAAK,MAAM,QAAQ,KAAK,MAAM,SAAS,KAAK,MAAM,UAAU;AAAA,EAAA;AAG/D,QAAM,QAAS,UAAU,QAAQ,cAAc;AAC/C,QAAM,UAAU,QAAQ;AACxB,QAAM,YAAY,KAAK,IAAId,SAAQ,KAAK,IAAI,GAAG,QAAQ,SAAS,CAAC,CAAC;AAClE,QAAM,SAAS,QAAQ,SAAS;AAChC,QAAM,UAAS,iCAAQ,WAAU;AACjC,QAAM,YAAY,QAAQ,iCAAQ,UAAU;AAE5C,YAAU,MAAM;AACd,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,UAAU,CAAC,OAAQ;AACxB,aAAS,UAAU,oBAAoB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,IAAA,CACjB;AAAA,EACH,GAAG,CAAC,QAAQ,SAAS,KAAK,CAAC;AAE3B,YAAU,MAAM;AACd,WAAO,MAAM;AACX,mBAAa,SAAS,OAAO;AAC7B,eAAS,UAAU;AAAA,IACrB;AAAA,EACF,GAAG,CAAA,CAAE;AAGL,YAAU,MAAM;AACd,iBAAa,SAAS,OAAO;AAC7B,aAAS,UAAU;AACnB,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,UAAU,CAAC,OAAQ;AACxB,aAAS,UAAU,oBAAoB;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IAAA,CACR;AAAA,EACH,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,GAAI,UAAU,QAAQ;AAAA,EAAA;AAKxB,QAAM,cAAc,MAAM;AACxB,QAAI,CAAC,UAAU,CAAC,UAAW;AAC3B,UAAM,MAAM,OAAA;AACZ,QAAI,OAAO,QAAQ,SAAU;AAC7B,WAAO,SAAS,iBAAiB,GAAG;AAAA,EACtC;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,IAAG;AAAA,MACH,WAAW,YAAY,YAAY,4BAA4B,EAAE,GAC/D,WAAW,8BAA8B,EAC3C;AAAA,MACA,aAAU;AAAA,MACV,iBAAe,WAAW,SAAS;AAAA,MACnC,iBAAiB;AAAA,MACjB,aAAa,CAACD,OAAkB;AAC9B,YAAKA,GAAE,OAAuB,QAAQ,QAAQ,EAAG;AACjD,YAAIA,GAAE,WAAW,EAAG;AAEpB,oBAAA;AAAA,MACF;AAAA,MAEC,UAAA;AAAA,SAAA,iCAAQ,SACP,oBAAC,OAAA,EAAI,WAAU,mBAAmB,UAAA,OAAO,OAAM,IAC7C;AAAA,SACH,iCAAQ,YACP,oBAAC,OAAA,EAAI,WAAU,kBAAkB,UAAA,OAAO,UAAS,IAC/C;AAAA,QACH,QAAQ,SAAS,IAChB,oBAAC,OAAA,EAAI,WAAU,kBAAiB,MAAK,WAClC,UAAA,QAAQ,IAAI,CAAC,GAAG,MACf;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,WAAU;AAAA,YACV,eAAa,MAAM,YAAY,SAAS;AAAA,YACxC,iBAAe,MAAM;AAAA,YACrB,aAAa,CAACA,OAAMA,GAAE,gBAAA;AAAA,YACtB,SAAS,CAACA,OAAM;AACd,cAAAA,GAAE,gBAAA;AACF,cAAAe,WAAU,CAAC;AAAA,YACb;AAAA,YAEC,mBAAS,EAAE,WAAW,EAAE,OAAO,GAAG,OAAO,QAAQ;AAAA,UAAA;AAAA,UAZ7C,GAAG,EAAE,SAAS,IAAI,CAAC;AAAA,QAAA,CAc3B,GACH,IACE;AAAA,QACJ,oBAAC,OAAA,EAAI,WAAU,yBAAwB,OAAO,EAAE,OAAA,GAC9C,UAAA,oBAAC,UAAA,EAAO,KAAK,UAAA,CAAW,EAAA,CAC1B;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;ACtIO,SAAS,YAAY,UAA8B,IAAI;AAE5D,QAAM,EAAE,WAAW,OAAO,aAAa,MAAM,gBAAgB;AAC7D,SAAO,YAAY,OAAgC;AAAA,IACjD,aAAa;AACX,aAAO;AAAA,QACL,gBAAgB,CAAA;AAAA,QAChB,eAAe;AAAA,QACf;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,cAAc;AACZ,aAAO,sBAAsB,SAAS;AAAA,IACxC;AAAA,EAAA,CACD;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACnBA,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;AAWO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;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,QACR,OAAO;AACb,QAAM,WAAW,OAAO;AACxB,QAAMC,YAAW,CAAC;AAElB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAACC,SAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,WAAW,YAAY,IAAI;AAAA,IAAS,MACzC,KAAK,KAAK,KAAK,eAAe,IAAI,MAAM,IAAI,EAAE,QAAQ,CAAC;AAAA,EAAA;AAEzD,QAAM,SAAS,OAA8B,IAAI;AAGjD,YAAU,MAAM;AACd,QAAI,CAACD,UAAU;AACf,UAAME,OAAM,OAAO;AACnB,QAAI,CAACA,KAAK;AACV,UAAM,SAAS,MAAM;AACnB,mBAAa,KAAK,KAAKA,KAAI,eAAe,IAAI,MAAM,IAAI,EAAE,QAAQ,CAAC,CAAC;AAAA,IACtE;AACA,WAAA;AACA,UAAM,KAAK,IAAI,iBAAiB,MAAM;AACtC,OAAG,QAAQA,MAAK,EAAE,WAAW,MAAM,SAAS,MAAM,eAAe,MAAM;AACvE,WAAO,MAAM,GAAG,WAAA;AAAA,EAClB,GAAG,CAACF,SAAQ,CAAC;AAEb,QAAM,aAAa,MAAM;;AACvB,UAAM,OAAO,KAAK,eAAe;AACjC,UAAM,OAAO,MAAM;AACjB,gBAAU,IAAI;AACd,aAAO,WAAW,MAAM,UAAU,KAAK,GAAG,IAAI;AAAA,IAChD;AACA,SAAIG,MAAA,UAAU,cAAV,gBAAAA,IAAqB,WAAW;AAClC,gBAAU,UAAU,UAAU,IAAI,EAAE,KAAK,MAAM,MAAM;AAAA,MAAC,CAAC;AACvD;AAAA,IACF;AAEA,UAAM,KAAK,SAAS,cAAc,UAAU;AAC5C,OAAG,QAAQ;AACX,aAAS,KAAK,YAAY,EAAE;AAC5B,OAAG,OAAA;AACH,QAAI;AACF,eAAS,YAAY,MAAM;AAC3B,WAAA;AAAA,IACF,QAAQ;AAAA,IAER;AACA,OAAG,OAAA;AAAA,EACL;AAEA,QAAM,eAAe;AAAA,IACnBd,SAAO;AAAA,IACPW,YAAWX,SAAO,WAAW;AAAA,IAC7BY,UAASZ,SAAO,SAAS;AAAA,EAAA,EAExB,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,SACE,qBAAC,iBAAA,EAAgB,WAAW,cACzB,UAAA;AAAA,IAAA,gCACE,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;AAAA,2BAGC,OAAA,EAAI,WAAWA,SAAO,gBAAgB,iBAAiB,OACtD,UAAA;AAAA,QAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,YAAa,UAAA,MAAK;AAAA,UACzC;AAAA,QAAA,GACH;AAAA,QACA,qBAAC,QAAA,EAAK,WAAWA,SAAO,iBACtB,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAWA,SAAO;AAAA,cAClB,SAAS;AAAA,cACT,cAAY,OAAO;AAAA,cACnB,OAAO,OAAO;AAAA,cAEb,UAAA,6BAAU,WAAA,EAAU,MAAM,IAAI,IAAK,oBAAC,UAAA,EAAS,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAE1D;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAWA,SAAO;AAAA,cAClB,SAAS,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;AAAA,cAClC,cAAYY,UAAS,OAAO,SAAS,OAAO;AAAA,cAC5C,OAAOA,UAAS,OAAO,SAAS,OAAO;AAAA,cACvC,iBAAe,CAACA;AAAA,cAEhB,UAAA,oBAAC,oBAAA,EAAmB,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,QAChC,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA;AAAA,yBAED,OAAA,EAAI,KAAK,QAAQ,WAAWZ,SAAO,KACjC,UAAA;AAAA,MAAAW,YACC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWX,SAAO;AAAA,UAClB,iBAAiB;AAAA,UACjB,eAAY;AAAA,UAEX,gBAAM,KAAK,EAAE,QAAQ,aAAa,CAAC,GAAG,MACrC,oBAAC,UAAa,WAAWA,SAAO,YAC7B,UAAA,IAAI,EAAA,GADI,CAEX,CACD;AAAA,QAAA;AAAA,MAAA,IAED;AAAA,MAEJ,oBAAC,iBAAA,EAAgB,IAAI,OAAA,CAAiB;AAAA,IAAA,EAAA,CACxC;AAAA,EAAA,GACF;AAEJ;AC3IA,MAAM,YAAY,kBAAkB,OAAyB;AAAA,EAC3D,aAAa;;AACX,WAAO;AAAA,MACL,IAAG,UAAK,WAAL;AAAA,MACH,iBAAiB;AAAA,IAAA;AAAA,EAErB;AAAA;AAAA;AAAA,EAGA,eAAe,CAAC,OAAO,YACrB,iCAAiC,OAAO,SAAS,WAAW;AAAA,EAC9D,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;AAUD,MAAM,0BAAyC,EAAE,KAAK,GAAG,OAAO,EAAA;AAEhE,SAAS,mBAAmB,QAAsC;AAChE,QAAM,KAAK,CAAC,MACV,OAAO,MAAM,WAAW,GAAG,CAAC,OAAO;AACrC,SAAO;AAAA,IACL,UAAU;AAAA,IACV,KAAK,GAAG,OAAO,GAAG;AAAA,IAClB,OAAO,GAAG,OAAO,KAAK;AAAA,IACtB,QAAQ,GAAG,OAAO,MAAM;AAAA,IACxB,MAAM,GAAG,OAAO,IAAI;AAAA,EAAA;AAExB;AAQA,SAAS,mBAAmB,QAAyB;AACnD,QAAMJ,UAAS,SAAS;AACxB,QAAM,WAAW,CAAC,CAACA,WAAU,OAAO,KAAK,IAAI,SAASA,OAAM;AAC5D,MAAI,YAAY,OAAO,UAAW,QAAO;AACzC,QAAM,iBAAiBA,YAAW,QAAQA,YAAW,SAAS;AAC9D,SAAO,kBAAkB,SAAS,iBAAiB,cAAc,EAAE,UAAU;AAC/E;AAgLO,MAAM,wBAAwB,WAGnC,SAASmB,uBACT;AAAA,EACE,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB,qBAAqB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,UAAU;AAAA,EACV;AAAA,EACA,gBAAgB;AAAA,EAClB,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AACA,GACA,KACA;AACA,QAAM,kBAAkB;AAAA,IACtB,wBAAwB,iBAAiB,WAAW,CAAA,CAAE;AAAA,EAAA;AAGxD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,eAAe,OAAgC,IAAI;AAEzD,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;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,GAAI,cAAc,CAAC,YAAY,UAAU,EAAE,YAAA,CAAa,CAAC,IAAI,CAAA;AAAA,MAC7D,YAAY,EAAE,UAAU,OAAO;AAAA,MAC/B,kBAAkB,EAAE,gBAAgB;AAAA,MACpC;AAAA,MACA,uBAAuB;AAAA,QACrB,YAAY;AAAA,QACZ,aAAa;AAAA,MAAA,CACd;AAAA,MACD;AAAA,MACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,GAAI,cACA,CAAC,eAAe,UAAU,EAAE,WAAW,OAAO,kBAAkB,GAAG,CAAC,IACpE,CAAA;AAAA,MACJ,gBAAgB,UAAU;AAAA,QACxB,OAAO,aAAA;AAAA,QACP,UAAU,CAAC,YAAY;AACrB;AAAA,YACE,QACG,OAAO,CAACC,OAAMA,GAAE,SAAS,CAAC,EAC1B,IAAI,CAACA,QAAO,EAAE,IAAIA,GAAE,IAAI,OAAOA,GAAE,OAAO,MAAMA,GAAE,cAAc;AAAA;AAAA,QAErE;AAAA,MAAA,CACD;AAAA,MACD,GAAI,gBAAgB,CAAC,aAAa,IAAI,CAAA;AAAA,MACtC,GAAI,mBAAmB,CAAC,gBAAgB,IAAI,CAAA;AAAA;AAAA,MAE5C,GAAI,YAAY,CAAC,UAAU,UAAU,EAAE,QAAQ,gBAAA,CAAiB,CAAC,IAAI,CAAA;AAAA,MACrE,GAAI,mBAAmB,CAAA;AAAA,IAAC;AAAA,IAE1B,SAAS;AAAA,IACT,aAAa;AAAA,IACb;AAAA;AAAA,IAEA,mBAAmB;AAAA,IACnB,aAAa;AAAA,MACX,YAAY;AAAA,QACV,OAAOhB,SAAO;AAAA,MAAA;AAAA,IAChB;AAAA,EACF,CACD;AAED,YAAU,MAAM;AACd,mDAAgB;AAChB,WAAO,MAAM,+CAAgB;AAAA,EAC/B,GAAG,CAAC,QAAQ,aAAa,CAAC;AAG1B,YAAU,MAAM;AACd,qCAAQ,YAAY;AAAA,EACtB,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAMrB,QAAM,WAAW,YAAY,MAAM;AACjC,gBAAY,IAAI;AAChB,0BAAsB,MAAA;;AAAM,gCAAa,YAAb,mBAAsB;AAAA,KAAQ;AAAA,EAC5D,GAAG,CAAA,CAAE;AAEL,QAAM,YAAY,YAAY,MAAM;AAClC,gBAAY,KAAK;AAGjB,qCAAQ,SAAS;AAAA,EACnB,GAAG,CAAC,MAAM,CAAC;AAMX,QAAM,aAAa,YAAY,MAAM;AACnC,QAAI,SAAU,WAAA;AAAA,QACT,UAAA;AAAA,EACP,GAAG,CAAC,UAAU,WAAW,QAAQ,CAAC;AAKlC,QAAM,cAAc,YAAY,WAAW;AAC3C,QAAM,sBAAsB,OAAO,gBAAgB;AACnD,sBAAoB,UAAU;AAE9B,QAAM,sBAAsB,OAAO,KAAK;AACxC,YAAU,MAAM;;AACd,QAAI,oBAAoB,YAAY,YAAa;AACjD,wBAAoB,UAAU;AAC9B,8BAAoB,YAApB,6CAA8B;AAAA,EAChC,GAAG,CAAC,WAAW,CAAC;AAMhB,QAAM,iBAAiB,OAAO,WAAW;AACzC,iBAAe,UAAU;AACzB;AAAA,IACE,MAAM,MAAM;;AACV,UAAI,eAAe,QAAS,2BAAoB,YAApB,6CAA8B;AAAA,IAC5D;AAAA,IACA,CAAA;AAAA,EAAC;AAKH,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,aAAc;AAC1D,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,EAAE,MAAM,WAAW,MAAM,YAAY,MAAM,UAAU,MAAM,UAAU;AACvE;AAAA,MACF;AACA,UAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,IAAK;AAC5C,UAAI,CAAC,mBAAmB,MAAM,EAAG;AACjC,YAAM,eAAA;AACN,eAAA;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,WAAW,IAAI;AACpD,WAAO,MAAM,SAAS,oBAAoB,WAAW,WAAW,IAAI;AAAA,EACtE,GAAG,CAAC,QAAQ,aAAa,SAAS,cAAc,QAAQ,CAAC;AAYzD,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,YAAa;AAC7B,UAAM,YAAY,CAAC,UAAyB;AAC1C,UAAI,MAAM,QAAQ,SAAU;AAC5B,UAAI,oBAAoB,KAAK,EAAG;AAChC,UAAI,CAAC,mBAAmB,MAAM,EAAG;AACjC,YAAM,eAAA;AACN,YAAM,gBAAA;AACN,gBAAA;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,SAAS;AAC9C,WAAO,MAAM,SAAS,oBAAoB,WAAW,SAAS;AAAA,EAChE,GAAG,CAAC,QAAQ,aAAa,SAAS,CAAC;AAInC,QAAM,uBAAuB,OAAe,EAAE;AAC9C,YAAU,MAAM;AAEd,QAAI,CAAC,UAAU,CAAC,SAAU;AAC1B,UAAM,aAAa,YAAY,CAAA,GAC5B,IAAI,CAAC,MAAM,GAAG,EAAE,SAAS,IAAI,EAAE,SAAS,MAAM,EAAE,EAChD,KAAK,GAAG;AACX,QAAI,cAAc,qBAAqB,QAAS;AAChD,yBAAqB,UAAU;AAC/B,gCAA4B,QAAQ,YAAY,EAAE;AAAA,EACpD,GAAG,CAAC,QAAQ,UAAU,QAAQ,CAAC;AAG/B,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,WAAO,KAAK;AAAA,MACV,OAAO,MAAM,GAAG;AAAA,QACd;AAAA,QACA,mBAAmB;AAAA,MAAA;AAAA,IACrB;AAAA,EAEJ,GAAG,CAAC,QAAQ,eAAe,CAAC;AAG5B,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,sBAAkB,QAAQ,kBAAkB,EAAE;AAAA,EAChD,GAAG,CAAC,QAAQ,cAAc,CAAC;AAG3B,QAAM,mBAAmB,OAAO,aAAa;AAC7C,YAAU,MAAM;AACd,qBAAiB,UAAU;AAAA,EAC7B,GAAG,CAAC,aAAa,CAAC;AAClB,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,MAAM,OAAO,KAAK;AACxB,UAAM,UAAU,CAAC,UAAsB;;AACrC,YAAM,SAAS,MAAM;AACrB,YAAM,MAAK,4CAAQ,YAAR,gCAAkB,yBAAlB,mBAAwC,aAAa;AAChE,UAAI,GAAI,wBAAiB,YAAjB,0CAA2B;AAAA,IACrC;AACA,QAAI,iBAAiB,SAAS,OAAO;AACrC,WAAO,MAAM,IAAI,oBAAoB,SAAS,OAAO;AAAA,EACvD,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,uBAAuB,OAAO,iBAAiB;AACrD,YAAU,MAAM;AACd,yBAAqB,UAAU;AAAA,EACjC,GAAG,CAAC,iBAAiB,CAAC;AACtB,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,oBAAoB,MAAM;;AAC9B,YAAM,EAAE,MAAM,IAAI,MAAA,IAAU,OAAO,MAAM;AACzC,iCAAqB,YAArB,8CAA+B;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,cAAc,OAAO,MAAM,SAAS;AAAA,MAAA;AAAA,IAE9C;AACA,WAAO,GAAG,mBAAmB,iBAAiB;AAC9C,WAAO,MAAM;AACX,aAAO,IAAI,mBAAmB,iBAAiB;AAAA,IACjD;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,oBAAoB,OAAO,cAAc;AAC/C,QAAM,2BAA2B,OAAO,qBAAqB;AAC7D,oBAAkB,UAAU;AAC5B,2BAAyB,UAAU;AACnC,YAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,gBAAgB,CAAC;AAAA,MACrB;AAAA,IAAA,MAGI;;AACJ,YAAM,QAAQ,YAAY,QAAQ,kBAAkB;AAGpD,UAAI,OAAO;AACT,gCAAkB,YAAlB,2CAA4B;AAC5B,uCAAyB,YAAzB,kDAAmC,MAAM,WAAW,CAAC,KAAK;AAAA,MAC5D;AACA,YAAMiB,UAAS,YAAY,QAAQ,mBAAmB;AAGtD,UAAIA,SAAQ;AACV,gCAAkB,YAAlB,2CAA4B;AAAA,UAC1B,YAAYA,QAAO;AAAA,UACnB,UAAU;AAAA,UACV,KAAKA,QAAO;AAAA,QAAA;AAEd,uCAAyB,YAAzB,kDAAmCA,QAAO,WAAW,CAAC,KAAK;AAAA,MAC7D;AAAA,IACF;AACA,WAAO,GAAG,eAAe,aAAa;AACtC,WAAO,MAAM;AACX,aAAO,IAAI,eAAe,aAAa;AAAA,IACzC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX;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,MAC3B,cAAc,CAAC,cACb,SAAS,aAAa,QAAQ,SAAS,IAAI;AAAA,MAC7C,aAAa,CAAC,QACZ,SAAS,YAAY,QAAQ,OAAO,MAAM,IAAI;AAAA,MAChD,eAAe,MAAO,SAAS,kBAAkB,MAAM,IAAI,CAAA;AAAA,MAC3D,UAAU,MAAM,SAAA;AAAA,MAChB;AAAA,MACA,YAAY,MAAM,WAAA;AAAA,IAAW;AAAA,IAE/B,CAAC,QAAQ,WAAW,UAAU,UAAU;AAAA,EAAA;AAI1C,QAAM,gBACJ,OAAO,qBAAqB,aACxB,iBAAA,IACC,oBAAoB;AAI3B,YAAU,MAAM;AACd,QAAI,CAAC,cAAe;AACpB,QAAI,iBAAiB,aAAa,EAAE,aAAa,UAAU;AACzD,oBAAc,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,QAAM,cACJ,UAAU,WAAW,WACnB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAWjB,SAAO;AAAA,MAClB,OAAO,mBAAmB,aAAa;AAAA,IAAA;AAAA,EAAA,IAEvC;AAEN,QAAM,YAA4B;AAAA,IAChC,OAAO,EAAE,GAAG,uBAAuB,GAAG;IACtC,CAAC,cAAc;AAAA,EAAA;AAOjB,QAAM,CAAC,mBAAmB,oBAAoB,IAAI;AAAA,IAChD;AAAA,EAAA;AAEF,QAAM,qBACJ,OAAO,WAAW,cAAc,YAAY;AAC9C,qBAAmB,MAAM;AACvB,UAAM,SACJ,OAAO,yBAAyB,aAC5B,qBAAA,IACC,wBAAwB;AAC/B,yBAAqB,CAAC,SAAU,SAAS,SAAS,OAAO,MAAO;AAAA,EAClE,CAAC;AAED,QAAM,kBACJ,iBAAiB,WACf;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WACE,oBACI,GAAGA,SAAO,WAAW,IAAIA,SAAO,iBAAiB,KACjDA,SAAO;AAAA,MAEb,OAAO,UAAU;AAAA,MACjB,cAAY,UAAU;AAAA,MACtB,iBAAe;AAAA,MACf,SAAS,MAAM,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAAA,MAEzC,UAAA,oBAAC,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,IAAA;AAAA,EAAA,IAExB;AAEN,SACE,qBAAC,OAAA,EAAI,WAAWA,SAAO,YAEpB,UAAA;AAAA,IAAA,eAAe,CAAC,gBACf,oBAAC,OAAA,EAAI,WAAWA,SAAO,eAAgB,uBAAY,IACjD;AAAA,IACH,eAAe,gBACZ,aAAa,aAAa,aAAa,IACvC;AAAA,IACJ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WACE,YAAY,GAAGA,SAAO,YAAY,IAAI,SAAS,KAAKA,SAAO;AAAA,MAAA;AAAA,IAAA;AAAA,IAK9D,mBAAmB,oBAChB,aAAa,iBAAiB,iBAAiB,IAC/C;AAAA,IACH,iBAAiB,WAChB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,SAAS,MAAM,iBAAiB,KAAK;AAAA,QACrC,QAAQ;AAAA,MAAA;AAAA,IAAA,IAER;AAAA,EAAA,GACN;AAEJ,CAAC;AClvBM,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAyB;AACvB,QAAM,WAAW;AAAA,IACf,MACE;AAAA,MACE,wBAAwB,UAAU,WAAW,CAAA,CAAE;AAAA,IAAA;AAAA,IAEnD,CAAC,UAAU,OAAO;AAAA,EAAA;AAKpB,QAAM,mBAAmB;AAAA,IACvB,MACE,cAAc,OAAO;AAAA,MACnB,cAAc;AACZ,eAAO,sBAAsB,aAAa;AAAA,MAC5C;AAAA,IAAA,CACD;AAAA,IACH,CAAA;AAAA,EAAC;AAGH,QAAM,aAAa;AAAA,IACjB,MAAM;AAAA,MACJ,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,YAAY,EAAE,UAAU,OAAO;AAAA,MAC/B,kBAAkB,EAAE,gBAAgB;AAAA,MACpC;AAAA,IAAA;AAAA,IAEF,CAAC,cAAc;AAAA,EAAA;AAGjB,QAAM,SAAS;AAAA,IACb;AAAA,MACE;AAAA,MACA,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU;AAAA,MACV,mBAAmB;AAAA,MACnB,aAAa;AAAA,QACX,YAAY,EAAE,OAAOA,SAAO,cAAA;AAAA,MAAc;AAAA,IAC5C;AAAA,IAEF,CAAC,UAAU;AAAA,EAAA;AAOb,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;AC3GO,MAAM,aAAa;AACnB,MAAM,YAAY;AASlB,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKqB;AACnB,MAAI,mDAAiB,OAAQ,QAAO;AACpC,QAAM,WAA2B;AAAA,IAC/B,KAAK;AAAA,IACL,OAAO,OAAO;AAAA,IACd,QAAQ;AAAA,EAAA;AAEV,MAAI,oBAAoB,cAAc;AACpC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,KAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,QAAQ;AAAA,MAAA;AAAA,IACV;AAAA,EAEJ;AACA,SAAO,CAAC,QAAQ;AAClB;AC1BO,SAAS,eACd,QACA,UACA,UAAuB,CAAA,GACjB;AACN,QAAM,WAAW;AAAA,IACf,wBAAwB,UAAU,OAAO;AAAA,EAAA;AAE3C,MAAI,CAAC,SAAU;AACf,MAAI,kBAAkB,QAAQ,QAAQ,EAAG;AACzC,aAAW,SAAS,oBAAoB,QAAQ,GAAG;AACjD,QAAI,kBAAkB,QAAQ,KAAK,EAAG;AACtC,yBAAqB,QAAQ,iBAAiB,KAAK,CAAC;AAAA,EACtD;AACF;AAEA,SAAS,kBAAkB,QAAgB,UAA2B;AACpE,MAAI;AACF,WAAO,OACJ,QACA,QACA,cAAc,UAAU,EAAE,aAAa,WAAA,CAAY,EACnD,IAAA;AAAA,EACL,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,qBAAqB,QAAgB,MAAoB;AAChE,MAAI,CAAC,KAAM;AACX,SACG,MAAA,EACA,MAAA,EACA,cAAc;AAAA,IACb,MAAM;AAAA,IACN,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM;AAAA,EAAA,CACjC,EACA,IAAA;AACL;AAGO,SAAS,oBAAoB,UAA4B;AAC9D,QAAM,MAAgB,CAAA;AACtB,aAAW,CAAC,GAAG,IAAI,KAAK,SAAS,MAAM,kBAAkB,EAAE,WAAW;AACpE,QAAI,CAAC,KAAM;AACX,QAAI,IAAI,MAAM,GAAG;AACf,UAAI,KAAK,IAAI;AACb;AAAA,IACF;AACA,eAAW,SAAS,KAAK,MAAM,QAAQ,GAAG;AACxC,UAAI,MAAM,KAAA,EAAQ,KAAI,KAAK,KAAK;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAA0B;AACzD,SAAO,SACJ,QAAQ,yBAAyB,EAAE,EACnC,QAAQ,0BAA0B,IAAI,EACtC,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,qBAAqB,EAAE,EAC/B,QAAQ,qBAAqB,EAAE,EAC/B,QAAQ,YAAY,EAAE,EACtB,QAAQ,YAAY,EAAE,EACtB,QAAQ,OAAO,GAAG,EAClB,QAAQ,QAAQ,GAAG,EACnB,KAAA;AACL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC1EA,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,CAACL,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,IAAI;AAAA,QAE1B,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWK,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,CAACL,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,CAAC;AAAA,MAAA;AAAA,MATlB;AAAA,IAAA,CAWR,GACH;AAAA,wBAEC,OAAA,EAAI,WAAWK,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,CAACL,OAAMA,GAAE,eAAA;AAAA,QACtB,SAAS,MAAM,OAAO,CAAC;AAAA,MAAA;AAAA,MATlB;AAAA,IAAA,CAWR,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AC3DA,MAAM,yCAAyB,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGD,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAMzB,MAAM,eAAe;AAErB,MAAM,eAAe;AAGd,SAAS,WAAW,QAA4C;AACrE,MAAI,CAAC,UAAU,OAAO,eAAe,MAAO,QAAO;AACnD,MAAI;AACF,WAAO,OAAO,MAAM,QAAQ,MAAM;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,aAAa,QAA4C;AACvE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,SAAS,MAAM;AAC/B;AAGO,SAAS,aAAa,QAA2C;AACtE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,EAAE,KAAA,IAAS,OAAO,cAAc,MAAM;AAC5C,SAAO,OAAO,SAAS,WAAW,OAAO;AAC3C;AAGA,SAAS,gBAAgB,QAAwB;;AAC/C,QAAM,QAAO,YAAO,qBAAP,mBAAyB,WAAW;AAAA,IAC/C,CAAC,cAAc,UAAU,SAAS;AAAA;AAEpC,QAAM,cAAc,kCAAM,YAAN,mBAChB;AACJ,SAAO,cAAc;AACvB;AASO,SAAS,kBAAkB,QAAgB,KAAqB;AACrE,QAAM,QAAQ,IAAI,KAAA;AAClB,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,iBAAiB,KAAK,KAAK,EAAG,QAAO;AACzC,MAAI,aAAa,KAAK,KAAK,EAAG,QAAO,GAAG,gBAAgB,MAAM,CAAC,MAAM,KAAK;AAC1E,MAAI,cAAc,KAAK,KAAK,EAAG,QAAO;AACtC,MAAI,CAAC,aAAa,KAAK,KAAK,EAAG,QAAO;AACtC,SAAO,GAAG,gBAAgB,MAAM,CAAC,MAAM,KAAK;AAC9C;AAYO,SAAS,UAAU,QAAmC,KAAsB;AACjF,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,OAAO,kBAAkB,QAAQ,GAAG;AAC1C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,CAAC,OAAO,IAAA,EAAM,QAAQ,EAAE,KAAA,CAAM,EAAG,QAAO;AAE5C,QAAM,UAAU,OAAO,MAAM,UAAU;AACvC,QAAM,aAAa,aAAa,MAAM;AACtC,QAAM,QAAQ,OACX,MAAA,EACA,MAAA,EACA,gBAAgB,MAAM,EACtB,QAAQ,EAAE,KAAA,CAAM;AAEnB,MAAI,WAAW,CAAC,WAAY,OAAM,cAAc,EAAE,MAAM,QAAQ,MAAM,MAAM;AAE5E,SAAO,MAAM,IAAA;AACf;AAGO,SAAS,WAAW,QAA4C;AACrE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OACJ,MAAA,EACA,MAAA,EACA,gBAAgB,MAAM,EACtB,UAAA,EACA,QAAQ,mBAAmB,IAAI,EAC/B,IAAA;AACL;AAQO,SAAS,gBAAgBc,QAAe,SAAyB;AACtE,MAAI;AACF,UAAM,MAAM,IAAI,IAAIA,QAAO,OAAO;AAClC,QAAI,mBAAmB,IAAI,IAAI,QAAQ,UAAU,IAAI;AAAA,EACvD,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAMO,SAAS,YAAYA,QAAe,SAA0B;AACnE,MAAI,CAACA,OAAM,KAAA,EAAQ,QAAO;AAC1B,QAAM,OAAO,gBAAgBA,QAAO,OAAO;AAC3C,MAAI,SAAS,IAAK,QAAO;AACzB,SAAO,KAAK,MAAM,UAAU,qBAAqB;AACjD,SAAO;AACT;AAGO,SAAS,WAAW,OAGf;AACV,MAAI,MAAM,QAAQ,QAAS,QAAO;AAClC,SAAO,CAAC,oBAAoB,MAAM,WAAW;AAC/C;;;;;;;;;;;;;;;;;AC7HO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAqB;AACnB,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AAEtC,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,YAAY;AAAA,QACZ,OAAM;AAAA,QAEN,kBAAkB,CAACd,OAAMA,GAAE,eAAA;AAAA,QAE3B,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,SAAS,MAAM,QAAQ,KAAK;AAAA,UAAA;AAAA,QAAA;AAAA,MAC9B;AAAA,IAAA,EACF,CACF;AAAA,EAAA,GACF;AAEJ;AAEA,SAAS,UAAU;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMG;AACD,QAAM,IAAuB,EAAE,GAAG,0BAA0B,GAAG,OAAA;AAG/D,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,MAAM,aAAa,MAAM,CAAC;AACzD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,QAAM,UAAU,WAAW,MAAM;AACjC,QAAM,SAAS,IAAI,KAAA,EAAO,SAAS;AACnC,QAAM,YAAY,CAACA,OAAuBA,GAAE,eAAA;AAE5C,QAAMuB,SAAQ,MAAM;AAClB,QAAI,CAAC,UAAU,QAAQ,GAAG,GAAG;AAC3B,iBAAW,IAAI;AACf;AAAA,IACF;AACA,eAAW,KAAK;AAChB,YAAA;AAAA,EACF;AAEA,QAAM,kBAAkB,MAAM;AAE5B,gBAAY,kBAAkB,QAAQ,GAAG,GAAG,OAAO,SAAS,IAAI;AAAA,EAClE;AAEA,QAAM,SAAS,MAAM;AACnB,eAAW,MAAM;AACjB,YAAA;AAAA,EACF;AAEA,QAAM,iBAAiB,CAACvB,OAA4C;AAElE,QAAI,CAAC,WAAWA,EAAC,EAAG;AACpB,IAAAA,GAAE,eAAA;AACF,IAAAuB,OAAA;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,YAAY,GAAGlB,SAAO,KAAK,IAAI,SAAS,KAAKA,SAAO;AAAA,MAC/D;AAAA,MACA,qBAAkB;AAAA,MAClB,MAAK;AAAA,MACL,cAAY,EAAE;AAAA,MAEd,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAW,GAAGA,SAAO,KAAK,GAAG,UAAU,IAAIA,SAAO,YAAY,KAAK,EAAE,IACzE,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWA,SAAO;AAAA,YAClB,mBAAgB;AAAA,YAChB,qBAAmB,UAAU,KAAK;AAAA,YAClC,MAAK;AAAA,YACL,OAAO;AAAA,YACP,UAAU,CAACL,OAAM;AACf,qBAAOA,GAAE,OAAO,KAAK;AACrB,yBAAW,KAAK;AAAA,YAClB;AAAA,YACA,WAAW;AAAA,YACX,aAAa,EAAE;AAAA,YACf,cAAY,EAAE;AAAA,YACd,gBAAc,WAAW;AAAA,YACzB,OAAO,UAAU,EAAE,UAAU;AAAA,YAC7B,WAAS;AAAA,YACT,cAAa;AAAA,YACb,aAAY;AAAA,YACZ,gBAAe;AAAA,YACf,YAAY;AAAA,UAAA;AAAA,QAAA,GAEhB;AAAA,QAEA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAW,GAAGK,SAAO,GAAG,IAAIA,SAAO,KAAK;AAAA,YACxC,oBAAiB;AAAA,YACjB,OAAO,EAAE;AAAA,YACT,cAAY,EAAE;AAAA,YACd,UAAU,CAAC,WAAW,CAAC;AAAA,YACvB,aAAa;AAAA,YACb,SAASkB;AAAA,YAET,UAAA,oBAAC,WAAA,EAAU,MAAM,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA;AAAA,4BAGtB,QAAA,EAAK,WAAWlB,SAAO,SAAS,eAAY,QAAO;AAAA,QAEpD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAWA,SAAO;AAAA,YAClB,oBAAiB;AAAA,YACjB,OAAO,EAAE;AAAA,YACT,cAAY,EAAE;AAAA,YACd,UAAU,CAAC;AAAA,YACX,aAAa;AAAA,YACb,SAAS;AAAA,YAET,UAAA,oBAAC,kBAAA,EAAiB,MAAM,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA;AAAA,QAE9B;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAWA,SAAO;AAAA,YAClB,oBAAiB;AAAA,YACjB,OAAO,EAAE;AAAA,YACT,cAAY,EAAE;AAAA,YACd,UAAU,CAAC;AAAA,YACX,aAAa;AAAA,YACb,SAAS;AAAA,YAET,UAAA,oBAAC,WAAA,EAAU,MAAM,GAAA,CAAI;AAAA,UAAA;AAAA,QAAA;AAAA,MACvB;AAAA,IAAA;AAAA,EAAA;AAGN;ACpLO,SAAS,sBACd,OAC2B;AAC3B,MAAI,CAAC,UAAU,KAAK,EAAG,QAAO;AAE9B,QAAM,OAAO,aAAa,KAAK;AAC/B,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,GAAG;AACnD,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,QAAQ,KAAK,IAAI;AAEnD,MAAI,oBAAoB;AACxB,WAASmB,OAAM,KAAK,KAAKA,OAAM,KAAK,QAAQA,QAAO;AACjD,QAAI,YAAY,KAAK,KAAK,KAAK,OAAOA,IAAG,GAAG;AAC1C,0BAAoB;AACpB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,WAAW,KAAK,WAAW;AAAA,IACxC;AAAA,IACA,eAAe,KAAK,QAAQ,KAAK,KAAK,WAAW,KAAK,IAAI;AAAA,IAC1D,eAAe,KAAK,SAAS,KAAK,KAAK,UAAU,KAAK,IAAI;AAAA,EAAA;AAE9D;AAGO,SAAS,qBACd,WACA,KACS;AACT,MAAI,QAAQ;AACZ,YAAU,YAAY,CAAC,MAAM,YAAY;AACvC,QAAI,OAAO,WAAW,OAAO,UAAU,KAAK,UAAU;AACpD,cAAQ;AAAA,IACV;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,SAAS,cAAc,QAAgB,OAAwB;AACpE,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK;AAC3B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,CAAC,OAAO,SAAS,aAAA,EAAgB,QAAO;AAAA,EAC9C;AACA,SAAO;AACT;AAEO,SAAS,aAAa,QAAgB,OAAwB;AACnE,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK;AAC3B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,CAAC,OAAO,SAAS,YAAA,EAAe,QAAO;AAAA,EAC7C;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,QAAgB,OAAwB;AACvE,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK;AAC3B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,CAAC,OAAO,SAAS,gBAAA,EAAmB,QAAO;AAAA,EACjD;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,QAAgB,OAAwB;AACtE,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK;AAC3B,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,CAAC,OAAO,SAAS,eAAA,EAAkB,QAAO;AAAA,EAChD;AACA,SAAO;AACT;AAGO,SAAS,mBAAmB,QAAyB;AAC1D,QAAM,OAAO,sBAAsB,OAAO,KAAK;AAC/C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,cAAe,QAAO,OAAO,SAAS,YAAA;AAC/C,SAAO,OAAO,SAAS,UAAA;AACzB;AAGO,SAAS,sBAAsB,QAAyB;AAC7D,QAAM,OAAO,sBAAsB,OAAO,KAAK;AAC/C,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,eAAe;AACtB,QAAI,KAAK,cAAe,QAAO,OAAO,SAAS,YAAA;AAC/C,WAAO;AAAA,EACT;AACA,SAAO,OAAO,SAAS,aAAA;AACzB;AAGA,MAAM,wBAAwB,oBAAI,IAAI,CAAC,WAAW,SAAS,CAAC;AAM5D,SAAS,oBACP,QACsC;AACtC,QAAM,EAAE,cAAc,OAAO;AAC7B,QAAM,UAAgD,CAAA;AAEtD,MAAI,qBAAqB,eAAe;AACtC,cAAU,YAAY,CAACC,OAAMC,SAAQ;AACnC,cAAQ,KAAK,EAAE,KAAAA,MAAK,MAAAD,OAAM;AAAA,IAC5B,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,WAAW,UAAU,KAAK;AACxC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAAM,MAAM,OAAO,MAAM,KAAK;AACpC,QAAM,OAAO,OAAO,MAAM,IAAI,OAAO,GAAG;AACxC,MAAI,KAAM,SAAQ,KAAK,EAAE,KAAK,MAAM;AACpC,SAAO;AACT;AAQO,SAAS,0BAA0B,QAAyB;;AACjE,QAAM,UAAU,oBAAoB,MAAM;AAC1C,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,QAAM,YAAY,OAAO,MAAM,OAAO,MAAM;AAC5C,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,KAAK,OAAO,MAAM;AAExB,aAAW,EAAE,KAAK,KAAA,KAAU,CAAC,GAAG,OAAO,EAAE,KAAK,CAACJ,IAAGnB,OAAMA,GAAE,MAAMmB,GAAE,GAAG,GAAG;AACtE,UAAM,UACJ,KAAK,eAAe,KACpB,CAAC,GAAC,UAAK,eAAL,mBAAiB,gBACnB,KAAK,WAAW,QAAQ,SAAS;AACnC,QAAI,QAAS;AACb,OAAG,YAAY,MAAM,GAAG,MAAM,KAAK,WAAW,GAAG,UAAU,eAAgB;AAAA,EAC7E;AAEA,MAAI,CAAC,GAAG,WAAY,QAAO;AAC3B,SAAO,KAAK,SAAS,GAAG,eAAA,CAAgB;AACxC,SAAO;AACT;AASO,SAAS,wBAAwB,QAAyB;AAC/D,QAAM,UAAU,oBAAoB,MAAM;AAC1C,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAE5B,QAAM,KAAK,OAAO,MAAM;AACxB,aAAW,EAAE,KAAK,KAAA,KAAU,SAAS;AACnC,UAAM,QAAS,KAAK,KAAK,KAAK,SAAS,CAAA;AAIvC,UAAM,OAAgC,EAAE,GAAG,KAAK,MAAA;AAChD,QAAI,UAAU;AACd,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,UAAI,sBAAsB,IAAI,GAAG,EAAG;AACpC,YAAM,YAAW,6BAAM,YAAW;AAClC,UAAI,KAAK,GAAG,MAAM,UAAU;AAC1B,aAAK,GAAG,IAAI;AACZ,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,QAAI,QAAS,IAAG,cAAc,KAAK,QAAW,IAAI;AAAA,EACpD;AAEA,MAAI,CAAC,GAAG,WAAY,QAAO;AAC3B,SAAO,KAAK,SAAS,EAAE;AACvB,SAAO;AACT;AAGA,SAAS,UAAU,QAAsD;AACvE,QAAM,QAAQ,OAAO,MAAM,UAAU;AACrC,WAAS,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,GAAG;AACvC,QAAI,MAAM,KAAK,CAAC,EAAE,KAAK,SAAS,SAAS;AACvC,aAAO,EAAE,KAAK,MAAM,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK,CAAC,EAAA;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,QAA8C;AAClD,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AAC1C,QAAI,UAAU,KAAM,QAAO;AAC3B,QAAI,KAAK,KAAK,SAAS,SAAS;AAC9B,cAAQ,EAAE,KAAK,KAAA;AACf,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAGA,SAAS,aACP,QACA,OACA,MACA,OACM;AACN,QAAM,MAAM,SAAS,IAAI,MAAM,IAAI;AACnC,QAAM,QAAQ,MAAM,MAAM;AAC1B,QAAM,aAAa,QAAQ,IAAI,WAAW,SAAS,QAAQ,QAAQ,GAAG,SAAS,QAAQ,QAAQ,GAAG,MAAM,IAAI;AAC5G,QAAM,WACJ,QACA,IAAI;AAAA,IACF,SAAS,QAAQ,QAAQ,IAAI,SAAS;AAAA,IACtC,SAAS,QAAQ,QAAQ,IAAI,QAAQ;AAAA,IACrC,MAAM;AAAA,EAAA;AAEV,SAAO,KAAK;AAAA,IACV,OAAO,MAAM,GAAG;AAAA,MACd,IAAI;AAAA,QACF,OAAO,MAAM,IAAI,QAAQ,UAAU;AAAA,QACnC,OAAO,MAAM,IAAI,QAAQ,QAAQ;AAAA,MAAA;AAAA,IACnC;AAAA,EACF;AAEJ;AAMO,SAAS,iBAAiB,QAAyB;AACxD,QAAM,QAAQ,UAAU,MAAM;AAC9B,MAAI,CAAC,MAAO,QAAO;AACnB,eAAa,QAAQ,OAAO,OAAO,SAAS,IAAI,MAAM,IAAI,EAAE,SAAS,CAAC;AACtE,SAAO,aAAa,QAAQ,CAAC;AAC/B;AAMO,SAAS,oBAAoB,QAAyB;AAC3D,QAAM,QAAQ,UAAU,MAAM;AAC9B,MAAI,CAAC,MAAO,QAAO;AACnB,eAAa,QAAQ,OAAO,OAAO,SAAS,IAAI,MAAM,IAAI,EAAE,QAAQ,CAAC;AACrE,SAAO,gBAAgB,QAAQ,CAAC;AAClC;;;;;;;;;;;;;;;;;;;;;AC7MA,SAAS,UACP,QACA,MAC4C;AAC5C,MAAI;AACF,UAAM,QAAQ,WAAW,OAAO,MAAM,IAAI,QAAQ,OAAO,KAAK,SAAS,MAAM,CAAC,CAAC,CAAC;AAChF,QAAI,CAAC,MAAO,QAAO,EAAE,WAAW,OAAO,WAAW,MAAA;AAIlD,UAAM,MAAM,SAAS,IAAI,MAAM,KAAK,EAAE,CAAC;AACvC,UAAM,OAAO,IAAI,SAAS,MAAM,MAAM,MAAM,MAAM,EAAE,CAAC;AACrD,WAAO;AAAA,MACL,WAAW,KAAK,WAAW,IAAI;AAAA,MAC/B,WAAW,KAAK,UAAU,IAAI;AAAA,IAAA;AAAA,EAElC,QAAQ;AACN,WAAO,EAAE,WAAW,OAAO,WAAW,MAAA;AAAA,EACxC;AACF;AAUA,MAAM,iBAAiB;AACvB,MAAM,iBAAiB;AAEvB,MAAM,aAAa;AAEnB,MAAM,mBAAmB;AAKzB,MAAM,gBAAgB;AAGtB,SAAS,YAAY,QAAgB,MAAqC;AACxE,QAAM,QAAQ,KAAK,QAAQ,OAAO;AAClC,QAAMG,OAAM,KAAK,QAAQ,IAAI;AAC7B,MAAI,CAAC,SAAS,CAACA,KAAK,QAAO;AAE3B,MAAI;AACF,WAAO,KAAK,SAAS,MAAM,CAAC;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,WAAW,KAAK,sBAAA;AACtB,QAAM,UAAUA,KAAI,sBAAA;AACpB,QAAM,YAAY,MAAM,sBAAA;AACxB,QAAM,QAAQ,UAAU,QAAQ,IAAI;AACpC,SAAO;AAAA,IACL;AAAA,IACA,GAAG;AAAA,IACH,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,SAAS,SAAS;AAAA,IAClB,UAAU,SAAS;AAAA,IACnB,WAAW,UAAU;AAAA,IACrB,UAAU,UAAU;AAAA,IACpB,YAAY,UAAU;AAAA,IACtB,aAAa,UAAU;AAAA,EAAA;AAE3B;AAGA,SAAS,kBACP,QACA,MACA,MACS;AACT,MAAI;AACJ,MAAI;AACF,UAAM,OAAO,KAAK,SAAS,MAAM,CAAC;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,WAAW,OAAO,MAAM,IAAI,QAAQ,GAAG,CAAC;AACtD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,YACJ,SAAS,QACL,cAAc,aAAa,KAAK,IAChC,cAAc,aAAa,KAAK;AACtC,SAAO,KAAK,SAAS,OAAO,MAAM,GAAG,aAAa,SAAS,CAAC;AAC5D,SAAO;AACT;AAaA,SAAS,aACP,QACA,QACA,MACgB;AAChB,QAAM,OAAO,sBAAsB,OAAO,KAAK;AAC/C,QAAM,QAAO,6BAAM,aAAY;AAC/B,QAAM,QAAO,6BAAM,aAAY;AAG/B,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAwB,CAAA;AAE9B,MAAI,SAAS,SAAS,SAAS,SAAS;AACtC,UAAM;AAAA,MACJ;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,sBAAsB,IAAI,IAAI,OAAO;AAAA,QAC3D,0BAAO,kBAAA,EAAiB;AAAA,QACxB,KAAK,MAAM,iBAAiB,QAAQ,IAAI;AAAA,MAAA;AAAA,MAE1C;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,qBAAqB,IAAI,IAAI,OAAO;AAAA,QAC1D,0BAAO,iBAAA,EAAgB;AAAA,QACvB,KAAK,MAAM,gBAAgB,QAAQ,IAAI;AAAA,MAAA;AAAA,MAEzC;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,mBAAmB,IAAI,IAAI,OAAO;AAAA,QACxD,0BAAO,kBAAA,EAAiB;AAAA;AAAA,QAExB,UAAU,CAAC,EAAC,6BAAM,kBAAiB,EAAC,6BAAM;AAAA,QAC1C,KAAK,MAAM,sBAAsB,MAAM;AAAA,MAAA;AAAA,IACzC;AAAA,EAEJ;AAEA,MAAI,SAAS,SAAS,SAAS,SAAS;AACtC,UAAM;AAAA,MACJ;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,mBAAmB,IAAI,IAAI,OAAO;AAAA,QACxD,0BAAO,eAAA,EAAc;AAAA;AAAA,QAErB,UAAU,CAAC,EAAC,6BAAM;AAAA,QAClB,KAAK,MAAM,cAAc,QAAQ,IAAI;AAAA,MAAA;AAAA,MAEvC;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,kBAAkB,IAAI,IAAI,OAAO;AAAA,QACvD,0BAAO,cAAA,EAAa;AAAA,QACpB,KAAK,MAAM,aAAa,QAAQ,IAAI;AAAA,MAAA;AAAA,MAEtC;AAAA,QACE,KAAK;AAAA,QACL,OAAO;AAAA,QACP,OAAO,QAAQ,OAAO,gBAAgB,IAAI,IAAI,OAAO;AAAA,QACrD,0BAAO,eAAA,EAAc;AAAA,QACrB,UAAU,CAAC,EAAC,6BAAM;AAAA,QAClB,KAAK,MAAM,mBAAmB,MAAM;AAAA,MAAA;AAAA,IACtC;AAAA,EAEJ;AAGA,QAAM;AAAA,IACJ;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO,OAAO;AAAA,MACd,0BAAO,YAAA,EAAW;AAAA,MAClB,KAAK,MAAM,0BAA0B,MAAM;AAAA,IAAA;AAAA,IAE7C;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAO,OAAO;AAAA,MACd,0BAAO,eAAA,EAAc;AAAA,MACrB,KAAK,MAAM,wBAAwB,MAAM;AAAA,IAAA;AAAA,EAC3C;AAGF,SAAO;AACT;AAYO,SAAS,aAAa,EAAE,QAAQ,UAA6B;AAClE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA2B,IAAI;AACzD,QAAM,CAACG,OAAM,OAAO,IAAI,SAA4B,IAAI;AAExD,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,UAAU,OAA0B,IAAI;AAC9C,UAAQ,UAAUA;AAElB,QAAM,aAAa,YAAY,MAAM;AACnC,QAAI,CAAC,SAAS,QAAS;AACvB,aAAS,UAAU;AACnB,aAAS,IAAI;AAAA,EACf,GAAG,CAAA,CAAE;AAEL,QAAM,YAAY,YAAY,MAAM,QAAQ,IAAI,GAAG,CAAA,CAAE;AAGrD,QAAM,iBAAiB,YAAY,MAAM;;AACvC,UAAM,QAAO,cAAS,YAAT,mBAAkB;AAC/B,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,KAAK,cAAc,YAAY,QAAQ,IAAI,IAAI;AAC5D,aAAS,UAAU;AACnB,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,gBAAgB,OAA6C,IAAI;AACvE,QAAM,qBAAqB,YAAY,MAAM;AAC3C,QAAI,cAAc,YAAY,KAAM;AACpC,iBAAa,cAAc,OAAO;AAClC,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAA,CAAE;AAQL,YAAU,MAAM;AACd,UAAM,SAAS,CAAC,UAAsB;;AACpC,UAAI,CAAC,OAAO,cAAc,QAAQ,QAAS;AAC3C,YAAM,SAAS,MAAM;AAGrB,WAAI,sCAAQ,YAAR,gCAAkB,6CAA6C;AACjE,2BAAA;AACA;AAAA,MACF;AAEA,YAAM,OACJ,UAAU,OAAO,KAAK,IAAI,SAAS,MAAM,IACpC,OAAO,QAAQ,QAAQ,IACxB;AAEN,UAAI,CAAC,MAAM;AAET,YAAI,SAAS,WAAW,cAAc,YAAY,MAAM;AACtD,wBAAc,UAAU,WAAW,MAAM;AACvC,0BAAc,UAAU;AACxB,uBAAA;AAAA,UACF,GAAG,aAAa;AAAA,QAClB;AACA;AAAA,MACF;AAEA,yBAAA;AACA,YAAI,cAAS,YAAT,mBAAkB,UAAS,KAAM;AACrC,YAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,eAAS,UAAU;AACnB,eAAS,IAAI;AAAA,IACf;AACA,UAAM,eAAe,MAAM;AACzB,yBAAA;AACA,iBAAA;AAAA,IACF;AAGA,aAAS,iBAAiB,aAAa,MAAM;AAC7C,aAAS,iBAAiB,cAAc,YAAY;AACpD,WAAO,iBAAiB,UAAU,gBAAgB,IAAI;AACtD,WAAO,iBAAiB,UAAU,cAAc;AAChD,WAAO,MAAM;AACX,yBAAA;AACA,eAAS,oBAAoB,aAAa,MAAM;AAChD,eAAS,oBAAoB,cAAc,YAAY;AACvD,aAAO,oBAAoB,UAAU,gBAAgB,IAAI;AACzD,aAAO,oBAAoB,UAAU,cAAc;AAAA,IACrD;AAAA,EACF,GAAG,CAAC,QAAQ,YAAY,oBAAoB,cAAc,CAAC;AAG3D,YAAU,MAAM;AACd,UAAM,MAAM,OAAO,KAAK;AACxB,UAAM,gBAAgB,CAAC,UAAsB;AAC3C,YAAM,OAAO,sBAAsB,OAAO,KAAK;AAC/C,YAAM,EAAE,cAAc,OAAO;AAC7B,UAAI,EAAC,6BAAM,gBAAe,EAAE,qBAAqB,eAAgB;AACjE,YAAM,SAAS,OAAO,KAAK,YAAY;AAAA,QACrC,MAAM,MAAM;AAAA,QACZ,KAAK,MAAM;AAAA,MAAA,CACZ;AACD,UAAI,CAAC,UAAU,CAAC,qBAAqB,WAAW,OAAO,GAAG,EAAG;AAC7D,YAAM,eAAA;AACN,eAAS,UAAU;AACnB,eAAS,IAAI;AACb,cAAQ,EAAE,MAAM,SAAS,GAAG,MAAM,SAAS,GAAG,MAAM,SAAS;AAAA,IAC/D;AACA,QAAI,iBAAiB,eAAe,aAAa;AACjD,WAAO,MAAM,IAAI,oBAAoB,eAAe,aAAa;AAAA,EACnE,GAAG,CAAC,MAAM,CAAC;AAGX,YAAU,MAAM;AACd,QAAI,CAACA,MAAM;AACX,UAAM,QAAQ,CAAC,UAAyB;AACtC,UAAI,MAAM,QAAQ,SAAU,WAAA;AAAA,IAC9B;AACA,UAAM,SAAS,CAAC,UAAsB;;AACpC,YAAM,SAAS,MAAM;AACrB,WAAI,sCAAQ,YAAR,gCAAkB,qBAAsB;AAC5C,gBAAA;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,OAAO,IAAI;AAChD,aAAS,iBAAiB,aAAa,MAAM;AAC7C,WAAO,MAAM;AACX,eAAS,oBAAoB,WAAW,OAAO,IAAI;AACnD,eAAS,oBAAoB,aAAa,MAAM;AAAA,IAClD;AAAA,EACF,GAAG,CAACA,OAAM,SAAS,CAAC;AAEpB,MAAI,OAAO,aAAa,YAAa,QAAO;AAE5C,QAAM,iBAAiB,CAAC,SAAwB;AAC9C,QAAI,CAAC,MAAO;AACZ,QAAI,CAAC,kBAAkB,QAAQ,MAAM,MAAM,IAAI,EAAG;AAClD,aAAS,IAAI;AACb,aAAS,UAAU;AACnB;AAAA,MACE,SAAS,QACL,EAAE,MAAM,GAAG,MAAM,YAAY,GAAG,GAAG,MAAM,WACzC,EAAE,MAAM,GAAG,MAAM,SAAS,GAAG,MAAM,WAAW,EAAA;AAAA,IAAE;AAAA,EAExD;AAEA,QAAM,QAAQA,QAAO,aAAa,QAAQ,QAAQA,MAAK,IAAI,IAAI,CAAA;AAC/D,QAAM,cAAc,CAAC,CAAC,SAAS,CAACA,SAAQ,OAAO;AAE/C,SAAO;AAAA,IACL,qBAAAjB,YAAA,EACG,UAAA;AAAA,MAAA,eAAe,QACd,qBAAAA,YAAA,EACE,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,qBAAkB;AAAA,YAClB,WAAW,GAAGL,SAAO,MAAM,IAAIA,SAAO,SAAS;AAAA,YAC/C,OAAO;AAAA,cACL,MAAM,MAAM,YAAY;AAAA;AAAA,cAExB,KAAK,MAAM;AAAA,cACX,QAAQ,MAAM;AAAA,YAAA;AAAA,YAEhB,OAAO,OAAO;AAAA,YACd,cAAY,OAAO;AAAA,YAEnB,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,YACtB,SAAS,MAAM,eAAe,KAAK;AAAA,YAEnC,UAAA,oBAAC,QAAA,EAAK,eAAW,MAAC,UAAA,IAAA,CAAC;AAAA,UAAA;AAAA,QAAA;AAAA,QAErB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,qBAAkB;AAAA,YAClB,WAAW,GAAGK,SAAO,MAAM,IAAIA,SAAO,SAAS;AAAA,YAC/C,OAAO;AAAA;AAAA,cAEL,MAAM,MAAM;AAAA,cACZ,KAAK,MAAM,WAAW;AAAA,cACtB,OAAO,MAAM;AAAA,YAAA;AAAA,YAEf,OAAO,OAAO;AAAA,YACd,cAAY,OAAO;AAAA,YACnB,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,YACtB,SAAS,MAAM,eAAe,KAAK;AAAA,YAEnC,UAAA,oBAAC,QAAA,EAAK,eAAW,MAAC,UAAA,IAAA,CAAC;AAAA,UAAA;AAAA,QAAA;AAAA,QAKpB,MAAM,YACP;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,qBAAkB;AAAA,YAClB,WAAWK,SAAO;AAAA,YAClB,OAAO;AAAA,cACL,MAAM,MAAM,aAAa;AAAA,cACzB,KAAK,MAAM;AAAA,cACX,OAAO;AAAA,cACP,QAAQ,KAAK,IAAI,kBAAkB,MAAM,cAAc,MAAM,QAAQ;AAAA,YAAA;AAAA,YAEvE,OAAO,OAAO;AAAA,YACd,cAAY,OAAO;AAAA,YACnB,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,YACtB,SAAS,MAAM;AACb,kCAAoB,MAAM;AAC1B,6BAAA;AAAA,YACF;AAAA,YAEA,UAAA,oBAAC,QAAA,EAAK,eAAW,MAAC,UAAA,IAAA,CAAC;AAAA,UAAA;AAAA,QAAA,IAEjB;AAAA,QACH,MAAM,YACP;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,qBAAkB;AAAA,YAClB,WAAWK,SAAO;AAAA,YAClB,OAAO;AAAA,cACL,MAAM,MAAM;AAAA,cACZ,KAAK,MAAM,cAAc;AAAA,cACzB,OAAO,KAAK,IAAI,kBAAkB,MAAM,aAAa,MAAM,SAAS;AAAA,cACpE,QAAQ;AAAA,YAAA;AAAA,YAEV,OAAO,OAAO;AAAA,YACd,cAAY,OAAO;AAAA,YACnB,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,YACtB,SAAS,MAAM;AACb,+BAAiB,MAAM;AACvB,6BAAA;AAAA,YACF;AAAA,YAEA,UAAA,oBAAC,QAAA,EAAK,eAAW,MAAC,UAAA,IAAA,CAAC;AAAA,UAAA;AAAA,QAAA,IAEjB;AAAA,MAAA,EAAA,CACN,IACE;AAAA,MAEH2B,QACC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAWtB,SAAO;AAAA,UAClB,mBAAgB;AAAA,UAChB,OAAO,EAAE,MAAMsB,MAAK,GAAG,KAAKA,MAAK,EAAA;AAAA,UACjC,MAAK;AAAA,UACL,aAAa,CAAC3B,OAAMA,GAAE,gBAAA;AAAA,UACtB,eAAe,CAACA,OAAMA,GAAE,eAAA;AAAA,UAEvB,UAAA;AAAA,YAAA,MAAM,IAAI,CAACO,OAAM,UAChB,qBAACG,YAAA,EACE,UAAA;AAAA,cAAA,QAAQ,KAAKH,MAAK,UAAU,MAAM,QAAQ,CAAC,EAAE,QAC5C,oBAAC,UAAK,WAAWF,SAAO,kBAAkB,eAAW,MAAC,IACpD;AAAA,cACJ;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,WAAWA,SAAO;AAAA,kBAClB,UAAUE,MAAK;AAAA,kBACf,SAAS,MAAM;AACb,oBAAAA,MAAK,IAAA;AACL,8BAAA;AAAA,kBACF;AAAA,kBAEA,UAAA;AAAA,oBAAA,oBAAC,UAAK,WAAWF,SAAO,mBAAmB,eAAW,MACnD,gBAAK,KAAA,CACR;AAAA,wCACC,QAAA,EAAK,WAAWA,SAAO,oBAAqB,gBAAK,MAAA,CAAM;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YAC1D,KAlBaE,MAAK,GAmBpB,CACD;AAAA,gCACA,QAAA,EAAK,WAAWF,SAAO,kBAAkB,eAAW,MAAC;AAAA,YACtD;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,WAAWA,SAAO;AAAA,gBAClB,SAAS,MAAM;AACb,yBAAO,SAAS,YAAA;AAChB,4BAAA;AAAA,gBACF;AAAA,gBAEA,UAAA;AAAA,kBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,mBAAmB,eAAW,MACpD,UAAA,oBAAC,mBAAgB,EAAA,CACnB;AAAA,sCACC,QAAA,EAAK,WAAWA,SAAO,oBACrB,iBAAO,iBAAA,CACV;AAAA,gBAAA;AAAA,cAAA;AAAA,YAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAAA,IAEA;AAAA,IAAA,GACN;AAAA,IACA,SAAS;AAAA,EAAA;AAEb;ACphBA,SAAS,cAAc,QAAgB,KAAiC;AACtE,QAAM,MAAM,OAAO,KAAK,QAAQ,GAAG;AACnC,MAAI,eAAe,YAAa,QAAO;AACvC,MAAI,eAAe,KAAM,QAAO,IAAI;AACpC,SAAO;AACT;AAEA,SAAS,iBAAiB,IAAiB,SAA+B;AACxE,MAAI,CAAC,QAAS,QAAO;AACrB,SAAQ,GAAG,cAAc,mBAAmB,KAA4B;AAC1E;AAEA,SAAS,kBACP,QACA,MACA,KACe;AACf,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,MAAI,CAAC,KAAM,QAAO,CAAA;AAClB,QAAM,WAAW,KAAK,sBAAA;AACtB,QAAM,aAAa,OAAO,KAAK,IAAI,sBAAA;AACnC,QAAM,MAAM;AACZ,QAAM,aAAa,OAAO,KAAK,IAAI;AAEnC,MAAI,OAAO,MAAM;AACf,UAAM,KAAK,cAAc,QAAQ,GAAG;AACpC,QAAI,IAAI;AACN,YAAMN,KAAI,GAAG,sBAAA;AACb,YAAM,MAAMA,GAAE,SAAS,SAAS,MAAM;AACtC,UAAI,SAAS,SAAS;AACpB,eAAO;AAAA,UACL,MAAM,WAAW,OAAO,SAAS;AAAA,UACjC;AAAA,UACA,OAAO;AAAA,QAAA;AAAA,MAEX;AACA,aAAO;AAAA,QACL,MAAMA,GAAE,OAAO,SAAS;AAAA,QACxB;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,KAAK,YAAY,OAAO,MAAM,UAAU,IAAI;AAClE,MAAI,SAAS,SAAS;AACpB,WAAO;AAAA,MACL,MAAM,WAAW,OAAO,SAAS;AAAA,MACjC,KAAK,OAAO,SAAS,SAAS,MAAM;AAAA,MACpC,OAAO;AAAA,IAAA;AAAA,EAEX;AACA,SAAO;AAAA,IACL,MAAM,OAAO,OAAO,SAAS;AAAA,IAC7B,KAAK,OAAO,SAAS,SAAS,MAAM;AAAA,EAAA;AAExC;AAEO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AACxC,QAAM,CAAC,YAAY,aAAa,IAAI;AAAA,IAAwB,MAC1D,kBAAkB,QAAQ,MAAM,GAAG;AAAA,EAAA;AAErC,QAAM,UAAU,MAAA;AAChB,QAAM,WAAW,OAA+C,IAAI;AACpE,QAAM,UAAU,OAAuB,IAAI;AAC3C,QAAM,UAAU,SAAS;AACzB,QAAM,OAAO,OAAO,KAAK,IAAI;AAE7B,YAAU,MAAM;AACd,aAAS,KAAK;AAAA,EAChB,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,UAAM,SAAS,MAAM,cAAc,kBAAkB,QAAQ,MAAM,GAAG,CAAC;AACvE,WAAA;AACA,WAAO,iBAAiB,UAAU,MAAM;AACxC,WAAO,MAAM,OAAO,oBAAoB,UAAU,MAAM;AAAA,EAC1D,GAAG,CAAC,QAAQ,MAAM,KAAK,KAAK,CAAC;AAE7B,YAAU,MAAM;;AACd,mBAAS,YAAT,mBAAkB;AAAA,EACpB,GAAG,CAAA,CAAE;AAEL,YAAU,MAAM;AACd,QAAI,OAAO,KAAM;AACjB,UAAM,KAAK,cAAc,QAAQ,GAAG;AACpC,QAAI,CAAC,GAAI;AACT,OAAG,UAAU,IAAI,kBAAkB;AACnC,WAAO,MAAM;AACX,SAAG,UAAU,OAAO,kBAAkB;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,YAAU,MAAM;AACd,QAAI,OAAO,KAAM;AACjB,UAAM,KAAK,cAAc,QAAQ,GAAG;AACpC,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,iBAAiB,IAAI,OAAO;AAC3C,UAAM,MAAM,MAAM,KAAA;AAClB,QAAI,IAAK,gBAAe,QAAQ,KAAK,OAAO;AAAA,gBAChC,cAAc;AAAA,EAC5B,GAAG,CAAC,OAAO,KAAK,QAAQ,OAAO,CAAC;AAEhC,YAAU,MAAM;AACd,QAAI,OAAO,QAAQ,MAAO;AAC1B,UAAM,KAAK,cAAc,QAAQ,GAAG;AACpC,QAAI,CAAC,GAAI;AACT,UAAM,SAAS,iBAAiB,IAAI,OAAO;AAC3C,WAAO,MAAM;AACX,YAAM,UAAU,MAAM,KAAA;AACtB,UAAI,QAAS,gBAAe,QAAQ,SAAS,OAAO;AAAA,kBACxC,cAAc;AAAA,IAC5B;AAAA,EACF,GAAG,CAAC,KAAK,QAAQ,SAAS,OAAO,KAAK,CAAC;AAEvC,YAAU,MAAM;AACd,UAAM,QAAQ,CAACC,OAAoB;;AACjC,YAAM,SAASA,GAAE;AACjB,UAAI,EAAE,kBAAkB,MAAO;AAC/B,WAAI,aAAQ,YAAR,mBAAiB,SAAS,QAAS;AACvC,UAAI,OAAO,MAAM;AACf,cAAM,KAAK,cAAc,QAAQ,GAAG;AACpC,YAAI,yBAAI,SAAS,QAAS;AAAA,MAC5B;AACA,eAAA;AAAA,IACF;AACA,aAAS,iBAAiB,eAAe,KAAK;AAC9C,WAAO,MAAM,SAAS,oBAAoB,eAAe,KAAK;AAAA,EAChE,GAAG,CAAC,UAAU,QAAQ,GAAG,CAAC;AAE1B,QAAM,YAAY,MAAM,KAAA,EAAO,SAAS;AACxC,QAAM,WAAW,CAAC,cAAc,SAAS,YAAY;AAErD,QAAM,SAAS,MAAM;AACnB,QAAI,CAAC,UAAW;AAChB,cAAU,MAAM,MAAM;AAAA,EACxB;AAEA,QAAM,YAAY,CAChBA,OACG;AACH,QAAIA,GAAE,QAAQ,UAAU;AACtB,MAAAA,GAAE,eAAA;AACF,eAAA;AACA;AAAA,IACF;AACA,QAAIA,GAAE,QAAQ,QAAS;AACvB,QAAI,WAAW,EAAEA,GAAE,WAAWA,GAAE,SAAU;AAC1C,IAAAA,GAAE,eAAA;AACF,WAAA;AAAA,EACF;AAEA,QAAM4B,SAAQ,UACZ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAWvB,SAAO;AAAA,MAClB,OAAO;AAAA,MACP;AAAA,MACA,MAAM,KAAK,IAAI,GAAG,MAAM,MAAM,IAAI,EAAE,MAAM;AAAA,MAC1C,mBAAiB;AAAA,MACjB,UAAU,CAACL,OAAM,SAASA,GAAE,OAAO,KAAK;AAAA,MACxC;AAAA,IAAA;AAAA,EAAA,IAGF;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAK;AAAA,MACL,WAAWK,SAAO;AAAA,MAClB,OAAO;AAAA,MACP;AAAA,MACA,mBAAiB;AAAA,MACjB,UAAU,CAACL,OAAM,SAASA,GAAE,OAAO,KAAK;AAAA,MACxC;AAAA,IAAA;AAAA,EAAA;AAIJ,MAAI,CAAC,KAAM,QAAO;AAElB,SAAO;AAAA,IACL;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAWK,SAAO;AAAA,QAClB,OAAO;AAAA,QACP,MAAK;AAAA,QACL,cAAW;AAAA,QACX,mBAAiB;AAAA,QAEjB,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WACE,UACI,GAAGA,SAAO,SAAS,IAAIA,SAAO,cAAc,KAC5CA,SAAO;AAAA,YAGZ,UAAA;AAAA,cAAA,WACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAI;AAAA,kBACJ,WACE,UACI,GAAGA,SAAO,QAAQ,IAAIA,SAAO,aAAa,KAC1CA,SAAO;AAAA,kBAGb,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,cAAc,eAAW,MAC9C,UAAA,UAAU,QAAQ,KAAA,CACrB;AAAA,oBACC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA,IAED;AAAA,cACJ;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAI,WAAW,SAAY;AAAA,kBAC3B,WACE,UACI,GAAGA,SAAO,SAAS,IAAIA,SAAO,cAAc,KAC5CA,SAAO;AAAA,kBAGZ,UAAA;AAAA,oBAAAuB;AAAA,oBACD;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAWvB,SAAO;AAAA,wBAClB,UAAU,CAAC;AAAA,wBACX,OACE,UAAU,GAAG,SAAS,oBAAoB,GAAG,SAAS;AAAA,wBAExD,SAAS;AAAA,wBAER,UAAA;AAAA,0BAAA;AAAA,8CACA,QAAA,EAAK,WAAWA,SAAO,aAAa,eAAW,MAAC,UAAA,IAAA,CAEjD;AAAA,wBAAA;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACF;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF;AAAA,UAAA;AAAA,QAAA;AAAA,MACF;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAEJ;AChJA,MAAM,gBAAgB,WAUpB,SAASwB,eACT,EAAE,OAAO,QAAA5B,SAAQ,UAAU,MAAM,SAAS,UAAU,WAAW,GAAG,KAAA,GAClE,KACA;AACA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,MAAK;AAAA,MACL;AAAA,MACA,cAAY;AAAA,MACZ,gBAAcA;AAAA,MACd,aAAW;AAAA,MACX;AAAA,MACA,WAAW,GAAGI,SAAO,GAAG,IAAIJ,UAASI,SAAO,YAAY,EAAE,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE;AAAA,MAE7F,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,MACtB;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAED,SAAS,UAAU;AACjB,6BAAQ,QAAA,EAAK,WAAWK,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,CAACL,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,GAAGK,SAAO,QAAQ,IAAI,WAAWA,SAAO,mBAAmB,EAAE;AAAA,MACxE,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,MACtB,SAAS,MAAM;AACb,iBAAA;AACA,cAAA;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAM1B,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,YAAY,WAAW,YAAY;AACzC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG;AAEvD,QAAM,aAAa,YAAY,MAAM,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,EAAE;AAEvE,SACE;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACC;AAAA,MACA,cAAc,CAAC,SAAS;AACtB,gBAAQ,IAAI;AACZ,YAAI,CAAC,KAAM,YAAA;AAAA,MACb;AAAA,MAEA,UAAA;AAAA,QAAA,oBAAC,QAAQ,SAAR,EAAgB,SAAO,MACtB,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL;AAAA,YACA,WAAW,GAAGK,SAAO,QAAQ,IAAI,OAAOA,SAAO,mBAAmB,EAAE;AAAA,YACpE,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,YAEtB,UAAA;AAAA,cAAA,qBAAC,QAAA,EAAK,WAAWK,SAAO,WACtB,UAAA;AAAA,gBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,KAAC;AAAA,gBACnC,OAAO;AAAA,cAAA,GACV;AAAA,kCACC,iBAAA,EAAgB,MAAM,IAAI,WAAWA,SAAO,iBAAA,CAAkB;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,GAEnE;AAAA,QACA,oBAAC,QAAQ,QAAR,EACC,UAAA;AAAA,UAAC,QAAQ;AAAA,UAAR;AAAA,YACC,WAAWA,SAAO;AAAA,YAClB,MAAK;AAAA,YACL,OAAM;AAAA,YACN,YAAY;AAAA,YACZ,iBAAiB,CAACL,OAAMA,GAAE,eAAA;AAAA,YAC1B,kBAAkB,CAACA,OAAMA,GAAE,eAAA;AAAA,YAE3B,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWK,SAAO;AAAA,kBAClB,OAAO;AAAA,oBACL,qBAAqB,UAAU,iBAAiB;AAAA,kBAAA;AAAA,kBAElD,cAAc;AAAA,kBAEb,UAAA,MAAM,KAAK,EAAE,QAAQ,oBAAoB,kBAAA,GAAqB,CAAC,GAAG,MAAM;AACvE,0BAAM,MAAO,IAAI,oBAAqB;AACtC,0BAAMmB,OAAM,KAAK,MAAM,IAAI,iBAAiB,IAAI;AAChD,0BAAMvB,UAAS,MAAM,OAAO,KAAK,OAAO,MAAM,QAAQuB,QAAO,MAAM;AACnE,2BACE;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBAEC,MAAK;AAAA,wBACL,cAAY,OAAO,kBAAkB,KAAKA,IAAG;AAAA,wBAC7C,WAAW,GAAGnB,SAAO,aAAa,IAAIJ,UAASI,SAAO,sBAAsB,EAAE;AAAA,wBAC9E,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,wBACtB,cAAc,MAAM,SAAS,EAAE,MAAM,KAAK,MAAMwB,MAAK;AAAA,wBACrD,SAAS,MAAM;AACb,mCAASA,MAAK,GAAG;AACjB,kCAAQ,KAAK;AACb,qCAAA;AACA,oCAAA;AAAA,wBACF;AAAA,sBAAA;AAAA,sBAXK;AAAA,oBAAA;AAAA,kBAcX,CAAC;AAAA,gBAAA;AAAA,cAAA;AAAA,kCAEF,OAAA,EAAI,WAAWnB,SAAO,gBACpB,gBAAM,OAAO,IACV,OAAO,kBAAkB,MAAM,MAAM,MAAM,IAAI,IAC/C,OAAO,YAAA,CACb;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,EACF,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAGA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA,KAAAyB;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,WAAWzB,SAAO;AAAA,QAClB;AAAA,QACA,cAAY;AAAA,QACZ,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,QAEtB,UAAA,qBAAC,QAAA,EAAK,WAAWK,SAAO,WACtB,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,gBAAiB,UAAA,OAAM;AAAA,UAC/C,oBAAC,UAAK,WAAWA,SAAO,cAAc,OAAO,EAAE,YAAYyB,OAAI,CAAG;AAAA,QAAA,EAAA,CACpE;AAAA,MAAA;AAAA,IAAA,GAEJ;AAAA,IACA,oBAAC,QAAQ,QAAR,EACC,UAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,WAAWzB,SAAO;AAAA,QAClB,YAAY;AAAA,QACZ,OAAM;AAAA,QACN,iBAAiB,CAACL,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;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;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,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;AAInC,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,KAAK;AAAA,IACjB;AAAA,EACF;AAGA,QAAM,iBAAiB,OAAyB,IAAI;AACpD,QAAM,CAAC,WAAW,YAAY,IAAI;AAAA,IAChC;AAAA,EAAA;AAEF,QAAM,iBAAiB,OAA+B,IAAI;AAG1D,YAAU,MAAM,MAAA;;AAAM,gCAAe,YAAf,mBAAwB;AAAA,KAAS,CAAA,CAAE;AAEzD,QAAM,qBAAqB,OAAOA,OAA2C;;AAC3E,UAAM,QAAO,KAAAA,GAAE,OAAO,UAAT,mBAAiB;AAC9B,IAAAA,GAAE,OAAO,QAAQ;AACjB,QAAI,CAAC,KAAM;AAEX,QAAI,WAAW,KAAK,KAAK,IAAI,GAAG;AAC9B,UAAI;AACF,uBAAe,QAAQ,MAAM,KAAK,KAAA,CAAM;AAAA,MAC1C,SAAS,KAAK;AACZ,gBAAQ,MAAM,2BAA2B,GAAG;AAC5C,2CAAU,KAAK;AAAA,MACjB;AACA;AAAA,IACF;AAEA,QAAI,CAAC,kBAAkB;AACrB,yCAAU,IAAI,MAAM,qBAAqB,KAAK,IAAI,EAAE,GAAG;AACvD;AAAA,IACF;AAEA,UAAM,OAAO,IAAI,gBAAA;AACjB,mBAAe,UAAU;AACzB,iBAAa,EAAE,OAAO,UAAU,OAAO,GAAG;AAC1C,UAAM,UAAU,CAAC,MACf,EAAE,UAAU,YACR,EAAE,2BACF,EAAE,wBAAwB,KAAK,OAAO,EAAE,SAAS,KAAK,GAAG,CAAC;AAChE,WAAO,SAAS,wBAAwB,QAAQ,EAAE,OAAO,UAAU,OAAO,EAAA,CAAG,CAAC;AAC9E,QAAI;AACF,YAAM,MAAM,MAAM,iBAAiB,MAAM;AAAA,QACvC,QAAQ,KAAK;AAAA,QACb,YAAY,CAAC,MAAM;AACjB,cAAI,KAAK,OAAO,QAAS;AACzB,uBAAa,CAAC;AACd,iBAAO,SAAS,wBAAwB,QAAQ,CAAC,CAAC;AAAA,QACpD;AAAA,MAAA,CACD;AACD,aAAO,SAAS,wBAAA;AAChB,YAAM,KAAK,OAAO,QAAQ,WAAW,MAAM,IAAI;AAC/C,YAAM,UAAU,OAAO,QAAQ,WAAW,CAAA,IAAK,IAAI,WAAW,CAAA;AAC9D,qBAAe,QAAQ,IAAI,OAAO;AAAA,IACpC,SAAS,KAAK;AACZ,aAAO,SAAS,wBAAA;AAEhB,UAAI,CAAC,KAAK,OAAO,SAAS;AACxB,gBAAQ,MAAM,2BAA2B,GAAG;AAC5C,2CAAU,KAAK;AAAA,MACjB;AAAA,IACF,UAAA;AACE,UAAI,eAAe,YAAY,KAAM,gBAAe,UAAU;AAC9D,mBAAa,IAAI;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,cAAc,uBAAuB;AAAA,IACzC,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AAED,QAAM,aAAa,CAAC,WAAmB;AACrC,UAAMc,SAAQ,eAAe;AAC7B,QAAI,CAACA,OAAO;AACZ,IAAAA,OAAM,SAAS;AACf,IAAAA,OAAM,QAAQ;AACd,IAAAA,OAAM,MAAA;AAAA,EACR;AAGA,QAAM,cAAc,YAAY,EAAE,qBAAqB,EAAE;AAEzD,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,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,CAAC,UAAU,WAAW,IAAI,SAMtB,IAAI;AAEd,YAAU,MAAM,mBAAmB,CAAC,YAAY;AAC9C,gBAAY;AAAA,MACV,MAAM,QAAQ;AAAA,MACd,MAAM;AAAA,MACN,KAAK,QAAQ;AAAA,MACb,OAAO,QAAQ;AAAA,IAAA,CAChB;AAAA,EACH,CAAC,GAAG,CAAA,CAAE;AAEN,QAAM,iBAAiB,CAAC,SAAmB;AACzC,UAAM,EAAE,MAAM,GAAA,IAAO,OAAO,MAAM;AAClC,UAAM,WACJ,SAAS,KAAK,KAAK,OAAO,MAAM,IAAI,YAAY,MAAM,IAAI,GAAG;AAC/D,UAAM,OAAO,SAAS,WAAW,eAAe;AAChD,UAAM,aAAa;AACnB,UAAA,EAAQ,cAAc,EAAE,MAAM,OAAO,EAAE,OAAO,SAAA,GAAY,EAAE,IAAA;AAC5D,QAAI,MAAqB;AACzB,WAAO,MAAM,IAAI;AAAA,MACf;AAAA,MACA,OAAO,MAAM,IAAI,QAAQ;AAAA,MACzB,CAAC,MAAM,YAAY;AACjB,YAAI,OAAO,KAAM,QAAO;AACxB,YACE,KAAK,KAAK,SAAS,QACnB,OAAO,KAAK,MAAM,SAAS,EAAE,MAAM,UACnC;AACA,gBAAM;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IAAA;AAEF,QAAI,OAAO,MAAM;AACf,kBAAY,EAAE,MAAM,MAAM,UAAU,OAAO,UAAU,OAAO,MAAM;AAClE;AAAA,IACF;AACA,gBAAY;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,IAAA,CACR;AAAA,EACH;AAEA,QAAM,YAAY,CAAC,UAAkB;AACnC,QAAI,CAAC,SAAU;AACf,UAAM,EAAE,MAAM,MAAM,IAAA,IAAQ;AAC5B,gBAAY,IAAI;AAChB,QAAI,SAAS,UAAU,OAAO,MAAM;AAClC,UAAI,SAAS,UAAU;AACrB,cAAA,EAAQ,iBAAiB,EAAE,OAAO,IAAA,CAAK,EAAE,IAAA;AAAA,MAC3C,OAAO;AACL,cAAA,EAAQ,gBAAgB,EAAE,OAAO,IAAA,CAAK,EAAE,IAAA;AAAA,MAC1C;AACA;AAAA,IACF;AACA,QAAI,SAAS,UAAU;AACrB,YAAA,EAAQ,cAAc,EAAE,MAAM,cAAc,OAAO,EAAE,MAAA,GAAS,EAAE,IAAA;AAAA,IAClE,OAAO;AACL,YAAA,EAAQ,cAAc,EAAE,MAAM,aAAa,OAAO,EAAE,MAAA,GAAS,EAAE,IAAA;AAAA,IACjE;AAAA,EACF;AAEA,QAAM,aAAa,MAAM;AACvB,QAAI,CAAC,SAAU;AACf,UAAM,EAAE,OAAO,IAAA,IAAQ;AACvB,QAAI,SAAS,OAAO,MAAM;AACxB,YAAM,OAAO,OAAO,MAAM,IAAI,OAAO,GAAG;AACxC,UACE,SACC,KAAK,KAAK,SAAS,gBAAgB,KAAK,KAAK,SAAS,cACvD;AACA,eACG,MAAA,EACA,MAAA,EACA,YAAY,EAAE,MAAM,KAAK,IAAI,MAAM,KAAK,SAAA,CAAU,EAClD,IAAA;AAAA,MACL;AAAA,IACF;AACA,gBAAY,IAAI;AAAA,EAClB;AAEA,QAAM,eAAe,MAAM,cACvB,gBACA,MAAM,YACJ,cACA;AAEN,SACE,qBAAAJ,YAAA,EACE,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WACE,YAAY,GAAGL,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,CAACL,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWK,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,CAACL,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,UAAK,WAAWK,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,CAACL,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWK,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,UAIT;AAAA,YAAC;AAAA,YAAA;AAAA,cACC;AAAA,cACA,QAAQ;AAAA,gBACN,OAAO,EAAE;AAAA,gBACT,OAAO,EAAE;AAAA,gBACT,MAAM,EAAE;AAAA,gBACR,QAAQ,EAAE;AAAA,gBACV,SAAS,EAAE;AAAA,cAAA;AAAA,cAEb,SACE,oBAAC,eAAA,EAAc,OAAO,EAAE,MAAM,QAAQ,MAAM,MAC1C,UAAA,oBAAC,UAAA,CAAA,CAAS,EAAA,CACZ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGH,gBACC,qBAAAK,YAAA,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,UACH,aACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SACE;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAWL,SAAO;AAAA,kBAClB,OAAO;AAAA,kBACP,cAAY;AAAA,kBACZ,aAAW,CAAC,CAAC;AAAA,kBACb,UAAU,CAAC,CAAC;AAAA,kBACZ,aAAa,CAACL,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWK,SAAO,mBACrB,YAAE,gBACL;AAAA,oBACA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAM;AAAA,wBACN,WAAWA,SAAO;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACpB;AAAA,gBAAA;AAAA,cAAA;AAAA,cAIH,UAAA,YAAY,IAAI,CAACE,UAChB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,UAAU,MAAM,WAAWA,MAAK,MAAM;AAAA,kBAErC,UAAAA,MAAK;AAAA,gBAAA;AAAA,gBAHDA,MAAK;AAAA,cAAA,CAKb;AAAA,YAAA;AAAA,UAAA,IAED;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,WAAWF,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,UAKR,WACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,EAAE;AAAA,cACT,QAAQ;AAAA,cACR,SAAS;AAAA,cAET,8BAAC,YAAA,CAAA,CAAW;AAAA,YAAA;AAAA,UAAA,IAEZ;AAAA,UAGJ;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,CAACL,OAAMA,GAAE,eAAA;AAAA,kBAEtB,UAAA;AAAA,oBAAA,oBAAC,QAAA,EAAK,WAAWK,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,eAAe,QAAQ,GAC/C,UAAA,qBAAC,QAAA,EAAK,WAAWA,SAAO,WACtB,UAAA;AAAA,kBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAW,UAAA,MAAE;AAAA,kBACpC,EAAE;AAAA,gBAAA,EAAA,CACL,EAAA,CACF;AAAA,gBACA,oBAAC,UAAA,EAAS,UAAU,MAAM,eAAe,OAAO,GAC9C,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,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,QAAQ;AAAA,oBACR,UAAU,CAAC,MAAM,SACf,QACG,YAAY,EAAE,MAAM,MAAM,eAAe,KAAA,CAAM,EAC/C,IAAA;AAAA,kBAAI;AAAA,gBAAA;AAAA,gBAGV,uDAAmB,IAAI,CAACE,UACvB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBAEC,UAAUA,MAAK;AAAA,oBACf,UAAU,MAAMA,MAAK,SAAS,MAAM;AAAA,oBAEpC,UAAA,qBAAC,QAAA,EAAK,WAAWF,SAAO,WACtB,UAAA;AAAA,sBAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,WAAY,gBAAK,MAAK;AAAA,sBAC7CE,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,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,QAAM;AAAA,QACN,UAAU;AAAA,MAAA;AAAA,IAAA,IAEV;AAAA,IAEH,WACC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,MAAM,SAAS;AAAA,QACf,MAAM,SAAS;AAAA,QACf,KAAK,SAAS;AAAA,QACd,OAAO,SAAS;AAAA,QAChB,OAAO,SAAS;AAAA,QAChB,UACE,SAAS,SAAS,WAAW,EAAE,gBAAgB,EAAE;AAAA,QAEnD,aAAa,EAAE;AAAA,QACf,WAAW,EAAE;AAAA,QACb,WAAW;AAAA,QACX,UAAU;AAAA,MAAA;AAAA,IAAA,IAEV;AAAA,IAIJ,oBAAC,cAAA,EAAa,QAAgB,QAAQ,EAAA,CAAG;AAAA,EAAA,GAC3C;AAEJ;AChkCO,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,CAACA,UAAkB;AACrC,QAAIA,MAAK,OAAQ;AACjB,+CAAcA;AACd,QAAI,wBAAwB,KAAK;AAAA,EACnC;AAEA,QAAMwB,QACJ,oBAAC,MAAA,EAAG,WAAW1B,SAAO,MACnB,UAAA,MAAM,IAAI,CAACE,UACV,oBAAC,MAAA,EACC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAMA,MAAK,SAAS,SAAY,IAAIA,MAAK,EAAE;AAAA,MAC3C,WAAW,GAAGF,SAAO,IAAI,IACvBE,MAAK,OAAO,WAAWF,SAAO,SAAS,EACzC,IAAIE,MAAK,SAASF,SAAO,SAAS,EAAE;AAAA,MACpC,OAAO,EAAE,aAAa,IAAIE,MAAK,QAAQ,YAAY,KAAK,EAAE,KAAA;AAAA,MAC1D,gBAAcA,MAAK,OAAO,WAAW,SAAS;AAAA,MAC9C,iBAAeA,MAAK,SAAS,SAAS;AAAA,MACtC,SAAS,CAACP,OAAM;AACd,QAAAA,GAAE,eAAA;AACF,oBAAYO,KAAI;AAAA,MAClB;AAAA,MAEA,UAAA;AAAA,QAAA,oBAAC,QAAA,EAAK,WAAWF,SAAO,UAAW,gBAAK,MAAK;AAAA,QAC5CE,MAAK,SACJ,oBAAC,UAAA,EAAS,WAAWF,SAAO,UAAU,eAAW,KAAA,CAAC,IAChD;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,EACN,GAlBOE,MAAK,EAmBd,CACD,GACH;AAIF,MAAI,UAAU;AACZ,gCACG,OAAA,EAAI,WAAWF,SAAO,QAAQ,cAAY,EAAE,OAC3C,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWA,SAAO;AAAA,UAClB,iBAAe;AAAA,UACf,SAAS,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;AAAA,UAEtC,UAAA;AAAA,YAAA,oBAAC,UAAA,EAAS,WAAWA,SAAO,eAAe,eAAW,MAAC;AAAA,YACvD,oBAAC,QAAA,EAAM,UAAA,EAAE,MAAA,CAAM;AAAA,YACf;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW,GAAGA,SAAO,OAAO,IAC1B,aAAaA,SAAO,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,GAAGA,SAAO,WAAW,IAC9B,aAAaA,SAAO,kBAAkB,EACxC;AAAA,UAEC,UAAA0B;AAAA,QAAA;AAAA,MAAA;AAAA,IACH,GACF;AAAA,EAEJ;AAGA,MAAI,WAAW;AACb,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAW1B,SAAO;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,WAAWA,SAAO,SAAS,cAAY,EAAE,OAAO,KAAK,eACxD,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAWA,SAAO,QACrB,UAAA;AAAA,MAAA,oBAAC,QAAA,EAAK,WAAWA,SAAO,aAAc,YAAE,OAAM;AAAA,MAC9C;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAWA,SAAO;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,IACC0B;AAAA,EAAA,GACH;AAEJ;;;;;;;ACpIO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,aAAa;AACf,GAAwB;AACtB,QAAM,OAAO,QAAQ,WAAW,SAAS,0BAA0B;AACnE,SACE,qBAAC,QAAQ,MAAR,EAAa,MAAY,cACvB,UAAA;AAAA,IAAA,QACC,oBAAC,QAAQ,QAAR,EAAe,SAAO,MACrB,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAW,OAAO;AAAA,QAClB,OAAO,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,IAAA;AAAA,MAAI;AAAA,IAAA,GAE5C;AAAA,IAEF,oBAAC,QAAQ,QAAR,EACC,UAAA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,WAAW,OAAO;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB,CAAC/B,OAAMA,GAAE,eAAA;AAAA,QAC1B,kBAAkB,CAACA,OAAMA,GAAE,eAAA;AAAA,QAE1B;AAAA,MAAA;AAAA,IAAA,EACH,CACF;AAAA,EAAA,GACF;AAEJ;ACtBA,MAAM,WAAW;AAEV,SAAS,kBACd,QACA,QACoB;AACpB,MAAI,CAAC,UAAU,CAAC,OAAO,MAAO,QAAO;AAErC,QAAM,CAAC,MAAM,IAAI,kBAAkB,OAAO,MAAM,KAAK;AAAA,IACnD,EAAE,WAAW,UAAU,UAAU,CAAC,MAAM,EAAA;AAAA,EAAE,CAC3C;AACD,QAAM,QAAQ,iCAAQ,OAAO;AAC7B,MAAI,CAAC,MAAO,QAAO;AAEnB,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,IAAI,MAAM;AAAA;AAAA,IAEV,MAAM,OAAO,MAAM,IAAI,YAAY,MAAM,MAAM,MAAM,EAAE;AAAA,IACvD,QAAQ,OAAO;AAAA,EAAA;AAEnB;ACNA,MAAM,kBAAkB;AASxB,SAAS,eAAe,QAAiC;AACvD,QAAM,SAA0B,CAAA;AAChC,SAAO,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW;AACzC,WAAO,KAAK;AAAA,MACV,MAAM,KAAK,OAAA;AAAA,MACX,MAAM;AAAA,MACN,IAAI,SAAS,KAAK;AAAA,IAAA,CACnB;AAAA,EACH,CAAC;AACD,SAAO;AACT;AAEO,SAAS,oBACd,QACA,MACA,IACA,UAAsC,CAAA,GAChB;AACtB,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,OAAO,OAAO,MAAM,IAAI,QAAQ;AACtC,MAAI,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AAC1C,MAAI,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;AAC3C,MAAI,SAAS,IAAK,QAAO;AAEzB,QAAM,SAAS,eAAe,MAAM;AACpC,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,SAAS,QAAQ,mBAAmB;AAI1C,MAAI,QAAQ;AACZ,MAAI,OAAO,OAAO,SAAS;AAC3B,MAAI,QAAQ;AACV,YAAQ,OAAO,UAAU,CAACE,OAAMA,GAAE,KAAK,KAAK;AAC5C,QAAI,QAAQ,EAAG,QAAO;AACtB,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,OAAO,KAAK,GAAG;AAClD,UAAI,OAAO,CAAC,EAAE,OAAO,KAAK;AACxB,eAAO;AACP;AAAA,MACF;AAAA,IACF;AACA,YAAQ,OAAO,KAAK,EAAE;AACtB,UAAM,OAAO,IAAI,EAAE;AAAA,EACrB;AAEA,QAAM,QAAQ,OAAO,IAAI,CAACA,OAAM,QAAQ,UAAU,EAAE,MAAM,OAAO,SAAS,CAACA,GAAE,IAAI,EAAA,CAAG,CAAC;AACrF,QAAM,OAAO,OAAO,YAAA;AAEpB,MAAI,UAAU,MAAM,KAAK,eAAe,MAAM,MAAM;AAClD,UAAM8B,YAAW,MAAM,MAAM,OAAO,OAAO,CAAC,EAAE,KAAK,eAAe;AAElE,QAAI,CAACA,UAAU,QAAO;AACtB,UAAMC,MACJ,UAAU,IACN,IACA,MAAM,MAAM,GAAG,KAAK,EAAE,KAAK,eAAe,EAAE,SAAS,gBAAgB;AAC3E,WAAO,EAAE,UAAAD,WAAU,MAAMC,KAAI,IAAIA,MAAKD,UAAS,QAAQ,SAAS,OAAO,OAAO,IAAA;AAAA,EAChF;AAGA,QAAM,WAAW,QAAQ;AAAA,IACvB,OAAO,MAAM,IAAI,IAAI,OAAO,GAAG,EAAE,OAAA;AAAA,EAAO;AAE1C,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,KAAK,KAAK,QAAQ,QAAQ;AAChC,MAAI,KAAK,KAAK,KAAK,QAAQ,UAAU,KAAK,CAAC,KAAK,EAAG,QAAO;AAC1D,SAAO,EAAE,UAAU,MAAM,IAAI,IAAI,KAAK,SAAS,QAAQ,SAAS,OAAO,OAAO,IAAA;AAChF;ACjGO,SAAS,kBAAkB,UAA0B;AAC1D,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,UAAU,WAAA;AAChB,SAAO,QAAQ,UAAU,QAAQ,MAAM,qBAAqB,QAAQ,CAAC,CAAC;AACxE;AAIA,IAAI,gBAAwC;AAE5C,SAAS,aAA8B;AACrC,oCAAkB,IAAI,gBAAgB;AAAA,IACpC,YAAY,CAAC,GAAG,gBAAgB,eAAe,WAAW,WAAW,WAAW;AAAA,EAAA,CACjF;AACD,SAAO;AACT;ACnBO,SAAS,yBACd,QACA,OACA,UACA,UAA+B,CAAA,GACtB;AACT,QAAM,WAAW;AAAA,IACf,wBAAwB,YAAY,IAAI,QAAQ,WAAW,CAAA,CAAE;AAAA,EAAA;AAE/D,MAAI,CAAC,SAAS,KAAA,EAAQ,QAAO;AAE7B,MAAI,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,MAAM,MAAM,EAAE,CAAC;AACrD,MAAI,KAAK,KAAK,IAAI,MAAM,MAAM,MAAM,EAAE;AACtC,MAAI,SAAS,GAAI,QAAO;AAGxB,MAAI,oBAAoB,QAAQ,MAAM,IAAI,QAAQ,EAAG,QAAO;AAG5D,aAAW,SAAS,oBAAoB,QAAQ,GAAG;AACjD,UAAM,SAAS,OAAO,MAAM,IAAI,QAAQ;AACxC,UAAM,UACJ,oBAAoB,QAAQ,MAAM,IAAI,KAAK,KAC3C,uBAAuB,QAAQ,MAAM,IAAI,iBAAiB,KAAK,CAAC;AAClE,QAAI,CAAC,QAAS;AAEd,UAAM,WAAW,OAAO,MAAM,IAAI,QAAQ,OAAO,UAAU,KAAK;AAChE,YAAQ;AACR,SAAK;AAAA,EACP;AACA,SAAO;AACT;AAGA,SAAS,oBACP,QACA,MACA,IACA,UACS;AACT,MAAI;AACF,WAAO,OACJ,MAAA,EACA,gBAAgB,EAAE,MAAM,MAAM,UAAU,EAAE,aAAa,WAAA,CAAY,EACnE,IAAA;AAAA,EACL,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,uBACP,QACA,MACA,IACA,MACS;AACT,MAAI;AACF,WAAO,OACJ,QACA;AAAA,MACC,EAAE,MAAM,GAAA;AAAA,MACR,EAAE,MAAM,aAAa,SAAS,OAAO,CAAC,EAAE,MAAM,QAAQ,KAAA,CAAM,IAAI,CAAA,EAAC;AAAA,IAAE,EAEpE,IAAA;AAAA,EACL,QAAQ;AACN,WAAO;AAAA,EACT;AACF;ACrFO,SAAS,oBACd,QACA,OACA,UACM;AACN,QAAM,WAAW,qBAAqB,QAAQ;AAC9C,MAAI,CAAC,SAAU;AACf,MAAI;AACF,UAAM,KAAK,OACR,MAAA,EACA,MAAA,EACA,YAAY,KAAK,EACjB,cAAc,UAAU,EAAE,aAAa,WAAA,CAAY,EACnD,IAAA;AACH,QAAI,GAAI;AAAA,EACV,QAAQ;AAAA,EAER;AACA,SAAO,QAAQ,MAAA,EAAQ,YAAY,KAAK,EAAE,IAAA;AAC1C,iBAAe,QAAQ,QAAQ;AACjC;"}
|