@kungal/editor-core 0.9.0 → 0.10.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 CHANGED
@@ -1,5 +1,30 @@
1
1
  # @kungal/editor-core
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ebe6c61: Make the @mention link URL form injectable (host policy).
8
+
9
+ The mention markdown form was hardcoded to `[@name](kungal-user:<id>)`. But the
10
+ URL shape is a server contract — different hosts render/parse it differently — so
11
+ it's host policy, not editor mechanism. Two new (optional) `KunEditorAdapters`
12
+ fields let a host define it:
13
+
14
+ - `mentionToUrl(userId) => string` — build the link URL (default `kungal-user:<id>`)
15
+ - `mentionFromUrl(url) => number | null` — parse a link back to a user id, or
16
+ null if it isn't a mention (default: the `kungal-user:` scheme)
17
+
18
+ `createMentionPlugin(config?)` now takes `{ toUrl, fromUrl }`; the preset threads
19
+ the adapters through. Omit them for the unchanged default — fully backward
20
+ compatible, no data migration.
21
+
22
+ This unblocks downstream adoption (e.g. moyu, whose mentions are real
23
+ `/user/<id>/resource` links): the host passes its own `mentionToUrl` /
24
+ `mentionFromUrl`, existing content keeps working, and its server + goldmark
25
+ renderer stay untouched. `insertMentionCommand` now resolves the node type by id
26
+ from the live schema, so it works with any mention config.
27
+
3
28
  ## 0.9.0
4
29
 
5
30
  ## 0.8.0
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { K as KunEditorAdapters, a as KunEditorFeatures, b as KunEditorLocale, M as MentionUser, N as Notify, c as NotifyLevel, S as SearchMentionUsers, d as StickerItem, e as StickerPack, f as StickerSource, U as UploadImage } from './types-BXLT8DV7.cjs';
1
+ export { K as KunEditorAdapters, a as KunEditorFeatures, b as KunEditorLocale, M as MentionUser, N as Notify, c as NotifyLevel, S as SearchMentionUsers, d as StickerItem, e as StickerPack, f as StickerSource, U as UploadImage } from './types-EgTLraa1.cjs';
2
2
 
3
3
  declare const MENTION_SCHEME = "kungal-user:";
4
4
  declare const QUOTE_SCHEME = "kungal-reply:";
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { K as KunEditorAdapters, a as KunEditorFeatures, b as KunEditorLocale, M as MentionUser, N as Notify, c as NotifyLevel, S as SearchMentionUsers, d as StickerItem, e as StickerPack, f as StickerSource, U as UploadImage } from './types-BXLT8DV7.js';
1
+ export { K as KunEditorAdapters, a as KunEditorFeatures, b as KunEditorLocale, M as MentionUser, N as Notify, c as NotifyLevel, S as SearchMentionUsers, d as StickerItem, e as StickerPack, f as StickerSource, U as UploadImage } from './types-EgTLraa1.js';
2
2
 
3
3
  declare const MENTION_SCHEME = "kungal-user:";
4
4
  declare const QUOTE_SCHEME = "kungal-reply:";
@@ -729,7 +729,13 @@ var QUOTE_SCHEME = "kungal-reply:";
729
729
 
730
730
  // src/plugins/mention/index.ts
731
731
  var mentionId = "mention";
732
- var mentionSchema = utils.$nodeSchema(mentionId, () => ({
732
+ var defaultToUrl = (userId) => `${MENTION_SCHEME}${userId}`;
733
+ var defaultFromUrl = (url) => {
734
+ if (!url.startsWith(MENTION_SCHEME)) return null;
735
+ const id = Number.parseInt(url.slice(MENTION_SCHEME.length), 10);
736
+ return Number.isInteger(id) && id > 0 ? id : null;
737
+ };
738
+ var makeMentionSchema = (toUrl) => utils.$nodeSchema(mentionId, () => ({
733
739
  group: "inline",
734
740
  inline: true,
735
741
  atom: true,
@@ -768,29 +774,24 @@ var mentionSchema = utils.$nodeSchema(mentionId, () => ({
768
774
  toMarkdown: {
769
775
  match: (node) => node.type.name === mentionId,
770
776
  runner: (state, node) => {
771
- state.openNode("link", void 0, {
772
- url: `${MENTION_SCHEME}${node.attrs.userId}`
773
- });
777
+ state.openNode("link", void 0, { url: toUrl(node.attrs.userId) });
774
778
  state.addNode("text", void 0, `@${node.attrs.name}`);
775
779
  state.closeNode();
776
780
  }
777
781
  }
778
782
  }));
779
- var remarkMentionPlugin = utils.$remark("remarkMention", () => () => {
783
+ var makeRemarkMention = (fromUrl) => utils.$remark("remarkMention", () => () => {
780
784
  const transformer = (tree) => {
781
785
  unistUtilVisit.visit(tree, "link", (node, index, parent) => {
782
- if (typeof node.url !== "string" || !node.url.startsWith(MENTION_SCHEME)) {
786
+ if (typeof node.url !== "string") {
783
787
  return;
784
788
  }
785
- const userId = Number.parseInt(node.url.slice(MENTION_SCHEME.length), 10);
786
- if (!Number.isInteger(userId) || userId <= 0) {
789
+ const userId = fromUrl(node.url);
790
+ if (userId == null) {
787
791
  return;
788
792
  }
789
793
  const first = node.children?.[0];
790
- const name = (typeof first?.value === "string" ? first.value : "").replace(
791
- /^@/,
792
- ""
793
- );
794
+ const name = (typeof first?.value === "string" ? first.value : "").replace(/^@/, "");
794
795
  if (typeof index === "number" && parent.children) {
795
796
  parent.children.splice(index, 1, {
796
797
  type: mentionId,
@@ -802,9 +803,11 @@ var remarkMentionPlugin = utils.$remark("remarkMention", () => () => {
802
803
  };
803
804
  return transformer;
804
805
  });
806
+ var mentionSchema = makeMentionSchema(defaultToUrl);
807
+ var remarkMentionPlugin = makeRemarkMention(defaultFromUrl);
805
808
  var insertMentionCommand = utils.$command(
806
809
  "InsertKunMention",
807
- (ctx) => (payload) => (state, dispatch) => {
810
+ () => (payload) => (state, dispatch) => {
808
811
  if (!payload || !dispatch) {
809
812
  return false;
810
813
  }
@@ -812,17 +815,22 @@ var insertMentionCommand = utils.$command(
812
815
  if (!Number.isInteger(userId) || userId <= 0) {
813
816
  return false;
814
817
  }
815
- const node = mentionSchema.type(ctx).create({ userId, name });
816
- if (!node) {
818
+ const type = state.schema.nodes[mentionId];
819
+ if (!type) {
817
820
  return false;
818
821
  }
822
+ const node = type.create({ userId, name });
819
823
  const tr = state.tr.replaceSelectionWith(node);
820
824
  tr.insertText(" ");
821
825
  dispatch(tr.scrollIntoView());
822
826
  return true;
823
827
  }
824
828
  );
825
- var createMentionPlugin = () => [mentionSchema, remarkMentionPlugin, insertMentionCommand].flat();
829
+ var createMentionPlugin = (config = {}) => {
830
+ const schema = config.toUrl ? makeMentionSchema(config.toUrl) : mentionSchema;
831
+ const remark = config.fromUrl ? makeRemarkMention(config.fromUrl) : remarkMentionPlugin;
832
+ return [schema, remark, insertMentionCommand].flat();
833
+ };
826
834
  var quoteId = "quote";
827
835
  var quoteSchema = utils.$nodeSchema(quoteId, () => ({
828
836
  group: "inline",
@@ -997,7 +1005,12 @@ var createKunEditorPlugins = (adapters = {}, features = {}, options = {}) => {
997
1005
  plugins.push(createSpoilerPlugin());
998
1006
  }
999
1007
  if (mention) {
1000
- plugins.push(createMentionPlugin());
1008
+ plugins.push(
1009
+ createMentionPlugin({
1010
+ toUrl: adapters.mentionToUrl,
1011
+ fromUrl: adapters.mentionFromUrl
1012
+ })
1013
+ );
1001
1014
  }
1002
1015
  if (quote) {
1003
1016
  plugins.push(createQuotePlugin());
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/spoiler/index.ts","../../src/plugins/stop-link/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/index.ts","../../src/plugins/mention/index.ts","../../src/plugins/quote/index.ts","../../src/plugins/upload/index.ts","../../src/preset/index.ts"],"names":["$nodeAttr","$nodeSchema","expectDomTypeError","$command","$inputRule","InputRule","$remark","visit","linkSchema","$useKeymap","commandsCtx","codeBlockSchema","katex","state","findNodeInSelection","_tr","NodeSelection","TextSelection","nodeRule","textblockTypeInputRule","remarkMath","EditorView","HighlightStyle","t","syntaxHighlighting","codeBlockConfig","keymap","defaultKeymap","indentWithTab","basicSetup","languages","codeBlockComponent","Decoration","uploadConfig","upload","commonmark","gfm","history","listener","clipboard","indent","trailing"],"mappings":"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","file":"index.cjs","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 { expectDomTypeError } from '@milkdown/kit/exception'\nimport { InputRule } from '@milkdown/kit/prose/inputrules'\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 `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 state.addNode('text', undefined, '||')\n state.next(node.content)\n state.addNode('text', undefined, '||')\n }\n }\n}))\n\n/** Toolbar entry point: wraps the current selection in a spoiler node. The\n * render layer's toolbar calls this via commandsCtx (P3). */\nexport const insertKunSpoilerCommand = $command(\n 'InsertKunSpoiler',\n (ctx) => () => (state, dispatch) => {\n if (!dispatch) {\n return true\n }\n const node = spoilerSchema.type(ctx).create()\n if (!node) {\n return true\n }\n dispatch(state.tr.replaceSelectionWith(node).scrollIntoView())\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('​')\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 keymap — pressing Space clears the active link mark so typing after\n// a link doesn't keep extending the link. Ported from the forum's\n// plugins/stop-link/stopLinkPlugin.ts. Pure: no host policy.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command, $useKeymap } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { commandsCtx } from '@milkdown/kit/core'\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?.(state.tr.removeStoredMark(markType))\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\n/** The stop-link plugin bundle: the command + its Space keymap. Pure.\n * `$useKeymap` returns a `[ctx, shortcut]` tuple, so flatten before use. */\nexport const createStopLinkPlugin = (): MilkdownPlugin[] =>\n [stopLinkCommand, linkCustomKeymap].flat() as MilkdownPlugin[]\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","// @kungal/editor-core — public entry.\n//\n// STATUS: scaffold. The adapter contracts (the stable public surface) are\n// defined and exported now; the Milkdown plugin ports land incrementally per\n// docs/architecture.md § migration. Consumers should code against the types\n// below — those are the contract that will not churn as plugins move over.\n\nexport * from './types'\n\n// Markdown scheme used to encode an @mention as a plain link the server can\n// render + parse: `[@name](kungal-user:<id>)`. Lives here (not the plugin) so\n// hosts and the server can share the exact string. See ./plugins/mention.\nexport const MENTION_SCHEME = 'kungal-user:'\n\n// Markdown scheme for an inline reference (reply quote): `[label](kungal-reply:<refId>)`.\n// Like MENTION_SCHEME, shared with the server renderer so both agree on the\n// exact string. The reference is opaque here — the host decides what `refId` /\n// `label` mean (see docs/architecture.md § the reply-quote question, option 1).\nexport const QUOTE_SCHEME = 'kungal-reply:'\n\nexport const KUN_EDITOR_CORE_VERSION = '0.0.0'\n\n// ── The Milkdown plugins live in the `./preset` subpath ──────────────────────\n// This main entry stays light on purpose: types + MENTION_SCHEME, ZERO runtime\n// deps, so the server (which only needs the @mention scheme string) can import\n// it without installing @milkdown/kit / katex / codemirror.\n//\n// The composed Milkdown bundle and the individual plugin factories are exported\n// from `@kungal/editor-core/preset` (they pull in the peer deps):\n//\n// import { createKunEditorPlugins } from '@kungal/editor-core/preset'\n//\n// P1 landed (docs/architecture.md § migration): spoiler, katex, code-block,\n// stop-link — each a factory (createXxxPlugin), never a host-bound singleton.\n// P2 adds the adapter-driven plugins (upload / mention / sticker).\n","// @mention plugin — the inline mention atom + its markdown round-trip.\n//\n// Ported from the forum's plugins/mention/mentionPlugin.ts. Stored markdown form:\n// `[@name](kungal-user:<id>)` — an ordinary markdown link whose custom\n// `kungal-user:` scheme the server renders into a mention chip (and parses for\n// notifications). In the editor it becomes a `mention` inline ATOM carrying the\n// user id (stable identity) plus a display-name snapshot.\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, so the schema only matches its own type. Serialize\n// emits a plain link mdast node back ($remark transformers run on parse only).\n//\n// This is the CORE mechanism. The `@` autocomplete DROPDOWN (which consumes the\n// `searchMentionUsers` adapter, debounces, and inserts a node) is a render-layer\n// view (P3) — it just needs this schema + the insert command below.\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// 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\nexport const mentionSchema = $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, {\n url: `${MENTION_SCHEME}${node.attrs.userId}`\n })\n state.addNode('text', undefined, `@${node.attrs.name}`)\n state.closeNode()\n }\n }\n}))\n\n/** Rewrites `[@name](kungal-user:id)` links into mention nodes on parse. */\nexport const remarkMentionPlugin = $remark('remarkMention', () => () => {\n const transformer = (tree: UnistNode) => {\n visit(tree, 'link', (node: MdastNode, index, parent: MdastNode) => {\n if (\n typeof node.url !== 'string' ||\n !node.url.startsWith(MENTION_SCHEME)\n ) {\n return\n }\n const userId = Number.parseInt(node.url.slice(MENTION_SCHEME.length), 10)\n if (!Number.isInteger(userId) || userId <= 0) {\n return\n }\n const first = node.children?.[0]\n const name = (typeof first?.value === 'string' ? first.value : '').replace(\n /^@/,\n ''\n )\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/**\n * Insert a mention chip at the cursor, replacing the selection. The render-layer\n * dropdown (P3) usually replaces the `@query` range itself; this command is the\n * simple programmatic path (toolbar / tests). A trailing space lets the caret\n * continue past the atom naturally.\n */\nexport const insertMentionCommand = $command(\n 'InsertKunMention',\n (ctx) =>\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 node = mentionSchema.type(ctx).create({ userId, name })\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 mention plugin bundle: schema + remark round-trip + insert command. The\n * `searchMentionUsers` adapter is consumed by the render-layer dropdown (P3). */\nexport const createMentionPlugin = (): MilkdownPlugin[] =>\n [mentionSchema, remarkMentionPlugin, insertMentionCommand].flat()\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 { Decoration } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\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/** The in-flight \"uploading…\" placeholder shown at the drop position. */\nexport const createUploadWidgetFactory = (options: UploadPluginOptions = {}) => {\n return (pos: number, spec: Parameters<typeof Decoration.widget>[2]) => {\n const widgetDOM = document.createElement('span')\n widgetDOM.textContent = uploadingLabel(options.locale)\n widgetDOM.style.color = 'var(--color-primary)'\n return Decoration.widget(pos, widgetDOM, 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","// @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 { createKatexPlugins } from '../plugins/katex'\nimport { createCodeBlockPlugins } from '../plugins/code-block'\nimport { createMentionPlugin } from '../plugins/mention'\nimport { createQuotePlugin } from '../plugins/quote'\nimport { createUploadPlugin } from '../plugins/upload'\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/katex'\nexport * from '../plugins/code-block'\nexport * from '../plugins/mention'\nexport * from '../plugins/quote'\nexport * from '../plugins/upload'\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}\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).\n if (mention) {\n plugins.push(createMentionPlugin())\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 }\n // stop-link is pure chrome-free behaviour; always on.\n plugins.push(createStopLinkPlugin())\n\n return plugins.flat()\n}\n"]}
1
+ {"version":3,"sources":["../../src/plugins/spoiler/index.ts","../../src/plugins/stop-link/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/index.ts","../../src/plugins/mention/index.ts","../../src/plugins/quote/index.ts","../../src/plugins/upload/index.ts","../../src/preset/index.ts"],"names":["$nodeAttr","$nodeSchema","expectDomTypeError","$command","$inputRule","InputRule","$remark","visit","linkSchema","$useKeymap","commandsCtx","codeBlockSchema","katex","state","findNodeInSelection","_tr","NodeSelection","TextSelection","nodeRule","textblockTypeInputRule","remarkMath","EditorView","HighlightStyle","t","syntaxHighlighting","codeBlockConfig","keymap","defaultKeymap","indentWithTab","basicSetup","languages","codeBlockComponent","Decoration","uploadConfig","upload","commonmark","gfm","history","listener","clipboard","indent","trailing"],"mappings":"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","file":"index.cjs","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 { expectDomTypeError } from '@milkdown/kit/exception'\nimport { InputRule } from '@milkdown/kit/prose/inputrules'\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 `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 state.addNode('text', undefined, '||')\n state.next(node.content)\n state.addNode('text', undefined, '||')\n }\n }\n}))\n\n/** Toolbar entry point: wraps the current selection in a spoiler node. The\n * render layer's toolbar calls this via commandsCtx (P3). */\nexport const insertKunSpoilerCommand = $command(\n 'InsertKunSpoiler',\n (ctx) => () => (state, dispatch) => {\n if (!dispatch) {\n return true\n }\n const node = spoilerSchema.type(ctx).create()\n if (!node) {\n return true\n }\n dispatch(state.tr.replaceSelectionWith(node).scrollIntoView())\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('​')\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 keymap — pressing Space clears the active link mark so typing after\n// a link doesn't keep extending the link. Ported from the forum's\n// plugins/stop-link/stopLinkPlugin.ts. Pure: no host policy.\nimport type { MilkdownPlugin } from '@milkdown/kit/ctx'\nimport { $command, $useKeymap } from '@milkdown/kit/utils'\nimport { linkSchema } from '@milkdown/kit/preset/commonmark'\nimport { commandsCtx } from '@milkdown/kit/core'\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?.(state.tr.removeStoredMark(markType))\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\n/** The stop-link plugin bundle: the command + its Space keymap. Pure.\n * `$useKeymap` returns a `[ctx, shortcut]` tuple, so flatten before use. */\nexport const createStopLinkPlugin = (): MilkdownPlugin[] =>\n [stopLinkCommand, linkCustomKeymap].flat() as MilkdownPlugin[]\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","// @kungal/editor-core — public entry.\n//\n// STATUS: scaffold. The adapter contracts (the stable public surface) are\n// defined and exported now; the Milkdown plugin ports land incrementally per\n// docs/architecture.md § migration. Consumers should code against the types\n// below — those are the contract that will not churn as plugins move over.\n\nexport * from './types'\n\n// Markdown scheme used to encode an @mention as a plain link the server can\n// render + parse: `[@name](kungal-user:<id>)`. Lives here (not the plugin) so\n// hosts and the server can share the exact string. See ./plugins/mention.\nexport const MENTION_SCHEME = 'kungal-user:'\n\n// Markdown scheme for an inline reference (reply quote): `[label](kungal-reply:<refId>)`.\n// Like MENTION_SCHEME, shared with the server renderer so both agree on the\n// exact string. The reference is opaque here — the host decides what `refId` /\n// `label` mean (see docs/architecture.md § the reply-quote question, option 1).\nexport const QUOTE_SCHEME = 'kungal-reply:'\n\nexport const KUN_EDITOR_CORE_VERSION = '0.0.0'\n\n// ── The Milkdown plugins live in the `./preset` subpath ──────────────────────\n// This main entry stays light on purpose: types + MENTION_SCHEME, ZERO runtime\n// deps, so the server (which only needs the @mention scheme string) can import\n// it without installing @milkdown/kit / katex / codemirror.\n//\n// The composed Milkdown bundle and the individual plugin factories are exported\n// from `@kungal/editor-core/preset` (they pull in the peer deps):\n//\n// import { createKunEditorPlugins } from '@kungal/editor-core/preset'\n//\n// P1 landed (docs/architecture.md § migration): spoiler, katex, code-block,\n// stop-link — each a factory (createXxxPlugin), never a host-bound singleton.\n// P2 adds the adapter-driven plugins (upload / mention / sticker).\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 /** Parse a link URL back to a user id, or `null` if it isn't a mention. */\n fromUrl?: (url: 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 = (fromUrl: (url: string) => number | null) =>\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 const userId = fromUrl(node.url)\n if (userId == null) {\n return\n }\n const first = node.children?.[0]\n const name = (\n typeof first?.value === 'string' ? first.value : ''\n ).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 { Decoration } from '@milkdown/kit/prose/view'\nimport type { Node } from '@milkdown/kit/prose/model'\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/** The in-flight \"uploading…\" placeholder shown at the drop position. */\nexport const createUploadWidgetFactory = (options: UploadPluginOptions = {}) => {\n return (pos: number, spec: Parameters<typeof Decoration.widget>[2]) => {\n const widgetDOM = document.createElement('span')\n widgetDOM.textContent = uploadingLabel(options.locale)\n widgetDOM.style.color = 'var(--color-primary)'\n return Decoration.widget(pos, widgetDOM, 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","// @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 { createKatexPlugins } from '../plugins/katex'\nimport { createCodeBlockPlugins } from '../plugins/code-block'\nimport { createMentionPlugin } from '../plugins/mention'\nimport { createQuotePlugin } from '../plugins/quote'\nimport { createUploadPlugin } from '../plugins/upload'\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/katex'\nexport * from '../plugins/code-block'\nexport * from '../plugins/mention'\nexport * from '../plugins/quote'\nexport * from '../plugins/upload'\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}\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 }\n // stop-link is pure chrome-free behaviour; always on.\n plugins.push(createStopLinkPlugin())\n\n return plugins.flat()\n}\n"]}