@kungal/editor-core 0.36.0 → 0.38.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/CHANGELOG.md +47 -0
- package/dist/preset/index.cjs +21 -8
- package/dist/preset/index.cjs.map +1 -1
- package/dist/preset/index.d.cts +31 -8
- package/dist/preset/index.d.ts +31 -8
- package/dist/preset/index.js +21 -8
- package/dist/preset/index.js.map +1 -1
- package/package.json +1 -1
package/dist/preset/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/spoiler/index.ts","../../src/plugins/stop-link/index.ts","../../src/plugins/link/index.ts","../../src/plugins/heading/index.ts","../../src/plugins/katex/blockKatex.ts","../../src/plugins/katex/inlineKatex.ts","../../src/plugins/katex/command.ts","../../src/plugins/katex/inputRule.ts","../../src/plugins/katex/remark.ts","../../src/plugins/katex/index.ts","../../src/plugins/code-block/theme.ts","../../src/plugins/code-block/icons.ts","../../src/plugins/code-block/index.ts","../../src/plugins/mention/index.ts","../../src/plugins/quote/index.ts","../../src/plugins/upload/index.ts","../../src/plugins/placeholder/index.ts","../../src/preset/index.ts"],"names":["node","trailing","tr","$command","linkSchema","$nodeSchema","_tr","NodeSelection","TextSelection","$inputRule","codeBlockSchema","$remark","visit","t","EditorView","katex","PluginKey","$prose","Plugin","DecorationSet","Decoration"],"mappings":"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","file":"index.js","sourcesContent":["// Spoiler plugin — the `||hidden text||` inline node.\n//\n// Ported (behaviour-wise) from the forum's plugins/spoiler/spoilerPlugin.ts.\n// This is a PURE plugin: it needs no host policy, so there is no adapter\n// argument — just a `createSpoilerPlugin()` factory returning the Milkdown\n// plugin bundle, matching the folder contract in ../README.md.\n//\n// The syntax `||text||` is the KUN ecosystem's own markdown extension (shared\n// with the server renderer), so the round-trip lives here in core, not in a host.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport type { Node } from '@milkdown/kit/transformer'\nimport type {\n NodeType,\n Node as ProseNode,\n ResolvedPos\n} from '@milkdown/kit/prose/model'\nimport { Fragment } from '@milkdown/kit/prose/model'\nimport { expectDomTypeError } from '@milkdown/kit/exception'\nimport { InputRule } from '@milkdown/kit/prose/inputrules'\nimport { NodeSelection, TextSelection } from '@milkdown/kit/prose/state'\nimport {\n $command,\n $inputRule,\n $nodeAttr,\n $nodeSchema,\n $remark\n} from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\ninterface SpoilerNode extends Node {\n type: 'kun-spoiler' | 'text'\n value?: string\n children?: SpoilerNode[]\n}\n\n/** DOM attrs for the rendered spoiler chip. The styling references KunUI CSS\n * variables so it inherits the host theme (the render layer ships the vars). */\nexport const spoilerAttr = $nodeAttr('kun-spoiler', () => ({\n container: {\n class: 'kun-spoiler',\n style:\n 'background: var(--color-default-500); border-radius: var(--radius-sm); padding: 0 4px; cursor: pointer;'\n }\n}))\n\n/** The zero-width space this plugin parks the caret on. A caret has to sit in a\n * TEXT node: with nothing after a spoiler the browser puts the next keystroke\n * inside it, and an empty spoiler has nowhere to type at all. Spelled as an\n * escape because the literal character is invisible in a source file. */\nconst CARET_ANCHOR = '\\u200b'\n\n/** Anchors are an editor device, never content: strip them from any text moving\n * between a spoiler and the document (or the markdown). */\nconst withoutAnchors = (content: Fragment): Fragment => {\n const kept: ProseNode[] = []\n content.forEach((child) => {\n if (!child.isText) {\n kept.push(child)\n return\n }\n const text = (child.text ?? '').replaceAll(CARET_ANCHOR, '')\n if (text) {\n kept.push(child.type.schema.text(text, child.marks))\n }\n })\n return Fragment.fromArray(kept)\n}\n\n/** The `kun-spoiler` inline node: parses/serializes `||text||` and renders a\n * `<span data-type=\"kun-spoiler\">` the render layer toggles on click. */\nexport const spoilerSchema = $nodeSchema('kun-spoiler', (ctx) => ({\n group: 'inline',\n inline: true,\n content: 'inline*',\n marks: '',\n attrs: {\n revealed: {\n default: false\n }\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"kun-spoiler\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom)\n return {\n revealed: dom.getAttribute('data-revealed') === 'true'\n }\n }\n }\n ],\n toDOM: (node) => {\n const attrs = ctx.get(spoilerAttr.key)(node)\n return [\n 'span',\n {\n ...attrs.container,\n 'data-type': 'kun-spoiler',\n 'data-revealed': node.attrs.revealed\n },\n 0\n ]\n },\n parseMarkdown: {\n match: ({ type }) => type === 'kun-spoiler',\n runner: (state, node, type) => {\n state.openNode(type)\n state.next(node.children || [])\n state.closeNode()\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === 'kun-spoiler',\n runner: (state, node) => {\n const content = withoutAnchors(node.content)\n // Nothing but the caret anchor: the button was clicked and never typed\n // into. Emit nothing rather than a bare `||||`.\n if (!content.size) {\n return\n }\n state.addNode('text', undefined, '||')\n state.next(content)\n state.addNode('text', undefined, '||')\n }\n }\n}))\n\n/** The spoiler the position sits inside, if any. A spoiler holds inline content\n * (it is not an atom), so a caret in one resolves to a deeper `parent`. */\nconst enclosingSpoiler = (\n $pos: ResolvedPos,\n type: NodeType\n): { pos: number; node: ProseNode } | null => {\n for (let depth = $pos.depth; depth > 0; depth--) {\n const node = $pos.node(depth)\n if (node.type === type) {\n return { pos: $pos.before(depth), node }\n }\n }\n return null\n}\n\n/**\n * Toolbar entry point (\"隐藏文本\"): hide the selection, or reveal the spoiler the\n * caret is in. The only way into a spoiler other than typing `||…||`, so it has\n * to cover the same cases the syntax does:\n *\n * - a selection → its TEXT moves INSIDE the node. It has to be moved, not\n * replaced: `replaceSelectionWith` on its own deletes what you selected. The\n * schema is `marks: ''` (bold inside `||…||` cannot round-trip), so the\n * formatting is what's dropped, never the words.\n * - an empty selection → an empty spoiler with the caret inside it: type, and\n * what you type is hidden. \"Empty\" means holding a caret anchor — a caret\n * cannot sit in an inline node with no text node in it — and a spoiler with\n * nothing but an anchor serializes to nothing at all, so an unused one cannot\n * rot into the document.\n * - the caret already inside a spoiler → reveal it, leaving the text selected.\n * Nesting would serialize to `||||text||||`, which reads back as nothing at\n * all, so this button has to toggle.\n *\n * Returns false where there is nothing to hide or nowhere to put it — inside a\n * code block, or with a NODE selected (an image is not text; replacing it would\n * delete it) — so a host can grey the button out. A spoiler holds text, so any\n * other inline node caught in a text selection (an image, inline math) does not\n * survive the move: `||…||` cannot carry one.\n */\nexport const insertKunSpoilerCommand = $command(\n 'InsertKunSpoiler',\n (ctx) => () => (state, dispatch) => {\n const type = spoilerSchema.type(ctx)\n const { $from, from, to, empty } = state.selection\n\n const open = enclosingSpoiler($from, type)\n if (open) {\n if (dispatch) {\n const { pos, node } = open\n const revealed = withoutAnchors(node.content)\n // Take the anchor that follows the node with it, or toggling the button\n // back and forth stacks up invisible characters.\n const end = pos + node.nodeSize\n const trailing = state.doc.textBetween(\n end,\n Math.min(end + CARET_ANCHOR.length, state.doc.content.size)\n )\n const tr = state.tr.replaceWith(\n pos,\n trailing === CARET_ANCHOR ? end + CARET_ANCHOR.length : end,\n revealed\n )\n if (revealed.size) {\n // Leave the revealed text selected: the next click re-hides exactly\n // what this one revealed.\n tr.setSelection(TextSelection.create(tr.doc, pos, pos + revealed.size))\n }\n dispatch(tr.scrollIntoView())\n }\n return true\n }\n\n // A selected NODE (an image, a code block) is not text to hide, and\n // replacing the selection would delete it. Refuse.\n if (state.selection instanceof NodeSelection) {\n return false\n }\n // Refuse where a spoiler cannot go — a code block holds plain text. Guarded\n // on `isTextblock` because select-all is an `AllSelection`, which resolves\n // to the DOC: no textblock to ask, and `replaceSelection` puts the node in\n // a paragraph of its own.\n if (\n $from.parent.isTextblock &&\n !$from.parent.canReplaceWith($from.index(), $from.index(), type)\n ) {\n return false\n }\n if (!dispatch) {\n return true\n }\n\n // ' ' as the block separator: a selection spanning paragraphs collapses into\n // one spoiler, and the words either side of the break stay apart. With\n // nothing selected the node still needs a text node to hold the caret, so\n // it starts on an anchor — the serializer drops it again.\n const text = state.doc\n .textBetween(from, to, ' ')\n .replaceAll(CARET_ANCHOR, '')\n const node = type.create(null, state.schema.text(text || CARET_ANCHOR))\n const tr = state.tr.replaceSelectionWith(node, false)\n // `replaceSelectionWith` leaves the selection right after the node.\n const after = tr.selection.to\n tr.insertText(CARET_ANCHOR, after)\n dispatch(\n tr\n .setSelection(\n TextSelection.create(\n tr.doc,\n // On the anchor inside the empty node (type and it is hidden), or\n // past the one after a wrap (type and it is not).\n empty\n ? after - node.nodeSize + 1 + CARET_ANCHOR.length\n : after + 1\n )\n )\n .scrollIntoView()\n )\n return true\n }\n)\n\n/** Typing `||text||` in the editor turns it into a spoiler node in place. The\n * trailing zero-width space gives the caret a stable anchor after the atom. */\nexport const insertSpoilerInputRule = $inputRule(\n () =>\n new InputRule(/(?:^|\\s)\\|\\|(.*?)\\|\\|$/, (state, match, start, end) => {\n const [fullMatch, content] = match\n if (!content) return null\n const startPos = start + (fullMatch.startsWith(' ') ? 1 : 0)\n const { tr } = state\n const schema = state.schema\n const spoilerNodeType = schema.nodes['kun-spoiler']\n if (!spoilerNodeType) return null\n\n const spoilerNode = spoilerNodeType.create(\n { revealed: false },\n schema.text(content)\n )\n const zeroWidthSpace = schema.text(CARET_ANCHOR)\n return tr\n .replaceWith(startPos, end, [spoilerNode, zeroWidthSpace])\n .setStoredMarks([])\n .scrollIntoView()\n })\n)\n\n/** Remark transform: splits `||...||` runs inside text nodes into `kun-spoiler`\n * mdast nodes on parse, so pasted / loaded markdown becomes real spoiler nodes. */\nexport const remarkSpoilerPlugin = $remark('remarkSpoiler', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'text', (node: SpoilerNode, index, parent: SpoilerNode) => {\n if (typeof node.value !== 'string' || !parent) {\n return\n }\n if (!node.value.includes('||')) {\n return\n }\n\n const regex = /\\|\\|(.*?)\\|\\|/g\n const newNodes: SpoilerNode[] = []\n let lastIndex = 0\n\n for (const match of node.value.matchAll(regex)) {\n const [full, content] = match\n const matchIndex = match.index ?? 0\n\n if (matchIndex > lastIndex) {\n newNodes.push({\n type: 'text',\n value: node.value.slice(lastIndex, matchIndex)\n })\n }\n\n if (content) {\n newNodes.push({\n type: 'kun-spoiler',\n children: [{ type: 'text', value: content }]\n })\n }\n\n lastIndex = matchIndex + full.length\n }\n\n if (lastIndex < node.value.length) {\n newNodes.push({ type: 'text', value: node.value.slice(lastIndex) })\n }\n\n if (newNodes.length > 0 && typeof index === 'number') {\n parent.children?.splice(index, 1, ...newNodes)\n }\n })\n }\n\n return transformer\n})\n\n/**\n * The spoiler plugin bundle: schema attrs, node schema, the `||…||` input rule,\n * the insert command and the remark round-trip. Pure — no adapter needed.\n */\nexport const createSpoilerPlugin = (): MilkdownPlugin[] =>\n [\n spoilerAttr,\n spoilerSchema,\n insertSpoilerInputRule,\n insertKunSpoilerCommand,\n remarkSpoilerPlugin\n ].flat()\n","// Stop-link — keep the link mark from leaking onto text that is not a link.\n//\n// A link is a MARK, so ProseMirror stores it as a pending mark after a delete\n// (the same mechanism that makes typing after a deleted bold word stay bold).\n// For a link that is wrong: the next keystroke must not inherit a href that\n// is no longer under the cursor. Two complementary pieces:\n//\n// 1. A $prose plugin that strips an orphan stored link the moment the\n// cursor is not inside a link (covers select-delete, backspace, …).\n// 2. A Space keymap that also clears the stored mark — Milkdown's link\n// mark is inclusive, so Space is how you stop extending a live link\n// while typing at its end (the forum's original stop-link behaviour).\n//\n// A stored link mark is ONLY valid while the cursor sits inside a link. This\n// plugin will therefore strip an \"armed\" toggleLink on an empty selection\n// outside a link — insert via insertLinkCommand instead. Pure: no host policy.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command, $prose, $useKeymap } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { commandsCtx } from '@milkdown/kit/core'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport type { MarkType } from '@milkdown/kit/prose/model'\nimport type { EditorState } from '@milkdown/kit/prose/state'\n\nconst hasMark = (state: EditorState, type: MarkType) => {\n if (!type) {\n return false\n }\n const { from, $from, to, empty } = state.selection\n if (empty) {\n return !!type.isInSet(state.storedMarks || $from.marks())\n }\n return state.doc.rangeHasMark(from, to, type)\n}\n\n/** Removes the stored link mark if one is active, letting the next keystroke\n * start un-linked text. Returns false so the Space still inserts a space. */\nexport const stopLinkCommand = $command('StopLink', (ctx) => () => {\n return (state, dispatch) => {\n const markType = linkSchema.type(ctx)\n const checkMark = hasMark(state, markType)\n if (checkMark) {\n dispatch?.(\n state.tr.removeStoredMark(markType).setMeta('addToHistory', false)\n )\n }\n return false\n }\n})\n\n/** Binds Space to the stop-link command. */\nexport const linkCustomKeymap = $useKeymap('linkCustomKeymap', {\n StopLink: {\n shortcuts: ['Space'],\n command: (ctx) => {\n const commands = ctx.get(commandsCtx)\n return () => commands.call(stopLinkCommand.key)\n }\n }\n})\n\nconst orphanLinkKey = new PluginKey('KUN_ORPHAN_LINK')\n\nconst clearOrphanLink = $prose(\n (ctx) =>\n new Plugin({\n key: orphanLinkKey,\n appendTransaction(_transactions, _oldState, newState) {\n const { storedMarks, selection } = newState\n if (!selection.empty || !storedMarks) {\n return null\n }\n const linkType = linkSchema.type(ctx)\n if (!linkType.isInSet(storedMarks)) {\n return null\n }\n // Still inside a link — keep the stored mark so typing continues it.\n if (linkType.isInSet(selection.$from.marks())) {\n return null\n }\n // Housekeeping: do not occupy an undo step of its own.\n return newState.tr\n .removeStoredMark(linkType)\n .setMeta('addToHistory', false)\n }\n })\n)\n\n/** The stop-link plugin bundle: the command, its Space keymap, and the orphan\n * cleanup. Pure. `$useKeymap` returns a `[ctx, shortcut]` tuple, so flatten\n * before use. */\nexport const createStopLinkPlugin = (): MilkdownPlugin[] =>\n [stopLinkCommand, linkCustomKeymap, clearOrphanLink].flat() as MilkdownPlugin[]\n","// Insert-link command — the click-to-insert behaviour over the commonmark `link`\n// MARK. The mark itself already exists (commonmark, so `[text](url)` round-trips\n// and pasted URLs autolink); this adds a command the toolbar / selection bubble\n// call to apply it. Standard markdown `[text](url)`.\n//\n// A link is a MARK (inline formatting on text) — deliberately distinct from the\n// custom NODE embeds (mention, quote) that follow the schema + toUrl/fromUrl\n// pattern. A rich \"article card\" would be a node like those, not this.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { normalizeLinkHref } from '../../href'\n\nexport interface InsertLinkPayload {\n /**\n * The URL. Required — a blank href is a no-op. Normalized on the way in, so a\n * schemeless host gets one: `www.a.com/x` → `https://www.a.com/x`. See\n * {@link normalizeLinkHref} for the exact rules.\n */\n href: string\n /** Text to insert + link when the selection is empty. Defaults to the href. */\n text?: string\n}\n\n/**\n * Apply the `link` mark with `href` to the selection; on an EMPTY selection,\n * insert `text` (or the href) and link that. Clears the stored mark afterwards so\n * typing past the link isn't linked (same intent as the stop-link keymap).\n *\n * The href is normalized here — this command is the single funnel every link\n * entry point (bubble, toolbar, host `linkPrompt`) goes through, so a UI never\n * has to, and every one of them behaves the same.\n */\nexport const insertLinkCommand = $command(\n 'InsertKunLink',\n (ctx) =>\n (payload?: InsertLinkPayload) =>\n (state, dispatch) => {\n const href = normalizeLinkHref(payload?.href ?? '')\n if (!href) {\n return false\n }\n const markType = linkSchema.type(ctx)\n const mark = markType.create({ href })\n const { from, to, empty } = state.selection\n if (empty) {\n const text = payload?.text?.trim() || href\n const tr = state.tr.insertText(text, from)\n tr.addMark(from, from + text.length, mark)\n tr.removeStoredMark(markType)\n dispatch?.(tr.scrollIntoView())\n } else {\n dispatch?.(state.tr.addMark(from, to, mark).scrollIntoView())\n }\n return true\n }\n)\n\n/** The link plugin bundle: the insert-link command. */\nexport const createLinkPlugin = (): MilkdownPlugin[] => [insertLinkCommand].flat()\n","// Absolute block-type command for a \"text size\" dropdown.\n//\n// commonmark ships `wrapInHeadingCommand` (a TOGGLE) but no \"set paragraph\"\n// command, so a heading dropdown (Paragraph / H1–H6, where each option sets one\n// exact level and Paragraph resets) can't be built from it. `setHeadingCommand`\n// sets the block type ABSOLUTELY: level 0 → paragraph, 1–6 → heading — the same\n// `setBlockType` approach the forum's header dropdown uses, exposed as a proper\n// command so a headless or KunUI toolbar drives it via `run(setHeadingCommand.key,\n// level)`. It's idempotent (re-selecting the current level is a no-op), unlike the\n// toggle which would flip a heading back to a paragraph.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command } from '@milkdown/kit/utils'\nimport { setBlockType } from '@milkdown/kit/prose/commands'\nimport { headingSchema, paragraphSchema } from '@milkdown/kit/preset/commonmark'\n\n/** Set the current block to a paragraph (`level` 0, the default) or a heading\n * (`level` 1–6). */\nexport const setHeadingCommand = $command(\n 'SetHeadingKun',\n (ctx) =>\n (level: number = 0) =>\n level >= 1 && level <= 6\n ? setBlockType(headingSchema.type(ctx), { level })\n : setBlockType(paragraphSchema.type(ctx))\n)\n\n/** The heading command bundle — no schema (commonmark owns paragraph/heading). */\nexport const createHeadingPlugin = (): MilkdownPlugin[] =>\n [setHeadingCommand].flat()\n","import { codeBlockSchema } from '@milkdown/kit/preset/commonmark'\n\n/// Extends commonmark's code-block schema so a fenced block whose language is\n/// `latex` serializes back to a `$$…$$` math block instead of a ``` fence. The\n/// parse direction is handled by remarkMathBlock (math mdast → code node).\nexport const blockKatexSchema = codeBlockSchema.extendSchema((prev) => {\n return (ctx) => {\n const baseSchema = prev(ctx)\n return {\n ...baseSchema,\n toMarkdown: {\n match: baseSchema.toMarkdown.match,\n runner: (state, node) => {\n const language = node.attrs.language ?? ''\n if (language.toLowerCase() === 'latex') {\n state.addNode(\n 'math',\n undefined,\n node.content.firstChild?.text || ''\n )\n } else {\n return baseSchema.toMarkdown.runner(state, node)\n }\n }\n }\n }\n }\n})\n","import { $nodeSchema } from '@milkdown/kit/utils'\nimport katex from 'katex'\n\nexport const mathInlineId = 'math_inline'\n\n/// Schema for the inline math node. Adds support for:\n///\n/// ```markdown\n/// $a^2 + b^2 = c^2$\n/// ```\n///\n/// The `value` attr holds the raw LaTeX; `toDOM` renders it with KaTeX. Pure\n/// mechanism — `katex` is an (optional) peer the host installs.\nexport const mathInlineSchema = $nodeSchema(mathInlineId, () => ({\n group: 'inline',\n inline: true,\n draggable: true,\n atom: true,\n attrs: {\n value: {\n default: ''\n }\n },\n parseDOM: [\n {\n tag: `span[data-type=\"${mathInlineId}\"]`,\n getAttrs: (dom) => {\n return {\n value: (dom as HTMLElement).dataset.value ?? ''\n }\n }\n }\n ],\n toDOM: (node) => {\n const code: string = node.attrs.value\n const dom = document.createElement('span')\n dom.dataset.type = mathInlineId\n dom.dataset.value = code\n katex.render(code, dom, {\n throwOnError: false\n })\n\n return dom\n },\n parseMarkdown: {\n match: (node) => node.type === 'inlineMath',\n runner: (state, node, type) => {\n state.addNode(type, { value: node.value as string })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === mathInlineId,\n runner: (state, node) => {\n state.addNode('inlineMath', undefined, node.attrs.value)\n }\n }\n}))\n","import type { Node } from '@milkdown/kit/prose/model'\n\nimport { findNodeInSelection } from '@milkdown/kit/prose'\nimport { NodeSelection, TextSelection } from '@milkdown/kit/prose/state'\nimport { $command } from '@milkdown/kit/utils'\n\nimport { mathInlineSchema } from './inlineKatex'\n\n/// Toggles the selection between inline math and plain text: wraps selected\n/// text in a math node, or unwraps an existing math node back to its source.\nexport const toggleLatexCommand = $command('ToggleLatex', (ctx) => {\n return () => (state, dispatch) => {\n const {\n hasNode: hasLatex,\n pos: latexPos,\n target: latexNode\n } = findNodeInSelection(state, mathInlineSchema.type(ctx))\n\n const { selection, doc, tr } = state\n if (!hasLatex) {\n const text = doc.textBetween(selection.from, selection.to)\n const _tr = tr.replaceSelectionWith(\n mathInlineSchema.type(ctx).create({\n value: text\n })\n )\n if (dispatch) {\n dispatch(\n _tr.setSelection(NodeSelection.create(_tr.doc, selection.from))\n )\n }\n return true\n }\n\n const { from, to } = selection\n if (!latexNode || latexPos < 0) return false\n\n let _tr = tr.delete(latexPos, latexPos + 1)\n const content = (latexNode as Node).attrs.value\n _tr = _tr.insertText(content, latexPos)\n if (dispatch) {\n dispatch(\n _tr.setSelection(\n TextSelection.create(_tr.doc, from, to + content.length - 1)\n )\n )\n }\n return true\n }\n})\n","import { codeBlockSchema } from '@milkdown/kit/preset/commonmark'\nimport { nodeRule } from '@milkdown/kit/prose'\nimport { textblockTypeInputRule } from '@milkdown/kit/prose/inputrules'\nimport { $inputRule } from '@milkdown/kit/utils'\nimport { TextSelection } from '@milkdown/kit/prose/state'\n\nimport { mathInlineSchema } from './inlineKatex'\n\n/// Typing `$…$` becomes an inline math atom.\nexport const mathInlineInputRule = $inputRule((ctx) =>\n nodeRule(/(?:\\$)([^$]+)(?:\\$)$/, mathInlineSchema.type(ctx), {\n getAttr: (match) => ({ value: match[1] ?? '' }),\n beforeDispatch: ({ tr, start }) => {\n // After replaceRangeWith, insert a zero-width space after the inline math\n // atom so ProseMirror doesn't need a trailing <br>, avoiding a caret\n // newline.\n const posAfter = start + 1\n tr.insertText('', posAfter, posAfter)\n // Move selection after the ZWSP so the caret sits right after the math.\n tr.setSelection(TextSelection.create(tr.doc, posAfter + 1))\n }\n })\n)\n\n/// Typing `$$` + Enter/Space opens a LaTeX code block (rendered as a math block).\nexport const mathBlockInputRule = $inputRule((ctx) =>\n textblockTypeInputRule(/^\\$\\$[\\s\\n]$/, codeBlockSchema.type(ctx), () => ({\n language: 'LaTeX'\n }))\n)\n","import type { Node } from '@milkdown/kit/transformer'\nimport { $remark } from '@milkdown/kit/utils'\nimport remarkMath from 'remark-math'\nimport { visit } from 'unist-util-visit'\n\n/// The remark-math plugin: parses `$…$` / `$$…$$` into mdast `inlineMath` /\n/// `math` nodes and stringifies them back. Both directions come from remark-math.\nexport const remarkMathPlugin = $remark<'remarkMath', undefined>(\n 'remarkMath',\n () => remarkMath\n)\n\nconst visitMathBlock = (ast: Node) => {\n return visit(\n ast,\n 'math',\n (\n node: Node & { value: string },\n index: number,\n parent: Node & { children: Node[] }\n ) => {\n const { value } = node as Node & { value: string }\n const newNode = {\n type: 'code',\n lang: 'LaTeX',\n value\n }\n parent.children.splice(index, 1, newNode as unknown as Node)\n }\n )\n}\n\n/// Rewrites block `math` mdast nodes into `code` nodes with lang `LaTeX` on\n/// parse, so a `$$…$$` block enters the editor as a code block. blockKatex\n/// serializes it back to `math` (→ `$$…$$`).\nexport const remarkMathBlockPlugin = $remark(\n 'remarkMathBlock',\n () => () => visitMathBlock\n)\n","// KaTeX plugin set — inline `$…$` and block `$$…$$` LaTeX.\n//\n// Ported from the forum's plugins/katex/*. Pure mechanism; `katex` is an\n// (optional) peer and `remark-math` a runtime dependency. The plugins must be\n// used AFTER the commonmark preset (blockKatex extends its code-block schema),\n// which createKunEditorPlugins guarantees.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\n\nimport { blockKatexSchema } from './blockKatex'\nimport { toggleLatexCommand } from './command'\nimport { mathInlineSchema } from './inlineKatex'\nimport { mathBlockInputRule, mathInlineInputRule } from './inputRule'\nimport { remarkMathBlockPlugin, remarkMathPlugin } from './remark'\n\nexport { blockKatexSchema } from './blockKatex'\nexport { toggleLatexCommand } from './command'\nexport { mathInlineId, mathInlineSchema } from './inlineKatex'\nexport { mathBlockInputRule, mathInlineInputRule } from './inputRule'\nexport { remarkMathBlockPlugin, remarkMathPlugin } from './remark'\n\n/**\n * The KaTeX plugin bundle, in dependency order: remark parse/serialize, the\n * inline math node, the `$…$` / `$$` input rules, the block-LaTeX serializer\n * and the toggle command. Pure — no adapter needed.\n */\nexport const createKatexPlugins = (): MilkdownPlugin[] =>\n [\n remarkMathPlugin,\n remarkMathBlockPlugin,\n mathInlineSchema,\n mathInlineInputRule,\n mathBlockInputRule,\n blockKatexSchema,\n toggleLatexCommand\n ].flat() as MilkdownPlugin[]\n","// CodeMirror theme + syntax highlight for the code block (WYSIWYG) editor.\n// Ported from the forum's codemirror/theme.ts. Colours reference KunUI CSS\n// variables so the code block matches the host theme (the render layer ships\n// the vars). Pure config — `@codemirror/*` and `@lezer/highlight` are (optional)\n// peers the host installs when the code-block feature is enabled.\nimport { EditorView } from '@codemirror/view'\nimport { HighlightStyle, syntaxHighlighting } from '@codemirror/language'\nimport { tags as t } from '@lezer/highlight'\nimport type { Extension } from '@codemirror/state'\n\nconst colors = {\n primary: 'var(--color-primary)',\n selected: 'color-mix(in oklab,var(--color-primary)10%,transparent)',\n primaryLight: 'var(--color-primary-400)',\n primaryDark: 'var(--color-primary-600)',\n secondary: 'var(--color-secondary)',\n secondaryLight: 'var(--color-secondary-400)',\n success: 'var(--color-success)',\n successLight: 'var(--color-success-400)',\n warning: 'var(--color-warning)',\n warningLight: 'var(--color-warning-400)',\n danger: 'var(--color-danger)',\n dangerLight: 'var(--color-danger-400)',\n foreground: 'var(--color-foreground)',\n background: 'var(--color-background)',\n backgroundAlpha: 'var(--color-background) / 0.7',\n overlay: 'var(--color-default-200)',\n overlayLight: 'var(--color-default-100)',\n divider: 'var(--color-default-100)',\n content1: 'var(--color-content1)',\n content2: 'var(--color-content2)',\n content3: 'var(--color-content3)',\n content4: 'var(--color-content4)'\n}\n\nexport const kunCMTheme = () => {\n return EditorView.theme({\n '&': {\n backgroundColor: colors.backgroundAlpha,\n borderRadius: '0.75rem',\n lineHeight: '1.5',\n scrollbarWidth: 'none',\n minHeight: '300px'\n },\n\n '&.cm-focused': {\n outline: 'none'\n },\n\n '.cm-scroller': {\n lineHeight: '1.5',\n maxWidth: '100%',\n scrollbarWidth: 'none'\n },\n\n '.cm-content': {\n padding: '1rem 0.5rem',\n maxWidth: '100%'\n },\n\n '.cm-line': {\n padding: '0.2rem 0',\n borderRadius: '0.375rem',\n maxWidth: '100%',\n fontSize: '1rem',\n '&:hover': {\n backgroundColor: colors.overlayLight\n }\n },\n\n '&.cm-focused .cm-cursor': {\n borderLeftColor: colors.primary,\n borderLeftWidth: '2px'\n },\n\n '.cm-panels': {\n backgroundColor: colors.background,\n color: colors.foreground,\n borderRadius: '0.5rem',\n margin: '0.5rem'\n },\n '.cm-panels.cm-panels-top': {\n borderBottom: `1px solid ${colors.divider}`\n },\n '.cm-panels.cm-panels-bottom': {\n borderTop: `1px solid ${colors.divider}`\n },\n\n '.cm-searchMatch': {\n backgroundColor: `${colors.primaryLight}50`,\n outline: `1px solid ${colors.primaryLight}`,\n borderRadius: '2px'\n },\n '.cm-searchMatch.cm-searchMatch-selected': {\n backgroundColor: `${colors.primary}40`\n },\n\n '.cm-activeLine': {\n backgroundColor: `${colors.content1}30`,\n borderRadius: '0.375rem'\n },\n '.cm-selectionMatch': {\n backgroundColor: `${colors.primary}20`,\n borderRadius: '2px'\n },\n\n '.cm-matchingBracket, .cm-nonmatchingBracket': {\n backgroundColor: `${colors.warning}30`,\n outline: 'none',\n borderRadius: '2px',\n padding: '0 1px',\n fontWeight: '600'\n },\n\n '.cm-gutters': {\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '0',\n fontSize: '1rem',\n padding: '0'\n },\n\n '.cm-lineNumbers': {\n color: colors.content3\n },\n\n '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':\n {\n backgroundColor: colors.selected\n },\n\n '.cm-activeLineGutter': {\n backgroundColor: colors.selected\n },\n\n '.cm-foldGutter': {\n color: colors.content3\n },\n\n '.cm-tooltip': {\n backgroundColor: colors.background,\n border: `1px solid ${colors.divider}`,\n borderRadius: '0.5rem',\n boxShadow:\n '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n overflow: 'hidden'\n },\n\n '.cm-tooltip-autocomplete': {\n '& > ul': {\n fontSize: '0.9rem',\n maxHeight: '20rem'\n },\n '& > ul > li': {\n padding: '0.375rem 0.75rem',\n borderRadius: '0.25rem'\n },\n '& > ul > li[aria-selected]': {\n backgroundColor: colors.content1,\n color: colors.foreground\n }\n },\n\n '&::-webkit-scrollbar': {\n width: '6px',\n height: '6px'\n },\n '&::-webkit-scrollbar-track': {\n background: 'transparent'\n },\n '&::-webkit-scrollbar-thumb': {\n backgroundColor: colors.content3,\n borderRadius: '3px',\n '&:hover': {\n backgroundColor: colors.content2\n }\n }\n })\n}\n\nexport const kunCMHighlightStyle = () =>\n HighlightStyle.define([\n // Keywords and control flow\n { tag: t.keyword, color: colors.primary, fontWeight: '600' },\n { tag: t.controlKeyword, color: colors.primary, fontWeight: '600' },\n { tag: t.moduleKeyword, color: colors.primary, fontWeight: '600' },\n\n // Variables and properties\n { tag: [t.propertyName, t.macroName], color: colors.secondary },\n { tag: t.variableName, color: colors.foreground },\n {\n tag: t.definition(t.variableName),\n color: colors.secondary,\n fontWeight: '600'\n },\n\n // Functions\n {\n tag: [t.function(t.variableName), t.labelName],\n color: colors.success,\n fontWeight: '500'\n },\n {\n tag: t.definition(t.function(t.variableName)),\n color: colors.success,\n fontWeight: '600'\n },\n\n // Types and classes\n {\n tag: [t.typeName, t.className, t.namespace],\n color: colors.warning,\n fontWeight: '500'\n },\n { tag: [t.annotation, t.modifier], color: colors.warningLight },\n\n // Constants and literals\n {\n tag: [t.number, t.bool, t.null],\n color: colors.secondary,\n fontWeight: '500'\n },\n { tag: t.string, color: colors.success },\n { tag: t.regexp, color: colors.warning },\n\n // Special syntax\n { tag: [t.meta, t.comment], color: colors.foreground, fontStyle: 'italic' },\n { tag: t.tagName, color: colors.primary, fontWeight: '500' },\n { tag: t.attributeName, color: colors.warning },\n\n // Markdown specific\n { tag: t.heading, color: colors.primary, fontWeight: '700' },\n {\n tag: [t.url, t.link],\n color: colors.success,\n textDecoration: 'underline'\n },\n { tag: t.emphasis, fontStyle: 'italic' },\n { tag: t.strong, fontWeight: '700' },\n\n // Special cases\n {\n tag: t.invalid,\n color: colors.danger,\n borderBottom: `2px dotted ${colors.danger}`\n },\n { tag: t.changed, color: colors.warning },\n { tag: t.inserted, color: colors.success },\n { tag: t.deleted, color: colors.danger }\n ])\n\n/** The KUN CodeMirror theme: base theme + syntax highlighting. */\nexport const kunCM = (): Extension => [\n kunCMTheme(),\n syntaxHighlighting(kunCMHighlightStyle())\n]\n","// SVG icon strings for the code-block toolbar (expand / search / clear / copy /\n// edit / hide). Ported verbatim from the forum's plugins/code/icons.ts. These\n// are inline SVG so the code-block component (a web component) can render them\n// without a framework icon dependency.\n\nexport const chevronDownIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-6 h-6\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\"\n />\n </svg>\n`\n\nexport const clearIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n >\n <g clip-path=\"url(#clip0_1098_15553)\">\n <path\n d=\"M18.3007 5.70973C17.9107 5.31973 17.2807 5.31973 16.8907 5.70973L12.0007 10.5897L7.1107 5.69973C6.7207 5.30973 6.0907 5.30973 5.7007 5.69973C5.3107 6.08973 5.3107 6.71973 5.7007 7.10973L10.5907 11.9997L5.7007 16.8897C5.3107 17.2797 5.3107 17.9097 5.7007 18.2997C6.0907 18.6897 6.7207 18.6897 7.1107 18.2997L12.0007 13.4097L16.8907 18.2997C17.2807 18.6897 17.9107 18.6897 18.3007 18.2997C18.6907 17.9097 18.6907 17.2797 18.3007 16.8897L13.4107 11.9997L18.3007 7.10973C18.6807 6.72973 18.6807 6.08973 18.3007 5.70973Z\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_1098_15553\">\n <rect width=\"24\" height=\"24\" />\n </clipPath>\n </defs>\n </svg>\n`\n\nexport const copyIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"24px\"\n viewBox=\"0 -960 960 960\"\n width=\"24px\"\n fill=\"none\"\n >\n <path\n d=\"M360-240q-33 0-56.5-23.5T280-320v-480q0-33 23.5-56.5T360-880h360q33 0 56.5 23.5T800-800v480q0 33-23.5 56.5T720-240H360Zm0-80h360v-480H360v480ZM200-80q-33 0-56.5-23.5T120-160v-560h80v560h440v80H200Zm160-240v-480 480Z\"\n />\n </svg>\n`\n\nexport const editIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n >\n <g clip-path=\"url(#clip0_1013_1585)\">\n <path\n d=\"M14.06 9.02L14.98 9.94L5.92 19H5V18.08L14.06 9.02ZM17.66 3C17.41 3 17.15 3.1 16.96 3.29L15.13 5.12L18.88 8.87L20.71 7.04C21.1 6.65 21.1 6.02 20.71 5.63L18.37 3.29C18.17 3.09 17.92 3 17.66 3ZM14.06 6.19L3 17.25V21H6.75L17.81 9.94L14.06 6.19Z\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_1013_1585\">\n <rect width=\"24\" height=\"24\" />\n </clipPath>\n </defs>\n </svg>\n`\n\nexport const searchIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-6 h-6\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\"\n />\n </svg>\n`\n\nexport const visibilityOffIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"24px\"\n viewBox=\"0 -960 960 960\"\n width=\"24px\"\n >\n <path\n d=\"m644-428-58-58q9-47-27-88t-93-32l-58-58q17-8 34.5-12t37.5-4q75 0 127.5 52.5T660-500q0 20-4 37.5T644-428Zm128 126-58-56q38-29 67.5-63.5T832-500q-50-101-143.5-160.5T480-720q-29 0-57 4t-55 12l-62-62q41-17 84-25.5t90-8.5q151 0 269 83.5T920-500q-23 59-60.5 109.5T772-302Zm20 246L624-222q-35 11-70.5 16.5T480-200q-151 0-269-83.5T40-500q21-53 53-98.5t73-81.5L56-792l56-56 736 736-56 56ZM222-624q-29 26-53 57t-41 67q50 101 143.5 160.5T480-280q20 0 39-2.5t39-5.5l-36-38q-11 3-21 4.5t-21 1.5q-75 0-127.5-52.5T300-500q0-11 1.5-21t4.5-21l-84-82Zm319 93Zm-151 75Z\"\n />\n </svg>\n`\n","// Code block (CodeMirror) — Milkdown's code-block component wired with the KUN\n// CodeMirror theme, language list, toolbar icons, localized labels and a KaTeX\n// preview for `latex` blocks.\n//\n// Ported from the forum's Editor.vue codeBlockConfig wiring + plugins/code/*.\n// Pure mechanism: the CodeMirror packages and `katex` are (optional) peers the\n// host installs when the code-block feature is on. Labels are localized via the\n// `locale` option (mechanism owns the strings, the host picks the language).\nimport type { Ctx, MilkdownPlugin } from '@milkdown/kit/ctx'\nimport {\n codeBlockComponent,\n codeBlockConfig\n} from '@milkdown/kit/component/code-block'\nimport { defaultKeymap, indentWithTab } from '@codemirror/commands'\nimport { EditorView, keymap } from '@codemirror/view'\nimport { languages } from '@codemirror/language-data'\nimport type { Extension } from '@codemirror/state'\nimport { basicSetup } from 'codemirror'\nimport katex from 'katex'\nimport type { KatexOptions } from 'katex'\n\nimport type { KunEditorLocale } from '../../types'\nimport { kunCM } from './theme'\nimport {\n chevronDownIcon,\n clearIcon,\n copyIcon,\n editIcon,\n searchIcon,\n visibilityOffIcon\n} from './icons'\n\nexport { kunCM, kunCMTheme, kunCMHighlightStyle } from './theme'\nexport * from './icons'\n\n/** Options for the code-block plugin. All optional. */\nexport interface CodeBlockOptions {\n /** UI language for the toolbar labels. Default: `'zh-cn'`. */\n locale?: KunEditorLocale\n /** KaTeX options for the `latex` block preview. */\n katexOptions?: KatexOptions\n /** Extra CodeMirror extensions appended after the KUN defaults. */\n extensions?: Extension[]\n /** Called when the user copies a code block. */\n onCopy?: (text: string) => void\n}\n\ninterface CodeBlockLabels {\n searchPlaceholder: string\n copyText: string\n noResultText: string\n previewLoading: string\n edit: string\n hide: string\n}\n\n// The forum's playful zh-cn strings (\"搜索咒文\"/\"复制咒文\" — galgame flavor) are the\n// default; en-us is the neutral fallback for other hosts.\nconst LABELS: Record<'zh-cn' | 'en-us', CodeBlockLabels> = {\n 'zh-cn': {\n searchPlaceholder: '搜索咒文',\n copyText: '复制咒文',\n noResultText: '无结果',\n previewLoading: '加载中...',\n edit: '编辑',\n hide: '隐藏'\n },\n 'en-us': {\n searchPlaceholder: 'Search language',\n copyText: 'Copy',\n noResultText: 'No results',\n previewLoading: 'Loading...',\n edit: 'Edit',\n hide: 'Hide'\n }\n}\n\nconst labelsFor = (locale: KunEditorLocale | undefined): CodeBlockLabels =>\n locale && locale.toLowerCase().startsWith('en')\n ? LABELS['en-us']\n : LABELS['zh-cn']\n\n/**\n * Applies the KUN code-block config to a Milkdown ctx: CodeMirror extensions,\n * the language list, toolbar icons, localized labels, and a KaTeX preview for\n * `latex` blocks. Call inside a plugin runner or `.config()` — after\n * `codeBlockComponent` has registered its config slice.\n */\nexport const applyCodeBlockConfig = (\n ctx: Ctx,\n options: CodeBlockOptions = {}\n): void => {\n const labels = labelsFor(options.locale)\n const onCopy = options.onCopy ?? (() => {})\n\n ctx.update(codeBlockConfig.key, (prev) => ({\n ...prev,\n extensions: [\n kunCM(),\n EditorView.lineWrapping,\n keymap.of(defaultKeymap.concat(indentWithTab)),\n basicSetup,\n ...(options.extensions ?? [])\n ],\n languages,\n expandIcon: chevronDownIcon,\n searchIcon,\n clearSearchIcon: clearIcon,\n searchPlaceholder: labels.searchPlaceholder,\n copyText: labels.copyText,\n copyIcon,\n onCopy,\n noResultText: labels.noResultText,\n previewLoading: labels.previewLoading,\n // Render `latex` code blocks as rendered math; defer everything else to the\n // component default.\n renderPreview: (language, content, applyPreview) => {\n if (language.toLowerCase() === 'latex' && content.length > 0) {\n return katex.renderToString(content, {\n ...options.katexOptions,\n throwOnError: false,\n displayMode: true\n })\n }\n return prev.renderPreview(language, content, applyPreview)\n },\n previewToggleButton: (previewOnlyMode) => {\n const icon = previewOnlyMode ? editIcon : visibilityOffIcon\n const text = previewOnlyMode ? labels.edit : labels.hide\n return [icon, text].map((v) => v.trim()).join(' ')\n }\n }))\n}\n\n/** A Milkdown plugin that applies the code-block config on setup. Bundled into\n * `createCodeBlockPlugins` so the render layer needs no separate config call. */\nconst codeBlockConfigPlugin =\n (options: CodeBlockOptions): MilkdownPlugin =>\n (ctx) =>\n () => {\n applyCodeBlockConfig(ctx, options)\n }\n\n/**\n * The code-block plugin bundle: Milkdown's `codeBlockComponent` plus the KUN\n * config (CodeMirror theme/languages/icons/labels + KaTeX preview). Pure — the\n * CodeMirror + katex peers must be installed when this feature is enabled.\n */\nexport const createCodeBlockPlugins = (\n options: CodeBlockOptions = {}\n): MilkdownPlugin[] => [...codeBlockComponent, codeBlockConfigPlugin(options)]\n","// @mention plugin — the inline mention atom + its markdown round-trip.\n//\n// The stored markdown form is an ordinary link whose URL the server renders into\n// a mention chip (and parses for notifications). The DEFAULT form is\n// `[@name](kungal-user:<id>)`, but the URL shape is host POLICY — the KUN server\n// uses `kungal-user:`, moyu uses a real `/user/<id>/…` link, another host could\n// use something else. So it's injectable via `toUrl` / `fromUrl` (mechanism vs\n// policy — see docs/architecture.md); the hardcoded scheme was the one thing\n// that stopped a host with a different mention link form from adopting the editor.\n//\n// A markdown link is a MARK (not a node) in milkdown, so a node schema that\n// matched links would fight the commonmark link mark. Instead — like spoiler — a\n// $remark transformer rewrites the matching link mdast nodes into a custom\n// `mention` node on PARSE; toMarkdown emits a plain link back.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport type { Node } from '@milkdown/kit/transformer'\nimport { $command, $nodeSchema, $remark } from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\nimport { MENTION_SCHEME } from '../../index'\n\nexport const mentionId = 'mention'\n\n/**\n * How an @mention's user id maps TO / FROM its markdown link URL — host policy.\n * Default: the `kungal-user:<id>` scheme (shared with the KUN server).\n */\nexport interface MentionUrlConfig {\n /** Build the link URL for a mention of `userId`. */\n toUrl?: (userId: number) => string\n /**\n * Parse a link back to a user id, or `null` if it isn't a mention. Gets the\n * link URL AND its plain text, so a host can replicate text-based guards — e.g.\n * moyu treats `/user/<id>` as a mention only when the link text starts with\n * `@`, so `[see here](/user/5/x)` stays a plain link.\n */\n fromUrl?: (url: string, text: string) => number | null\n}\n\nconst defaultToUrl = (userId: number): string => `${MENTION_SCHEME}${userId}`\nconst defaultFromUrl = (url: string): number | null => {\n if (!url.startsWith(MENTION_SCHEME)) return null\n const id = Number.parseInt(url.slice(MENTION_SCHEME.length), 10)\n return Number.isInteger(id) && id > 0 ? id : null\n}\n\n// Minimal shape of the mdast nodes we touch (link on the way in, our synthetic\n// `mention` node on the way out).\ninterface MdastNode extends Node {\n type: string\n url?: string\n value?: string\n userId?: number\n name?: string\n children?: MdastNode[]\n}\n\n/** The mention node schema; `toUrl` decides the serialized link URL. */\nconst makeMentionSchema = (toUrl: (userId: number) => string) =>\n $nodeSchema(mentionId, () => ({\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n userId: { default: 0 },\n name: { default: '' }\n },\n parseDOM: [\n {\n // Pasted rendered content (server emits <a class=\"kun-mention\" data-uid>).\n tag: 'a.kun-mention',\n getAttrs: (dom) => {\n const el = dom as HTMLElement\n return {\n userId: Number.parseInt(el.dataset.uid ?? '0', 10) || 0,\n name: (el.textContent ?? '').replace(/^@/, '')\n }\n }\n }\n ],\n toDOM: (node) => {\n // A non-navigating span chip inside the editor (a real <a> would steal the\n // click and leave the page mid-compose). data-uid mirrors the server form.\n const span = document.createElement('span')\n span.className = 'kun-mention'\n span.dataset.uid = String(node.attrs.userId)\n span.setAttribute('contenteditable', 'false')\n span.textContent = `@${node.attrs.name}`\n return span\n },\n parseMarkdown: {\n match: (node) => node.type === mentionId,\n runner: (state, node, type) => {\n const n = node as MdastNode\n state.addNode(type, { userId: n.userId ?? 0, name: n.name ?? '' })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === mentionId,\n runner: (state, node) => {\n state.openNode('link', undefined, { url: toUrl(node.attrs.userId) })\n state.addNode('text', undefined, `@${node.attrs.name}`)\n state.closeNode()\n }\n }\n }))\n\n/** Rewrites links that `fromUrl` recognizes as mentions into mention nodes. */\nconst makeRemarkMention = (\n fromUrl: (url: string, text: string) => number | null\n) =>\n $remark('remarkMention', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'link', (node: MdastNode, index, parent: MdastNode) => {\n if (typeof node.url !== 'string') {\n return\n }\n // The link's plain text, so fromUrl can apply text-based guards (e.g.\n // moyu requires the text to start with `@`). Concatenated across children\n // to be robust to `[**@name**](url)` etc.\n const text = (node.children ?? [])\n .map((child) => (typeof child.value === 'string' ? child.value : ''))\n .join('')\n const userId = fromUrl(node.url, text)\n if (userId == null) {\n return\n }\n const name = text.replace(/^@/, '')\n if (typeof index === 'number' && parent.children) {\n parent.children.splice(index, 1, {\n type: mentionId,\n userId,\n name\n } as MdastNode)\n }\n })\n }\n return transformer\n })\n\n/** Default (kungal-user:) mention schema — for advanced direct use. */\nexport const mentionSchema = makeMentionSchema(defaultToUrl)\n/** Default (kungal-user:) mention remark transform — for advanced direct use. */\nexport const remarkMentionPlugin = makeRemarkMention(defaultFromUrl)\n\n/**\n * Insert a mention chip at the cursor, replacing the selection. The render-layer\n * dropdown usually replaces the `@query` range itself; this is the programmatic\n * path (toolbar / tests / the imperative insertMention handle). A trailing space\n * lets the caret continue past the atom naturally. Resolves the node type by id\n * from the live schema, so it works with any mention config.\n */\nexport const insertMentionCommand = $command(\n 'InsertKunMention',\n () =>\n (payload?: { userId: number; name: string }) =>\n (state, dispatch) => {\n if (!payload || !dispatch) {\n return false\n }\n const { userId, name } = payload\n if (!Number.isInteger(userId) || userId <= 0) {\n return false\n }\n const type = state.schema.nodes[mentionId]\n if (!type) {\n return false\n }\n const node = type.create({ userId, name })\n const tr = state.tr.replaceSelectionWith(node)\n tr.insertText(' ')\n dispatch(tr.scrollIntoView())\n return true\n }\n)\n\n/**\n * The mention plugin bundle: schema + remark round-trip + insert command. Pass\n * `toUrl` / `fromUrl` to use a host-specific mention link form; omit for the\n * default `kungal-user:` scheme. The `searchMentionUsers` adapter (the `@`\n * autocomplete) is consumed by the render-layer dropdown.\n */\nexport const createMentionPlugin = (\n config: MentionUrlConfig = {}\n): MilkdownPlugin[] => {\n const schema = config.toUrl ? makeMentionSchema(config.toUrl) : mentionSchema\n const remark = config.fromUrl\n ? makeRemarkMention(config.fromUrl)\n : remarkMentionPlugin\n return [schema, remark, insertMentionCommand].flat()\n}\n","// Quote / inline-reference plugin — a non-editable inline atom that points at\n// something the HOST defines (a reply, a comment, …).\n//\n// Ported from the forum's plugins/quote/quotePlugin.ts, but GENERALIZED per\n// docs/architecture.md § the reply-quote question (option 1): the forum's\n// `{ replyId, floor }` becomes an opaque `{ refId, label }`. The editor owns the\n// mechanism — a stable inline atom with a trailing-caret insert — while the host\n// owns what a reference means (it supplies refId + the display label).\n//\n// Stored markdown form: `[label](kungal-reply:<refId>)` — an ordinary link whose\n// custom `kungal-reply:` scheme the server renders into a quote card. Same shape\n// as the mention plugin: a $remark transformer rewrites matching links into a\n// `quote` node on PARSE; toMarkdown emits a plain link back.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport type { Node } from '@milkdown/kit/transformer'\nimport { $command, $nodeSchema, $remark } from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\nimport { QUOTE_SCHEME } from '../../index'\n\nexport const quoteId = 'quote'\n\n/** The payload a host passes to insert a reference. `refId` is opaque (the host\n * decides its meaning); `label` is what the chip shows. */\nexport interface QuoteReference {\n refId: string\n label: string\n}\n\n// Minimal shape of the mdast nodes we touch (link on the way in, our synthetic\n// `quote` node on the way out).\ninterface MdastNode extends Node {\n type: string\n url?: string\n value?: string\n refId?: string\n label?: string\n children?: MdastNode[]\n}\n\nexport const quoteSchema = $nodeSchema(quoteId, () => ({\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n refId: { default: '' },\n label: { default: '' }\n },\n parseDOM: [\n {\n // Pasted rendered content (server emits <span class=\"kun-quote\" data-ref-id>).\n tag: 'span.kun-quote',\n getAttrs: (dom) => {\n const el = dom as HTMLElement\n return {\n refId: el.dataset.refId ?? '',\n label: el.textContent ?? ''\n }\n }\n }\n ],\n toDOM: (node) => {\n // A non-navigating span chip inside the editor; mirrors the server form so a\n // round-trip through paste/copy is lossless.\n const span = document.createElement('span')\n span.className = 'kun-quote'\n span.dataset.refId = String(node.attrs.refId)\n span.setAttribute('contenteditable', 'false')\n span.textContent = String(node.attrs.label)\n return span\n },\n parseMarkdown: {\n match: (node) => node.type === quoteId,\n runner: (state, node, type) => {\n const n = node as MdastNode\n state.addNode(type, { refId: n.refId ?? '', label: n.label ?? '' })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === quoteId,\n runner: (state, node) => {\n state.openNode('link', undefined, {\n url: `${QUOTE_SCHEME}${node.attrs.refId}`\n })\n state.addNode('text', undefined, String(node.attrs.label))\n state.closeNode()\n }\n }\n}))\n\n/** Rewrites `[label](kungal-reply:refId)` links into quote nodes on parse. */\nexport const remarkQuotePlugin = $remark('remarkQuote', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'link', (node: MdastNode, index, parent: MdastNode) => {\n if (typeof node.url !== 'string' || !node.url.startsWith(QUOTE_SCHEME)) {\n return\n }\n const refId = node.url.slice(QUOTE_SCHEME.length)\n if (!refId) {\n return\n }\n const first = node.children?.[0]\n const label = typeof first?.value === 'string' ? first.value : ''\n if (typeof index === 'number' && parent.children) {\n parent.children.splice(index, 1, {\n type: quoteId,\n refId,\n label\n } as MdastNode)\n }\n })\n }\n return transformer\n})\n\n/**\n * Insert a quote chip at the cursor, replacing the selection. The host supplies\n * `{ refId, label }`. A trailing space is the whole caret fix: a paragraph that\n * ENDS in a non-editable inline atom has no stable caret position after it, so\n * the next keystroke (esp. an IME composition) snaps to before the atom. A real\n * text node after it gives the caret somewhere to anchor.\n */\nexport const insertQuoteCommand = $command(\n 'InsertKunQuote',\n (ctx) =>\n (payload?: QuoteReference) =>\n (state, dispatch) => {\n if (!payload || !dispatch) {\n return false\n }\n const { refId, label } = payload\n if (!refId) {\n return false\n }\n const node = quoteSchema.type(ctx).create({ refId, label })\n if (!node) {\n return false\n }\n const tr = state.tr.replaceSelectionWith(node)\n tr.insertText(' ')\n dispatch(tr.scrollIntoView())\n return true\n }\n)\n\n/** The quote plugin bundle: schema + remark round-trip + insert command. */\nexport const createQuotePlugin = (): MilkdownPlugin[] =>\n [quoteSchema, remarkQuotePlugin, insertQuoteCommand].flat()\n","// Image upload plugin — paste / drop / toolbar image upload.\n//\n// Ported from the forum's plugins/upload/uploader.ts, generalized over the\n// `uploadImage` adapter. This is the plugin the architecture calls out as the\n// clearest mechanism-vs-policy split: the forum hardcoded\n// `kunFetch('/image/topic')`; here the host injects WHERE the upload goes, and\n// the editor owns the paste/drop wiring and the in-flight placeholder.\n//\n// Built on @milkdown/kit/plugin/upload: we set its `uploader` (per-image → url)\n// and `uploadWidgetFactory` (the \"uploading…\" placeholder) via ctx config,\n// bundled as a plugin so the render layer needs no separate config call.\nimport type { Ctx, MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { upload, uploadConfig } from '@milkdown/kit/plugin/upload'\nimport type { Uploader } from '@milkdown/kit/plugin/upload'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport { Decoration, DecorationSet } from '@milkdown/kit/prose/view'\nimport type { EditorView } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\nimport { $prose } from '@milkdown/kit/utils'\n\nimport type { KunEditorLocale, Notify, UploadImage } from '../../types'\n\n/** Options for the upload plugin. */\nexport interface UploadPluginOptions {\n /** UI language for the in-flight placeholder text. Default `'zh-cn'`. */\n locale?: KunEditorLocale\n /** Surface an \"upload failed\" notice per image. Omit to fail silently. */\n notify?: Notify\n}\n\nconst uploadingLabel = (locale: KunEditorLocale | undefined): string =>\n locale && locale.toLowerCase().startsWith('en') ? 'Uploading…' : '正在上传中...'\n\nconst uploadFailedLabel = (locale: KunEditorLocale | undefined): string =>\n locale && locale.toLowerCase().startsWith('en')\n ? 'Image upload failed'\n : '图片上传失败'\n\n/**\n * Build a Milkdown `Uploader` from the host's `uploadImage` adapter. Filters to\n * image files, uploads each via the adapter, and returns image nodes. A failed\n * image is skipped (and reported via `notify` if provided) instead of aborting\n * the whole batch — more robust than the forum's all-or-nothing Promise.all.\n */\nexport const createUploader = (\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): Uploader => {\n return async (files, schema) => {\n const images: File[] = []\n for (let i = 0; i < files.length; i++) {\n const file = files.item(i)\n if (!file || !file.type.startsWith('image/')) {\n continue\n }\n images.push(file)\n }\n\n const nodes = await Promise.all(\n images.map(async (image): Promise<Node | null> => {\n try {\n const src = await uploadImage(image)\n return schema.nodes.image!.createAndFill({\n src,\n alt: image.name\n }) as Node\n } catch {\n options.notify?.(uploadFailedLabel(options.locale), 'error')\n return null\n }\n })\n )\n\n return nodes.filter((node): node is Node => node !== null)\n }\n}\n\n/** Build the in-flight \"uploading…\" placeholder DOM — a `.kun-editor__uploading`\n * span (class hook, styled by the host stylesheet — headless). Shared by the\n * paste/drop path and the toolbar path so they look identical. */\nconst uploadingWidget = (locale: KunEditorLocale | undefined): HTMLElement => {\n const el = document.createElement('span')\n el.className = 'kun-editor__uploading'\n el.textContent = uploadingLabel(locale)\n return el\n}\n\n/** The in-flight \"uploading…\" placeholder shown at the drop position (paste/drop\n * path — Milkdown's `upload` plugin calls this). */\nexport const createUploadWidgetFactory = (options: UploadPluginOptions = {}) => {\n return (pos: number, spec: Parameters<typeof Decoration.widget>[2]) => {\n return Decoration.widget(pos, uploadingWidget(options.locale), spec)\n }\n}\n\n/** Applies the uploader + placeholder to a Milkdown ctx. Call after the `upload`\n * plugin has registered its config slice. */\nexport const applyUploadConfig = (\n ctx: Ctx,\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): void => {\n ctx.update(uploadConfig.key, (prev) => ({\n ...prev,\n uploader: createUploader(uploadImage, options),\n uploadWidgetFactory: createUploadWidgetFactory(options)\n }))\n}\n\nconst uploadConfigPlugin =\n (uploadImage: UploadImage, options: UploadPluginOptions): MilkdownPlugin =>\n (ctx) =>\n () => {\n applyUploadConfig(ctx, uploadImage, options)\n }\n\n/**\n * The image-upload plugin bundle: Milkdown's `upload` plugin plus the KUN config\n * (uploader over the `uploadImage` adapter + localized placeholder). Wire this\n * only when a host provides `uploadImage` — its absence is exactly how the\n * image-free editor (galgame 简介) is expressed.\n */\nexport const createUploadPlugin = (\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): MilkdownPlugin[] => [...upload, uploadConfigPlugin(uploadImage, options)]\n\n// ── Toolbar / programmatic upload (in-document placeholder) ─────────────────\n//\n// Milkdown's `upload` plugin only shows the in-flight placeholder for paste/drop\n// (it intercepts those DOM events). The toolbar's image button uploads a File\n// programmatically, so it gets no placeholder — the image just pops in when the\n// upload resolves. This mirrors ProseMirror's official \"upload\" example: a\n// DecorationSet plugin holds a widget placeholder (keyed by a unique id) that\n// maps through edits; `startImageUpload` inserts it, awaits the adapter, then\n// replaces the placeholder with the image (or removes it on failure). Same\n// `.kun-editor__uploading` widget as paste/drop, so both look identical.\n\ninterface PlaceholderMeta {\n add?: { id: object; pos: number; locale: KunEditorLocale | undefined }\n remove?: { id: object }\n}\n\nconst placeholderKey = new PluginKey<DecorationSet>('KUN_IMAGE_UPLOAD_PLACEHOLDER')\n\n/** The placeholder DecorationSet plugin — add it when uploads are enabled. */\nexport const imageUploadPlaceholder: MilkdownPlugin = $prose(\n () =>\n new Plugin<DecorationSet>({\n key: placeholderKey,\n state: {\n init: () => DecorationSet.empty,\n apply(tr, set) {\n let next = set.map(tr.mapping, tr.doc)\n const meta = tr.getMeta(placeholderKey) as PlaceholderMeta | undefined\n if (meta?.add) {\n const deco = Decoration.widget(\n meta.add.pos,\n uploadingWidget(meta.add.locale),\n { id: meta.add.id } as Parameters<typeof Decoration.widget>[2]\n )\n next = next.add(tr.doc, [deco])\n } else if (meta?.remove) {\n const { id } = meta.remove\n next = next.remove(\n next.find(undefined, undefined, (spec) => spec.id === id)\n )\n }\n return next\n }\n },\n props: {\n decorations: (state) => placeholderKey.getState(state)\n }\n })\n)\n\nconst findPlaceholder = (view: EditorView, id: object): number | null => {\n const set = placeholderKey.getState(view.state)\n const found = set?.find(undefined, undefined, (spec) => spec.id === id)\n return found && found.length ? found[0]!.from : null\n}\n\n/**\n * Upload a File and show an in-document \"uploading…\" placeholder at the caret\n * until it resolves, then replace it with the image (or remove it + notify on\n * failure). The placeholder isn't an undo step (`addToHistory: false`), so undo\n * removes the inserted image cleanly. Used by the toolbar image button.\n */\nexport const startImageUpload = async (\n view: EditorView,\n file: File,\n options: { uploadImage: UploadImage; notify?: Notify; locale?: KunEditorLocale }\n): Promise<void> => {\n if (!file.type.startsWith('image/')) {\n return\n }\n const id = {}\n const tr = view.state.tr\n if (!tr.selection.empty) {\n tr.deleteSelection()\n }\n tr.setMeta(placeholderKey, {\n add: { id, pos: tr.selection.from, locale: options.locale }\n } satisfies PlaceholderMeta)\n tr.setMeta('addToHistory', false)\n view.dispatch(tr)\n\n try {\n const src = await options.uploadImage(file)\n const pos = findPlaceholder(view, id)\n if (pos === null) {\n return // placeholder gone (e.g. user undid) — drop the result\n }\n const imageType = view.state.schema.nodes.image\n const node = imageType?.createAndFill({ src, alt: file.name })\n if (!node) {\n return\n }\n view.dispatch(\n view.state.tr\n .replaceWith(pos, pos, node)\n .setMeta(placeholderKey, { remove: { id } } satisfies PlaceholderMeta)\n )\n } catch {\n view.dispatch(\n view.state.tr\n .setMeta(placeholderKey, { remove: { id } } satisfies PlaceholderMeta)\n .setMeta('addToHistory', false)\n )\n options.notify?.(uploadFailedLabel(options.locale), 'error')\n }\n}\n","// Placeholder — text shown when the editor (or the current block) is empty.\n//\n// Same mechanism as Milkdown Crepe's placeholder feature (the current, v7 way):\n// a $prose ProseMirror plugin that adds a NODE DECORATION to the empty block —\n// a `.kun-editor__placeholder` class + a `data-placeholder` attribute. The text\n// is rendered by CSS (`::before { content: attr(data-placeholder) }`), so it's\n// purely visual — never part of the doc or the markdown output. Headless: this\n// core ships only the class/attr hook; the `::before` rule lives in the host's\n// stylesheet (see the reference editor.css in @kungal/editor-nuxt).\n//\n// mode 'block' (default): show on whichever empty block the cursor is in (Notion\n// style). mode 'doc': show only when the whole document is empty. Skipped in\n// readonly, code blocks, lists and tables, and whenever there's a selection.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { editorViewOptionsCtx } from '@milkdown/kit/core'\nimport type { EditorState } from '@milkdown/kit/prose/state'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport { Decoration, DecorationSet } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\nimport { $prose } from '@milkdown/kit/utils'\n\nexport type PlaceholderMode = 'doc' | 'block'\n\nexport interface PlaceholderConfig {\n /** The placeholder text. Empty string disables the placeholder. */\n text?: string\n /** `'block'` (default) shows on any empty block; `'doc'` only when empty. */\n mode?: PlaceholderMode\n}\n\n// Blocks whose own emptiness shouldn't trigger the paragraph-style placeholder.\nconst SKIP_PARENTS = new Set([\n 'code_block',\n 'bullet_list',\n 'ordered_list',\n 'list_item',\n 'table'\n])\n\nconst isDocEmpty = (doc: Node): boolean =>\n doc.childCount <= 1 && !doc.firstChild?.content.size\n\nconst isInSkippedParent = (state: EditorState): boolean => {\n const { $anchor } = state.selection\n for (let depth = $anchor.depth; depth > 0; depth--) {\n if (SKIP_PARENTS.has($anchor.node(depth).type.name)) {\n return true\n }\n }\n return false\n}\n\n/**\n * The placeholder plugin. `text` is baked in at creation (the editor is built\n * once); pass it from `createKunEditorPlugins(..., { placeholder })`.\n */\nexport const createPlaceholderPlugin = (\n config: PlaceholderConfig = {}\n): MilkdownPlugin[] => {\n const text = config.text ?? ''\n const mode = config.mode ?? 'block'\n\n const plugin = $prose(\n (ctx) =>\n new Plugin({\n key: new PluginKey('KUN_PLACEHOLDER'),\n props: {\n decorations: (state) => {\n if (!text) {\n return null\n }\n // Don't show in a read-only editor.\n const editable = ctx.get(editorViewOptionsCtx).editable\n if (editable && !editable(state)) {\n return null\n }\n if (mode === 'doc' && !isDocEmpty(state.doc)) {\n return null\n }\n const { selection } = state\n if (!selection.empty || isInSkippedParent(state)) {\n return null\n }\n const node = selection.$anchor.parent\n if (node.content.size > 0) {\n return null\n }\n const before = selection.$anchor.before()\n return DecorationSet.create(state.doc, [\n Decoration.node(before, before + node.nodeSize, {\n class: 'kun-editor__placeholder',\n 'data-placeholder': text\n })\n ])\n }\n }\n })\n )\n\n return [plugin].flat()\n}\n","// @kungal/editor-core/preset — the composed Milkdown bundle.\n//\n// `createKunEditorPlugins(adapters, features, options)` assembles the Milkdown\n// baseline (commonmark + gfm + history + listener + clipboard + indent +\n// trailing) with the KunEditor plugins from ../plugins, wiring each optional\n// plugin only when its feature/adapter is present. This is the SINGLE call a\n// render layer (@kungal/editor-vue) makes — it must never re-derive the plugin\n// list itself, so the WYSIWYG and markdown-source views always agree on the\n// schema. See docs/architecture.md § migration (P1).\n//\n// This entry pulls in @milkdown/kit and (for the katex / code-block features)\n// the katex + codemirror peers, so it is intentionally SEPARATE from the light\n// main entry (@kungal/editor-core), which the server can import for just the\n// adapter types + MENTION_SCHEME without any peer installed.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { commonmark } from '@milkdown/kit/preset/commonmark'\nimport { gfm } from '@milkdown/kit/preset/gfm'\nimport { history } from '@milkdown/kit/plugin/history'\nimport { listener } from '@milkdown/kit/plugin/listener'\nimport { clipboard } from '@milkdown/kit/plugin/clipboard'\nimport { indent } from '@milkdown/kit/plugin/indent'\nimport { trailing } from '@milkdown/kit/plugin/trailing'\nimport type { KatexOptions } from 'katex'\n\nimport type {\n KunEditorAdapters,\n KunEditorFeatures,\n KunEditorLocale\n} from '../types'\nimport { createSpoilerPlugin } from '../plugins/spoiler'\nimport { createStopLinkPlugin } from '../plugins/stop-link'\nimport { createLinkPlugin } from '../plugins/link'\nimport { createHeadingPlugin } from '../plugins/heading'\nimport { createKatexPlugins } from '../plugins/katex'\nimport { createCodeBlockPlugins } from '../plugins/code-block'\nimport { createMentionPlugin } from '../plugins/mention'\nimport { createQuotePlugin } from '../plugins/quote'\nimport { createUploadPlugin, imageUploadPlaceholder } from '../plugins/upload'\nimport { createPlaceholderPlugin } from '../plugins/placeholder'\n\n// Re-export the individual plugin factories + building blocks so advanced hosts\n// can compose their own bundle instead of using the preset.\nexport * from '../plugins/spoiler'\nexport * from '../plugins/stop-link'\nexport * from '../plugins/link'\nexport * from '../plugins/heading'\nexport * from '../plugins/katex'\nexport * from '../plugins/code-block'\nexport * from '../plugins/mention'\nexport * from '../plugins/quote'\nexport * from '../plugins/upload'\nexport * from '../plugins/placeholder'\n\n/** Extra, non-adapter options for the composed bundle. */\nexport interface KunEditorPluginOptions {\n /** UI language for plugin chrome (code-block toolbar labels). Default `'zh-cn'`. */\n locale?: KunEditorLocale\n /** KaTeX options forwarded to the code-block `latex` preview. */\n katexOptions?: KatexOptions\n /** Placeholder text shown when empty. Omit / empty string → no placeholder. */\n placeholder?: string\n /** `'block'` (default) shows on any empty block; `'doc'` only when empty. */\n placeholderMode?: 'doc' | 'block'\n}\n\n/**\n * Assemble the KunEditor Milkdown plugin list.\n *\n * P1 wired the pure plugins (spoiler, katex, code-block, stop-link); P2 adds the\n * adapter-driven ones — image upload (gated on the `uploadImage` adapter), the\n * mention schema, and the opt-in quote atom. Sticker has no core plugin: a\n * sticker is a plain image node, so its picker is a render-layer view (P3) that\n * consumes the `stickerSource` adapter and inserts an image.\n *\n * Feature flags default to on (except `quote`, host-specific → off); an absent\n * feature simply drops its plugins. The order matters — the baseline comes first\n * so katex's block schema can extend commonmark's code-block schema.\n */\nexport const createKunEditorPlugins = (\n adapters: KunEditorAdapters = {},\n features: KunEditorFeatures = {},\n options: KunEditorPluginOptions = {}\n): MilkdownPlugin[] => {\n const {\n spoiler = true,\n katex = true,\n codeBlock = true,\n mention = true,\n quote = false\n } = features\n\n const plugins: (MilkdownPlugin | MilkdownPlugin[])[] = [\n commonmark,\n gfm,\n history,\n listener,\n clipboard,\n indent,\n trailing\n ]\n\n if (codeBlock) {\n plugins.push(\n createCodeBlockPlugins({\n locale: options.locale,\n katexOptions: options.katexOptions\n })\n )\n }\n if (katex) {\n plugins.push(createKatexPlugins())\n }\n if (spoiler) {\n plugins.push(createSpoilerPlugin())\n }\n // The mention SCHEMA (round-trip) is wired here; the `@` autocomplete dropdown\n // that uses `searchMentionUsers` is a render-layer view (P3). The link-URL form\n // is host policy — default `kungal-user:`, overridable per host.\n if (mention) {\n plugins.push(\n createMentionPlugin({\n toUrl: adapters.mentionToUrl,\n fromUrl: adapters.mentionFromUrl\n })\n )\n }\n // Quote is opt-in — the host inserts references via insertQuoteCommand.\n if (quote) {\n plugins.push(createQuotePlugin())\n }\n // Image upload is gated purely on the adapter: no `uploadImage` → no upload,\n // paste and drop paths (the image-free galgame 简介 editor).\n if (adapters.uploadImage) {\n plugins.push(\n createUploadPlugin(adapters.uploadImage, {\n locale: options.locale,\n notify: adapters.notify\n })\n )\n // The in-document placeholder for the TOOLBAR upload path (paste/drop already\n // gets one from Milkdown's upload plugin above). Both render the same\n // `.kun-editor__uploading` widget. Driven by startImageUpload().\n plugins.push(imageUploadPlaceholder)\n }\n // stop-link is pure chrome-free behaviour; always on.\n plugins.push(createStopLinkPlugin())\n // insert-link command (click-to-link over the commonmark link mark); always on.\n plugins.push(createLinkPlugin())\n // setHeadingCommand (absolute block-type) — powers the \"text size\" dropdown.\n plugins.push(createHeadingPlugin())\n // Placeholder (empty-state text) — only when the host supplies text.\n if (options.placeholder) {\n plugins.push(\n createPlaceholderPlugin({\n text: options.placeholder,\n mode: options.placeholderMode\n })\n )\n }\n\n return plugins.flat()\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/spoiler/index.ts","../../src/plugins/stop-link/index.ts","../../src/plugins/link/index.ts","../../src/plugins/heading/index.ts","../../src/plugins/katex/blockKatex.ts","../../src/plugins/katex/inlineKatex.ts","../../src/plugins/katex/command.ts","../../src/plugins/katex/inputRule.ts","../../src/plugins/katex/remark.ts","../../src/plugins/katex/index.ts","../../src/plugins/code-block/theme.ts","../../src/plugins/code-block/icons.ts","../../src/plugins/code-block/index.ts","../../src/plugins/mention/index.ts","../../src/plugins/quote/index.ts","../../src/plugins/upload/index.ts","../../src/plugins/placeholder/index.ts","../../src/preset/index.ts"],"names":["node","trailing","tr","$command","linkSchema","$nodeSchema","_tr","NodeSelection","TextSelection","$inputRule","codeBlockSchema","$remark","visit","t","EditorView","katex","PluginKey","$prose","Plugin","DecorationSet","Decoration"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DO,IAAM,WAAA,GAAc,SAAA,CAAU,aAAA,EAAe,OAAO;AAAA,EACzD,SAAA,EAAW;AAAA,IACT,KAAA,EAAO,aAAA;AAAA,IACP,KAAA,EACE;AAAA;AAIN,CAAA,CAAE;AAYF,IAAM,YAAA,GAAe,QAAA;AAWrB,IAAM,iBAAA,GAAoC,CAAC,GAAA,KAAQ,YAAY;AAC7D,EAAA,MAAM,GAAA,CAAI,KAAK,eAAe,CAAA;AAC9B,EAAA,GAAA,CAAI,MAAA;AAAA,IACF,aAAA;AAAA,IACA,CAAC,cAAc,CAAC,GAAA,KAAQ,UAAU,GAAG,CAAA,CAAE,UAAA,CAAW,YAAA,EAAc,EAAE;AAAA,GACpE;AACF,CAAA;AAIA,IAAM,cAAA,GAAiB,CAAC,OAAA,KAAgC;AACtD,EAAA,MAAM,OAAoB,EAAC;AAC3B,EAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,KAAU;AACzB,IAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACjB,MAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AACf,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,IAAQ,EAAA,EAAI,UAAA,CAAW,cAAc,EAAE,CAAA;AAC3D,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,CAAO,KAAK,IAAA,EAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,IACrD;AAAA,EACF,CAAC,CAAA;AACD,EAAA,OAAO,QAAA,CAAS,UAAU,IAAI,CAAA;AAChC,CAAA;AAIO,IAAM,aAAA,GAAgB,WAAA,CAAY,aAAA,EAAe,CAAC,GAAA,MAAS;AAAA,EAChE,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,IAAA;AAAA,EACR,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,EAAA;AAAA,EACP,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA;AACX,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR;AAAA,MACE,GAAA,EAAK,+BAAA;AAAA,MACL,QAAA,EAAU,CAAC,GAAA,KAAQ;AACjB,QAAA,IAAI,EAAE,GAAA,YAAe,WAAA,CAAA,EAAc,MAAM,mBAAmB,GAAG,CAAA;AAC/D,QAAA,OAAO;AAAA,UACL,QAAA,EAAU,GAAA,CAAI,YAAA,CAAa,eAAe,CAAA,KAAM;AAAA,SAClD;AAAA,MACF;AAAA;AACF,GACF;AAAA,EACA,KAAA,EAAO,CAAC,IAAA,KAAS;AACf,IAAA,MAAM,QAAQ,GAAA,CAAI,GAAA,CAAI,WAAA,CAAY,GAAG,EAAE,IAAI,CAAA;AAC3C,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA;AAAA,QACE,GAAG,KAAA,CAAM,SAAA;AAAA,QACT,WAAA,EAAa,aAAA;AAAA,QACb,eAAA,EAAiB,KAAK,KAAA,CAAM;AAAA,OAC9B;AAAA,MACA;AAAA,KACF;AAAA,EACF,CAAA;AAAA,EACA,aAAA,EAAe;AAAA,IACb,KAAA,EAAO,CAAC,EAAE,IAAA,OAAW,IAAA,KAAS,aAAA;AAAA,IAC9B,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,EAAM,IAAA,KAAS;AAC7B,MAAA,KAAA,CAAM,SAAS,IAAI,CAAA;AACnB,MAAA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,IAAY,EAAE,CAAA;AAC9B,MAAA,KAAA,CAAM,SAAA,EAAU;AAAA,IAClB;AAAA,GACF;AAAA,EACA,UAAA,EAAY;AAAA,IACV,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,KAAK,IAAA,KAAS,aAAA;AAAA,IACpC,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AACvB,MAAA,MAAM,OAAA,GAAU,cAAA,CAAe,IAAA,CAAK,OAAO,CAAA;AAG3C,MAAA,IAAI,CAAC,QAAQ,IAAA,EAAM;AACjB,QAAA;AAAA,MACF;AACA,MAAA,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ,MAAA,EAAW,IAAI,CAAA;AACrC,MAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAClB,MAAA,KAAA,CAAM,OAAA,CAAQ,MAAA,EAAQ,MAAA,EAAW,IAAI,CAAA;AAAA,IACvC;AAAA;AAEJ,CAAA,CAAE;AAIF,IAAM,gBAAA,GAAmB,CACvB,IAAA,EACA,IAAA,KAC4C;AAC5C,EAAA,KAAA,IAAS,KAAA,GAAQ,IAAA,CAAK,KAAA,EAAO,KAAA,GAAQ,GAAG,KAAA,EAAA,EAAS;AAC/C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,KAAK,CAAA;AAC5B,IAAA,IAAI,IAAA,CAAK,SAAS,IAAA,EAAM;AACtB,MAAA,OAAO,EAAE,GAAA,EAAK,IAAA,CAAK,MAAA,CAAO,KAAK,GAAG,IAAA,EAAK;AAAA,IACzC;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT,CAAA;AA6BO,IAAM,uBAAA,GAA0B,QAAA;AAAA,EACrC,kBAAA;AAAA,EACA,CAAC,GAAA,KAAQ,MAAM,CAAC,OAAO,QAAA,KAAa;AAClC,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,IAAA,CAAK,GAAG,CAAA;AACnC,IAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAM,EAAA,EAAI,KAAA,KAAU,KAAA,CAAM,SAAA;AAEzC,IAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,KAAA,EAAO,IAAI,CAAA;AACzC,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAAA,KAAAA,EAAK,GAAI,IAAA;AACtB,QAAA,MAAM,QAAA,GAAW,cAAA,CAAeA,KAAAA,CAAK,OAAO,CAAA;AAG5C,QAAA,MAAM,GAAA,GAAM,MAAMA,KAAAA,CAAK,QAAA;AACvB,QAAA,MAAMC,SAAAA,GAAW,MAAM,GAAA,CAAI,WAAA;AAAA,UACzB,GAAA;AAAA,UACA,IAAA,CAAK,IAAI,GAAA,GAAM,YAAA,CAAa,QAAQ,KAAA,CAAM,GAAA,CAAI,QAAQ,IAAI;AAAA,SAC5D;AACA,QAAA,MAAMC,GAAAA,GAAK,MAAM,EAAA,CAAG,WAAA;AAAA,UAClB,GAAA;AAAA,UACAD,SAAAA,KAAa,YAAA,GAAe,GAAA,GAAM,YAAA,CAAa,MAAA,GAAS,GAAA;AAAA,UACxD;AAAA,SACF;AACA,QAAA,IAAI,SAAS,IAAA,EAAM;AAGjB,UAAAC,GAAAA,CAAG,YAAA,CAAa,aAAA,CAAc,MAAA,CAAOA,GAAAA,CAAG,KAAK,GAAA,EAAK,GAAA,GAAM,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,QACxE;AACA,QAAA,QAAA,CAASA,GAAAA,CAAG,gBAAgB,CAAA;AAAA,MAC9B;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAIA,IAAA,IAAI,KAAA,CAAM,qBAAqB,aAAA,EAAe;AAC5C,MAAA,OAAO,KAAA;AAAA,IACT;AAKA,IAAA,IACE,KAAA,CAAM,MAAA,CAAO,WAAA,IACb,CAAC,MAAM,MAAA,CAAO,cAAA,CAAe,KAAA,CAAM,KAAA,EAAM,EAAG,KAAA,CAAM,KAAA,EAAM,EAAG,IAAI,CAAA,EAC/D;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAQA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,GAAA,CAChB,WAAA,CAAY,IAAA,EAAM,EAAA,EAAI,GAAA,EAAK,GAAG,CAAA,CAC9B,UAAA,CAAW,YAAA,EAAc,EAAE,CAAA;AAI9B,IAAA,IAAI,CAAC,KAAA,IAAS,CAAC,IAAA,CAAK,MAAK,EAAG;AAC1B,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA;AAAA,IACT;AAIA,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,IAAA,EAAM,MAAM,MAAA,CAAO,IAAA,CAAK,IAAA,IAAQ,YAAY,CAAC,CAAA;AACtE,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,EAAA,CAAG,oBAAA,CAAqB,MAAM,KAAK,CAAA;AAEpD,IAAA,MAAM,KAAA,GAAQ,GAAG,SAAA,CAAU,EAAA;AAC3B,IAAA,EAAA,CAAG,UAAA,CAAW,cAAc,KAAK,CAAA;AACjC,IAAA,QAAA;AAAA,MACE,EAAA,CACG,YAAA;AAAA,QACC,aAAA,CAAc,MAAA;AAAA,UACZ,EAAA,CAAG,GAAA;AAAA;AAAA;AAAA,UAGH,QACI,KAAA,GAAQ,IAAA,CAAK,WAAW,CAAA,GAAI,YAAA,CAAa,SACzC,KAAA,GAAQ;AAAA;AACd,QAED,cAAA;AAAe,KACpB;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAIO,IAAM,sBAAA,GAAyB,UAAA;AAAA,EACpC,MACE,IAAI,SAAA,CAAU,wBAAA,EAA0B,CAAC,KAAA,EAAO,KAAA,EAAO,OAAO,GAAA,KAAQ;AACpE,IAAA,MAAM,CAAC,SAAA,EAAW,OAAO,CAAA,GAAI,KAAA;AAC7B,IAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,IAAA,MAAM,WAAW,KAAA,IAAS,SAAA,CAAU,UAAA,CAAW,GAAG,IAAI,CAAA,GAAI,CAAA,CAAA;AAC1D,IAAA,MAAM,EAAE,IAAG,GAAI,KAAA;AACf,IAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA;AAClD,IAAA,IAAI,CAAC,iBAAiB,OAAO,IAAA;AAE7B,IAAA,MAAM,cAAc,eAAA,CAAgB,MAAA;AAAA,MAClC,EAAE,UAAU,KAAA,EAAM;AAAA,MAClB,MAAA,CAAO,KAAK,OAAO;AAAA,KACrB;AACA,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA;AAC/C,IAAA,OAAO,EAAA,CACJ,WAAA,CAAY,QAAA,EAAU,GAAA,EAAK,CAAC,WAAA,EAAa,cAAc,CAAC,CAAA,CACxD,cAAA,CAAe,EAAE,EACjB,cAAA,EAAe;AAAA,EACpB,CAAC;AACL;AAIO,IAAM,mBAAA,GAAsB,OAAA,CAAQ,eAAA,EAAiB,MAAM,MAAM;AACtE,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAoB;AACvC,IAAA,KAAA,CAAM,IAAA,EAAM,MAAA,EAAQ,CAAC,IAAA,EAAmB,OAAO,MAAA,KAAwB;AACrE,MAAA,IAAI,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,EAAQ;AAC7C,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAC,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,EAAG;AAC9B,QAAA;AAAA,MACF;AAKA,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,cAAc,EAAE,CAAA;AACpD,MAAA,MAAM,KAAA,GAAQ,gBAAA;AACd,MAAA,MAAM,WAA0B,EAAC;AACjC,MAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,MAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,QAAA,CAAS,KAAK,CAAA,EAAG;AACzC,QAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,KAAA;AACxB,QAAA,MAAM,UAAA,GAAa,MAAM,KAAA,IAAS,CAAA;AAElC,QAAA,IAAI,aAAa,SAAA,EAAW;AAC1B,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,IAAA,EAAM,MAAA;AAAA,YACN,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,SAAA,EAAW,UAAU;AAAA,WACzC,CAAA;AAAA,QACH;AAEA,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,IAAA,EAAM,aAAA;AAAA,YACN,UAAU,CAAC,EAAE,MAAM,MAAA,EAAQ,KAAA,EAAO,SAAS;AAAA,WAC5C,CAAA;AAKD,UAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,cAAc,CAAA;AAAA,QACrD;AAEA,QAAA,SAAA,GAAY,aAAa,IAAA,CAAK,MAAA;AAAA,MAChC;AAEA,MAAA,IAAI,SAAA,GAAY,MAAM,MAAA,EAAQ;AAC5B,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAO,KAAA,CAAM,KAAA,CAAM,SAAS,CAAA,EAAG,CAAA;AAAA,MAC/D;AAEA,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,IAAK,OAAO,UAAU,QAAA,EAAU;AACpD,QAAA,MAAA,CAAO,QAAA,EAAU,MAAA,CAAO,KAAA,EAAO,CAAA,EAAG,GAAG,QAAQ,CAAA;AAAA,MAC/C;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO,WAAA;AACT,CAAC;AAOM,IAAM,sBAAsB,MACjC;AAAA,EACE,WAAA;AAAA,EACA,aAAA;AAAA,EACA,sBAAA;AAAA,EACA,uBAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAA,CAAE,IAAA;AC7XJ,IAAM,OAAA,GAAU,CAAC,KAAA,EAAoB,IAAA,KAAmB;AACtD,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,EAAA,EAAI,KAAA,KAAU,KAAA,CAAM,SAAA;AACzC,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,CAAC,CAAC,IAAA,CAAK,OAAA,CAAQ,MAAM,WAAA,IAAe,KAAA,CAAM,OAAO,CAAA;AAAA,EAC1D;AACA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,YAAA,CAAa,IAAA,EAAM,IAAI,IAAI,CAAA;AAC9C,CAAA;AAIO,IAAM,eAAA,GAAkBC,QAAAA,CAAS,UAAA,EAAY,CAAC,QAAQ,MAAM;AACjE,EAAA,OAAO,CAAC,OAAO,QAAA,KAAa;AAC1B,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACpC,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,EAAO,QAAQ,CAAA;AACzC,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,QAAA;AAAA,QACE,MAAM,EAAA,CAAG,gBAAA,CAAiB,QAAQ,CAAA,CAAE,OAAA,CAAQ,gBAAgB,KAAK;AAAA,OACnE;AAAA,IACF;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AACF,CAAC;AAGM,IAAM,gBAAA,GAAmB,WAAW,kBAAA,EAAoB;AAAA,EAC7D,QAAA,EAAU;AAAA,IACR,SAAA,EAAW,CAAC,OAAO,CAAA;AAAA,IACnB,OAAA,EAAS,CAAC,GAAA,KAAQ;AAChB,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AACpC,MAAA,OAAO,MAAM,QAAA,CAAS,IAAA,CAAK,eAAA,CAAgB,GAAG,CAAA;AAAA,IAChD;AAAA;AAEJ,CAAC;AAED,IAAM,aAAA,GAAgB,IAAI,SAAA,CAAU,iBAAiB,CAAA;AAErD,IAAM,eAAA,GAAkB,MAAA;AAAA,EACtB,CAAC,GAAA,KACC,IAAI,MAAA,CAAO;AAAA,IACT,GAAA,EAAK,aAAA;AAAA,IACL,iBAAA,CAAkB,aAAA,EAAe,SAAA,EAAW,QAAA,EAAU;AACpD,MAAA,MAAM,EAAE,WAAA,EAAa,SAAA,EAAU,GAAI,QAAA;AACnC,MAAA,IAAI,CAAC,SAAA,CAAU,KAAA,IAAS,CAAC,WAAA,EAAa;AACpC,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,MAAM,QAAA,GAAW,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACpC,MAAA,IAAI,CAAC,QAAA,CAAS,OAAA,CAAQ,WAAW,CAAA,EAAG;AAClC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,SAAS,OAAA,CAAQ,SAAA,CAAU,KAAA,CAAM,KAAA,EAAO,CAAA,EAAG;AAC7C,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,OAAO,SAAS,EAAA,CACb,gBAAA,CAAiB,QAAQ,CAAA,CACzB,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAAA,IAClC;AAAA,GACD;AACL,CAAA;AAKO,IAAM,uBAAuB,MAClC,CAAC,iBAAiB,gBAAA,EAAkB,eAAe,EAAE,IAAA;AC3DhD,IAAM,iBAAA,GAAoBA,QAAAA;AAAA,EAC/B,eAAA;AAAA,EACA,CAAC,GAAA,KACC,CAAC,OAAA,KACD,CAAC,OAAO,QAAA,KAAa;AACnB,IAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,OAAA,EAAS,IAAA,IAAQ,EAAE,CAAA;AAClD,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,QAAA,GAAWC,UAAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,MAAA,CAAO,EAAE,MAAM,CAAA;AACrC,IAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAI,KAAA,KAAU,KAAA,CAAM,SAAA;AAClC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAM,IAAA,GAAO,OAAA,EAAS,IAAA,EAAM,IAAA,EAAK,IAAK,IAAA;AACtC,MAAA,MAAM,EAAA,GAAK,KAAA,CAAM,EAAA,CAAG,UAAA,CAAW,MAAM,IAAI,CAAA;AACzC,MAAA,EAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,IAAA,GAAO,IAAA,CAAK,QAAQ,IAAI,CAAA;AACzC,MAAA,EAAA,CAAG,iBAAiB,QAAQ,CAAA;AAC5B,MAAA,QAAA,GAAW,EAAA,CAAG,gBAAgB,CAAA;AAAA,IAChC,CAAA,MAAO;AACL,MAAA,QAAA,GAAW,KAAA,CAAM,GAAG,OAAA,CAAQ,IAAA,EAAM,IAAI,IAAI,CAAA,CAAE,gBAAgB,CAAA;AAAA,IAC9D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACJ;AAGO,IAAM,gBAAA,GAAmB,MAAwB,CAAC,iBAAiB,EAAE,IAAA;AC1CrE,IAAM,iBAAA,GAAoBD,QAAAA;AAAA,EAC/B,eAAA;AAAA,EACA,CAAC,QACC,CAAC,KAAA,GAAgB,MACf,KAAA,IAAS,CAAA,IAAK,KAAA,IAAS,CAAA,GACnB,YAAA,CAAa,aAAA,CAAc,KAAK,GAAG,CAAA,EAAG,EAAE,KAAA,EAAO,IAC/C,YAAA,CAAa,eAAA,CAAgB,IAAA,CAAK,GAAG,CAAC;AAChD;AAGO,IAAM,mBAAA,GAAsB,MACjC,CAAC,iBAAiB,EAAE,IAAA;ACvBf,IAAM,gBAAA,GAAmB,eAAA,CAAgB,YAAA,CAAa,CAAC,IAAA,KAAS;AACrE,EAAA,OAAO,CAAC,GAAA,KAAQ;AACd,IAAA,MAAM,UAAA,GAAa,KAAK,GAAG,CAAA;AAC3B,IAAA,OAAO;AAAA,MACL,GAAG,UAAA;AAAA,MACH,UAAA,EAAY;AAAA,QACV,KAAA,EAAO,WAAW,UAAA,CAAW,KAAA;AAAA,QAC7B,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AACvB,UAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,QAAA,IAAY,EAAA;AACxC,UAAA,IAAI,QAAA,CAAS,WAAA,EAAY,KAAM,OAAA,EAAS;AACtC,YAAA,KAAA,CAAM,OAAA;AAAA,cACJ,MAAA;AAAA,cACA,MAAA;AAAA,cACA,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,IAAA,IAAQ;AAAA,aACnC;AAAA,UACF,CAAA,MAAO;AACL,YAAA,OAAO,UAAA,CAAW,UAAA,CAAW,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAAA,UACjD;AAAA,QACF;AAAA;AACF,KACF;AAAA,EACF,CAAA;AACF,CAAC;ACxBM,IAAM,YAAA,GAAe;AAUrB,IAAM,gBAAA,GAAmBE,WAAAA,CAAY,YAAA,EAAc,OAAO;AAAA,EAC/D,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,IAAA;AAAA,EACR,SAAA,EAAW,IAAA;AAAA,EACX,IAAA,EAAM,IAAA;AAAA,EACN,KAAA,EAAO;AAAA,IACL,KAAA,EAAO;AAAA,MACL,OAAA,EAAS;AAAA;AACX,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR;AAAA,MACE,GAAA,EAAK,mBAAmB,YAAY,CAAA,EAAA,CAAA;AAAA,MACpC,QAAA,EAAU,CAAC,GAAA,KAAQ;AACjB,QAAA,OAAO;AAAA,UACL,KAAA,EAAQ,GAAA,CAAoB,OAAA,CAAQ,KAAA,IAAS;AAAA,SAC/C;AAAA,MACF;AAAA;AACF,GACF;AAAA,EACA,KAAA,EAAO,CAAC,IAAA,KAAS;AACf,IAAA,MAAM,IAAA,GAAe,KAAK,KAAA,CAAM,KAAA;AAChC,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AACzC,IAAA,GAAA,CAAI,QAAQ,IAAA,GAAO,YAAA;AACnB,IAAA,GAAA,CAAI,QAAQ,KAAA,GAAQ,IAAA;AACpB,IAAA,KAAA,CAAM,MAAA,CAAO,MAAM,GAAA,EAAK;AAAA,MACtB,YAAA,EAAc;AAAA,KACf,CAAA;AAED,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe;AAAA,IACb,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,KAAS,YAAA;AAAA,IAC/B,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,EAAM,IAAA,KAAS;AAC7B,MAAA,KAAA,CAAM,QAAQ,IAAA,EAAM,EAAE,KAAA,EAAO,IAAA,CAAK,OAAiB,CAAA;AAAA,IACrD;AAAA,GACF;AAAA,EACA,UAAA,EAAY;AAAA,IACV,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,KAAK,IAAA,KAAS,YAAA;AAAA,IACpC,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AACvB,MAAA,KAAA,CAAM,OAAA,CAAQ,YAAA,EAAc,MAAA,EAAW,IAAA,CAAK,MAAM,KAAK,CAAA;AAAA,IACzD;AAAA;AAEJ,CAAA,CAAE;;;AC9CK,IAAM,kBAAA,GAAqBF,QAAAA,CAAS,aAAA,EAAe,CAAC,GAAA,KAAQ;AACjE,EAAA,OAAO,MAAM,CAAC,KAAA,EAAO,QAAA,KAAa;AAChC,IAAA,MAAM;AAAA,MACJ,OAAA,EAAS,QAAA;AAAA,MACT,GAAA,EAAK,QAAA;AAAA,MACL,MAAA,EAAQ;AAAA,QACN,mBAAA,CAAoB,KAAA,EAAO,gBAAA,CAAiB,IAAA,CAAK,GAAG,CAAC,CAAA;AAEzD,IAAA,MAAM,EAAE,SAAA,EAAW,GAAA,EAAK,EAAA,EAAG,GAAI,KAAA;AAC/B,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,OAAO,GAAA,CAAI,WAAA,CAAY,SAAA,CAAU,IAAA,EAAM,UAAU,EAAE,CAAA;AACzD,MAAA,MAAMG,OAAM,EAAA,CAAG,oBAAA;AAAA,QACb,gBAAA,CAAiB,IAAA,CAAK,GAAG,CAAA,CAAE,MAAA,CAAO;AAAA,UAChC,KAAA,EAAO;AAAA,SACR;AAAA,OACH;AACA,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,QAAA;AAAA,UACEA,IAAAA,CAAI,aAAaC,aAAAA,CAAc,MAAA,CAAOD,KAAI,GAAA,EAAK,SAAA,CAAU,IAAI,CAAC;AAAA,SAChE;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,SAAA;AACrB,IAAA,IAAI,CAAC,SAAA,IAAa,QAAA,GAAW,CAAA,EAAG,OAAO,KAAA;AAEvC,IAAA,IAAI,GAAA,GAAM,EAAA,CAAG,MAAA,CAAO,QAAA,EAAU,WAAW,CAAC,CAAA;AAC1C,IAAA,MAAM,OAAA,GAAW,UAAmB,KAAA,CAAM,KAAA;AAC1C,IAAA,GAAA,GAAM,GAAA,CAAI,UAAA,CAAW,OAAA,EAAS,QAAQ,CAAA;AACtC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA;AAAA,QACE,GAAA,CAAI,YAAA;AAAA,UACFE,aAAAA,CAAc,OAAO,GAAA,CAAI,GAAA,EAAK,MAAM,EAAA,GAAK,OAAA,CAAQ,SAAS,CAAC;AAAA;AAC7D,OACF;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AACF,CAAC;ACxCM,IAAM,mBAAA,GAAsBC,UAAAA;AAAA,EAAW,CAAC,GAAA,KAC7C,QAAA,CAAS,wBAAwB,gBAAA,CAAiB,IAAA,CAAK,GAAG,CAAA,EAAG;AAAA,IAC3D,OAAA,EAAS,CAAC,KAAA,MAAW,EAAE,OAAO,KAAA,CAAM,CAAC,KAAK,EAAA,EAAG,CAAA;AAAA,IAC7C,cAAA,EAAgB,CAAC,EAAE,EAAA,EAAI,OAAM,KAAM;AAIjC,MAAA,MAAM,WAAW,KAAA,GAAQ,CAAA;AACzB,MAAA,EAAA,CAAG,UAAA,CAAW,QAAA,EAAK,QAAA,EAAU,QAAQ,CAAA;AAErC,MAAA,EAAA,CAAG,aAAaD,aAAAA,CAAc,MAAA,CAAO,GAAG,GAAA,EAAK,QAAA,GAAW,CAAC,CAAC,CAAA;AAAA,IAC5D;AAAA,GACD;AACH;AAGO,IAAM,kBAAA,GAAqBC,UAAAA;AAAA,EAAW,CAAC,QAC5C,sBAAA,CAAuB,cAAA,EAAgBC,gBAAgB,IAAA,CAAK,GAAG,GAAG,OAAO;AAAA,IACvE,QAAA,EAAU;AAAA,GACZ,CAAE;AACJ;ACtBO,IAAM,gBAAA,GAAmBC,OAAAA;AAAA,EAC9B,YAAA;AAAA,EACA,MAAM;AACR;AAEA,IAAM,cAAA,GAAiB,CAAC,GAAA,KAAc;AACpC,EAAA,OAAOC,KAAAA;AAAA,IACL,GAAA;AAAA,IACA,MAAA;AAAA,IACA,CACE,IAAA,EACA,KAAA,EACA,MAAA,KACG;AACH,MAAA,MAAM,EAAE,OAAM,GAAI,IAAA;AAClB,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,IAAA,EAAM,MAAA;AAAA,QACN,IAAA,EAAM,OAAA;AAAA,QACN;AAAA,OACF;AACA,MAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,CAAA,EAAG,OAA0B,CAAA;AAAA,IAC7D;AAAA,GACF;AACF,CAAA;AAKO,IAAM,qBAAA,GAAwBD,OAAAA;AAAA,EACnC,iBAAA;AAAA,EACA,MAAM,MAAM;AACd;;;ACbO,IAAM,qBAAqB,MAChC;AAAA,EACE,gBAAA;AAAA,EACA,qBAAA;AAAA,EACA,gBAAA;AAAA,EACA,mBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAA,CAAE,IAAA;ACxBJ,IAAM,MAAA,GAAS;AAAA,EACb,OAAA,EAAS,sBAAA;AAAA,EACT,QAAA,EAAU,yDAAA;AAAA,EACV,YAAA,EAAc,0BAAA;AAAA,EAEd,SAAA,EAAW,wBAAA;AAAA,EAEX,OAAA,EAAS,sBAAA;AAAA,EAET,OAAA,EAAS,sBAAA;AAAA,EACT,YAAA,EAAc,0BAAA;AAAA,EACd,MAAA,EAAQ,qBAAA;AAAA,EAER,UAAA,EAAY,yBAAA;AAAA,EACZ,UAAA,EAAY,yBAAA;AAAA,EACZ,eAAA,EAAiB,+BAAA;AAAA,EAEjB,YAAA,EAAc,0BAAA;AAAA,EACd,OAAA,EAAS,0BAAA;AAAA,EACT,QAAA,EAAU,uBAAA;AAAA,EACV,QAAA,EAAU,uBAAA;AAAA,EACV,QAAA,EAAU,uBAEZ,CAAA;AAEO,IAAM,aAAa,MAAM;AAC9B,EAAA,OAAO,WAAW,KAAA,CAAM;AAAA,IACtB,GAAA,EAAK;AAAA,MACH,iBAAiB,MAAA,CAAO,eAAA;AAAA,MACxB,YAAA,EAAc,SAAA;AAAA,MACd,UAAA,EAAY,KAAA;AAAA,MACZ,cAAA,EAAgB,MAAA;AAAA,MAChB,SAAA,EAAW;AAAA,KACb;AAAA,IAEA,cAAA,EAAgB;AAAA,MACd,OAAA,EAAS;AAAA,KACX;AAAA,IAEA,cAAA,EAAgB;AAAA,MACd,UAAA,EAAY,KAAA;AAAA,MACZ,QAAA,EAAU,MAAA;AAAA,MACV,cAAA,EAAgB;AAAA,KAClB;AAAA,IAEA,aAAA,EAAe;AAAA,MACb,OAAA,EAAS,aAAA;AAAA,MACT,QAAA,EAAU;AAAA,KACZ;AAAA,IAEA,UAAA,EAAY;AAAA,MACV,OAAA,EAAS,UAAA;AAAA,MACT,YAAA,EAAc,UAAA;AAAA,MACd,QAAA,EAAU,MAAA;AAAA,MACV,QAAA,EAAU,MAAA;AAAA,MACV,SAAA,EAAW;AAAA,QACT,iBAAiB,MAAA,CAAO;AAAA;AAC1B,KACF;AAAA,IAEA,yBAAA,EAA2B;AAAA,MACzB,iBAAiB,MAAA,CAAO,OAAA;AAAA,MACxB,eAAA,EAAiB;AAAA,KACnB;AAAA,IAEA,YAAA,EAAc;AAAA,MACZ,iBAAiB,MAAA,CAAO,UAAA;AAAA,MACxB,OAAO,MAAA,CAAO,UAAA;AAAA,MACd,YAAA,EAAc,QAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,0BAAA,EAA4B;AAAA,MAC1B,YAAA,EAAc,CAAA,UAAA,EAAa,MAAA,CAAO,OAAO,CAAA;AAAA,KAC3C;AAAA,IACA,6BAAA,EAA+B;AAAA,MAC7B,SAAA,EAAW,CAAA,UAAA,EAAa,MAAA,CAAO,OAAO,CAAA;AAAA,KACxC;AAAA,IAEA,iBAAA,EAAmB;AAAA,MACjB,eAAA,EAAiB,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,EAAA,CAAA;AAAA,MACvC,OAAA,EAAS,CAAA,UAAA,EAAa,MAAA,CAAO,YAAY,CAAA,CAAA;AAAA,MACzC,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,yCAAA,EAA2C;AAAA,MACzC,eAAA,EAAiB,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,EAAA;AAAA,KACpC;AAAA,IAEA,gBAAA,EAAkB;AAAA,MAChB,eAAA,EAAiB,CAAA,EAAG,MAAA,CAAO,QAAQ,CAAA,EAAA,CAAA;AAAA,MACnC,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,oBAAA,EAAsB;AAAA,MACpB,eAAA,EAAiB,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,EAAA,CAAA;AAAA,MAClC,YAAA,EAAc;AAAA,KAChB;AAAA,IAEA,6CAAA,EAA+C;AAAA,MAC7C,eAAA,EAAiB,CAAA,EAAG,MAAA,CAAO,OAAO,CAAA,EAAA,CAAA;AAAA,MAClC,OAAA,EAAS,MAAA;AAAA,MACT,YAAA,EAAc,KAAA;AAAA,MACd,OAAA,EAAS,OAAA;AAAA,MACT,UAAA,EAAY;AAAA,KACd;AAAA,IAEA,aAAA,EAAe;AAAA,MACb,eAAA,EAAiB,aAAA;AAAA,MACjB,MAAA,EAAQ,MAAA;AAAA,MACR,YAAA,EAAc,GAAA;AAAA,MACd,QAAA,EAAU,MAAA;AAAA,MACV,OAAA,EAAS;AAAA,KACX;AAAA,IAEA,iBAAA,EAAmB;AAAA,MACjB,OAAO,MAAA,CAAO;AAAA,KAChB;AAAA,IAEA,4HAAA,EACE;AAAA,MACE,iBAAiB,MAAA,CAAO;AAAA,KAC1B;AAAA,IAEF,sBAAA,EAAwB;AAAA,MACtB,iBAAiB,MAAA,CAAO;AAAA,KAC1B;AAAA,IAEA,gBAAA,EAAkB;AAAA,MAChB,OAAO,MAAA,CAAO;AAAA,KAChB;AAAA,IAEA,aAAA,EAAe;AAAA,MACb,iBAAiB,MAAA,CAAO,UAAA;AAAA,MACxB,MAAA,EAAQ,CAAA,UAAA,EAAa,MAAA,CAAO,OAAO,CAAA,CAAA;AAAA,MACnC,YAAA,EAAc,QAAA;AAAA,MACd,SAAA,EACE,kEAAA;AAAA,MACF,QAAA,EAAU;AAAA,KACZ;AAAA,IAEA,0BAAA,EAA4B;AAAA,MAC1B,QAAA,EAAU;AAAA,QACR,QAAA,EAAU,QAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AAAA,MACA,aAAA,EAAe;AAAA,QACb,OAAA,EAAS,kBAAA;AAAA,QACT,YAAA,EAAc;AAAA,OAChB;AAAA,MACA,4BAAA,EAA8B;AAAA,QAC5B,iBAAiB,MAAA,CAAO,QAAA;AAAA,QACxB,OAAO,MAAA,CAAO;AAAA;AAChB,KACF;AAAA,IAEA,sBAAA,EAAwB;AAAA,MACtB,KAAA,EAAO,KAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,4BAAA,EAA8B;AAAA,MAC5B,UAAA,EAAY;AAAA,KACd;AAAA,IACA,4BAAA,EAA8B;AAAA,MAC5B,iBAAiB,MAAA,CAAO,QAAA;AAAA,MACxB,YAAA,EAAc,KAAA;AAAA,MACd,SAAA,EAAW;AAAA,QACT,iBAAiB,MAAA,CAAO;AAAA;AAC1B;AACF,GACD,CAAA;AACH;AAEO,IAAM,mBAAA,GAAsB,MACjC,cAAA,CAAe,MAAA,CAAO;AAAA;AAAA,EAEpB,EAAE,KAAKE,IAAA,CAAE,OAAA,EAAS,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA,EAC3D,EAAE,KAAKA,IAAA,CAAE,cAAA,EAAgB,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA,EAClE,EAAE,KAAKA,IAAA,CAAE,aAAA,EAAe,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA;AAAA,EAGjE,EAAE,GAAA,EAAK,CAACA,IAAA,CAAE,YAAA,EAAcA,KAAE,SAAS,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,SAAA,EAAU;AAAA,EAC9D,EAAE,GAAA,EAAKA,IAAA,CAAE,YAAA,EAAc,KAAA,EAAO,OAAO,UAAA,EAAW;AAAA,EAChD;AAAA,IACE,GAAA,EAAKA,IAAA,CAAE,UAAA,CAAWA,IAAA,CAAE,YAAY,CAAA;AAAA,IAChC,OAAO,MAAA,CAAO,SAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA;AAAA,EAGA;AAAA,IACE,GAAA,EAAK,CAACA,IAAA,CAAE,QAAA,CAASA,KAAE,YAAY,CAAA,EAAGA,KAAE,SAAS,CAAA;AAAA,IAC7C,OAAO,MAAA,CAAO,OAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA,EACA;AAAA,IACE,KAAKA,IAAA,CAAE,UAAA,CAAWA,KAAE,QAAA,CAASA,IAAA,CAAE,YAAY,CAAC,CAAA;AAAA,IAC5C,OAAO,MAAA,CAAO,OAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA;AAAA,EAGA;AAAA,IACE,KAAK,CAACA,IAAA,CAAE,UAAUA,IAAA,CAAE,SAAA,EAAWA,KAAE,SAAS,CAAA;AAAA,IAC1C,OAAO,MAAA,CAAO,OAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,GAAA,EAAK,CAACA,IAAA,CAAE,UAAA,EAAYA,KAAE,QAAQ,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,YAAA,EAAa;AAAA;AAAA,EAG9D;AAAA,IACE,KAAK,CAACA,IAAA,CAAE,QAAQA,IAAA,CAAE,IAAA,EAAMA,KAAE,IAAI,CAAA;AAAA,IAC9B,OAAO,MAAA,CAAO,SAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA,EACA,EAAE,GAAA,EAAKA,IAAA,CAAE,MAAA,EAAQ,KAAA,EAAO,OAAO,OAAA,EAAQ;AAAA,EACvC,EAAE,GAAA,EAAKA,IAAA,CAAE,MAAA,EAAQ,KAAA,EAAO,OAAO,OAAA,EAAQ;AAAA;AAAA,EAGvC,EAAE,GAAA,EAAK,CAACA,IAAA,CAAE,IAAA,EAAMA,IAAA,CAAE,OAAO,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,UAAA,EAAY,SAAA,EAAW,QAAA,EAAS;AAAA,EAC1E,EAAE,KAAKA,IAAA,CAAE,OAAA,EAAS,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA,EAC3D,EAAE,GAAA,EAAKA,IAAA,CAAE,aAAA,EAAe,KAAA,EAAO,OAAO,OAAA,EAAQ;AAAA;AAAA,EAG9C,EAAE,KAAKA,IAAA,CAAE,OAAA,EAAS,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,KAAA,EAAM;AAAA,EAC3D;AAAA,IACE,GAAA,EAAK,CAACA,IAAA,CAAE,GAAA,EAAKA,KAAE,IAAI,CAAA;AAAA,IACnB,OAAO,MAAA,CAAO,OAAA;AAAA,IACd,cAAA,EAAgB;AAAA,GAClB;AAAA,EACA,EAAE,GAAA,EAAKA,IAAA,CAAE,QAAA,EAAU,WAAW,QAAA,EAAS;AAAA,EACvC,EAAE,GAAA,EAAKA,IAAA,CAAE,MAAA,EAAQ,YAAY,KAAA,EAAM;AAAA;AAAA,EAGnC;AAAA,IACE,KAAKA,IAAA,CAAE,OAAA;AAAA,IACP,OAAO,MAAA,CAAO,MAAA;AAAA,IACd,YAAA,EAAc,CAAA,WAAA,EAAc,MAAA,CAAO,MAAM,CAAA;AAAA,GAC3C;AAAA,EACA,EAAE,GAAA,EAAKA,IAAA,CAAE,OAAA,EAAS,KAAA,EAAO,OAAO,OAAA,EAAQ;AAAA,EACxC,EAAE,GAAA,EAAKA,IAAA,CAAE,QAAA,EAAU,KAAA,EAAO,OAAO,OAAA,EAAQ;AAAA,EACzC,EAAE,GAAA,EAAKA,IAAA,CAAE,OAAA,EAAS,KAAA,EAAO,OAAO,MAAA;AAClC,CAAC;AAGI,IAAM,QAAQ,MAAiB;AAAA,EACpC,UAAA,EAAW;AAAA,EACX,kBAAA,CAAmB,qBAAqB;AAC1C;;;AC1PO,IAAM,eAAA,GAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBxB,IAAM,SAAA,GAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBlB,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcjB,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBjB,IAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBnB,IAAM,iBAAA,GAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACnCjC,IAAM,MAAA,GAAqD;AAAA,EACzD,OAAA,EAAS;AAAA,IACP,iBAAA,EAAmB,0BAAA;AAAA,IACnB,QAAA,EAAU,0BAAA;AAAA,IACV,YAAA,EAAc,oBAAA;AAAA,IACd,cAAA,EAAgB,uBAAA;AAAA,IAChB,IAAA,EAAM,cAAA;AAAA,IACN,IAAA,EAAM;AAAA,GACR;AAAA,EACA,OAAA,EAAS;AAAA,IACP,iBAAA,EAAmB,iBAAA;AAAA,IACnB,QAAA,EAAU,MAAA;AAAA,IACV,YAAA,EAAc,YAAA;AAAA,IACd,cAAA,EAAgB,YAAA;AAAA,IAChB,IAAA,EAAM,MAAA;AAAA,IACN,IAAA,EAAM;AAAA;AAEV,CAAA;AAEA,IAAM,SAAA,GAAY,CAAC,MAAA,KACjB,MAAA,IAAU,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,IAAI,CAAA,GAC1C,MAAA,CAAO,OAAO,CAAA,GACd,OAAO,OAAO,CAAA;AAQb,IAAM,oBAAA,GAAuB,CAClC,GAAA,EACA,OAAA,GAA4B,EAAC,KACpB;AACT,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,OAAA,CAAQ,MAAM,CAAA;AACvC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,KAAW,MAAM;AAAA,EAAC,CAAA,CAAA;AAEzC,EAAA,GAAA,CAAI,MAAA,CAAO,eAAA,CAAgB,GAAA,EAAK,CAAC,IAAA,MAAU;AAAA,IACzC,GAAG,IAAA;AAAA,IACH,UAAA,EAAY;AAAA,MACV,KAAA,EAAM;AAAA,MACNC,UAAAA,CAAW,YAAA;AAAA,MACX,MAAA,CAAO,EAAA,CAAG,aAAA,CAAc,MAAA,CAAO,aAAa,CAAC,CAAA;AAAA,MAC7C,UAAA;AAAA,MACA,GAAI,OAAA,CAAQ,UAAA,IAAc;AAAC,KAC7B;AAAA,IACA,SAAA;AAAA,IACA,UAAA,EAAY,eAAA;AAAA,IACZ,UAAA;AAAA,IACA,eAAA,EAAiB,SAAA;AAAA,IACjB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,IAC1B,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,QAAA;AAAA,IACA,MAAA;AAAA,IACA,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,gBAAgB,MAAA,CAAO,cAAA;AAAA;AAAA;AAAA,IAGvB,aAAA,EAAe,CAAC,QAAA,EAAU,OAAA,EAAS,YAAA,KAAiB;AAClD,MAAA,IAAI,SAAS,WAAA,EAAY,KAAM,OAAA,IAAW,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC5D,QAAA,OAAOC,KAAAA,CAAM,eAAe,OAAA,EAAS;AAAA,UACnC,GAAG,OAAA,CAAQ,YAAA;AAAA,UACX,YAAA,EAAc,KAAA;AAAA,UACd,WAAA,EAAa;AAAA,SACd,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,OAAA,EAAS,YAAY,CAAA;AAAA,IAC3D,CAAA;AAAA,IACA,mBAAA,EAAqB,CAAC,eAAA,KAAoB;AACxC,MAAA,MAAM,IAAA,GAAO,kBAAkB,QAAA,GAAW,iBAAA;AAC1C,MAAA,MAAM,IAAA,GAAO,eAAA,GAAkB,MAAA,CAAO,IAAA,GAAO,MAAA,CAAO,IAAA;AACpD,MAAA,OAAO,CAAC,IAAA,EAAM,IAAI,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,IACnD;AAAA,GACF,CAAE,CAAA;AACJ;AAIA,IAAM,qBAAA,GACJ,CAAC,OAAA,KACD,CAAC,QACD,MAAM;AACJ,EAAA,oBAAA,CAAqB,KAAK,OAAO,CAAA;AACnC,CAAA;AAOK,IAAM,sBAAA,GAAyB,CACpC,OAAA,GAA4B,EAAC,KACR,CAAC,GAAG,kBAAA,EAAoB,qBAAA,CAAsB,OAAO,CAAC;AChItE,IAAM,SAAA,GAAY;AAkBzB,IAAM,eAAe,CAAC,MAAA,KAA2B,CAAA,EAAG,cAAc,GAAG,MAAM,CAAA,CAAA;AAC3E,IAAM,cAAA,GAAiB,CAAC,GAAA,KAA+B;AACrD,EAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,cAAc,GAAG,OAAO,IAAA;AAC5C,EAAA,MAAM,EAAA,GAAK,OAAO,QAAA,CAAS,GAAA,CAAI,MAAM,cAAA,CAAe,MAAM,GAAG,EAAE,CAAA;AAC/D,EAAA,OAAO,OAAO,SAAA,CAAU,EAAE,CAAA,IAAK,EAAA,GAAK,IAAI,EAAA,GAAK,IAAA;AAC/C,CAAA;AAcA,IAAM,iBAAA,GAAoB,CAAC,KAAA,KACzBV,WAAAA,CAAY,WAAW,OAAO;AAAA,EAC5B,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,IAAA;AAAA,EACR,IAAA,EAAM,IAAA;AAAA,EACN,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ,EAAE,OAAA,EAAS,CAAA,EAAE;AAAA,IACrB,IAAA,EAAM,EAAE,OAAA,EAAS,EAAA;AAAG,GACtB;AAAA,EACA,QAAA,EAAU;AAAA,IACR;AAAA;AAAA,MAEE,GAAA,EAAK,eAAA;AAAA,MACL,QAAA,EAAU,CAAC,GAAA,KAAQ;AACjB,QAAA,MAAM,EAAA,GAAK,GAAA;AACX,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ,OAAO,QAAA,CAAS,EAAA,CAAG,QAAQ,GAAA,IAAO,GAAA,EAAK,EAAE,CAAA,IAAK,CAAA;AAAA,UACtD,OAAO,EAAA,CAAG,WAAA,IAAe,EAAA,EAAI,OAAA,CAAQ,MAAM,EAAE;AAAA,SAC/C;AAAA,MACF;AAAA;AACF,GACF;AAAA,EACA,KAAA,EAAO,CAAC,IAAA,KAAS;AAGf,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC1C,IAAA,IAAA,CAAK,SAAA,GAAY,aAAA;AACjB,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAC3C,IAAA,IAAA,CAAK,YAAA,CAAa,mBAAmB,OAAO,CAAA;AAC5C,IAAA,IAAA,CAAK,WAAA,GAAc,CAAA,CAAA,EAAI,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAA;AACtC,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe;AAAA,IACb,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,KAAS,SAAA;AAAA,IAC/B,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,EAAM,IAAA,KAAS;AAC7B,MAAA,MAAM,CAAA,GAAI,IAAA;AACV,MAAA,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAA,IAAU,CAAA,EAAG,IAAA,EAAM,CAAA,CAAE,IAAA,IAAQ,EAAA,EAAI,CAAA;AAAA,IACnE;AAAA,GACF;AAAA,EACA,UAAA,EAAY;AAAA,IACV,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,KAAK,IAAA,KAAS,SAAA;AAAA,IACpC,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AACvB,MAAA,KAAA,CAAM,QAAA,CAAS,MAAA,EAAQ,MAAA,EAAW,EAAE,GAAA,EAAK,MAAM,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA,EAAG,CAAA;AACnE,MAAA,KAAA,CAAM,QAAQ,MAAA,EAAQ,MAAA,EAAW,IAAI,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,CAAE,CAAA;AACtD,MAAA,KAAA,CAAM,SAAA,EAAU;AAAA,IAClB;AAAA;AAEJ,CAAA,CAAE,CAAA;AAGJ,IAAM,oBAAoB,CACxB,OAAA,KAEAM,OAAAA,CAAQ,eAAA,EAAiB,MAAM,MAAM;AACnC,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAoB;AACvC,IAAAC,MAAM,IAAA,EAAM,MAAA,EAAQ,CAAC,IAAA,EAAiB,OAAO,MAAA,KAAsB;AACjE,MAAA,IAAI,OAAO,IAAA,CAAK,GAAA,KAAQ,QAAA,EAAU;AAChC,QAAA;AAAA,MACF;AAIA,MAAA,MAAM,QAAQ,IAAA,CAAK,QAAA,IAAY,EAAC,EAC7B,IAAI,CAAC,KAAA,KAAW,OAAO,KAAA,CAAM,UAAU,QAAA,GAAW,KAAA,CAAM,QAAQ,EAAG,CAAA,CACnE,KAAK,EAAE,CAAA;AACV,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA;AACrC,MAAA,IAAI,UAAU,IAAA,EAAM;AAClB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA;AAClC,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,QAAA,EAAU;AAChD,QAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,CAAA,EAAG;AAAA,UAC/B,IAAA,EAAM,SAAA;AAAA,UACN,MAAA;AAAA,UACA;AAAA,SACY,CAAA;AAAA,MAChB;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA;AACA,EAAA,OAAO,WAAA;AACT,CAAC,CAAA;AAGI,IAAM,aAAA,GAAgB,kBAAkB,YAAY;AAEpD,IAAM,mBAAA,GAAsB,kBAAkB,cAAc;AAS5D,IAAM,oBAAA,GAAuBT,QAAAA;AAAA,EAClC,kBAAA;AAAA,EACA,MACE,CAAC,OAAA,KACD,CAAC,OAAO,QAAA,KAAa;AACnB,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AACzB,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAK,GAAI,OAAA;AACzB,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA,IAAK,UAAU,CAAA,EAAG;AAC5C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AACzC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,OAAO,IAAA,CAAK,MAAA,CAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AACzC,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,EAAA,CAAG,oBAAA,CAAqB,IAAI,CAAA;AAC7C,IAAA,EAAA,CAAG,WAAW,GAAG,CAAA;AACjB,IAAA,QAAA,CAAS,EAAA,CAAG,gBAAgB,CAAA;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AACJ;AAQO,IAAM,mBAAA,GAAsB,CACjC,MAAA,GAA2B,EAAC,KACP;AACrB,EAAA,MAAM,SAAS,MAAA,CAAO,KAAA,GAAQ,iBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA,GAAI,aAAA;AAChE,EAAA,MAAM,SAAS,MAAA,CAAO,OAAA,GAClB,iBAAA,CAAkB,MAAA,CAAO,OAAO,CAAA,GAChC,mBAAA;AACJ,EAAA,OAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,oBAAoB,EAAE,IAAA,EAAK;AACrD;AC1KO,IAAM,OAAA,GAAU;AAoBhB,IAAM,WAAA,GAAcE,WAAAA,CAAY,OAAA,EAAS,OAAO;AAAA,EACrD,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,IAAA;AAAA,EACR,IAAA,EAAM,IAAA;AAAA,EACN,KAAA,EAAO;AAAA,IACL,KAAA,EAAO,EAAE,OAAA,EAAS,EAAA,EAAG;AAAA,IACrB,KAAA,EAAO,EAAE,OAAA,EAAS,EAAA;AAAG,GACvB;AAAA,EACA,QAAA,EAAU;AAAA,IACR;AAAA;AAAA,MAEE,GAAA,EAAK,gBAAA;AAAA,MACL,QAAA,EAAU,CAAC,GAAA,KAAQ;AACjB,QAAA,MAAM,EAAA,GAAK,GAAA;AACX,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,EAAA,CAAG,OAAA,CAAQ,KAAA,IAAS,EAAA;AAAA,UAC3B,KAAA,EAAO,GAAG,WAAA,IAAe;AAAA,SAC3B;AAAA,MACF;AAAA;AACF,GACF;AAAA,EACA,KAAA,EAAO,CAAC,IAAA,KAAS;AAGf,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC1C,IAAA,IAAA,CAAK,SAAA,GAAY,WAAA;AACjB,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,MAAM,KAAK,CAAA;AAC5C,IAAA,IAAA,CAAK,YAAA,CAAa,mBAAmB,OAAO,CAAA;AAC5C,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC1C,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EACA,aAAA,EAAe;AAAA,IACb,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,KAAS,OAAA;AAAA,IAC/B,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,EAAM,IAAA,KAAS;AAC7B,MAAA,MAAM,CAAA,GAAI,IAAA;AACV,MAAA,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,EAAE,KAAA,EAAO,CAAA,CAAE,KAAA,IAAS,EAAA,EAAI,KAAA,EAAO,CAAA,CAAE,KAAA,IAAS,EAAA,EAAI,CAAA;AAAA,IACpE;AAAA,GACF;AAAA,EACA,UAAA,EAAY;AAAA,IACV,KAAA,EAAO,CAAC,IAAA,KAAS,IAAA,CAAK,KAAK,IAAA,KAAS,OAAA;AAAA,IACpC,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS;AACvB,MAAA,KAAA,CAAM,QAAA,CAAS,QAAQ,MAAA,EAAW;AAAA,QAChC,KAAK,CAAA,EAAG,YAAY,CAAA,EAAG,IAAA,CAAK,MAAM,KAAK,CAAA;AAAA,OACxC,CAAA;AACD,MAAA,KAAA,CAAM,QAAQ,MAAA,EAAQ,MAAA,EAAW,OAAO,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AACzD,MAAA,KAAA,CAAM,SAAA,EAAU;AAAA,IAClB;AAAA;AAEJ,CAAA,CAAE;AAGK,IAAM,iBAAA,GAAoBM,OAAAA,CAAQ,aAAA,EAAe,MAAM,MAAM;AAClE,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAoB;AACvC,IAAAC,MAAM,IAAA,EAAM,MAAA,EAAQ,CAAC,IAAA,EAAiB,OAAO,MAAA,KAAsB;AACjE,MAAA,IAAI,OAAO,KAAK,GAAA,KAAQ,QAAA,IAAY,CAAC,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EAAG;AACtE,QAAA;AAAA,MACF;AACA,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,aAAa,MAAM,CAAA;AAChD,MAAA,IAAI,CAAC,KAAA,EAAO;AACV,QAAA;AAAA,MACF;AACA,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,GAAW,CAAC,CAAA;AAC/B,MAAA,MAAM,QAAQ,OAAO,KAAA,EAAO,KAAA,KAAU,QAAA,GAAW,MAAM,KAAA,GAAQ,EAAA;AAC/D,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,QAAA,EAAU;AAChD,QAAA,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,KAAA,EAAO,CAAA,EAAG;AAAA,UAC/B,IAAA,EAAM,OAAA;AAAA,UACN,KAAA;AAAA,UACA;AAAA,SACY,CAAA;AAAA,MAChB;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAA;AACA,EAAA,OAAO,WAAA;AACT,CAAC;AASM,IAAM,kBAAA,GAAqBT,QAAAA;AAAA,EAChC,gBAAA;AAAA,EACA,CAAC,GAAA,KACC,CAAC,OAAA,KACD,CAAC,OAAO,QAAA,KAAa;AACnB,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,QAAA,EAAU;AACzB,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,OAAA;AACzB,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,YAAY,IAAA,CAAK,GAAG,EAAE,MAAA,CAAO,EAAE,KAAA,EAAO,KAAA,EAAO,CAAA;AAC1D,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,EAAA,CAAG,oBAAA,CAAqB,IAAI,CAAA;AAC7C,IAAA,EAAA,CAAG,WAAW,GAAG,CAAA;AACjB,IAAA,QAAA,CAAS,EAAA,CAAG,gBAAgB,CAAA;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AACJ;AAGO,IAAM,oBAAoB,MAC/B,CAAC,aAAa,iBAAA,EAAmB,kBAAkB,EAAE,IAAA;ACtHvD,IAAM,cAAA,GAAiB,CAAC,MAAA,KACtB,MAAA,IAAU,MAAA,CAAO,aAAY,CAAE,UAAA,CAAW,IAAI,CAAA,GAAI,iBAAA,GAAe,mCAAA;AAEnE,IAAM,iBAAA,GAAoB,CAAC,MAAA,KACzB,MAAA,IAAU,MAAA,CAAO,aAAY,CAAE,UAAA,CAAW,IAAI,CAAA,GAC1C,qBAAA,GACA,sCAAA;AAQC,IAAM,cAAA,GAAiB,CAC5B,WAAA,EACA,OAAA,GAA+B,EAAC,KACnB;AACb,EAAA,OAAO,OAAO,OAAO,MAAA,KAAW;AAC9B,IAAA,MAAM,SAAiB,EAAC;AACxB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA;AACzB,MAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,KAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5C,QAAA;AAAA,MACF;AACA,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA;AAAA,MAC1B,MAAA,CAAO,GAAA,CAAI,OAAO,KAAA,KAAgC;AAChD,QAAA,IAAI;AACF,UAAA,MAAM,GAAA,GAAM,MAAM,WAAA,CAAY,KAAK,CAAA;AACnC,UAAA,OAAO,MAAA,CAAO,KAAA,CAAM,KAAA,CAAO,aAAA,CAAc;AAAA,YACvC,GAAA;AAAA,YACA,KAAK,KAAA,CAAM;AAAA,WACZ,CAAA;AAAA,QACH,CAAA,CAAA,MAAQ;AACN,UAAA,OAAA,CAAQ,MAAA,GAAS,iBAAA,CAAkB,OAAA,CAAQ,MAAM,GAAG,OAAO,CAAA;AAC3D,UAAA,OAAO,IAAA;AAAA,QACT;AAAA,MACF,CAAC;AAAA,KACH;AAEA,IAAA,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,IAAA,KAAuB,SAAS,IAAI,CAAA;AAAA,EAC3D,CAAA;AACF;AAKA,IAAM,eAAA,GAAkB,CAAC,MAAA,KAAqD;AAC5E,EAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AACxC,EAAA,EAAA,CAAG,SAAA,GAAY,uBAAA;AACf,EAAA,EAAA,CAAG,WAAA,GAAc,eAAe,MAAM,CAAA;AACtC,EAAA,OAAO,EAAA;AACT,CAAA;AAIO,IAAM,yBAAA,GAA4B,CAAC,OAAA,GAA+B,EAAC,KAAM;AAC9E,EAAA,OAAO,CAAC,KAAa,IAAA,KAAkD;AACrE,IAAA,OAAO,WAAW,MAAA,CAAO,GAAA,EAAK,gBAAgB,OAAA,CAAQ,MAAM,GAAG,IAAI,CAAA;AAAA,EACrE,CAAA;AACF;AAIO,IAAM,oBAAoB,CAC/B,GAAA,EACA,WAAA,EACA,OAAA,GAA+B,EAAC,KACvB;AACT,EAAA,GAAA,CAAI,MAAA,CAAO,YAAA,CAAa,GAAA,EAAK,CAAC,IAAA,MAAU;AAAA,IACtC,GAAG,IAAA;AAAA,IACH,QAAA,EAAU,cAAA,CAAe,WAAA,EAAa,OAAO,CAAA;AAAA,IAC7C,mBAAA,EAAqB,0BAA0B,OAAO;AAAA,GACxD,CAAE,CAAA;AACJ;AAEA,IAAM,qBACJ,CAAC,WAAA,EAA0B,OAAA,KAC3B,CAAC,QACD,MAAM;AACJ,EAAA,iBAAA,CAAkB,GAAA,EAAK,aAAa,OAAO,CAAA;AAC7C,CAAA;AAQK,IAAM,kBAAA,GAAqB,CAChC,WAAA,EACA,OAAA,GAA+B,EAAC,KACX,CAAC,GAAG,MAAA,EAAQ,kBAAA,CAAmB,WAAA,EAAa,OAAO,CAAC;AAkB3E,IAAM,cAAA,GAAiB,IAAIa,SAAAA,CAAyB,8BAA8B,CAAA;AAG3E,IAAM,sBAAA,GAAyCC,MAAAA;AAAA,EACpD,MACE,IAAIC,MAAAA,CAAsB;AAAA,IACxB,GAAA,EAAK,cAAA;AAAA,IACL,KAAA,EAAO;AAAA,MACL,IAAA,EAAM,MAAM,aAAA,CAAc,KAAA;AAAA,MAC1B,KAAA,CAAM,IAAI,GAAA,EAAK;AACb,QAAA,IAAI,OAAO,GAAA,CAAI,GAAA,CAAI,EAAA,CAAG,OAAA,EAAS,GAAG,GAAG,CAAA;AACrC,QAAA,MAAM,IAAA,GAAO,EAAA,CAAG,OAAA,CAAQ,cAAc,CAAA;AACtC,QAAA,IAAI,MAAM,GAAA,EAAK;AACb,UAAA,MAAM,OAAO,UAAA,CAAW,MAAA;AAAA,YACtB,KAAK,GAAA,CAAI,GAAA;AAAA,YACT,eAAA,CAAgB,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAAA,YAC/B,EAAE,EAAA,EAAI,IAAA,CAAK,GAAA,CAAI,EAAA;AAAG,WACpB;AACA,UAAA,IAAA,GAAO,KAAK,GAAA,CAAI,EAAA,CAAG,GAAA,EAAK,CAAC,IAAI,CAAC,CAAA;AAAA,QAChC,CAAA,MAAA,IAAW,MAAM,MAAA,EAAQ;AACvB,UAAA,MAAM,EAAE,EAAA,EAAG,GAAI,IAAA,CAAK,MAAA;AACpB,UAAA,IAAA,GAAO,IAAA,CAAK,MAAA;AAAA,YACV,IAAA,CAAK,KAAK,MAAA,EAAW,MAAA,EAAW,CAAC,IAAA,KAAS,IAAA,CAAK,OAAO,EAAE;AAAA,WAC1D;AAAA,QACF;AACA,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,KACF;AAAA,IACA,KAAA,EAAO;AAAA,MACL,WAAA,EAAa,CAAC,KAAA,KAAU,cAAA,CAAe,SAAS,KAAK;AAAA;AACvD,GACD;AACL;AAEA,IAAM,eAAA,GAAkB,CAAC,IAAA,EAAkB,EAAA,KAA8B;AACvE,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA;AAC9C,EAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,CAAK,MAAA,EAAW,QAAW,CAAC,IAAA,KAAS,IAAA,CAAK,EAAA,KAAO,EAAE,CAAA;AACtE,EAAA,OAAO,SAAS,KAAA,CAAM,MAAA,GAAS,KAAA,CAAM,CAAC,EAAG,IAAA,GAAO,IAAA;AAClD,CAAA;AAQO,IAAM,gBAAA,GAAmB,OAC9B,IAAA,EACA,IAAA,EACA,OAAA,KACkB;AAClB,EAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,EAAG;AACnC,IAAA;AAAA,EACF;AACA,EAAA,MAAM,KAAK,EAAC;AACZ,EAAA,MAAM,EAAA,GAAK,KAAK,KAAA,CAAM,EAAA;AACtB,EAAA,IAAI,CAAC,EAAA,CAAG,SAAA,CAAU,KAAA,EAAO;AACvB,IAAA,EAAA,CAAG,eAAA,EAAgB;AAAA,EACrB;AACA,EAAA,EAAA,CAAG,QAAQ,cAAA,EAAgB;AAAA,IACzB,GAAA,EAAK,EAAE,EAAA,EAAI,GAAA,EAAK,GAAG,SAAA,CAAU,IAAA,EAAM,MAAA,EAAQ,OAAA,CAAQ,MAAA;AAAO,GACjC,CAAA;AAC3B,EAAA,EAAA,CAAG,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAChC,EAAA,IAAA,CAAK,SAAS,EAAE,CAAA;AAEhB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,WAAA,CAAY,IAAI,CAAA;AAC1C,IAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,IAAA,EAAM,EAAE,CAAA;AACpC,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,KAAA;AAC1C,IAAA,MAAM,IAAA,GAAO,WAAW,aAAA,CAAc,EAAE,KAAK,GAAA,EAAK,IAAA,CAAK,MAAM,CAAA;AAC7D,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA;AAAA,MACH,IAAA,CAAK,KAAA,CAAM,EAAA,CACR,WAAA,CAAY,KAAK,GAAA,EAAK,IAAI,CAAA,CAC1B,OAAA,CAAQ,gBAAgB,EAAE,MAAA,EAAQ,EAAE,EAAA,IAAgC;AAAA,KACzE;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,IAAA,CAAK,QAAA;AAAA,MACH,IAAA,CAAK,KAAA,CAAM,EAAA,CACR,OAAA,CAAQ,gBAAgB,EAAE,MAAA,EAAQ,EAAE,EAAA,EAAG,EAA6B,CAAA,CACpE,OAAA,CAAQ,gBAAgB,KAAK;AAAA,KAClC;AACA,IAAA,OAAA,CAAQ,MAAA,GAAS,iBAAA,CAAkB,OAAA,CAAQ,MAAM,GAAG,OAAO,CAAA;AAAA,EAC7D;AACF;ACzMA,IAAM,YAAA,uBAAmB,GAAA,CAAI;AAAA,EAC3B,YAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,IAAM,UAAA,GAAa,CAAC,GAAA,KAClB,GAAA,CAAI,cAAc,CAAA,IAAK,CAAC,GAAA,CAAI,UAAA,EAAY,OAAA,CAAQ,IAAA;AAElD,IAAM,iBAAA,GAAoB,CAAC,KAAA,KAAgC;AACzD,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,KAAA,CAAM,SAAA;AAC1B,EAAA,KAAA,IAAS,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,KAAA,GAAQ,GAAG,KAAA,EAAA,EAAS;AAClD,IAAA,IAAI,YAAA,CAAa,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,EAAG;AACnD,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT,CAAA;AAMO,IAAM,uBAAA,GAA0B,CACrC,MAAA,GAA4B,EAAC,KACR;AACrB,EAAA,MAAM,IAAA,GAAO,OAAO,IAAA,IAAQ,EAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,OAAO,IAAA,IAAQ,OAAA;AAE5B,EAAA,MAAM,MAAA,GAASD,MAAAA;AAAA,IACb,CAAC,GAAA,KACC,IAAIC,MAAAA,CAAO;AAAA,MACT,GAAA,EAAK,IAAIF,SAAAA,CAAU,iBAAiB,CAAA;AAAA,MACpC,KAAA,EAAO;AAAA,QACL,WAAA,EAAa,CAAC,KAAA,KAAU;AACtB,UAAA,IAAI,CAAC,IAAA,EAAM;AACT,YAAA,OAAO,IAAA;AAAA,UACT;AAEA,UAAA,MAAM,QAAA,GAAW,GAAA,CAAI,GAAA,CAAI,oBAAoB,CAAA,CAAE,QAAA;AAC/C,UAAA,IAAI,QAAA,IAAY,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AAChC,YAAA,OAAO,IAAA;AAAA,UACT;AACA,UAAA,IAAI,SAAS,KAAA,IAAS,CAAC,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA,EAAG;AAC5C,YAAA,OAAO,IAAA;AAAA,UACT;AACA,UAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AACtB,UAAA,IAAI,CAAC,SAAA,CAAU,KAAA,IAAS,iBAAA,CAAkB,KAAK,CAAA,EAAG;AAChD,YAAA,OAAO,IAAA;AAAA,UACT;AACA,UAAA,MAAM,IAAA,GAAO,UAAU,OAAA,CAAQ,MAAA;AAC/B,UAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,GAAO,CAAA,EAAG;AACzB,YAAA,OAAO,IAAA;AAAA,UACT;AACA,UAAA,MAAM,MAAA,GAAS,SAAA,CAAU,OAAA,CAAQ,MAAA,EAAO;AACxC,UAAA,OAAOG,aAAAA,CAAc,MAAA,CAAO,KAAA,CAAM,GAAA,EAAK;AAAA,YACrCC,UAAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,MAAA,GAAS,KAAK,QAAA,EAAU;AAAA,cAC9C,KAAA,EAAO,yBAAA;AAAA,cACP,kBAAA,EAAoB;AAAA,aACrB;AAAA,WACF,CAAA;AAAA,QACH;AAAA;AACF,KACD;AAAA,GACL;AAEA,EAAA,OAAO,CAAC,MAAM,CAAA,CAAE,IAAA,EAAK;AACvB;;;ACtBO,IAAM,sBAAA,GAAyB,CACpC,QAAA,GAA8B,EAAC,EAC/B,WAA8B,EAAC,EAC/B,OAAA,GAAkC,EAAC,KACd;AACrB,EAAA,MAAM;AAAA,IACJ,OAAA,GAAU,IAAA;AAAA,IACV,OAAAL,MAAAA,GAAQ,IAAA;AAAA,IACR,SAAA,GAAY,IAAA;AAAA,IACZ,OAAA,GAAU,IAAA;AAAA,IACV,KAAA,GAAQ;AAAA,GACV,GAAI,QAAA;AAEJ,EAAA,MAAM,OAAA,GAAiD;AAAA,IACrD,UAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,sBAAA,CAAuB;AAAA,QACrB,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,cAAc,OAAA,CAAQ;AAAA,OACvB;AAAA,KACH;AAAA,EACF;AACA,EAAA,IAAIA,MAAAA,EAAO;AACT,IAAA,OAAA,CAAQ,IAAA,CAAK,oBAAoB,CAAA;AAAA,EACnC;AACA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK,qBAAqB,CAAA;AAAA,EACpC;AAIA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,mBAAA,CAAoB;AAAA,QAClB,OAAO,QAAA,CAAS,YAAA;AAAA,QAChB,SAAS,QAAA,CAAS;AAAA,OACnB;AAAA,KACH;AAAA,EACF;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAA,CAAQ,IAAA,CAAK,mBAAmB,CAAA;AAAA,EAClC;AAGA,EAAA,IAAI,SAAS,WAAA,EAAa;AACxB,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,kBAAA,CAAmB,SAAS,WAAA,EAAa;AAAA,QACvC,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,QAAQ,QAAA,CAAS;AAAA,OAClB;AAAA,KACH;AAIA,IAAA,OAAA,CAAQ,KAAK,sBAAsB,CAAA;AAAA,EACrC;AAEA,EAAA,OAAA,CAAQ,IAAA,CAAK,sBAAsB,CAAA;AAEnC,EAAA,OAAA,CAAQ,IAAA,CAAK,kBAAkB,CAAA;AAE/B,EAAA,OAAA,CAAQ,IAAA,CAAK,qBAAqB,CAAA;AAElC,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,uBAAA,CAAwB;AAAA,QACtB,MAAM,OAAA,CAAQ,WAAA;AAAA,QACd,MAAM,OAAA,CAAQ;AAAA,OACf;AAAA,KACH;AAAA,EACF;AAEA,EAAA,OAAO,QAAQ,IAAA,EAAK;AACtB","file":"index.js","sourcesContent":["// Spoiler plugin — the `||hidden text||` inline node.\n//\n// Ported (behaviour-wise) from the forum's plugins/spoiler/spoilerPlugin.ts.\n// This is a PURE plugin: it needs no host policy, so there is no adapter\n// argument — just a `createSpoilerPlugin()` factory returning the Milkdown\n// plugin bundle, matching the folder contract in ../README.md.\n//\n// The syntax `||text||` is the KUN ecosystem's own markdown extension (shared\n// with the server renderer), so the round-trip lives here in core, not in a host.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { SerializerReady, serializerCtx } from '@milkdown/kit/core'\nimport type { Node } from '@milkdown/kit/transformer'\nimport type {\n NodeType,\n Node as ProseNode,\n ResolvedPos\n} from '@milkdown/kit/prose/model'\nimport { Fragment } from '@milkdown/kit/prose/model'\nimport { expectDomTypeError } from '@milkdown/kit/exception'\nimport { InputRule } from '@milkdown/kit/prose/inputrules'\nimport { NodeSelection, TextSelection } from '@milkdown/kit/prose/state'\nimport {\n $command,\n $inputRule,\n $nodeAttr,\n $nodeSchema,\n $remark\n} from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\ninterface SpoilerNode extends Node {\n type: 'kun-spoiler' | 'text'\n value?: string\n children?: SpoilerNode[]\n}\n\n/**\n * DOM attrs for the spoiler chip AS SEEN WHILE EDITING — a tinted chip, so you\n * can tell hidden text from ordinary text while you write it. (The published\n * page renders `||…||` itself; this styling never leaves the editor.)\n *\n * Self-sufficient on purpose: it used to be `background: var(--color-default-500)`\n * with no fallback, so in any host that does not define that palette token — the\n * headless editor being exactly such a host — the whole declaration was invalid\n * and the chip computed to `rgba(0, 0, 0, 0)`. Hidden text looked like plain text.\n *\n * `--kun-spoiler-bg` is the theming hook: an INLINE style beats every selector a\n * host stylesheet can write, so without a custom property the chip would be\n * untouchable from CSS. Setting the property is not (a rule may set it on\n * `.kun-spoiler` freely) — which is how @kungal/editor-nuxt paints it in KunUI\n * colors, and how any host re-tints it in one line.\n *\n * The default is `currentColor`-derived rather than a fixed grey so it works on a\n * light and a dark background alike; the plain rgba before it is what a browser\n * without `color-mix()` keeps (an unknown function is dropped at parse time, so\n * the earlier declaration survives — unlike a bad `var()`, which kills both).\n */\nexport const spoilerAttr = $nodeAttr('kun-spoiler', () => ({\n container: {\n class: 'kun-spoiler',\n style:\n 'background: rgba(127, 127, 127, 0.3);' +\n ' background: var(--kun-spoiler-bg, color-mix(in oklab, currentColor 22%, transparent));' +\n ' border-radius: var(--radius-sm, 0.25rem); padding: 0 4px; cursor: pointer;'\n }\n}))\n\n/** The zero-width space this plugin parks the caret on. A caret has to sit in a\n * TEXT node: with nothing after a spoiler the browser puts the next keystroke\n * inside it, and an empty spoiler has nowhere to type at all. Spelled as an\n * escape because the literal character is invisible in a source file.\n *\n * The invariant, held by `stripCaretAnchors` (out) and the remark transform (in):\n * an anchor is an EDITOR device \\u2014 it lives in the ProseMirror document, and never\n * in the markdown. It used to ride along into whatever the host stored, so a\n * saved post read `\\u9cb2 ||Galgame||<U+200B> \\u8bba\\u575b`: an invisible character in the\n * database, in every diff, and in every consumer that never heard of this editor. */\nconst CARET_ANCHOR = '\\u200b'\n\n/**\n * Take the anchors back out of every markdown string the editor hands over.\n *\n * At the SERIALIZER, not at one caller: `getMarkdown()`, the listener that backs\n * `v-model`, the source view and any host action all read through this one slice,\n * and only the last of those is ours to police. Wrapping it also covers anchors\n * that arrived from stored content or a paste, so a document heals itself the\n * next time it is saved.\n */\nconst stripCaretAnchors: MilkdownPlugin = (ctx) => async () => {\n await ctx.wait(SerializerReady)\n ctx.update(\n serializerCtx,\n (serialize) => (doc) => serialize(doc).replaceAll(CARET_ANCHOR, '')\n )\n}\n\n/** Anchors are an editor device, never content: strip them from any text moving\n * between a spoiler and the document (or the markdown). */\nconst withoutAnchors = (content: Fragment): Fragment => {\n const kept: ProseNode[] = []\n content.forEach((child) => {\n if (!child.isText) {\n kept.push(child)\n return\n }\n const text = (child.text ?? '').replaceAll(CARET_ANCHOR, '')\n if (text) {\n kept.push(child.type.schema.text(text, child.marks))\n }\n })\n return Fragment.fromArray(kept)\n}\n\n/** The `kun-spoiler` inline node: parses/serializes `||text||` and renders a\n * `<span data-type=\"kun-spoiler\">` the render layer toggles on click. */\nexport const spoilerSchema = $nodeSchema('kun-spoiler', (ctx) => ({\n group: 'inline',\n inline: true,\n content: 'inline*',\n marks: '',\n attrs: {\n revealed: {\n default: false\n }\n },\n parseDOM: [\n {\n tag: 'span[data-type=\"kun-spoiler\"]',\n getAttrs: (dom) => {\n if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom)\n return {\n revealed: dom.getAttribute('data-revealed') === 'true'\n }\n }\n }\n ],\n toDOM: (node) => {\n const attrs = ctx.get(spoilerAttr.key)(node)\n return [\n 'span',\n {\n ...attrs.container,\n 'data-type': 'kun-spoiler',\n 'data-revealed': node.attrs.revealed\n },\n 0\n ]\n },\n parseMarkdown: {\n match: ({ type }) => type === 'kun-spoiler',\n runner: (state, node, type) => {\n state.openNode(type)\n state.next(node.children || [])\n state.closeNode()\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === 'kun-spoiler',\n runner: (state, node) => {\n const content = withoutAnchors(node.content)\n // Nothing but the caret anchor: the button was clicked and never typed\n // into. Emit nothing rather than a bare `||||`.\n if (!content.size) {\n return\n }\n state.addNode('text', undefined, '||')\n state.next(content)\n state.addNode('text', undefined, '||')\n }\n }\n}))\n\n/** The spoiler the position sits inside, if any. A spoiler holds inline content\n * (it is not an atom), so a caret in one resolves to a deeper `parent`. */\nconst enclosingSpoiler = (\n $pos: ResolvedPos,\n type: NodeType\n): { pos: number; node: ProseNode } | null => {\n for (let depth = $pos.depth; depth > 0; depth--) {\n const node = $pos.node(depth)\n if (node.type === type) {\n return { pos: $pos.before(depth), node }\n }\n }\n return null\n}\n\n/**\n * Toolbar entry point (\"隐藏文本\"): hide the selection, or reveal the spoiler the\n * caret is in. The only way into a spoiler other than typing `||…||`, so it has\n * to cover the same cases the syntax does:\n *\n * - a selection → its TEXT moves INSIDE the node. It has to be moved, not\n * replaced: `replaceSelectionWith` on its own deletes what you selected. The\n * schema is `marks: ''` (bold inside `||…||` cannot round-trip), so the\n * formatting is what's dropped, never the words. Line breaks become spaces:\n * `||…||` pairs within one line in every reader of the syntax, so a spoiler\n * spanning lines would serialize to markdown that reads back as literal `||`.\n * - an empty selection → an empty spoiler with the caret inside it: type, and\n * what you type is hidden. \"Empty\" means holding a caret anchor — a caret\n * cannot sit in an inline node with no text node in it — and a spoiler with\n * nothing but an anchor serializes to nothing at all, so an unused one cannot\n * rot into the document.\n * - the caret already inside a spoiler → reveal it, leaving the text selected.\n * Nesting would serialize to `||||text||||`, which reads back as nothing at\n * all, so this button has to toggle.\n *\n * Returns false where there is nothing to hide or nowhere to put it — inside a\n * code block, with a NODE selected, or over a selection holding no words at all\n * (an image is not text; replacing it would delete it) — so a host can grey the\n * button out. A spoiler holds text, so any other inline node caught in a text\n * selection alongside words (an image, inline math) does not survive the move:\n * `||…||` cannot carry one.\n */\nexport const insertKunSpoilerCommand = $command(\n 'InsertKunSpoiler',\n (ctx) => () => (state, dispatch) => {\n const type = spoilerSchema.type(ctx)\n const { $from, from, to, empty } = state.selection\n\n const open = enclosingSpoiler($from, type)\n if (open) {\n if (dispatch) {\n const { pos, node } = open\n const revealed = withoutAnchors(node.content)\n // Take the anchor that follows the node with it, or toggling the button\n // back and forth stacks up invisible characters.\n const end = pos + node.nodeSize\n const trailing = state.doc.textBetween(\n end,\n Math.min(end + CARET_ANCHOR.length, state.doc.content.size)\n )\n const tr = state.tr.replaceWith(\n pos,\n trailing === CARET_ANCHOR ? end + CARET_ANCHOR.length : end,\n revealed\n )\n if (revealed.size) {\n // Leave the revealed text selected: the next click re-hides exactly\n // what this one revealed.\n tr.setSelection(TextSelection.create(tr.doc, pos, pos + revealed.size))\n }\n dispatch(tr.scrollIntoView())\n }\n return true\n }\n\n // A selected NODE (an image, a code block) is not text to hide, and\n // replacing the selection would delete it. Refuse.\n if (state.selection instanceof NodeSelection) {\n return false\n }\n // Refuse where a spoiler cannot go — a code block holds plain text. Guarded\n // on `isTextblock` because select-all is an `AllSelection`, which resolves\n // to the DOC: no textblock to ask, and `replaceSelection` puts the node in\n // a paragraph of its own.\n if (\n $from.parent.isTextblock &&\n !$from.parent.canReplaceWith($from.index(), $from.index(), type)\n ) {\n return false\n }\n // ' ' for BOTH separators, because `||…||` is line-scoped everywhere it is\n // read — the remark transform below, and the server renderer that shares the\n // syntax — so a spoiler holding a line break would serialize to markdown\n // that reads back as literal `||`. The block separator keeps the words apart\n // when a selection spans paragraphs; the leaf one covers a line break inside\n // one (commonmark's hardbreak declares `leafText: () => '\\n'`, so without it\n // the button writes the very cross-line `||` it cannot parse).\n const text = state.doc\n .textBetween(from, to, ' ', ' ')\n .replaceAll(CARET_ANCHOR, '')\n // A selection with no words in it (an image on its own) is nothing to hide,\n // and hiding it would delete it. An EMPTY selection is the other thing\n // entirely: an empty spoiler to type into.\n if (!empty && !text.trim()) {\n return false\n }\n if (!dispatch) {\n return true\n }\n\n // Empty selection → the node still needs a text node to hold the caret, so\n // it starts on an anchor; the serializer drops it again.\n const node = type.create(null, state.schema.text(text || CARET_ANCHOR))\n const tr = state.tr.replaceSelectionWith(node, false)\n // `replaceSelectionWith` leaves the selection right after the node.\n const after = tr.selection.to\n tr.insertText(CARET_ANCHOR, after)\n dispatch(\n tr\n .setSelection(\n TextSelection.create(\n tr.doc,\n // On the anchor inside the empty node (type and it is hidden), or\n // past the one after a wrap (type and it is not).\n empty\n ? after - node.nodeSize + 1 + CARET_ANCHOR.length\n : after + 1\n )\n )\n .scrollIntoView()\n )\n return true\n }\n)\n\n/** Typing `||text||` in the editor turns it into a spoiler node in place. The\n * trailing zero-width space gives the caret a stable anchor after the atom. */\nexport const insertSpoilerInputRule = $inputRule(\n () =>\n new InputRule(/(?:^|\\s)\\|\\|(.*?)\\|\\|$/, (state, match, start, end) => {\n const [fullMatch, content] = match\n if (!content) return null\n const startPos = start + (fullMatch.startsWith(' ') ? 1 : 0)\n const { tr } = state\n const schema = state.schema\n const spoilerNodeType = schema.nodes['kun-spoiler']\n if (!spoilerNodeType) return null\n\n const spoilerNode = spoilerNodeType.create(\n { revealed: false },\n schema.text(content)\n )\n const zeroWidthSpace = schema.text(CARET_ANCHOR)\n return tr\n .replaceWith(startPos, end, [spoilerNode, zeroWidthSpace])\n .setStoredMarks([])\n .scrollIntoView()\n })\n)\n\n/** Remark transform: splits `||...||` runs inside text nodes into `kun-spoiler`\n * mdast nodes on parse, so pasted / loaded markdown becomes real spoiler nodes. */\nexport const remarkSpoilerPlugin = $remark('remarkSpoiler', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'text', (node: SpoilerNode, index, parent: SpoilerNode) => {\n if (typeof node.value !== 'string' || !parent) {\n return\n }\n if (!node.value.includes('||')) {\n return\n }\n\n // Anchors that rode in with stored content (this plugin used to write them\n // to markdown) are dropped here and re-added below, so a loaded spoiler\n // ends up with exactly the one the editor needs.\n const value = node.value.replaceAll(CARET_ANCHOR, '')\n const regex = /\\|\\|(.*?)\\|\\|/g\n const newNodes: SpoilerNode[] = []\n let lastIndex = 0\n\n for (const match of value.matchAll(regex)) {\n const [full, content] = match\n const matchIndex = match.index ?? 0\n\n if (matchIndex > lastIndex) {\n newNodes.push({\n type: 'text',\n value: value.slice(lastIndex, matchIndex)\n })\n }\n\n if (content) {\n newNodes.push({\n type: 'kun-spoiler',\n children: [{ type: 'text', value: content }]\n })\n // Loading a spoiler has to leave the same caret anchor after it that\n // typing one does — it is what lets you click past a spoiler sitting at\n // the end of a paragraph and type OUTSIDE it. The serializer takes it\n // off again, so it costs the stored markdown nothing.\n newNodes.push({ type: 'text', value: CARET_ANCHOR })\n }\n\n lastIndex = matchIndex + full.length\n }\n\n if (lastIndex < value.length) {\n newNodes.push({ type: 'text', value: value.slice(lastIndex) })\n }\n\n if (newNodes.length > 0 && typeof index === 'number') {\n parent.children?.splice(index, 1, ...newNodes)\n }\n })\n }\n\n return transformer\n})\n\n/**\n * The spoiler plugin bundle: schema attrs, node schema, the `||…||` input rule,\n * the insert command, the remark round-trip and the serializer guard that keeps\n * caret anchors out of the markdown. Pure — no adapter needed.\n */\nexport const createSpoilerPlugin = (): MilkdownPlugin[] =>\n [\n spoilerAttr,\n spoilerSchema,\n insertSpoilerInputRule,\n insertKunSpoilerCommand,\n remarkSpoilerPlugin,\n stripCaretAnchors\n ].flat()\n","// Stop-link — keep the link mark from leaking onto text that is not a link.\n//\n// A link is a MARK, so ProseMirror stores it as a pending mark after a delete\n// (the same mechanism that makes typing after a deleted bold word stay bold).\n// For a link that is wrong: the next keystroke must not inherit a href that\n// is no longer under the cursor. Two complementary pieces:\n//\n// 1. A $prose plugin that strips an orphan stored link the moment the\n// cursor is not inside a link (covers select-delete, backspace, …).\n// 2. A Space keymap that also clears the stored mark — Milkdown's link\n// mark is inclusive, so Space is how you stop extending a live link\n// while typing at its end (the forum's original stop-link behaviour).\n//\n// A stored link mark is ONLY valid while the cursor sits inside a link. This\n// plugin will therefore strip an \"armed\" toggleLink on an empty selection\n// outside a link — insert via insertLinkCommand instead. Pure: no host policy.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command, $prose, $useKeymap } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { commandsCtx } from '@milkdown/kit/core'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport type { MarkType } from '@milkdown/kit/prose/model'\nimport type { EditorState } from '@milkdown/kit/prose/state'\n\nconst hasMark = (state: EditorState, type: MarkType) => {\n if (!type) {\n return false\n }\n const { from, $from, to, empty } = state.selection\n if (empty) {\n return !!type.isInSet(state.storedMarks || $from.marks())\n }\n return state.doc.rangeHasMark(from, to, type)\n}\n\n/** Removes the stored link mark if one is active, letting the next keystroke\n * start un-linked text. Returns false so the Space still inserts a space. */\nexport const stopLinkCommand = $command('StopLink', (ctx) => () => {\n return (state, dispatch) => {\n const markType = linkSchema.type(ctx)\n const checkMark = hasMark(state, markType)\n if (checkMark) {\n dispatch?.(\n state.tr.removeStoredMark(markType).setMeta('addToHistory', false)\n )\n }\n return false\n }\n})\n\n/** Binds Space to the stop-link command. */\nexport const linkCustomKeymap = $useKeymap('linkCustomKeymap', {\n StopLink: {\n shortcuts: ['Space'],\n command: (ctx) => {\n const commands = ctx.get(commandsCtx)\n return () => commands.call(stopLinkCommand.key)\n }\n }\n})\n\nconst orphanLinkKey = new PluginKey('KUN_ORPHAN_LINK')\n\nconst clearOrphanLink = $prose(\n (ctx) =>\n new Plugin({\n key: orphanLinkKey,\n appendTransaction(_transactions, _oldState, newState) {\n const { storedMarks, selection } = newState\n if (!selection.empty || !storedMarks) {\n return null\n }\n const linkType = linkSchema.type(ctx)\n if (!linkType.isInSet(storedMarks)) {\n return null\n }\n // Still inside a link — keep the stored mark so typing continues it.\n if (linkType.isInSet(selection.$from.marks())) {\n return null\n }\n // Housekeeping: do not occupy an undo step of its own.\n return newState.tr\n .removeStoredMark(linkType)\n .setMeta('addToHistory', false)\n }\n })\n)\n\n/** The stop-link plugin bundle: the command, its Space keymap, and the orphan\n * cleanup. Pure. `$useKeymap` returns a `[ctx, shortcut]` tuple, so flatten\n * before use. */\nexport const createStopLinkPlugin = (): MilkdownPlugin[] =>\n [stopLinkCommand, linkCustomKeymap, clearOrphanLink].flat() as MilkdownPlugin[]\n","// Insert-link command — the click-to-insert behaviour over the commonmark `link`\n// MARK. The mark itself already exists (commonmark, so `[text](url)` round-trips\n// and pasted URLs autolink); this adds a command the toolbar / selection bubble\n// call to apply it. Standard markdown `[text](url)`.\n//\n// A link is a MARK (inline formatting on text) — deliberately distinct from the\n// custom NODE embeds (mention, quote) that follow the schema + toUrl/fromUrl\n// pattern. A rich \"article card\" would be a node like those, not this.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { normalizeLinkHref } from '../../href'\n\nexport interface InsertLinkPayload {\n /**\n * The URL. Required — a blank href is a no-op. Normalized on the way in, so a\n * schemeless host gets one: `www.a.com/x` → `https://www.a.com/x`. See\n * {@link normalizeLinkHref} for the exact rules.\n */\n href: string\n /** Text to insert + link when the selection is empty. Defaults to the href. */\n text?: string\n}\n\n/**\n * Apply the `link` mark with `href` to the selection; on an EMPTY selection,\n * insert `text` (or the href) and link that. Clears the stored mark afterwards so\n * typing past the link isn't linked (same intent as the stop-link keymap).\n *\n * The href is normalized here — this command is the single funnel every link\n * entry point (bubble, toolbar, host `linkPrompt`) goes through, so a UI never\n * has to, and every one of them behaves the same.\n */\nexport const insertLinkCommand = $command(\n 'InsertKunLink',\n (ctx) =>\n (payload?: InsertLinkPayload) =>\n (state, dispatch) => {\n const href = normalizeLinkHref(payload?.href ?? '')\n if (!href) {\n return false\n }\n const markType = linkSchema.type(ctx)\n const mark = markType.create({ href })\n const { from, to, empty } = state.selection\n if (empty) {\n const text = payload?.text?.trim() || href\n const tr = state.tr.insertText(text, from)\n tr.addMark(from, from + text.length, mark)\n tr.removeStoredMark(markType)\n dispatch?.(tr.scrollIntoView())\n } else {\n dispatch?.(state.tr.addMark(from, to, mark).scrollIntoView())\n }\n return true\n }\n)\n\n/** The link plugin bundle: the insert-link command. */\nexport const createLinkPlugin = (): MilkdownPlugin[] => [insertLinkCommand].flat()\n","// Absolute block-type command for a \"text size\" dropdown.\n//\n// commonmark ships `wrapInHeadingCommand` (a TOGGLE) but no \"set paragraph\"\n// command, so a heading dropdown (Paragraph / H1–H6, where each option sets one\n// exact level and Paragraph resets) can't be built from it. `setHeadingCommand`\n// sets the block type ABSOLUTELY: level 0 → paragraph, 1–6 → heading — the same\n// `setBlockType` approach the forum's header dropdown uses, exposed as a proper\n// command so a headless or KunUI toolbar drives it via `run(setHeadingCommand.key,\n// level)`. It's idempotent (re-selecting the current level is a no-op), unlike the\n// toggle which would flip a heading back to a paragraph.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command } from '@milkdown/kit/utils'\nimport { setBlockType } from '@milkdown/kit/prose/commands'\nimport { headingSchema, paragraphSchema } from '@milkdown/kit/preset/commonmark'\n\n/** Set the current block to a paragraph (`level` 0, the default) or a heading\n * (`level` 1–6). */\nexport const setHeadingCommand = $command(\n 'SetHeadingKun',\n (ctx) =>\n (level: number = 0) =>\n level >= 1 && level <= 6\n ? setBlockType(headingSchema.type(ctx), { level })\n : setBlockType(paragraphSchema.type(ctx))\n)\n\n/** The heading command bundle — no schema (commonmark owns paragraph/heading). */\nexport const createHeadingPlugin = (): MilkdownPlugin[] =>\n [setHeadingCommand].flat()\n","import { codeBlockSchema } from '@milkdown/kit/preset/commonmark'\n\n/// Extends commonmark's code-block schema so a fenced block whose language is\n/// `latex` serializes back to a `$$…$$` math block instead of a ``` fence. The\n/// parse direction is handled by remarkMathBlock (math mdast → code node).\nexport const blockKatexSchema = codeBlockSchema.extendSchema((prev) => {\n return (ctx) => {\n const baseSchema = prev(ctx)\n return {\n ...baseSchema,\n toMarkdown: {\n match: baseSchema.toMarkdown.match,\n runner: (state, node) => {\n const language = node.attrs.language ?? ''\n if (language.toLowerCase() === 'latex') {\n state.addNode(\n 'math',\n undefined,\n node.content.firstChild?.text || ''\n )\n } else {\n return baseSchema.toMarkdown.runner(state, node)\n }\n }\n }\n }\n }\n})\n","import { $nodeSchema } from '@milkdown/kit/utils'\nimport katex from 'katex'\n\nexport const mathInlineId = 'math_inline'\n\n/// Schema for the inline math node. Adds support for:\n///\n/// ```markdown\n/// $a^2 + b^2 = c^2$\n/// ```\n///\n/// The `value` attr holds the raw LaTeX; `toDOM` renders it with KaTeX. Pure\n/// mechanism — `katex` is an (optional) peer the host installs.\nexport const mathInlineSchema = $nodeSchema(mathInlineId, () => ({\n group: 'inline',\n inline: true,\n draggable: true,\n atom: true,\n attrs: {\n value: {\n default: ''\n }\n },\n parseDOM: [\n {\n tag: `span[data-type=\"${mathInlineId}\"]`,\n getAttrs: (dom) => {\n return {\n value: (dom as HTMLElement).dataset.value ?? ''\n }\n }\n }\n ],\n toDOM: (node) => {\n const code: string = node.attrs.value\n const dom = document.createElement('span')\n dom.dataset.type = mathInlineId\n dom.dataset.value = code\n katex.render(code, dom, {\n throwOnError: false\n })\n\n return dom\n },\n parseMarkdown: {\n match: (node) => node.type === 'inlineMath',\n runner: (state, node, type) => {\n state.addNode(type, { value: node.value as string })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === mathInlineId,\n runner: (state, node) => {\n state.addNode('inlineMath', undefined, node.attrs.value)\n }\n }\n}))\n","import type { Node } from '@milkdown/kit/prose/model'\n\nimport { findNodeInSelection } from '@milkdown/kit/prose'\nimport { NodeSelection, TextSelection } from '@milkdown/kit/prose/state'\nimport { $command } from '@milkdown/kit/utils'\n\nimport { mathInlineSchema } from './inlineKatex'\n\n/// Toggles the selection between inline math and plain text: wraps selected\n/// text in a math node, or unwraps an existing math node back to its source.\nexport const toggleLatexCommand = $command('ToggleLatex', (ctx) => {\n return () => (state, dispatch) => {\n const {\n hasNode: hasLatex,\n pos: latexPos,\n target: latexNode\n } = findNodeInSelection(state, mathInlineSchema.type(ctx))\n\n const { selection, doc, tr } = state\n if (!hasLatex) {\n const text = doc.textBetween(selection.from, selection.to)\n const _tr = tr.replaceSelectionWith(\n mathInlineSchema.type(ctx).create({\n value: text\n })\n )\n if (dispatch) {\n dispatch(\n _tr.setSelection(NodeSelection.create(_tr.doc, selection.from))\n )\n }\n return true\n }\n\n const { from, to } = selection\n if (!latexNode || latexPos < 0) return false\n\n let _tr = tr.delete(latexPos, latexPos + 1)\n const content = (latexNode as Node).attrs.value\n _tr = _tr.insertText(content, latexPos)\n if (dispatch) {\n dispatch(\n _tr.setSelection(\n TextSelection.create(_tr.doc, from, to + content.length - 1)\n )\n )\n }\n return true\n }\n})\n","import { codeBlockSchema } from '@milkdown/kit/preset/commonmark'\nimport { nodeRule } from '@milkdown/kit/prose'\nimport { textblockTypeInputRule } from '@milkdown/kit/prose/inputrules'\nimport { $inputRule } from '@milkdown/kit/utils'\nimport { TextSelection } from '@milkdown/kit/prose/state'\n\nimport { mathInlineSchema } from './inlineKatex'\n\n/// Typing `$…$` becomes an inline math atom.\nexport const mathInlineInputRule = $inputRule((ctx) =>\n nodeRule(/(?:\\$)([^$]+)(?:\\$)$/, mathInlineSchema.type(ctx), {\n getAttr: (match) => ({ value: match[1] ?? '' }),\n beforeDispatch: ({ tr, start }) => {\n // After replaceRangeWith, insert a zero-width space after the inline math\n // atom so ProseMirror doesn't need a trailing <br>, avoiding a caret\n // newline.\n const posAfter = start + 1\n tr.insertText('', posAfter, posAfter)\n // Move selection after the ZWSP so the caret sits right after the math.\n tr.setSelection(TextSelection.create(tr.doc, posAfter + 1))\n }\n })\n)\n\n/// Typing `$$` + Enter/Space opens a LaTeX code block (rendered as a math block).\nexport const mathBlockInputRule = $inputRule((ctx) =>\n textblockTypeInputRule(/^\\$\\$[\\s\\n]$/, codeBlockSchema.type(ctx), () => ({\n language: 'LaTeX'\n }))\n)\n","import type { Node } from '@milkdown/kit/transformer'\nimport { $remark } from '@milkdown/kit/utils'\nimport remarkMath from 'remark-math'\nimport { visit } from 'unist-util-visit'\n\n/// The remark-math plugin: parses `$…$` / `$$…$$` into mdast `inlineMath` /\n/// `math` nodes and stringifies them back. Both directions come from remark-math.\nexport const remarkMathPlugin = $remark<'remarkMath', undefined>(\n 'remarkMath',\n () => remarkMath\n)\n\nconst visitMathBlock = (ast: Node) => {\n return visit(\n ast,\n 'math',\n (\n node: Node & { value: string },\n index: number,\n parent: Node & { children: Node[] }\n ) => {\n const { value } = node as Node & { value: string }\n const newNode = {\n type: 'code',\n lang: 'LaTeX',\n value\n }\n parent.children.splice(index, 1, newNode as unknown as Node)\n }\n )\n}\n\n/// Rewrites block `math` mdast nodes into `code` nodes with lang `LaTeX` on\n/// parse, so a `$$…$$` block enters the editor as a code block. blockKatex\n/// serializes it back to `math` (→ `$$…$$`).\nexport const remarkMathBlockPlugin = $remark(\n 'remarkMathBlock',\n () => () => visitMathBlock\n)\n","// KaTeX plugin set — inline `$…$` and block `$$…$$` LaTeX.\n//\n// Ported from the forum's plugins/katex/*. Pure mechanism; `katex` is an\n// (optional) peer and `remark-math` a runtime dependency. The plugins must be\n// used AFTER the commonmark preset (blockKatex extends its code-block schema),\n// which createKunEditorPlugins guarantees.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\n\nimport { blockKatexSchema } from './blockKatex'\nimport { toggleLatexCommand } from './command'\nimport { mathInlineSchema } from './inlineKatex'\nimport { mathBlockInputRule, mathInlineInputRule } from './inputRule'\nimport { remarkMathBlockPlugin, remarkMathPlugin } from './remark'\n\nexport { blockKatexSchema } from './blockKatex'\nexport { toggleLatexCommand } from './command'\nexport { mathInlineId, mathInlineSchema } from './inlineKatex'\nexport { mathBlockInputRule, mathInlineInputRule } from './inputRule'\nexport { remarkMathBlockPlugin, remarkMathPlugin } from './remark'\n\n/**\n * The KaTeX plugin bundle, in dependency order: remark parse/serialize, the\n * inline math node, the `$…$` / `$$` input rules, the block-LaTeX serializer\n * and the toggle command. Pure — no adapter needed.\n */\nexport const createKatexPlugins = (): MilkdownPlugin[] =>\n [\n remarkMathPlugin,\n remarkMathBlockPlugin,\n mathInlineSchema,\n mathInlineInputRule,\n mathBlockInputRule,\n blockKatexSchema,\n toggleLatexCommand\n ].flat() as MilkdownPlugin[]\n","// CodeMirror theme + syntax highlight for the code block (WYSIWYG) editor.\n// Ported from the forum's codemirror/theme.ts. Colours reference KunUI CSS\n// variables so the code block matches the host theme (the render layer ships\n// the vars). Pure config — `@codemirror/*` and `@lezer/highlight` are (optional)\n// peers the host installs when the code-block feature is enabled.\nimport { EditorView } from '@codemirror/view'\nimport { HighlightStyle, syntaxHighlighting } from '@codemirror/language'\nimport { tags as t } from '@lezer/highlight'\nimport type { Extension } from '@codemirror/state'\n\nconst colors = {\n primary: 'var(--color-primary)',\n selected: 'color-mix(in oklab,var(--color-primary)10%,transparent)',\n primaryLight: 'var(--color-primary-400)',\n primaryDark: 'var(--color-primary-600)',\n secondary: 'var(--color-secondary)',\n secondaryLight: 'var(--color-secondary-400)',\n success: 'var(--color-success)',\n successLight: 'var(--color-success-400)',\n warning: 'var(--color-warning)',\n warningLight: 'var(--color-warning-400)',\n danger: 'var(--color-danger)',\n dangerLight: 'var(--color-danger-400)',\n foreground: 'var(--color-foreground)',\n background: 'var(--color-background)',\n backgroundAlpha: 'var(--color-background) / 0.7',\n overlay: 'var(--color-default-200)',\n overlayLight: 'var(--color-default-100)',\n divider: 'var(--color-default-100)',\n content1: 'var(--color-content1)',\n content2: 'var(--color-content2)',\n content3: 'var(--color-content3)',\n content4: 'var(--color-content4)'\n}\n\nexport const kunCMTheme = () => {\n return EditorView.theme({\n '&': {\n backgroundColor: colors.backgroundAlpha,\n borderRadius: '0.75rem',\n lineHeight: '1.5',\n scrollbarWidth: 'none',\n minHeight: '300px'\n },\n\n '&.cm-focused': {\n outline: 'none'\n },\n\n '.cm-scroller': {\n lineHeight: '1.5',\n maxWidth: '100%',\n scrollbarWidth: 'none'\n },\n\n '.cm-content': {\n padding: '1rem 0.5rem',\n maxWidth: '100%'\n },\n\n '.cm-line': {\n padding: '0.2rem 0',\n borderRadius: '0.375rem',\n maxWidth: '100%',\n fontSize: '1rem',\n '&:hover': {\n backgroundColor: colors.overlayLight\n }\n },\n\n '&.cm-focused .cm-cursor': {\n borderLeftColor: colors.primary,\n borderLeftWidth: '2px'\n },\n\n '.cm-panels': {\n backgroundColor: colors.background,\n color: colors.foreground,\n borderRadius: '0.5rem',\n margin: '0.5rem'\n },\n '.cm-panels.cm-panels-top': {\n borderBottom: `1px solid ${colors.divider}`\n },\n '.cm-panels.cm-panels-bottom': {\n borderTop: `1px solid ${colors.divider}`\n },\n\n '.cm-searchMatch': {\n backgroundColor: `${colors.primaryLight}50`,\n outline: `1px solid ${colors.primaryLight}`,\n borderRadius: '2px'\n },\n '.cm-searchMatch.cm-searchMatch-selected': {\n backgroundColor: `${colors.primary}40`\n },\n\n '.cm-activeLine': {\n backgroundColor: `${colors.content1}30`,\n borderRadius: '0.375rem'\n },\n '.cm-selectionMatch': {\n backgroundColor: `${colors.primary}20`,\n borderRadius: '2px'\n },\n\n '.cm-matchingBracket, .cm-nonmatchingBracket': {\n backgroundColor: `${colors.warning}30`,\n outline: 'none',\n borderRadius: '2px',\n padding: '0 1px',\n fontWeight: '600'\n },\n\n '.cm-gutters': {\n backgroundColor: 'transparent',\n border: 'none',\n borderRadius: '0',\n fontSize: '1rem',\n padding: '0'\n },\n\n '.cm-lineNumbers': {\n color: colors.content3\n },\n\n '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':\n {\n backgroundColor: colors.selected\n },\n\n '.cm-activeLineGutter': {\n backgroundColor: colors.selected\n },\n\n '.cm-foldGutter': {\n color: colors.content3\n },\n\n '.cm-tooltip': {\n backgroundColor: colors.background,\n border: `1px solid ${colors.divider}`,\n borderRadius: '0.5rem',\n boxShadow:\n '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',\n overflow: 'hidden'\n },\n\n '.cm-tooltip-autocomplete': {\n '& > ul': {\n fontSize: '0.9rem',\n maxHeight: '20rem'\n },\n '& > ul > li': {\n padding: '0.375rem 0.75rem',\n borderRadius: '0.25rem'\n },\n '& > ul > li[aria-selected]': {\n backgroundColor: colors.content1,\n color: colors.foreground\n }\n },\n\n '&::-webkit-scrollbar': {\n width: '6px',\n height: '6px'\n },\n '&::-webkit-scrollbar-track': {\n background: 'transparent'\n },\n '&::-webkit-scrollbar-thumb': {\n backgroundColor: colors.content3,\n borderRadius: '3px',\n '&:hover': {\n backgroundColor: colors.content2\n }\n }\n })\n}\n\nexport const kunCMHighlightStyle = () =>\n HighlightStyle.define([\n // Keywords and control flow\n { tag: t.keyword, color: colors.primary, fontWeight: '600' },\n { tag: t.controlKeyword, color: colors.primary, fontWeight: '600' },\n { tag: t.moduleKeyword, color: colors.primary, fontWeight: '600' },\n\n // Variables and properties\n { tag: [t.propertyName, t.macroName], color: colors.secondary },\n { tag: t.variableName, color: colors.foreground },\n {\n tag: t.definition(t.variableName),\n color: colors.secondary,\n fontWeight: '600'\n },\n\n // Functions\n {\n tag: [t.function(t.variableName), t.labelName],\n color: colors.success,\n fontWeight: '500'\n },\n {\n tag: t.definition(t.function(t.variableName)),\n color: colors.success,\n fontWeight: '600'\n },\n\n // Types and classes\n {\n tag: [t.typeName, t.className, t.namespace],\n color: colors.warning,\n fontWeight: '500'\n },\n { tag: [t.annotation, t.modifier], color: colors.warningLight },\n\n // Constants and literals\n {\n tag: [t.number, t.bool, t.null],\n color: colors.secondary,\n fontWeight: '500'\n },\n { tag: t.string, color: colors.success },\n { tag: t.regexp, color: colors.warning },\n\n // Special syntax\n { tag: [t.meta, t.comment], color: colors.foreground, fontStyle: 'italic' },\n { tag: t.tagName, color: colors.primary, fontWeight: '500' },\n { tag: t.attributeName, color: colors.warning },\n\n // Markdown specific\n { tag: t.heading, color: colors.primary, fontWeight: '700' },\n {\n tag: [t.url, t.link],\n color: colors.success,\n textDecoration: 'underline'\n },\n { tag: t.emphasis, fontStyle: 'italic' },\n { tag: t.strong, fontWeight: '700' },\n\n // Special cases\n {\n tag: t.invalid,\n color: colors.danger,\n borderBottom: `2px dotted ${colors.danger}`\n },\n { tag: t.changed, color: colors.warning },\n { tag: t.inserted, color: colors.success },\n { tag: t.deleted, color: colors.danger }\n ])\n\n/** The KUN CodeMirror theme: base theme + syntax highlighting. */\nexport const kunCM = (): Extension => [\n kunCMTheme(),\n syntaxHighlighting(kunCMHighlightStyle())\n]\n","// SVG icon strings for the code-block toolbar (expand / search / clear / copy /\n// edit / hide). Ported verbatim from the forum's plugins/code/icons.ts. These\n// are inline SVG so the code-block component (a web component) can render them\n// without a framework icon dependency.\n\nexport const chevronDownIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-6 h-6\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\"\n />\n </svg>\n`\n\nexport const clearIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n >\n <g clip-path=\"url(#clip0_1098_15553)\">\n <path\n d=\"M18.3007 5.70973C17.9107 5.31973 17.2807 5.31973 16.8907 5.70973L12.0007 10.5897L7.1107 5.69973C6.7207 5.30973 6.0907 5.30973 5.7007 5.69973C5.3107 6.08973 5.3107 6.71973 5.7007 7.10973L10.5907 11.9997L5.7007 16.8897C5.3107 17.2797 5.3107 17.9097 5.7007 18.2997C6.0907 18.6897 6.7207 18.6897 7.1107 18.2997L12.0007 13.4097L16.8907 18.2997C17.2807 18.6897 17.9107 18.6897 18.3007 18.2997C18.6907 17.9097 18.6907 17.2797 18.3007 16.8897L13.4107 11.9997L18.3007 7.10973C18.6807 6.72973 18.6807 6.08973 18.3007 5.70973Z\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_1098_15553\">\n <rect width=\"24\" height=\"24\" />\n </clipPath>\n </defs>\n </svg>\n`\n\nexport const copyIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"24px\"\n viewBox=\"0 -960 960 960\"\n width=\"24px\"\n fill=\"none\"\n >\n <path\n d=\"M360-240q-33 0-56.5-23.5T280-320v-480q0-33 23.5-56.5T360-880h360q33 0 56.5 23.5T800-800v480q0 33-23.5 56.5T720-240H360Zm0-80h360v-480H360v480ZM200-80q-33 0-56.5-23.5T120-160v-560h80v560h440v80H200Zm160-240v-480 480Z\"\n />\n </svg>\n`\n\nexport const editIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n >\n <g clip-path=\"url(#clip0_1013_1585)\">\n <path\n d=\"M14.06 9.02L14.98 9.94L5.92 19H5V18.08L14.06 9.02ZM17.66 3C17.41 3 17.15 3.1 16.96 3.29L15.13 5.12L18.88 8.87L20.71 7.04C21.1 6.65 21.1 6.02 20.71 5.63L18.37 3.29C18.17 3.09 17.92 3 17.66 3ZM14.06 6.19L3 17.25V21H6.75L17.81 9.94L14.06 6.19Z\"\n />\n </g>\n <defs>\n <clipPath id=\"clip0_1013_1585\">\n <rect width=\"24\" height=\"24\" />\n </clipPath>\n </defs>\n </svg>\n`\n\nexport const searchIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-6 h-6\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\"\n />\n </svg>\n`\n\nexport const visibilityOffIcon = `\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n height=\"24px\"\n viewBox=\"0 -960 960 960\"\n width=\"24px\"\n >\n <path\n d=\"m644-428-58-58q9-47-27-88t-93-32l-58-58q17-8 34.5-12t37.5-4q75 0 127.5 52.5T660-500q0 20-4 37.5T644-428Zm128 126-58-56q38-29 67.5-63.5T832-500q-50-101-143.5-160.5T480-720q-29 0-57 4t-55 12l-62-62q41-17 84-25.5t90-8.5q151 0 269 83.5T920-500q-23 59-60.5 109.5T772-302Zm20 246L624-222q-35 11-70.5 16.5T480-200q-151 0-269-83.5T40-500q21-53 53-98.5t73-81.5L56-792l56-56 736 736-56 56ZM222-624q-29 26-53 57t-41 67q50 101 143.5 160.5T480-280q20 0 39-2.5t39-5.5l-36-38q-11 3-21 4.5t-21 1.5q-75 0-127.5-52.5T300-500q0-11 1.5-21t4.5-21l-84-82Zm319 93Zm-151 75Z\"\n />\n </svg>\n`\n","// Code block (CodeMirror) — Milkdown's code-block component wired with the KUN\n// CodeMirror theme, language list, toolbar icons, localized labels and a KaTeX\n// preview for `latex` blocks.\n//\n// Ported from the forum's Editor.vue codeBlockConfig wiring + plugins/code/*.\n// Pure mechanism: the CodeMirror packages and `katex` are (optional) peers the\n// host installs when the code-block feature is on. Labels are localized via the\n// `locale` option (mechanism owns the strings, the host picks the language).\nimport type { Ctx, MilkdownPlugin } from '@milkdown/kit/ctx'\nimport {\n codeBlockComponent,\n codeBlockConfig\n} from '@milkdown/kit/component/code-block'\nimport { defaultKeymap, indentWithTab } from '@codemirror/commands'\nimport { EditorView, keymap } from '@codemirror/view'\nimport { languages } from '@codemirror/language-data'\nimport type { Extension } from '@codemirror/state'\nimport { basicSetup } from 'codemirror'\nimport katex from 'katex'\nimport type { KatexOptions } from 'katex'\n\nimport type { KunEditorLocale } from '../../types'\nimport { kunCM } from './theme'\nimport {\n chevronDownIcon,\n clearIcon,\n copyIcon,\n editIcon,\n searchIcon,\n visibilityOffIcon\n} from './icons'\n\nexport { kunCM, kunCMTheme, kunCMHighlightStyle } from './theme'\nexport * from './icons'\n\n/** Options for the code-block plugin. All optional. */\nexport interface CodeBlockOptions {\n /** UI language for the toolbar labels. Default: `'zh-cn'`. */\n locale?: KunEditorLocale\n /** KaTeX options for the `latex` block preview. */\n katexOptions?: KatexOptions\n /** Extra CodeMirror extensions appended after the KUN defaults. */\n extensions?: Extension[]\n /** Called when the user copies a code block. */\n onCopy?: (text: string) => void\n}\n\ninterface CodeBlockLabels {\n searchPlaceholder: string\n copyText: string\n noResultText: string\n previewLoading: string\n edit: string\n hide: string\n}\n\n// The forum's playful zh-cn strings (\"搜索咒文\"/\"复制咒文\" — galgame flavor) are the\n// default; en-us is the neutral fallback for other hosts.\nconst LABELS: Record<'zh-cn' | 'en-us', CodeBlockLabels> = {\n 'zh-cn': {\n searchPlaceholder: '搜索咒文',\n copyText: '复制咒文',\n noResultText: '无结果',\n previewLoading: '加载中...',\n edit: '编辑',\n hide: '隐藏'\n },\n 'en-us': {\n searchPlaceholder: 'Search language',\n copyText: 'Copy',\n noResultText: 'No results',\n previewLoading: 'Loading...',\n edit: 'Edit',\n hide: 'Hide'\n }\n}\n\nconst labelsFor = (locale: KunEditorLocale | undefined): CodeBlockLabels =>\n locale && locale.toLowerCase().startsWith('en')\n ? LABELS['en-us']\n : LABELS['zh-cn']\n\n/**\n * Applies the KUN code-block config to a Milkdown ctx: CodeMirror extensions,\n * the language list, toolbar icons, localized labels, and a KaTeX preview for\n * `latex` blocks. Call inside a plugin runner or `.config()` — after\n * `codeBlockComponent` has registered its config slice.\n */\nexport const applyCodeBlockConfig = (\n ctx: Ctx,\n options: CodeBlockOptions = {}\n): void => {\n const labels = labelsFor(options.locale)\n const onCopy = options.onCopy ?? (() => {})\n\n ctx.update(codeBlockConfig.key, (prev) => ({\n ...prev,\n extensions: [\n kunCM(),\n EditorView.lineWrapping,\n keymap.of(defaultKeymap.concat(indentWithTab)),\n basicSetup,\n ...(options.extensions ?? [])\n ],\n languages,\n expandIcon: chevronDownIcon,\n searchIcon,\n clearSearchIcon: clearIcon,\n searchPlaceholder: labels.searchPlaceholder,\n copyText: labels.copyText,\n copyIcon,\n onCopy,\n noResultText: labels.noResultText,\n previewLoading: labels.previewLoading,\n // Render `latex` code blocks as rendered math; defer everything else to the\n // component default.\n renderPreview: (language, content, applyPreview) => {\n if (language.toLowerCase() === 'latex' && content.length > 0) {\n return katex.renderToString(content, {\n ...options.katexOptions,\n throwOnError: false,\n displayMode: true\n })\n }\n return prev.renderPreview(language, content, applyPreview)\n },\n previewToggleButton: (previewOnlyMode) => {\n const icon = previewOnlyMode ? editIcon : visibilityOffIcon\n const text = previewOnlyMode ? labels.edit : labels.hide\n return [icon, text].map((v) => v.trim()).join(' ')\n }\n }))\n}\n\n/** A Milkdown plugin that applies the code-block config on setup. Bundled into\n * `createCodeBlockPlugins` so the render layer needs no separate config call. */\nconst codeBlockConfigPlugin =\n (options: CodeBlockOptions): MilkdownPlugin =>\n (ctx) =>\n () => {\n applyCodeBlockConfig(ctx, options)\n }\n\n/**\n * The code-block plugin bundle: Milkdown's `codeBlockComponent` plus the KUN\n * config (CodeMirror theme/languages/icons/labels + KaTeX preview). Pure — the\n * CodeMirror + katex peers must be installed when this feature is enabled.\n */\nexport const createCodeBlockPlugins = (\n options: CodeBlockOptions = {}\n): MilkdownPlugin[] => [...codeBlockComponent, codeBlockConfigPlugin(options)]\n","// @mention plugin — the inline mention atom + its markdown round-trip.\n//\n// The stored markdown form is an ordinary link whose URL the server renders into\n// a mention chip (and parses for notifications). The DEFAULT form is\n// `[@name](kungal-user:<id>)`, but the URL shape is host POLICY — the KUN server\n// uses `kungal-user:`, moyu uses a real `/user/<id>/…` link, another host could\n// use something else. So it's injectable via `toUrl` / `fromUrl` (mechanism vs\n// policy — see docs/architecture.md); the hardcoded scheme was the one thing\n// that stopped a host with a different mention link form from adopting the editor.\n//\n// A markdown link is a MARK (not a node) in milkdown, so a node schema that\n// matched links would fight the commonmark link mark. Instead — like spoiler — a\n// $remark transformer rewrites the matching link mdast nodes into a custom\n// `mention` node on PARSE; toMarkdown emits a plain link back.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport type { Node } from '@milkdown/kit/transformer'\nimport { $command, $nodeSchema, $remark } from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\nimport { MENTION_SCHEME } from '../../index'\n\nexport const mentionId = 'mention'\n\n/**\n * How an @mention's user id maps TO / FROM its markdown link URL — host policy.\n * Default: the `kungal-user:<id>` scheme (shared with the KUN server).\n */\nexport interface MentionUrlConfig {\n /** Build the link URL for a mention of `userId`. */\n toUrl?: (userId: number) => string\n /**\n * Parse a link back to a user id, or `null` if it isn't a mention. Gets the\n * link URL AND its plain text, so a host can replicate text-based guards — e.g.\n * moyu treats `/user/<id>` as a mention only when the link text starts with\n * `@`, so `[see here](/user/5/x)` stays a plain link.\n */\n fromUrl?: (url: string, text: string) => number | null\n}\n\nconst defaultToUrl = (userId: number): string => `${MENTION_SCHEME}${userId}`\nconst defaultFromUrl = (url: string): number | null => {\n if (!url.startsWith(MENTION_SCHEME)) return null\n const id = Number.parseInt(url.slice(MENTION_SCHEME.length), 10)\n return Number.isInteger(id) && id > 0 ? id : null\n}\n\n// Minimal shape of the mdast nodes we touch (link on the way in, our synthetic\n// `mention` node on the way out).\ninterface MdastNode extends Node {\n type: string\n url?: string\n value?: string\n userId?: number\n name?: string\n children?: MdastNode[]\n}\n\n/** The mention node schema; `toUrl` decides the serialized link URL. */\nconst makeMentionSchema = (toUrl: (userId: number) => string) =>\n $nodeSchema(mentionId, () => ({\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n userId: { default: 0 },\n name: { default: '' }\n },\n parseDOM: [\n {\n // Pasted rendered content (server emits <a class=\"kun-mention\" data-uid>).\n tag: 'a.kun-mention',\n getAttrs: (dom) => {\n const el = dom as HTMLElement\n return {\n userId: Number.parseInt(el.dataset.uid ?? '0', 10) || 0,\n name: (el.textContent ?? '').replace(/^@/, '')\n }\n }\n }\n ],\n toDOM: (node) => {\n // A non-navigating span chip inside the editor (a real <a> would steal the\n // click and leave the page mid-compose). data-uid mirrors the server form.\n const span = document.createElement('span')\n span.className = 'kun-mention'\n span.dataset.uid = String(node.attrs.userId)\n span.setAttribute('contenteditable', 'false')\n span.textContent = `@${node.attrs.name}`\n return span\n },\n parseMarkdown: {\n match: (node) => node.type === mentionId,\n runner: (state, node, type) => {\n const n = node as MdastNode\n state.addNode(type, { userId: n.userId ?? 0, name: n.name ?? '' })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === mentionId,\n runner: (state, node) => {\n state.openNode('link', undefined, { url: toUrl(node.attrs.userId) })\n state.addNode('text', undefined, `@${node.attrs.name}`)\n state.closeNode()\n }\n }\n }))\n\n/** Rewrites links that `fromUrl` recognizes as mentions into mention nodes. */\nconst makeRemarkMention = (\n fromUrl: (url: string, text: string) => number | null\n) =>\n $remark('remarkMention', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'link', (node: MdastNode, index, parent: MdastNode) => {\n if (typeof node.url !== 'string') {\n return\n }\n // The link's plain text, so fromUrl can apply text-based guards (e.g.\n // moyu requires the text to start with `@`). Concatenated across children\n // to be robust to `[**@name**](url)` etc.\n const text = (node.children ?? [])\n .map((child) => (typeof child.value === 'string' ? child.value : ''))\n .join('')\n const userId = fromUrl(node.url, text)\n if (userId == null) {\n return\n }\n const name = text.replace(/^@/, '')\n if (typeof index === 'number' && parent.children) {\n parent.children.splice(index, 1, {\n type: mentionId,\n userId,\n name\n } as MdastNode)\n }\n })\n }\n return transformer\n })\n\n/** Default (kungal-user:) mention schema — for advanced direct use. */\nexport const mentionSchema = makeMentionSchema(defaultToUrl)\n/** Default (kungal-user:) mention remark transform — for advanced direct use. */\nexport const remarkMentionPlugin = makeRemarkMention(defaultFromUrl)\n\n/**\n * Insert a mention chip at the cursor, replacing the selection. The render-layer\n * dropdown usually replaces the `@query` range itself; this is the programmatic\n * path (toolbar / tests / the imperative insertMention handle). A trailing space\n * lets the caret continue past the atom naturally. Resolves the node type by id\n * from the live schema, so it works with any mention config.\n */\nexport const insertMentionCommand = $command(\n 'InsertKunMention',\n () =>\n (payload?: { userId: number; name: string }) =>\n (state, dispatch) => {\n if (!payload || !dispatch) {\n return false\n }\n const { userId, name } = payload\n if (!Number.isInteger(userId) || userId <= 0) {\n return false\n }\n const type = state.schema.nodes[mentionId]\n if (!type) {\n return false\n }\n const node = type.create({ userId, name })\n const tr = state.tr.replaceSelectionWith(node)\n tr.insertText(' ')\n dispatch(tr.scrollIntoView())\n return true\n }\n)\n\n/**\n * The mention plugin bundle: schema + remark round-trip + insert command. Pass\n * `toUrl` / `fromUrl` to use a host-specific mention link form; omit for the\n * default `kungal-user:` scheme. The `searchMentionUsers` adapter (the `@`\n * autocomplete) is consumed by the render-layer dropdown.\n */\nexport const createMentionPlugin = (\n config: MentionUrlConfig = {}\n): MilkdownPlugin[] => {\n const schema = config.toUrl ? makeMentionSchema(config.toUrl) : mentionSchema\n const remark = config.fromUrl\n ? makeRemarkMention(config.fromUrl)\n : remarkMentionPlugin\n return [schema, remark, insertMentionCommand].flat()\n}\n","// Quote / inline-reference plugin — a non-editable inline atom that points at\n// something the HOST defines (a reply, a comment, …).\n//\n// Ported from the forum's plugins/quote/quotePlugin.ts, but GENERALIZED per\n// docs/architecture.md § the reply-quote question (option 1): the forum's\n// `{ replyId, floor }` becomes an opaque `{ refId, label }`. The editor owns the\n// mechanism — a stable inline atom with a trailing-caret insert — while the host\n// owns what a reference means (it supplies refId + the display label).\n//\n// Stored markdown form: `[label](kungal-reply:<refId>)` — an ordinary link whose\n// custom `kungal-reply:` scheme the server renders into a quote card. Same shape\n// as the mention plugin: a $remark transformer rewrites matching links into a\n// `quote` node on PARSE; toMarkdown emits a plain link back.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport type { Node } from '@milkdown/kit/transformer'\nimport { $command, $nodeSchema, $remark } from '@milkdown/kit/utils'\nimport { visit } from 'unist-util-visit'\nimport type { Node as UnistNode } from 'unist'\n\nimport { QUOTE_SCHEME } from '../../index'\n\nexport const quoteId = 'quote'\n\n/** The payload a host passes to insert a reference. `refId` is opaque (the host\n * decides its meaning); `label` is what the chip shows. */\nexport interface QuoteReference {\n refId: string\n label: string\n}\n\n// Minimal shape of the mdast nodes we touch (link on the way in, our synthetic\n// `quote` node on the way out).\ninterface MdastNode extends Node {\n type: string\n url?: string\n value?: string\n refId?: string\n label?: string\n children?: MdastNode[]\n}\n\nexport const quoteSchema = $nodeSchema(quoteId, () => ({\n group: 'inline',\n inline: true,\n atom: true,\n attrs: {\n refId: { default: '' },\n label: { default: '' }\n },\n parseDOM: [\n {\n // Pasted rendered content (server emits <span class=\"kun-quote\" data-ref-id>).\n tag: 'span.kun-quote',\n getAttrs: (dom) => {\n const el = dom as HTMLElement\n return {\n refId: el.dataset.refId ?? '',\n label: el.textContent ?? ''\n }\n }\n }\n ],\n toDOM: (node) => {\n // A non-navigating span chip inside the editor; mirrors the server form so a\n // round-trip through paste/copy is lossless.\n const span = document.createElement('span')\n span.className = 'kun-quote'\n span.dataset.refId = String(node.attrs.refId)\n span.setAttribute('contenteditable', 'false')\n span.textContent = String(node.attrs.label)\n return span\n },\n parseMarkdown: {\n match: (node) => node.type === quoteId,\n runner: (state, node, type) => {\n const n = node as MdastNode\n state.addNode(type, { refId: n.refId ?? '', label: n.label ?? '' })\n }\n },\n toMarkdown: {\n match: (node) => node.type.name === quoteId,\n runner: (state, node) => {\n state.openNode('link', undefined, {\n url: `${QUOTE_SCHEME}${node.attrs.refId}`\n })\n state.addNode('text', undefined, String(node.attrs.label))\n state.closeNode()\n }\n }\n}))\n\n/** Rewrites `[label](kungal-reply:refId)` links into quote nodes on parse. */\nexport const remarkQuotePlugin = $remark('remarkQuote', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'link', (node: MdastNode, index, parent: MdastNode) => {\n if (typeof node.url !== 'string' || !node.url.startsWith(QUOTE_SCHEME)) {\n return\n }\n const refId = node.url.slice(QUOTE_SCHEME.length)\n if (!refId) {\n return\n }\n const first = node.children?.[0]\n const label = typeof first?.value === 'string' ? first.value : ''\n if (typeof index === 'number' && parent.children) {\n parent.children.splice(index, 1, {\n type: quoteId,\n refId,\n label\n } as MdastNode)\n }\n })\n }\n return transformer\n})\n\n/**\n * Insert a quote chip at the cursor, replacing the selection. The host supplies\n * `{ refId, label }`. A trailing space is the whole caret fix: a paragraph that\n * ENDS in a non-editable inline atom has no stable caret position after it, so\n * the next keystroke (esp. an IME composition) snaps to before the atom. A real\n * text node after it gives the caret somewhere to anchor.\n */\nexport const insertQuoteCommand = $command(\n 'InsertKunQuote',\n (ctx) =>\n (payload?: QuoteReference) =>\n (state, dispatch) => {\n if (!payload || !dispatch) {\n return false\n }\n const { refId, label } = payload\n if (!refId) {\n return false\n }\n const node = quoteSchema.type(ctx).create({ refId, label })\n if (!node) {\n return false\n }\n const tr = state.tr.replaceSelectionWith(node)\n tr.insertText(' ')\n dispatch(tr.scrollIntoView())\n return true\n }\n)\n\n/** The quote plugin bundle: schema + remark round-trip + insert command. */\nexport const createQuotePlugin = (): MilkdownPlugin[] =>\n [quoteSchema, remarkQuotePlugin, insertQuoteCommand].flat()\n","// Image upload plugin — paste / drop / toolbar image upload.\n//\n// Ported from the forum's plugins/upload/uploader.ts, generalized over the\n// `uploadImage` adapter. This is the plugin the architecture calls out as the\n// clearest mechanism-vs-policy split: the forum hardcoded\n// `kunFetch('/image/topic')`; here the host injects WHERE the upload goes, and\n// the editor owns the paste/drop wiring and the in-flight placeholder.\n//\n// Built on @milkdown/kit/plugin/upload: we set its `uploader` (per-image → url)\n// and `uploadWidgetFactory` (the \"uploading…\" placeholder) via ctx config,\n// bundled as a plugin so the render layer needs no separate config call.\nimport type { Ctx, MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { upload, uploadConfig } from '@milkdown/kit/plugin/upload'\nimport type { Uploader } from '@milkdown/kit/plugin/upload'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport { Decoration, DecorationSet } from '@milkdown/kit/prose/view'\nimport type { EditorView } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\nimport { $prose } from '@milkdown/kit/utils'\n\nimport type { KunEditorLocale, Notify, UploadImage } from '../../types'\n\n/** Options for the upload plugin. */\nexport interface UploadPluginOptions {\n /** UI language for the in-flight placeholder text. Default `'zh-cn'`. */\n locale?: KunEditorLocale\n /** Surface an \"upload failed\" notice per image. Omit to fail silently. */\n notify?: Notify\n}\n\nconst uploadingLabel = (locale: KunEditorLocale | undefined): string =>\n locale && locale.toLowerCase().startsWith('en') ? 'Uploading…' : '正在上传中...'\n\nconst uploadFailedLabel = (locale: KunEditorLocale | undefined): string =>\n locale && locale.toLowerCase().startsWith('en')\n ? 'Image upload failed'\n : '图片上传失败'\n\n/**\n * Build a Milkdown `Uploader` from the host's `uploadImage` adapter. Filters to\n * image files, uploads each via the adapter, and returns image nodes. A failed\n * image is skipped (and reported via `notify` if provided) instead of aborting\n * the whole batch — more robust than the forum's all-or-nothing Promise.all.\n */\nexport const createUploader = (\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): Uploader => {\n return async (files, schema) => {\n const images: File[] = []\n for (let i = 0; i < files.length; i++) {\n const file = files.item(i)\n if (!file || !file.type.startsWith('image/')) {\n continue\n }\n images.push(file)\n }\n\n const nodes = await Promise.all(\n images.map(async (image): Promise<Node | null> => {\n try {\n const src = await uploadImage(image)\n return schema.nodes.image!.createAndFill({\n src,\n alt: image.name\n }) as Node\n } catch {\n options.notify?.(uploadFailedLabel(options.locale), 'error')\n return null\n }\n })\n )\n\n return nodes.filter((node): node is Node => node !== null)\n }\n}\n\n/** Build the in-flight \"uploading…\" placeholder DOM — a `.kun-editor__uploading`\n * span (class hook, styled by the host stylesheet — headless). Shared by the\n * paste/drop path and the toolbar path so they look identical. */\nconst uploadingWidget = (locale: KunEditorLocale | undefined): HTMLElement => {\n const el = document.createElement('span')\n el.className = 'kun-editor__uploading'\n el.textContent = uploadingLabel(locale)\n return el\n}\n\n/** The in-flight \"uploading…\" placeholder shown at the drop position (paste/drop\n * path — Milkdown's `upload` plugin calls this). */\nexport const createUploadWidgetFactory = (options: UploadPluginOptions = {}) => {\n return (pos: number, spec: Parameters<typeof Decoration.widget>[2]) => {\n return Decoration.widget(pos, uploadingWidget(options.locale), spec)\n }\n}\n\n/** Applies the uploader + placeholder to a Milkdown ctx. Call after the `upload`\n * plugin has registered its config slice. */\nexport const applyUploadConfig = (\n ctx: Ctx,\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): void => {\n ctx.update(uploadConfig.key, (prev) => ({\n ...prev,\n uploader: createUploader(uploadImage, options),\n uploadWidgetFactory: createUploadWidgetFactory(options)\n }))\n}\n\nconst uploadConfigPlugin =\n (uploadImage: UploadImage, options: UploadPluginOptions): MilkdownPlugin =>\n (ctx) =>\n () => {\n applyUploadConfig(ctx, uploadImage, options)\n }\n\n/**\n * The image-upload plugin bundle: Milkdown's `upload` plugin plus the KUN config\n * (uploader over the `uploadImage` adapter + localized placeholder). Wire this\n * only when a host provides `uploadImage` — its absence is exactly how the\n * image-free editor (galgame 简介) is expressed.\n */\nexport const createUploadPlugin = (\n uploadImage: UploadImage,\n options: UploadPluginOptions = {}\n): MilkdownPlugin[] => [...upload, uploadConfigPlugin(uploadImage, options)]\n\n// ── Toolbar / programmatic upload (in-document placeholder) ─────────────────\n//\n// Milkdown's `upload` plugin only shows the in-flight placeholder for paste/drop\n// (it intercepts those DOM events). The toolbar's image button uploads a File\n// programmatically, so it gets no placeholder — the image just pops in when the\n// upload resolves. This mirrors ProseMirror's official \"upload\" example: a\n// DecorationSet plugin holds a widget placeholder (keyed by a unique id) that\n// maps through edits; `startImageUpload` inserts it, awaits the adapter, then\n// replaces the placeholder with the image (or removes it on failure). Same\n// `.kun-editor__uploading` widget as paste/drop, so both look identical.\n\ninterface PlaceholderMeta {\n add?: { id: object; pos: number; locale: KunEditorLocale | undefined }\n remove?: { id: object }\n}\n\nconst placeholderKey = new PluginKey<DecorationSet>('KUN_IMAGE_UPLOAD_PLACEHOLDER')\n\n/** The placeholder DecorationSet plugin — add it when uploads are enabled. */\nexport const imageUploadPlaceholder: MilkdownPlugin = $prose(\n () =>\n new Plugin<DecorationSet>({\n key: placeholderKey,\n state: {\n init: () => DecorationSet.empty,\n apply(tr, set) {\n let next = set.map(tr.mapping, tr.doc)\n const meta = tr.getMeta(placeholderKey) as PlaceholderMeta | undefined\n if (meta?.add) {\n const deco = Decoration.widget(\n meta.add.pos,\n uploadingWidget(meta.add.locale),\n { id: meta.add.id } as Parameters<typeof Decoration.widget>[2]\n )\n next = next.add(tr.doc, [deco])\n } else if (meta?.remove) {\n const { id } = meta.remove\n next = next.remove(\n next.find(undefined, undefined, (spec) => spec.id === id)\n )\n }\n return next\n }\n },\n props: {\n decorations: (state) => placeholderKey.getState(state)\n }\n })\n)\n\nconst findPlaceholder = (view: EditorView, id: object): number | null => {\n const set = placeholderKey.getState(view.state)\n const found = set?.find(undefined, undefined, (spec) => spec.id === id)\n return found && found.length ? found[0]!.from : null\n}\n\n/**\n * Upload a File and show an in-document \"uploading…\" placeholder at the caret\n * until it resolves, then replace it with the image (or remove it + notify on\n * failure). The placeholder isn't an undo step (`addToHistory: false`), so undo\n * removes the inserted image cleanly. Used by the toolbar image button.\n */\nexport const startImageUpload = async (\n view: EditorView,\n file: File,\n options: { uploadImage: UploadImage; notify?: Notify; locale?: KunEditorLocale }\n): Promise<void> => {\n if (!file.type.startsWith('image/')) {\n return\n }\n const id = {}\n const tr = view.state.tr\n if (!tr.selection.empty) {\n tr.deleteSelection()\n }\n tr.setMeta(placeholderKey, {\n add: { id, pos: tr.selection.from, locale: options.locale }\n } satisfies PlaceholderMeta)\n tr.setMeta('addToHistory', false)\n view.dispatch(tr)\n\n try {\n const src = await options.uploadImage(file)\n const pos = findPlaceholder(view, id)\n if (pos === null) {\n return // placeholder gone (e.g. user undid) — drop the result\n }\n const imageType = view.state.schema.nodes.image\n const node = imageType?.createAndFill({ src, alt: file.name })\n if (!node) {\n return\n }\n view.dispatch(\n view.state.tr\n .replaceWith(pos, pos, node)\n .setMeta(placeholderKey, { remove: { id } } satisfies PlaceholderMeta)\n )\n } catch {\n view.dispatch(\n view.state.tr\n .setMeta(placeholderKey, { remove: { id } } satisfies PlaceholderMeta)\n .setMeta('addToHistory', false)\n )\n options.notify?.(uploadFailedLabel(options.locale), 'error')\n }\n}\n","// Placeholder — text shown when the editor (or the current block) is empty.\n//\n// Same mechanism as Milkdown Crepe's placeholder feature (the current, v7 way):\n// a $prose ProseMirror plugin that adds a NODE DECORATION to the empty block —\n// a `.kun-editor__placeholder` class + a `data-placeholder` attribute. The text\n// is rendered by CSS (`::before { content: attr(data-placeholder) }`), so it's\n// purely visual — never part of the doc or the markdown output. Headless: this\n// core ships only the class/attr hook; the `::before` rule lives in the host's\n// stylesheet (see the reference editor.css in @kungal/editor-nuxt).\n//\n// mode 'block' (default): show on whichever empty block the cursor is in (Notion\n// style). mode 'doc': show only when the whole document is empty. Skipped in\n// readonly, code blocks, lists and tables, and whenever there's a selection.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { editorViewOptionsCtx } from '@milkdown/kit/core'\nimport type { EditorState } from '@milkdown/kit/prose/state'\nimport { Plugin, PluginKey } from '@milkdown/kit/prose/state'\nimport { Decoration, DecorationSet } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\nimport { $prose } from '@milkdown/kit/utils'\n\nexport type PlaceholderMode = 'doc' | 'block'\n\nexport interface PlaceholderConfig {\n /** The placeholder text. Empty string disables the placeholder. */\n text?: string\n /** `'block'` (default) shows on any empty block; `'doc'` only when empty. */\n mode?: PlaceholderMode\n}\n\n// Blocks whose own emptiness shouldn't trigger the paragraph-style placeholder.\nconst SKIP_PARENTS = new Set([\n 'code_block',\n 'bullet_list',\n 'ordered_list',\n 'list_item',\n 'table'\n])\n\nconst isDocEmpty = (doc: Node): boolean =>\n doc.childCount <= 1 && !doc.firstChild?.content.size\n\nconst isInSkippedParent = (state: EditorState): boolean => {\n const { $anchor } = state.selection\n for (let depth = $anchor.depth; depth > 0; depth--) {\n if (SKIP_PARENTS.has($anchor.node(depth).type.name)) {\n return true\n }\n }\n return false\n}\n\n/**\n * The placeholder plugin. `text` is baked in at creation (the editor is built\n * once); pass it from `createKunEditorPlugins(..., { placeholder })`.\n */\nexport const createPlaceholderPlugin = (\n config: PlaceholderConfig = {}\n): MilkdownPlugin[] => {\n const text = config.text ?? ''\n const mode = config.mode ?? 'block'\n\n const plugin = $prose(\n (ctx) =>\n new Plugin({\n key: new PluginKey('KUN_PLACEHOLDER'),\n props: {\n decorations: (state) => {\n if (!text) {\n return null\n }\n // Don't show in a read-only editor.\n const editable = ctx.get(editorViewOptionsCtx).editable\n if (editable && !editable(state)) {\n return null\n }\n if (mode === 'doc' && !isDocEmpty(state.doc)) {\n return null\n }\n const { selection } = state\n if (!selection.empty || isInSkippedParent(state)) {\n return null\n }\n const node = selection.$anchor.parent\n if (node.content.size > 0) {\n return null\n }\n const before = selection.$anchor.before()\n return DecorationSet.create(state.doc, [\n Decoration.node(before, before + node.nodeSize, {\n class: 'kun-editor__placeholder',\n 'data-placeholder': text\n })\n ])\n }\n }\n })\n )\n\n return [plugin].flat()\n}\n","// @kungal/editor-core/preset — the composed Milkdown bundle.\n//\n// `createKunEditorPlugins(adapters, features, options)` assembles the Milkdown\n// baseline (commonmark + gfm + history + listener + clipboard + indent +\n// trailing) with the KunEditor plugins from ../plugins, wiring each optional\n// plugin only when its feature/adapter is present. This is the SINGLE call a\n// render layer (@kungal/editor-vue) makes — it must never re-derive the plugin\n// list itself, so the WYSIWYG and markdown-source views always agree on the\n// schema. See docs/architecture.md § migration (P1).\n//\n// This entry pulls in @milkdown/kit and (for the katex / code-block features)\n// the katex + codemirror peers, so it is intentionally SEPARATE from the light\n// main entry (@kungal/editor-core), which the server can import for just the\n// adapter types + MENTION_SCHEME without any peer installed.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { commonmark } from '@milkdown/kit/preset/commonmark'\nimport { gfm } from '@milkdown/kit/preset/gfm'\nimport { history } from '@milkdown/kit/plugin/history'\nimport { listener } from '@milkdown/kit/plugin/listener'\nimport { clipboard } from '@milkdown/kit/plugin/clipboard'\nimport { indent } from '@milkdown/kit/plugin/indent'\nimport { trailing } from '@milkdown/kit/plugin/trailing'\nimport type { KatexOptions } from 'katex'\n\nimport type {\n KunEditorAdapters,\n KunEditorFeatures,\n KunEditorLocale\n} from '../types'\nimport { createSpoilerPlugin } from '../plugins/spoiler'\nimport { createStopLinkPlugin } from '../plugins/stop-link'\nimport { createLinkPlugin } from '../plugins/link'\nimport { createHeadingPlugin } from '../plugins/heading'\nimport { createKatexPlugins } from '../plugins/katex'\nimport { createCodeBlockPlugins } from '../plugins/code-block'\nimport { createMentionPlugin } from '../plugins/mention'\nimport { createQuotePlugin } from '../plugins/quote'\nimport { createUploadPlugin, imageUploadPlaceholder } from '../plugins/upload'\nimport { createPlaceholderPlugin } from '../plugins/placeholder'\n\n// Re-export the individual plugin factories + building blocks so advanced hosts\n// can compose their own bundle instead of using the preset.\nexport * from '../plugins/spoiler'\nexport * from '../plugins/stop-link'\nexport * from '../plugins/link'\nexport * from '../plugins/heading'\nexport * from '../plugins/katex'\nexport * from '../plugins/code-block'\nexport * from '../plugins/mention'\nexport * from '../plugins/quote'\nexport * from '../plugins/upload'\nexport * from '../plugins/placeholder'\n\n/** Extra, non-adapter options for the composed bundle. */\nexport interface KunEditorPluginOptions {\n /** UI language for plugin chrome (code-block toolbar labels). Default `'zh-cn'`. */\n locale?: KunEditorLocale\n /** KaTeX options forwarded to the code-block `latex` preview. */\n katexOptions?: KatexOptions\n /** Placeholder text shown when empty. Omit / empty string → no placeholder. */\n placeholder?: string\n /** `'block'` (default) shows on any empty block; `'doc'` only when empty. */\n placeholderMode?: 'doc' | 'block'\n}\n\n/**\n * Assemble the KunEditor Milkdown plugin list.\n *\n * P1 wired the pure plugins (spoiler, katex, code-block, stop-link); P2 adds the\n * adapter-driven ones — image upload (gated on the `uploadImage` adapter), the\n * mention schema, and the opt-in quote atom. Sticker has no core plugin: a\n * sticker is a plain image node, so its picker is a render-layer view (P3) that\n * consumes the `stickerSource` adapter and inserts an image.\n *\n * Feature flags default to on (except `quote`, host-specific → off); an absent\n * feature simply drops its plugins. The order matters — the baseline comes first\n * so katex's block schema can extend commonmark's code-block schema.\n */\nexport const createKunEditorPlugins = (\n adapters: KunEditorAdapters = {},\n features: KunEditorFeatures = {},\n options: KunEditorPluginOptions = {}\n): MilkdownPlugin[] => {\n const {\n spoiler = true,\n katex = true,\n codeBlock = true,\n mention = true,\n quote = false\n } = features\n\n const plugins: (MilkdownPlugin | MilkdownPlugin[])[] = [\n commonmark,\n gfm,\n history,\n listener,\n clipboard,\n indent,\n trailing\n ]\n\n if (codeBlock) {\n plugins.push(\n createCodeBlockPlugins({\n locale: options.locale,\n katexOptions: options.katexOptions\n })\n )\n }\n if (katex) {\n plugins.push(createKatexPlugins())\n }\n if (spoiler) {\n plugins.push(createSpoilerPlugin())\n }\n // The mention SCHEMA (round-trip) is wired here; the `@` autocomplete dropdown\n // that uses `searchMentionUsers` is a render-layer view (P3). The link-URL form\n // is host policy — default `kungal-user:`, overridable per host.\n if (mention) {\n plugins.push(\n createMentionPlugin({\n toUrl: adapters.mentionToUrl,\n fromUrl: adapters.mentionFromUrl\n })\n )\n }\n // Quote is opt-in — the host inserts references via insertQuoteCommand.\n if (quote) {\n plugins.push(createQuotePlugin())\n }\n // Image upload is gated purely on the adapter: no `uploadImage` → no upload,\n // paste and drop paths (the image-free galgame 简介 editor).\n if (adapters.uploadImage) {\n plugins.push(\n createUploadPlugin(adapters.uploadImage, {\n locale: options.locale,\n notify: adapters.notify\n })\n )\n // The in-document placeholder for the TOOLBAR upload path (paste/drop already\n // gets one from Milkdown's upload plugin above). Both render the same\n // `.kun-editor__uploading` widget. Driven by startImageUpload().\n plugins.push(imageUploadPlaceholder)\n }\n // stop-link is pure chrome-free behaviour; always on.\n plugins.push(createStopLinkPlugin())\n // insert-link command (click-to-link over the commonmark link mark); always on.\n plugins.push(createLinkPlugin())\n // setHeadingCommand (absolute block-type) — powers the \"text size\" dropdown.\n plugins.push(createHeadingPlugin())\n // Placeholder (empty-state text) — only when the host supplies text.\n if (options.placeholder) {\n plugins.push(\n createPlaceholderPlugin({\n text: options.placeholder,\n mode: options.placeholderMode\n })\n )\n }\n\n return plugins.flat()\n}\n"]}
|