@llui/markdown-editor 0.2.13 → 0.3.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.
Files changed (83) hide show
  1. package/dist/editor.d.ts +7 -0
  2. package/dist/editor.d.ts.map +1 -1
  3. package/dist/editor.js +66 -11
  4. package/dist/editor.js.map +1 -1
  5. package/dist/effects.d.ts +5 -4
  6. package/dist/effects.d.ts.map +1 -1
  7. package/dist/effects.js +11 -6
  8. package/dist/effects.js.map +1 -1
  9. package/dist/format.js.map +1 -1
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +3 -3
  13. package/dist/index.js.map +1 -1
  14. package/dist/paste.d.ts.map +1 -1
  15. package/dist/paste.js +5 -0
  16. package/dist/paste.js.map +1 -1
  17. package/dist/plugins/_preview.js.map +1 -1
  18. package/dist/plugins/callout.d.ts.map +1 -1
  19. package/dist/plugins/callout.js +37 -45
  20. package/dist/plugins/callout.js.map +1 -1
  21. package/dist/plugins/context-menu.js.map +1 -1
  22. package/dist/plugins/core.js.map +1 -1
  23. package/dist/plugins/emoji.js.map +1 -1
  24. package/dist/plugins/floating-toolbar.js.map +1 -1
  25. package/dist/plugins/hr.d.ts.map +1 -1
  26. package/dist/plugins/hr.js +4 -7
  27. package/dist/plugins/hr.js.map +1 -1
  28. package/dist/plugins/image.d.ts.map +1 -1
  29. package/dist/plugins/image.js +28 -20
  30. package/dist/plugins/image.js.map +1 -1
  31. package/dist/plugins/inline.js.map +1 -1
  32. package/dist/plugins/link.d.ts.map +1 -1
  33. package/dist/plugins/link.js +16 -9
  34. package/dist/plugins/link.js.map +1 -1
  35. package/dist/plugins/math.d.ts.map +1 -1
  36. package/dist/plugins/math.js +25 -34
  37. package/dist/plugins/math.js.map +1 -1
  38. package/dist/plugins/mention.js.map +1 -1
  39. package/dist/plugins/mermaid.d.ts.map +1 -1
  40. package/dist/plugins/mermaid.js +25 -34
  41. package/dist/plugins/mermaid.js.map +1 -1
  42. package/dist/plugins/overlay.js.map +1 -1
  43. package/dist/plugins/single-block.js.map +1 -1
  44. package/dist/plugins/slash.js.map +1 -1
  45. package/dist/plugins/table.d.ts.map +1 -1
  46. package/dist/plugins/table.js +84 -19
  47. package/dist/plugins/table.js.map +1 -1
  48. package/dist/plugins/types.js.map +1 -1
  49. package/dist/plugins/ui.js.map +1 -1
  50. package/dist/security.d.ts +26 -0
  51. package/dist/security.d.ts.map +1 -0
  52. package/dist/security.js +87 -0
  53. package/dist/security.js.map +1 -0
  54. package/dist/state.js.map +1 -1
  55. package/dist/styles/editor.css +0 -6
  56. package/dist/surfaces/link-dialog.js.map +1 -1
  57. package/dist/surfaces/toolbar.js.map +1 -1
  58. package/dist/theme.d.ts +2 -5
  59. package/dist/theme.d.ts.map +1 -1
  60. package/dist/theme.js +15 -11
  61. package/dist/theme.js.map +1 -1
  62. package/dist/transformers/gfm.d.ts +9 -1
  63. package/dist/transformers/gfm.d.ts.map +1 -1
  64. package/dist/transformers/gfm.js +9 -2
  65. package/dist/transformers/gfm.js.map +1 -1
  66. package/dist/transformers/registry.js.map +1 -1
  67. package/package.json +10 -8
  68. package/src/editor.ts +92 -11
  69. package/src/effects.ts +11 -7
  70. package/src/index.ts +3 -8
  71. package/src/paste.ts +5 -0
  72. package/src/plugins/callout.ts +44 -59
  73. package/src/plugins/hr.ts +4 -14
  74. package/src/plugins/image.ts +32 -29
  75. package/src/plugins/link.ts +20 -10
  76. package/src/plugins/math.ts +27 -41
  77. package/src/plugins/mermaid.ts +26 -45
  78. package/src/plugins/table.ts +94 -17
  79. package/src/security.ts +89 -0
  80. package/src/styles/editor.css +0 -6
  81. package/src/theme.ts +15 -11
  82. package/src/transformers/gfm.ts +10 -2
  83. package/dist/__llui_deps.json +0 -274
@@ -0,0 +1,26 @@
1
+ import { type LexicalEditor, type LexicalNode } from 'lexical';
2
+ /** Schemes allowed for a hyperlink href. A click navigates, so this is the strict
3
+ * set — identical to the renderer's default (`http`/`https`/`mailto`/`tel`). */
4
+ export declare const LINK_PROTOCOLS: readonly string[];
5
+ /** Schemes allowed for an image `src`. Adds `data:` on top of the link set: a
6
+ * base64 image never executes when loaded through `<img>` (unlike a `data:`
7
+ * hyperlink, which can carry `text/html`), and inline data images are a
8
+ * first-class editor feature (paste / upload). */
9
+ export declare const IMAGE_PROTOCOLS: readonly string[];
10
+ /** Sanitize a hyperlink href. Returns the safe URL, or `null` when the scheme is
11
+ * not on {@link LINK_PROTOCOLS} (the link must then be dropped/unwrapped). */
12
+ export declare function sanitizeLinkUrl(url: string): string | null;
13
+ /** Sanitize an image `src`. Returns the safe URL, or `null` when the scheme is
14
+ * not on {@link IMAGE_PROTOCOLS} (the image must then be dropped). */
15
+ export declare function sanitizeImageUrl(url: string): string | null;
16
+ /** Walk `node` (depth-first) neutralizing every unsafe `LinkNode` beneath it. Must
17
+ * run inside an `editor.update`. Use right after importing untrusted markdown
18
+ * (e.g. paste) into a detached scratch tree, before it reaches the live document. */
19
+ export declare function $sanitizeLinkNodes(node: LexicalNode): void;
20
+ /** Register a global `LinkNode` transform that keeps every link's href on the
21
+ * allowlist — the single choke point covering the link dialog, pasted/imported
22
+ * markdown, AND the typed `[text](url)` shortcut. Returns a disposer. A no-op when
23
+ * `LinkNode` isn't registered on the editor (no links are possible then, e.g. the
24
+ * single-block preset), since `registerNodeTransform` requires a registered node. */
25
+ export declare function registerLinkSanitizer(editor: LexicalEditor): () => void;
26
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAA;AAE9E;gFACgF;AAChF,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAA4B,CAAA;AAExE;;;kDAGkD;AAClD,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAyC,CAAA;AAEtF;8EAC8E;AAC9E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE1D;AAED;sEACsE;AACtE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE3D;AAkBD;;qFAEqF;AACrF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAY1D;AAED;;;;qFAIqF;AACrF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,CAKvE"}
@@ -0,0 +1,87 @@
1
+ // URL-scheme policy for the editor.
2
+ //
3
+ // The read-only renderer (`@llui/markdown`) already refuses dangerous link/image
4
+ // schemes (`javascript:`, `vbscript:`, `data:text/html`, …) via `sanitizeUrl`.
5
+ // The EDITOR has additional ingress points that must enforce the SAME policy or
6
+ // an attacker-authored document becomes live/clickable inside it:
7
+ //
8
+ // 1. link commit — `$toggleLink` on a raw, user-typed URL,
9
+ // 2. image src — an `![alt](src)` inserted or imported,
10
+ // 3. markdown paste/import — `$convertFromMarkdownString` builds real
11
+ // `LinkNode`s (and image decorator nodes) from untrusted text,
12
+ // 4. the typed `[x](url)` markdown shortcut — builds a `LinkNode` live.
13
+ //
14
+ // Links are additionally guarded by a global `LinkNode` node transform
15
+ // ({@link registerLinkSanitizer}) so #1/#3/#4 all funnel through one enforcement
16
+ // point. Rather than hand-roll (and drift from) a second allowlist, this module
17
+ // reuses `@llui/markdown`'s exact `sanitizeUrl` and only differs in the
18
+ // allowed-scheme SET per surface — which is data, not a divergent implementation.
19
+ import { sanitizeUrl, defaultAllowedProtocols } from '@llui/markdown/security';
20
+ import { $isLinkNode, LinkNode } from '@lexical/link';
21
+ import { $isElementNode } from 'lexical';
22
+ /** Schemes allowed for a hyperlink href. A click navigates, so this is the strict
23
+ * set — identical to the renderer's default (`http`/`https`/`mailto`/`tel`). */
24
+ export const LINK_PROTOCOLS = defaultAllowedProtocols;
25
+ /** Schemes allowed for an image `src`. Adds `data:` on top of the link set: a
26
+ * base64 image never executes when loaded through `<img>` (unlike a `data:`
27
+ * hyperlink, which can carry `text/html`), and inline data images are a
28
+ * first-class editor feature (paste / upload). */
29
+ export const IMAGE_PROTOCOLS = [...defaultAllowedProtocols, 'data'];
30
+ /** Sanitize a hyperlink href. Returns the safe URL, or `null` when the scheme is
31
+ * not on {@link LINK_PROTOCOLS} (the link must then be dropped/unwrapped). */
32
+ export function sanitizeLinkUrl(url) {
33
+ return sanitizeUrl(url, LINK_PROTOCOLS);
34
+ }
35
+ /** Sanitize an image `src`. Returns the safe URL, or `null` when the scheme is
36
+ * not on {@link IMAGE_PROTOCOLS} (the image must then be dropped). */
37
+ export function sanitizeImageUrl(url) {
38
+ return sanitizeUrl(url, IMAGE_PROTOCOLS);
39
+ }
40
+ /** Neutralize one `LinkNode` in place (must run inside `editor.update`): rewrite a
41
+ * merely-normalized href, or — when the scheme is disallowed — UNWRAP the link so
42
+ * its visible text survives but the clickable `javascript:`/`data:` payload is
43
+ * gone. Returns true if the node was unwrapped/removed. */
44
+ function neutralizeLink(node) {
45
+ const url = node.getURL();
46
+ const safe = sanitizeLinkUrl(url);
47
+ if (safe === null) {
48
+ for (const child of node.getChildren())
49
+ node.insertBefore(child);
50
+ node.remove();
51
+ return true;
52
+ }
53
+ if (safe !== url)
54
+ node.setURL(safe);
55
+ return false;
56
+ }
57
+ /** Walk `node` (depth-first) neutralizing every unsafe `LinkNode` beneath it. Must
58
+ * run inside an `editor.update`. Use right after importing untrusted markdown
59
+ * (e.g. paste) into a detached scratch tree, before it reaches the live document. */
60
+ export function $sanitizeLinkNodes(node) {
61
+ if ($isLinkNode(node)) {
62
+ // Snapshot children first: unwrapping lifts them out of the (removed) link,
63
+ // so recurse the snapshot to catch a defensively-nested inner link either way.
64
+ const children = node.getChildren();
65
+ neutralizeLink(node);
66
+ for (const child of children)
67
+ $sanitizeLinkNodes(child);
68
+ return;
69
+ }
70
+ if ($isElementNode(node)) {
71
+ for (const child of node.getChildren())
72
+ $sanitizeLinkNodes(child);
73
+ }
74
+ }
75
+ /** Register a global `LinkNode` transform that keeps every link's href on the
76
+ * allowlist — the single choke point covering the link dialog, pasted/imported
77
+ * markdown, AND the typed `[text](url)` shortcut. Returns a disposer. A no-op when
78
+ * `LinkNode` isn't registered on the editor (no links are possible then, e.g. the
79
+ * single-block preset), since `registerNodeTransform` requires a registered node. */
80
+ export function registerLinkSanitizer(editor) {
81
+ if (!editor.hasNodes([LinkNode]))
82
+ return () => { };
83
+ return editor.registerNodeTransform(LinkNode, (node) => {
84
+ neutralizeLink(node);
85
+ });
86
+ }
87
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAAA,oCAAoC;AACpC,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAChF,kEAAkE;AAClE,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,wEAAwE;AACxE,oEAAoE;AACpE,2EAA2E;AAC3E,EAAE;AACF,uEAAuE;AACvE,iFAAiF;AACjF,gFAAgF;AAChF,wEAAwE;AACxE,kFAAkF;AAElF,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,cAAc,EAAwC,MAAM,SAAS,CAAA;AAE9E;gFACgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAsB,uBAAuB,CAAA;AAExE;;;kDAGkD;AAClD,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,GAAG,uBAAuB,EAAE,MAAM,CAAC,CAAA;AAEtF;8EAC8E;AAC9E,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,WAAW,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;AACzC,CAAC;AAED;sEACsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,OAAO,WAAW,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;AAC1C,CAAC;AAED;;;2DAG2D;AAC3D,SAAS,cAAc,CAAC,IAAc;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAA;IACzB,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;QAChE,IAAI,CAAC,MAAM,EAAE,CAAA;QACb,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,IAAI,KAAK,GAAG;QAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACnC,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;qFAEqF;AACrF,MAAM,UAAU,kBAAkB,CAAC,IAAiB;IAClD,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,4EAA4E;QAC5E,+EAA+E;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACnC,cAAc,CAAC,IAAI,CAAC,CAAA;QACpB,KAAK,MAAM,KAAK,IAAI,QAAQ;YAAE,kBAAkB,CAAC,KAAK,CAAC,CAAA;QACvD,OAAM;IACR,CAAC;IACD,IAAI,cAAc,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;YAAE,kBAAkB,CAAC,KAAK,CAAC,CAAA;IACnE,CAAC;AACH,CAAC;AAED;;;;qFAIqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IACzD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACjD,OAAO,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE;QACrD,cAAc,CAAC,IAAI,CAAC,CAAA;IACtB,CAAC,CAAC,CAAA;AACJ,CAAC"}
package/dist/state.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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","sourcesContent":["// The editor's TEA state, messages, effects, and pure reducer. Lexical owns the\n// live document; this state holds JSON-serializable mirrors/derivations only, so\n// `update` stays pure and DOM-free (fully unit-testable).\n\nimport type { Alignment } from '@llui/lexical'\n\n/** The block kind at the selection — base rich-text kinds plus list/code,\n * resolved by the markdown layer. */\nexport type BlockType =\n | 'paragraph'\n | 'h1'\n | 'h2'\n | 'h3'\n | 'h4'\n | 'h5'\n | 'h6'\n | 'quote'\n | 'code'\n | 'bullet'\n | 'number'\n | 'check'\n | 'other'\n\n/** The toolbar-facing format surface at the current selection (all primitives). */\nexport interface FormatState {\n bold: boolean\n italic: boolean\n strikethrough: boolean\n code: boolean\n link: boolean\n blockType: BlockType\n alignment: Alignment\n canUndo: boolean\n canRedo: boolean\n}\n\nexport const EMPTY_FORMAT: FormatState = {\n bold: false,\n italic: false,\n strikethrough: false,\n code: false,\n link: false,\n blockType: 'paragraph',\n alignment: null,\n canUndo: false,\n canRedo: false,\n}\n\n/** Which floating surface is currently open. */\nexport type OverlayKind = 'none' | 'floating' | 'slash' | 'context' | 'link'\n\n/** Live collaborative-session status (mirror of the CRDT provider state).\n * `enabled` is false unless the editor was created with a `collab` factory. */\nexport interface CollabStatus {\n enabled: boolean\n connected: boolean\n synced: boolean\n /** Remote peers currently present (excludes this client). */\n peers: number\n}\n\nexport const COLLAB_OFF: CollabStatus = {\n enabled: false,\n connected: false,\n synced: false,\n peers: 0,\n}\n\nexport interface EditorState {\n /** Last serialized markdown (mirror of the live document). */\n value: string\n format: FormatState\n wordCount: number\n charCount: number\n ui: {\n activeOverlay: OverlayKind\n slashQuery: string\n menu: { x: number; y: number }\n }\n /** Per-plugin UI state slices, keyed by plugin name (see {@link PluginUI}). */\n plugins: Record<string, unknown>\n dirty: boolean\n readonly: boolean\n /** Collaborative-session status (always present; inert unless `collab` set). */\n collab: CollabStatus\n}\n\nexport type EditorMsg =\n | { type: 'markdownChanged'; value: string }\n | { type: 'formatChanged'; format: FormatState; wordCount: number; charCount: number }\n | { type: 'runCommand'; id: string }\n | { type: 'setValue'; value: string }\n | { type: 'openOverlay'; overlay: OverlayKind; x?: number; y?: number }\n | { type: 'closeOverlay' }\n | { type: 'slashQuery'; query: string }\n | { type: 'setReadOnly'; readonly: boolean }\n | { type: 'collabStatus'; connected: boolean }\n | { type: 'collabSync'; synced: boolean }\n | { type: 'collabPeers'; peers: number }\n /** Route a message to a plugin's UI reducer (see {@link PluginUI}). */\n | { type: 'plugin'; name: string; msg: unknown }\n\n/** The subset of messages a plugin may emit through its `PluginContext` (e.g. a\n * `register` listener routing an editor event into its own plugin UI). */\nexport type EditorOutMsg = Extract<\n EditorMsg,\n { type: 'openOverlay' | 'closeOverlay' | 'slashQuery' | 'plugin' }\n>\n\nexport type EditorEffect =\n | { type: 'execCommand'; id: string }\n | { type: 'applyValue'; value: string }\n | { type: 'emitChange'; value: string }\n | { type: 'emitFormat'; format: FormatState }\n /** An effect produced by a plugin's UI reducer (see {@link PluginUI}). */\n | { type: 'pluginEffect'; name: string; effect: unknown }\n\nexport interface InitOptions {\n value: string\n readonly: boolean\n /** Whether a collaborative session is wired (drives `collab.enabled`). */\n collab?: boolean\n}\n\nexport function init(opts: InitOptions): [EditorState, EditorEffect[]] {\n const wordCount = countWords(opts.value)\n return [\n {\n value: opts.value,\n format: EMPTY_FORMAT,\n wordCount,\n charCount: opts.value.length,\n ui: { activeOverlay: 'none', slashQuery: '', menu: { x: 0, y: 0 } },\n plugins: {},\n dirty: false,\n readonly: opts.readonly,\n collab: { ...COLLAB_OFF, enabled: opts.collab ?? false },\n },\n [],\n ]\n}\n\nexport function update(state: EditorState, msg: EditorMsg): [EditorState, EditorEffect[]] {\n switch (msg.type) {\n case 'markdownChanged': {\n // Idempotent: re-emitting the current value is a no-op (echo safety).\n if (msg.value === state.value) return [state, []]\n return [\n { ...state, value: msg.value, dirty: true },\n [{ type: 'emitChange', value: msg.value }],\n ]\n }\n case 'formatChanged': {\n return [\n { ...state, format: msg.format, wordCount: msg.wordCount, charCount: msg.charCount },\n [{ type: 'emitFormat', format: msg.format }],\n ]\n }\n case 'runCommand': {\n return [state, [{ type: 'execCommand', id: msg.id }]]\n }\n case 'setValue': {\n // External markdown push (via the component handle). Idempotent; does not\n // re-emit onChange (the consumer already owns this value).\n if (msg.value === state.value) return [state, []]\n return [\n { ...state, value: msg.value, dirty: true },\n [{ type: 'applyValue', value: msg.value }],\n ]\n }\n case 'openOverlay': {\n return [\n {\n ...state,\n ui: {\n ...state.ui,\n activeOverlay: msg.overlay,\n slashQuery: msg.overlay === 'slash' ? '' : state.ui.slashQuery,\n menu: { x: msg.x ?? state.ui.menu.x, y: msg.y ?? state.ui.menu.y },\n },\n },\n [],\n ]\n }\n case 'closeOverlay': {\n if (state.ui.activeOverlay === 'none') return [state, []]\n return [{ ...state, ui: { ...state.ui, activeOverlay: 'none', slashQuery: '' } }, []]\n }\n case 'slashQuery': {\n return [{ ...state, ui: { ...state.ui, slashQuery: msg.query } }, []]\n }\n case 'setReadOnly': {\n if (state.readonly === msg.readonly) return [state, []]\n return [{ ...state, readonly: msg.readonly }, []]\n }\n case 'collabStatus': {\n if (state.collab.connected === msg.connected) return [state, []]\n return [{ ...state, collab: { ...state.collab, connected: msg.connected } }, []]\n }\n case 'collabSync': {\n if (state.collab.synced === msg.synced) return [state, []]\n return [{ ...state, collab: { ...state.collab, synced: msg.synced } }, []]\n }\n case 'collabPeers': {\n if (state.collab.peers === msg.peers) return [state, []]\n return [{ ...state, collab: { ...state.collab, peers: msg.peers } }, []]\n }\n case 'plugin': {\n // Plugin messages are routed by the host's composed reducer (it holds the\n // plugin registry); the pure core reducer treats them as a no-op.\n return [state, []]\n }\n }\n}\n\n/** Count whitespace-delimited words (shared by init and the format handler). */\nexport function countWords(text: string): number {\n const trimmed = text.trim()\n return trimmed === '' ? 0 : trimmed.split(/\\s+/).length\n}\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,0DAA0D;AAkC1D,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,KAAK;IACb,aAAa,EAAE,KAAK;IACpB,IAAI,EAAE,KAAK;IACX,IAAI,EAAE,KAAK;IACX,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,KAAK;CACf,CAAA;AAeD,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,CAAC;CACT,CAAA;AA0DD,MAAM,UAAU,IAAI,CAAC,IAAiB;IACpC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACxC,OAAO;QACL;YACE,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,YAAY;YACpB,SAAS;YACT,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;YAC5B,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;YACnE,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE;SACzD;QACD,EAAE;KACH,CAAA;AACH,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,KAAkB,EAAE,GAAc;IACvD,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QACjB,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,sEAAsE;YACtE,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACjD,OAAO;gBACL,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;gBAC3C,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;aAC3C,CAAA;QACH,CAAC;QACD,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,OAAO;gBACL,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE;gBACpF,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;aAC7C,CAAA;QACH,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACvD,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,0EAA0E;YAC1E,2DAA2D;YAC3D,IAAI,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACjD,OAAO;gBACL,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;gBAC3C,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;aAC3C,CAAA;QACH,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,OAAO;gBACL;oBACE,GAAG,KAAK;oBACR,EAAE,EAAE;wBACF,GAAG,KAAK,CAAC,EAAE;wBACX,aAAa,EAAE,GAAG,CAAC,OAAO;wBAC1B,UAAU,EAAE,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU;wBAC9D,IAAI,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE;qBACnE;iBACF;gBACD,EAAE;aACH,CAAA;QACH,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,KAAK,CAAC,EAAE,CAAC,aAAa,KAAK,MAAM;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACzD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACvF,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACvE,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,IAAI,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACvD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAA;QACnD,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,KAAK,GAAG,CAAC,SAAS;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAChE,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAClF,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YAC1D,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAC5E,CAAC;QACD,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK;gBAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;YACxD,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QAC1E,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,0EAA0E;YAC1E,kEAAkE;YAClE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAA;AACzD,CAAC"}
@@ -83,12 +83,6 @@
83
83
  [data-lexical-editor] .md-strikethrough {
84
84
  text-decoration: line-through;
85
85
  }
86
- [data-lexical-editor] .md-underline {
87
- text-decoration: underline;
88
- }
89
- [data-lexical-editor] .md-underline-strikethrough {
90
- text-decoration: underline line-through;
91
- }
92
86
 
93
87
  /* Task-list items (li[role="checkbox"]) with a clickable checkbox. */
94
88
  [data-lexical-editor] li[role='checkbox'] {
@@ -1 +1 @@
1
- {"version":3,"file":"link-dialog.js","sourceRoot":"","sources":["../../src/surfaces/link-dialog.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,0BAA0B;AAE1B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAA+B,MAAM,WAAW,CAAA;AACjF,OAAO,EACL,OAAO,IAAI,aAAa,EACxB,OAAO,IAAI,aAAa,GAGzB,MAAM,yBAAyB,CAAA;AAiBhC,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE;QACtD,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,gBAAgB;QAC/B,UAAU,EAAE,QAAQ;KACrB,CAAC,CAAA;IAEF,OAAO,aAAa,CAAC;QACnB,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,IAAI,EAAE,IAAI,CAAC,QAAQ;QACnB,KAAK;QACL,aAAa,EAAE,IAAI;QACnB,mBAAmB,EAAE,IAAI;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBAC/C,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;gBACvE,KAAK,CAAC;oBACJ,cAAc,EAAE,OAAO;oBACvB,IAAI,EAAE,KAAK;oBACX,WAAW,EAAE,qBAAqB;oBAClC,KAAK,EAAE,IAAI,CAAC,GAAG;oBACf,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC;oBACzE,SAAS,EAAE,CAAC,CAAgB,EAAE,EAAE;wBAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;4BACtB,CAAC,CAAC,cAAc,EAAE,CAAA;4BAClB,IAAI,CAAC,QAAQ,EAAE,CAAA;wBACjB,CAAC;oBACH,CAAC;iBACF,CAAC;gBACF,GAAG,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE;oBACjC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAC7E,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE;wBAClF,IAAI,CAAC,OAAO,CAAC;qBACd,CAAC;iBACH,CAAC;aACH,CAAC;SACH;KACF,CAAC,CAAA;AACJ,CAAC","sourcesContent":["// The link editor — a modal dialog (built on the @llui/components `dialog`) for\n// entering/editing a URL. Pure view: it's driven by `{ open }` + `url` signals\n// and reports changes through callbacks, so any owner (the link plugin) can wire\n// it to its own messages.\n\nimport { button, div, input, text, type Mountable, type Signal } from '@llui/dom'\nimport {\n connect as connectDialog,\n overlay as overlayDialog,\n type DialogMsg,\n type DialogState,\n} from '@llui/components/dialog'\n\nexport interface LinkDialogOptions {\n /** The `{ open }` slice driving the modal. */\n dialog: Signal<DialogState>\n /** The URL input value. */\n url: Signal<string>\n /** Called as the user edits the URL. */\n onInput: (url: string) => void\n /** Called on Apply / Enter. */\n onSubmit: () => void\n /** Called when the dialog requests open/close (dismiss, close button). */\n onDialog: (msg: DialogMsg) => void\n /** Dialog instance id for ARIA wiring (default 'md-link-dialog'). */\n id?: string\n}\n\n/** Render the link dialog. Hidden (portal, nothing inline) until `dialog.open`. */\nexport function linkDialog(opts: LinkDialogOptions): Mountable {\n const parts = connectDialog(opts.dialog, opts.onDialog, {\n id: opts.id ?? 'md-link-dialog',\n closeLabel: 'Cancel',\n })\n\n return overlayDialog({\n state: opts.dialog,\n send: opts.onDialog,\n parts,\n closeOnEscape: true,\n closeOnOutsideClick: true,\n content: () => [\n div({ ...parts.content, 'data-md-link': 'box' }, [\n div({ ...parts.title, 'data-md-link': 'title' }, [text('Insert link')]),\n input({\n 'data-md-link': 'input',\n type: 'url',\n placeholder: 'https://example.com',\n value: opts.url,\n onInput: (e: Event) => opts.onInput((e.target as HTMLInputElement).value),\n onKeyDown: (e: KeyboardEvent) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n opts.onSubmit()\n }\n },\n }),\n div({ 'data-md-link': 'actions' }, [\n button({ ...parts.closeTrigger, 'data-md-link': 'cancel' }, [text('Cancel')]),\n button({ type: 'button', 'data-md-link': 'apply', onClick: () => opts.onSubmit() }, [\n text('Apply'),\n ]),\n ]),\n ]),\n ],\n })\n}\n"]}
1
+ {"version":3,"file":"link-dialog.js","sourceRoot":"","sources":["../../src/surfaces/link-dialog.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,0BAA0B;AAE1B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAA+B,MAAM,WAAW,CAAA;AACjF,OAAO,EACL,OAAO,IAAI,aAAa,EACxB,OAAO,IAAI,aAAa,GAGzB,MAAM,yBAAyB,CAAA;AAiBhC,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE;QACtD,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,gBAAgB;QAC/B,UAAU,EAAE,QAAQ;KACrB,CAAC,CAAA;IAEF,OAAO,aAAa,CAAC;QACnB,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,IAAI,EAAE,IAAI,CAAC,QAAQ;QACnB,KAAK;QACL,aAAa,EAAE,IAAI;QACnB,mBAAmB,EAAE,IAAI;QACzB,OAAO,EAAE,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE;gBAC/C,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;gBACvE,KAAK,CAAC;oBACJ,cAAc,EAAE,OAAO;oBACvB,IAAI,EAAE,KAAK;oBACX,WAAW,EAAE,qBAAqB;oBAClC,KAAK,EAAE,IAAI,CAAC,GAAG;oBACf,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAE,CAAC,CAAC,MAA2B,CAAC,KAAK,CAAC;oBACzE,SAAS,EAAE,CAAC,CAAgB,EAAE,EAAE;wBAC9B,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;4BACtB,CAAC,CAAC,cAAc,EAAE,CAAA;4BAClB,IAAI,CAAC,QAAQ,EAAE,CAAA;wBACjB,CAAC;oBACH,CAAC;iBACF,CAAC;gBACF,GAAG,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,EAAE;oBACjC,MAAM,CAAC,EAAE,GAAG,KAAK,CAAC,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;oBAC7E,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE;wBAClF,IAAI,CAAC,OAAO,CAAC;qBACd,CAAC;iBACH,CAAC;aACH,CAAC;SACH;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/surfaces/toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["// Toolbar surface. `connectToolbar` returns a parts bag (the @llui/components\n// idiom) driven reactively by the format signal; `toolbar` is a ready-made\n// grouped toolbar Mountable for consumers who don't want to hand-render buttons.\n\nimport {\n button,\n div,\n option,\n select,\n span,\n text,\n tagSend,\n unsafeHtml,\n type Mountable,\n type Send,\n type Signal,\n} from '@llui/dom'\nimport type { CommandItem } from '../plugins/types.js'\nimport type { CollabStatus, EditorMsg, FormatState } from '../state.js'\n\nexport interface ToolbarItemParts {\n type: 'button'\n 'data-scope': 'md-toolbar'\n 'data-part': 'item'\n 'data-id': string\n 'aria-label': string\n title: string\n 'aria-pressed': Signal<'true' | 'false'>\n 'aria-disabled': Signal<'true' | undefined>\n disabled: Signal<boolean>\n 'data-active': Signal<'' | undefined>\n onClick: (e: MouseEvent) => void\n}\n\nexport interface ToolbarParts {\n root: {\n role: 'toolbar'\n 'aria-label': string\n 'data-scope': 'md-toolbar'\n 'data-part': 'root'\n }\n item: (id: string) => ToolbarItemParts\n}\n\n/** Build reactive toolbar parts from the format signal. Spread `item(id)` onto a\n * `<button>`; `aria-pressed` / `data-active` / `disabled` track the format. */\nexport function connectToolbar(\n format: Signal<FormatState>,\n send: Send<EditorMsg>,\n items: readonly CommandItem[],\n): ToolbarParts {\n const byId = new Map(items.map((i) => [i.id, i]))\n return {\n root: {\n role: 'toolbar',\n 'aria-label': 'Formatting',\n 'data-scope': 'md-toolbar',\n 'data-part': 'root',\n },\n item: (id) => {\n const item = byId.get(id)\n const label = item?.label ?? id\n return {\n type: 'button',\n 'data-scope': 'md-toolbar',\n 'data-part': 'item',\n 'data-id': id,\n 'aria-label': label,\n title: label,\n 'aria-pressed': format.map((f) => (item?.isActive?.(f) ? 'true' : 'false')),\n 'aria-disabled': format.map((f) => (item?.isDisabled?.(f) ? 'true' : undefined)),\n disabled: format.map((f) => item?.isDisabled?.(f) ?? false),\n 'data-active': format.map((f) => (item?.isActive?.(f) ? '' : undefined)),\n onClick: tagSend(send, ['runCommand'], () => send({ type: 'runCommand', id })),\n }\n },\n }\n}\n\n/** Inline SVG icon (monochrome, inherits `currentColor`) used where a glyph\n * reads poorly. A glyph string starting with `<svg` is rendered as markup. */\nconst LINK_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M9.5 13.5a3.5 3.5 0 0 0 5 0l3-3a3.5 3.5 0 1 0-5-5l-1 1\"/><path d=\"M14.5 10.5a3.5 3.5 0 0 0-5 0l-3 3a3.5 3.5 0 1 0 5 5l1-1\"/></svg>'\n\nconst IMAGE_ICON =\n '<svg viewBox=\"0 0 24 24\" width=\"15\" height=\"15\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"16\" rx=\"2\"/><circle cx=\"9\" cy=\"9.5\" r=\"1.6\"/><path d=\"m4 18 5-5 4 4 3-3 4 4\"/></svg>'\n\n/** Compact glyphs so the default toolbar reads as a real toolbar without icon\n * assets. SVG strings render as icons; everything else as text. Override via\n * `ToolbarOptions.glyphs`. */\nexport const DEFAULT_GLYPHS: Readonly<Record<string, string>> = {\n bold: 'B',\n italic: 'I',\n strikethrough: 'S',\n code: '</>',\n link: LINK_ICON,\n image: IMAGE_ICON,\n hr: '—',\n table: '▦',\n paragraph: '¶',\n h1: 'H1',\n h2: 'H2',\n h3: 'H3',\n quote: '❝',\n codeBlock: '{ }',\n bulletList: '•',\n numberList: '1.',\n checkList: '☑',\n undo: '↺',\n redo: '↻',\n}\n\nconst GROUP_ORDER = ['inline', 'block', 'list', 'insert', 'history']\n\nfunction groupItems(items: readonly CommandItem[]): string[][] {\n const groups = new Map<string, string[]>()\n for (const item of items) {\n const key = item.group ?? 'other'\n const list = groups.get(key) ?? []\n list.push(item.id)\n groups.set(key, list)\n }\n const ordered: string[][] = []\n for (const key of GROUP_ORDER) {\n const list = groups.get(key)\n if (list) ordered.push(list)\n }\n for (const [key, list] of groups) {\n if (!GROUP_ORDER.includes(key)) ordered.push(list)\n }\n return ordered\n}\n\nexport interface ToolbarOptions {\n format: Signal<FormatState>\n send: Send<EditorMsg>\n items: readonly CommandItem[]\n /** Explicit grouped layout of ids; defaults to grouping by `item.group`. */\n groups?: readonly (readonly string[])[]\n /** Glyph overrides (id → text/emoji). Merged over {@link DEFAULT_GLYPHS}. */\n glyphs?: Readonly<Record<string, string>>\n /** Render the `block` group as a `<select>` dropdown instead of buttons\n * (default true). */\n blockSelect?: boolean\n /** Collaborative-session status. When supplied AND `enabled`, the toolbar\n * appends a presence indicator (connection dot + live peer count). */\n collab?: Signal<CollabStatus>\n 'aria-label'?: string\n}\n\n/** Connection/presence indicator for a collaborative session. */\nfunction presenceIndicator(collab: Signal<CollabStatus>): Mountable {\n const statusOf = (c: CollabStatus): string =>\n c.connected ? (c.synced ? 'synced' : 'connecting') : 'offline'\n return div({ 'data-scope': 'md-toolbar', 'data-part': 'presence' }, [\n span({\n 'data-part': 'presence-status',\n 'data-status': collab.map(statusOf),\n 'aria-hidden': 'true',\n title: collab.map(statusOf),\n }),\n span(\n {\n 'data-part': 'presence-peers',\n role: 'status',\n 'aria-live': 'polite',\n },\n [text(collab.map((c) => (c.peers === 0 ? 'Only you' : `${c.peers + 1} editing`)))],\n ),\n ])\n}\n\n/** Render the `block` group as a native `<select>` of block types. */\nfunction blockTypeSelect(\n format: Signal<FormatState>,\n send: Send<EditorMsg>,\n blockItems: readonly CommandItem[],\n): Mountable {\n return select(\n {\n 'data-scope': 'md-toolbar',\n 'data-part': 'block-select',\n 'aria-label': 'Block type',\n value: format.map((f) => blockItems.find((i) => i.isActive?.(f))?.id ?? ''),\n onChange: (e: Event) => {\n const id = (e.currentTarget as HTMLSelectElement).value\n if (id) send({ type: 'runCommand', id })\n },\n },\n [\n option({ value: '', hidden: true }, [text('—')]),\n ...blockItems.map((i) => option({ value: i.id }, [text(i.label)])),\n ],\n )\n}\n\n/** A ready-made grouped toolbar. Items not surfaced to `'toolbar'` are dropped. */\nexport function toolbar(opts: ToolbarOptions): Mountable {\n const surfaceItems = opts.items.filter((i) => i.surfaces?.includes('toolbar') ?? true)\n const byId = new Map(surfaceItems.map((i) => [i.id, i]))\n const parts = connectToolbar(opts.format, opts.send, surfaceItems)\n const glyphs = { ...DEFAULT_GLYPHS, ...(opts.glyphs ?? {}) }\n\n const useBlockSelect = opts.blockSelect !== false && !opts.groups\n const blockItems = useBlockSelect ? surfaceItems.filter((i) => i.group === 'block') : []\n const buttonItems = useBlockSelect\n ? surfaceItems.filter((i) => i.group !== 'block')\n : surfaceItems\n const groups = opts.groups ?? groupItems(buttonItems)\n\n const children: Mountable[] = []\n if (blockItems.length > 0) {\n children.push(\n div({ 'data-scope': 'md-toolbar', 'data-part': 'group' }, [\n blockTypeSelect(opts.format, opts.send, blockItems),\n ]),\n )\n }\n for (const ids of groups) {\n const present = ids.filter((id) => byId.has(id))\n if (present.length === 0) continue\n children.push(\n div(\n { 'data-scope': 'md-toolbar', 'data-part': 'group' },\n present.map((id) => {\n const item = byId.get(id)!\n const glyph = glyphs[id] ?? item.label\n const glyphNode = glyph.trimStart().startsWith('<svg') ? unsafeHtml(glyph) : text(glyph)\n return button({ ...parts.item(id) }, [\n span({ 'data-part': 'glyph', 'aria-hidden': 'true' }, [glyphNode]),\n ])\n }),\n ),\n )\n }\n\n // Presence indicator (constant `enabled` after init, so a one-shot peek is safe).\n if (opts.collab && opts.collab.peek().enabled) {\n children.push(presenceIndicator(opts.collab))\n }\n\n return div(\n { ...parts.root, ...(opts['aria-label'] ? { 'aria-label': opts['aria-label'] } : {}) },\n children,\n )\n}\n"]}
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../src/surfaces/toolbar.ts"],"names":[],"mappings":"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"}
package/dist/theme.d.ts CHANGED
@@ -1,13 +1,10 @@
1
1
  import type { EditorThemeClasses } from 'lexical';
2
2
  export declare const STRIKETHROUGH_CLASS = "md-strikethrough";
3
- export declare const UNDERLINE_CLASS = "md-underline";
4
- export declare const UNDERLINE_STRIKETHROUGH_CLASS = "md-underline-strikethrough";
5
3
  /** The class hooks Lexical needs for text-decoration formats it renders as a
6
- * plain <span>. (`underlineStrikethrough` is Lexical's special composite key for
7
- * the case where both apply — both want `text-decoration`.) */
4
+ * plain <span>. */
8
5
  export declare const defaultTheme: EditorThemeClasses;
9
6
  /** Merge a consumer theme over the default. `text` is merged per-key so a
10
- * consumer overriding (say) `strikethrough` keeps the default `underline`.
7
+ * consumer overriding (say) `strikethrough` keeps the other default entries.
11
8
  *
12
9
  * Always returns a FRESH theme (never the shared `defaultTheme` singleton):
13
10
  * Lexical caches resolved class arrays by MUTATING the `text` object it is
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD,eAAO,MAAM,mBAAmB,qBAAqB,CAAA;AACrD,eAAO,MAAM,eAAe,iBAAiB,CAAA;AAC7C,eAAO,MAAM,6BAA6B,+BAA+B,CAAA;AAEzE;;+DAE+D;AAC/D,eAAO,MAAM,YAAY,EAAE,kBAM1B,CAAA;AAED;;;;;;;8EAO8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAIzE"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAEjD,eAAO,MAAM,mBAAmB,qBAAqB,CAAA;AAErD;mBACmB;AACnB,eAAO,MAAM,YAAY,EAAE,kBAI1B,CAAA;AAED;;;;;;;8EAO8E;AAC9E,wBAAgB,UAAU,CAAC,KAAK,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,CAIzE"}
package/dist/theme.js CHANGED
@@ -2,28 +2,32 @@
2
2
  //
3
3
  // Lexical styles most inline formats through semantic tags that carry
4
4
  // browser-default styling — bold→<strong>, italic→<em>, code→<code>. But
5
- // `strikethrough` (and `underline`) render as a bare <span> whose ONLY styling
6
- // hook is a `theme.text.<format>` class. With no theme the format is applied to
7
- // the model but is visually invisible. This default theme supplies those class
8
- // names; the bundled `styles/editor.css` gives them their `text-decoration`.
5
+ // `strikethrough` renders as a bare <span> whose ONLY styling hook is a
6
+ // `theme.text.strikethrough` class. With no theme the format is applied to the
7
+ // model but is visually invisible. This default theme supplies that class name;
8
+ // the bundled `styles/editor.css` gives it its `text-decoration`.
9
+ //
10
+ // `underline` is deliberately NOT themed here: the GFM markdown dialect this
11
+ // editor serializes has no underline representation (Lexical's text-format
12
+ // transformers require a SYMMETRIC delimiter, and there is no standard symmetric
13
+ // underline syntax), so an applied underline would be silently stripped on save.
14
+ // To keep the WYSIWYG surface and the serialized dialect in lock-step, the
15
+ // underline command is also intercepted at the editor seam (see editor.ts) — so
16
+ // underline can be neither applied nor lost. Add it back (theme + transformer +
17
+ // command) only alongside a dialect that can round-trip it.
9
18
  //
10
19
  // Consumers can override any entry via `markdownEditor({ theme })` — the user's
11
20
  // theme is merged over this default (see `mergeTheme`).
12
21
  export const STRIKETHROUGH_CLASS = 'md-strikethrough';
13
- export const UNDERLINE_CLASS = 'md-underline';
14
- export const UNDERLINE_STRIKETHROUGH_CLASS = 'md-underline-strikethrough';
15
22
  /** The class hooks Lexical needs for text-decoration formats it renders as a
16
- * plain <span>. (`underlineStrikethrough` is Lexical's special composite key for
17
- * the case where both apply — both want `text-decoration`.) */
23
+ * plain <span>. */
18
24
  export const defaultTheme = {
19
25
  text: {
20
26
  strikethrough: STRIKETHROUGH_CLASS,
21
- underline: UNDERLINE_CLASS,
22
- underlineStrikethrough: UNDERLINE_STRIKETHROUGH_CLASS,
23
27
  },
24
28
  };
25
29
  /** Merge a consumer theme over the default. `text` is merged per-key so a
26
- * consumer overriding (say) `strikethrough` keeps the default `underline`.
30
+ * consumer overriding (say) `strikethrough` keeps the other default entries.
27
31
  *
28
32
  * Always returns a FRESH theme (never the shared `defaultTheme` singleton):
29
33
  * Lexical caches resolved class arrays by MUTATING the `text` object it is
package/dist/theme.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,6EAA6E;AAC7E,EAAE;AACF,gFAAgF;AAChF,wDAAwD;AAIxD,MAAM,CAAC,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AACrD,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAA;AAC7C,MAAM,CAAC,MAAM,6BAA6B,GAAG,4BAA4B,CAAA;AAEzE;;+DAE+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAuB;IAC9C,IAAI,EAAE;QACJ,aAAa,EAAE,mBAAmB;QAClC,SAAS,EAAE,eAAe;QAC1B,sBAAsB,EAAE,6BAA6B;KACtD;CACF,CAAA;AAED;;;;;;;8EAO8E;AAC9E,MAAM,UAAU,UAAU,CAAC,KAA0B;IACnD,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;IACrD,OAAQ,IAA8C,CAAC,uBAAuB,CAAA;IAC9E,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC","sourcesContent":["// Default Lexical theme for the markdown editor.\n//\n// Lexical styles most inline formats through semantic tags that carry\n// browser-default styling — bold→<strong>, italic→<em>, code→<code>. But\n// `strikethrough` (and `underline`) render as a bare <span> whose ONLY styling\n// hook is a `theme.text.<format>` class. With no theme the format is applied to\n// the model but is visually invisible. This default theme supplies those class\n// names; the bundled `styles/editor.css` gives them their `text-decoration`.\n//\n// Consumers can override any entry via `markdownEditor({ theme })` — the user's\n// theme is merged over this default (see `mergeTheme`).\n\nimport type { EditorThemeClasses } from 'lexical'\n\nexport const STRIKETHROUGH_CLASS = 'md-strikethrough'\nexport const UNDERLINE_CLASS = 'md-underline'\nexport const UNDERLINE_STRIKETHROUGH_CLASS = 'md-underline-strikethrough'\n\n/** The class hooks Lexical needs for text-decoration formats it renders as a\n * plain <span>. (`underlineStrikethrough` is Lexical's special composite key for\n * the case where both apply — both want `text-decoration`.) */\nexport const defaultTheme: EditorThemeClasses = {\n text: {\n strikethrough: STRIKETHROUGH_CLASS,\n underline: UNDERLINE_CLASS,\n underlineStrikethrough: UNDERLINE_STRIKETHROUGH_CLASS,\n },\n}\n\n/** Merge a consumer theme over the default. `text` is merged per-key so a\n * consumer overriding (say) `strikethrough` keeps the default `underline`.\n *\n * Always returns a FRESH theme (never the shared `defaultTheme` singleton):\n * Lexical caches resolved class arrays by MUTATING the `text` object it is\n * handed (`text.__lexicalClassNameCache`). Handing it a fresh copy keeps the\n * exported singleton clean, and stripping any inherited cache prevents a stale\n * entry from a previously-used theme object shadowing an overridden class. */\nexport function mergeTheme(theme?: EditorThemeClasses): EditorThemeClasses {\n const text = { ...defaultTheme.text, ...theme?.text }\n delete (text as { __lexicalClassNameCache?: unknown }).__lexicalClassNameCache\n return { ...theme, text }\n}\n"]}
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,+EAA+E;AAC/E,gFAAgF;AAChF,kEAAkE;AAClE,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,iFAAiF;AACjF,iFAAiF;AACjF,2EAA2E;AAC3E,gFAAgF;AAChF,gFAAgF;AAChF,4DAA4D;AAC5D,EAAE;AACF,gFAAgF;AAChF,wDAAwD;AAIxD,MAAM,CAAC,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AAErD;mBACmB;AACnB,MAAM,CAAC,MAAM,YAAY,GAAuB;IAC9C,IAAI,EAAE;QACJ,aAAa,EAAE,mBAAmB;KACnC;CACF,CAAA;AAED;;;;;;;8EAO8E;AAC9E,MAAM,UAAU,UAAU,CAAC,KAA0B;IACnD,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;IACrD,OAAQ,IAA8C,CAAC,uBAAuB,CAAA;IAC9E,OAAO,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,CAAA;AAC3B,CAAC"}
@@ -2,9 +2,17 @@ import type { Klass, LexicalNode } from 'lexical';
2
2
  import { type Transformer } from '@lexical/markdown';
3
3
  /** Node classes required to render the GFM superset. */
4
4
  export declare const GFM_NODES: ReadonlyArray<Klass<LexicalNode>>;
5
+ /** The `==highlight==` transformer. NOT part of the default GFM set: `==..==` is
6
+ * not GFM, so exporting it produces non-standard markdown other renderers won't
7
+ * understand. Offered as an opt-in a consumer can add to a plugin's transformers. */
8
+ export declare const HIGHLIGHT_TRANSFORMER: Transformer;
5
9
  /** Inline text-format transformers (no block nodes, no node registration). These
6
10
  * are the only transformers a single-block / inline-only editor needs; `LINK` is
7
- * kept separate since it requires `LinkNode` to be registered. */
11
+ * kept separate since it requires `LinkNode` to be registered.
12
+ *
13
+ * `HIGHLIGHT` is deliberately excluded: it round-trips as the non-GFM `==..==`
14
+ * syntax, so it would silently emit markdown outside the editor's stated dialect.
15
+ * Opt in with {@link HIGHLIGHT_TRANSFORMER}. */
8
16
  export declare const INLINE_TEXT_TRANSFORMERS: readonly Transformer[];
9
17
  /** Markdown ↔ node transformers for the GFM superset. */
10
18
  export declare const GFM_TRANSFORMERS: readonly Transformer[];
@@ -1 +1 @@
1
- {"version":3,"file":"gfm.d.ts","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOjD,OAAO,EACL,KAAK,WAAW,EAiBjB,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAQvD,CAAA;AAED;;kEAEkE;AAClE,eAAO,MAAM,wBAAwB,EAAE,SAAS,WAAW,EAU1D,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAWlD,CAAA"}
1
+ {"version":3,"file":"gfm.d.ts","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAOjD,OAAO,EACL,KAAK,WAAW,EAiBjB,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAQvD,CAAA;AAED;;qFAEqF;AACrF,eAAO,MAAM,qBAAqB,EAAE,WAAuB,CAAA;AAE3D;;;;;;gDAMgD;AAChD,eAAO,MAAM,wBAAwB,EAAE,SAAS,WAAW,EAS1D,CAAA;AAED,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,SAAS,WAAW,EAWlD,CAAA"}
@@ -17,9 +17,17 @@ export const GFM_NODES = [
17
17
  CodeHighlightNode,
18
18
  LinkNode,
19
19
  ];
20
+ /** The `==highlight==` transformer. NOT part of the default GFM set: `==..==` is
21
+ * not GFM, so exporting it produces non-standard markdown other renderers won't
22
+ * understand. Offered as an opt-in a consumer can add to a plugin's transformers. */
23
+ export const HIGHLIGHT_TRANSFORMER = HIGHLIGHT;
20
24
  /** Inline text-format transformers (no block nodes, no node registration). These
21
25
  * are the only transformers a single-block / inline-only editor needs; `LINK` is
22
- * kept separate since it requires `LinkNode` to be registered. */
26
+ * kept separate since it requires `LinkNode` to be registered.
27
+ *
28
+ * `HIGHLIGHT` is deliberately excluded: it round-trips as the non-GFM `==..==`
29
+ * syntax, so it would silently emit markdown outside the editor's stated dialect.
30
+ * Opt in with {@link HIGHLIGHT_TRANSFORMER}. */
23
31
  export const INLINE_TEXT_TRANSFORMERS = [
24
32
  BOLD_ITALIC_STAR,
25
33
  BOLD_ITALIC_UNDERSCORE,
@@ -29,7 +37,6 @@ export const INLINE_TEXT_TRANSFORMERS = [
29
37
  ITALIC_UNDERSCORE,
30
38
  STRIKETHROUGH,
31
39
  INLINE_CODE,
32
- HIGHLIGHT,
33
40
  ];
34
41
  /** Markdown ↔ node transformers for the GFM superset. */
35
42
  export const GFM_TRANSFORMERS = [
@@ -1 +1 @@
1
- {"version":3,"file":"gfm.js","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAGlF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,gFAAgF;AAChF,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAEL,OAAO,EACP,KAAK,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,SAAS,EACT,IAAI,GACL,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAsC;IAC1D,WAAW;IACX,SAAS;IACT,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,iBAAiB;IACjB,QAAQ;CACT,CAAA;AAED;;kEAEkE;AAClE,MAAM,CAAC,MAAM,wBAAwB,GAA2B;IAC9D,gBAAgB;IAChB,sBAAsB;IACtB,SAAS;IACT,eAAe;IACf,WAAW;IACX,iBAAiB;IACjB,aAAa;IACb,WAAW;IACX,SAAS;CACV,CAAA;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,OAAO;IACP,KAAK;IACL,4EAA4E;IAC5E,2EAA2E;IAC3E,UAAU;IACV,cAAc;IACd,YAAY;IACZ,IAAI;IACJ,GAAG,wBAAwB;IAC3B,IAAI;CACL,CAAA","sourcesContent":["// The built-in GFM superset: node classes + the explicit transformer set that\n// maps exactly to those nodes (no surprise nodes — HR/tables are opt-in plugins).\n\nimport type { Klass, LexicalNode } from 'lexical'\nimport { HeadingNode, QuoteNode } from '@lexical/rich-text'\nimport { ListNode, ListItemNode } from '@lexical/list'\nimport { LinkNode } from '@lexical/link'\n// `@lexical/code-core` (not `@lexical/code`) keeps Prism out of the bundle — we\n// never register syntax highlighting, so plain CodeNode is all we need.\nimport { CodeNode, CodeHighlightNode } from '@lexical/code-core'\nimport {\n type Transformer,\n HEADING,\n QUOTE,\n UNORDERED_LIST,\n ORDERED_LIST,\n CHECK_LIST,\n CODE,\n BOLD_ITALIC_STAR,\n BOLD_ITALIC_UNDERSCORE,\n BOLD_STAR,\n BOLD_UNDERSCORE,\n ITALIC_STAR,\n ITALIC_UNDERSCORE,\n STRIKETHROUGH,\n INLINE_CODE,\n HIGHLIGHT,\n LINK,\n} from '@lexical/markdown'\n\n/** Node classes required to render the GFM superset. */\nexport const GFM_NODES: ReadonlyArray<Klass<LexicalNode>> = [\n HeadingNode,\n QuoteNode,\n ListNode,\n ListItemNode,\n CodeNode,\n CodeHighlightNode,\n LinkNode,\n]\n\n/** Inline text-format transformers (no block nodes, no node registration). These\n * are the only transformers a single-block / inline-only editor needs; `LINK` is\n * kept separate since it requires `LinkNode` to be registered. */\nexport const INLINE_TEXT_TRANSFORMERS: readonly Transformer[] = [\n BOLD_ITALIC_STAR,\n BOLD_ITALIC_UNDERSCORE,\n BOLD_STAR,\n BOLD_UNDERSCORE,\n ITALIC_STAR,\n ITALIC_UNDERSCORE,\n STRIKETHROUGH,\n INLINE_CODE,\n HIGHLIGHT,\n]\n\n/** Markdown ↔ node transformers for the GFM superset. */\nexport const GFM_TRANSFORMERS: readonly Transformer[] = [\n HEADING,\n QUOTE,\n // CHECK_LIST must precede the plain list transformers: `- [ ]`/`- [x]` also\n // match `- `, so UNORDERED_LIST would otherwise swallow it as bullet text.\n CHECK_LIST,\n UNORDERED_LIST,\n ORDERED_LIST,\n CODE,\n ...INLINE_TEXT_TRANSFORMERS,\n LINK,\n]\n"]}
1
+ {"version":3,"file":"gfm.js","sourceRoot":"","sources":["../../src/transformers/gfm.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kFAAkF;AAGlF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,gFAAgF;AAChF,wEAAwE;AACxE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAEL,OAAO,EACP,KAAK,EACL,cAAc,EACd,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,SAAS,EACT,IAAI,GACL,MAAM,mBAAmB,CAAA;AAE1B,wDAAwD;AACxD,MAAM,CAAC,MAAM,SAAS,GAAsC;IAC1D,WAAW;IACX,SAAS;IACT,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,iBAAiB;IACjB,QAAQ;CACT,CAAA;AAED;;qFAEqF;AACrF,MAAM,CAAC,MAAM,qBAAqB,GAAgB,SAAS,CAAA;AAE3D;;;;;;gDAMgD;AAChD,MAAM,CAAC,MAAM,wBAAwB,GAA2B;IAC9D,gBAAgB;IAChB,sBAAsB;IACtB,SAAS;IACT,eAAe;IACf,WAAW;IACX,iBAAiB;IACjB,aAAa;IACb,WAAW;CACZ,CAAA;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,OAAO;IACP,KAAK;IACL,4EAA4E;IAC5E,2EAA2E;IAC3E,UAAU;IACV,cAAc;IACd,YAAY;IACZ,IAAI;IACJ,GAAG,wBAAwB;IAC3B,IAAI;CACL,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/transformers/registry.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,kDAAkD;AAKlD,6EAA6E;AAC7E,6EAA6E;AAC7E,mEAAmE;AACnE,MAAM,SAAS,GAA2B;IACxC,mBAAmB,EAAE,CAAC;IACtB,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;CAChB,CAAA;AAED,+DAA+D;AAC/D,MAAM,UAAU,iBAAiB,CAAC,YAAoC;IACpE,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAA;QAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACzD,qDAAqD;YACrD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAA;QACpC,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;kCAEkC;AAClC,MAAM,UAAU,iBAAiB,CAAC,OAAkC;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAe,CAAA;IACnC,MAAM,SAAS,GAAkB,EAAE,CAAA;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACrB,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAA;AACrC,CAAC","sourcesContent":["// The transformer registry: flatten plugin transformer contributions into a\n// single, correctly-ordered Lexical TRANSFORMERS array. Ordering is the single\n// place markdown round-trip fidelity is governed.\n\nimport type { Transformer } from '@lexical/markdown'\nimport type { MarkdownPlugin } from '../plugins/types.js'\n\n// Lexical resolves transformers in array order. Element/multiline constructs\n// must be tried before inline text matching, and longer text-format patterns\n// (e.g. `***`) before shorter (`**`, `*`) so they aren't shadowed.\nconst TYPE_RANK: Record<string, number> = {\n 'multiline-element': 0,\n element: 1,\n 'text-format': 2,\n 'text-match': 3,\n}\n\n/** Stable-sort transformers into the order Lexical expects. */\nexport function orderTransformers(transformers: readonly Transformer[]): Transformer[] {\n return [...transformers].sort((a, b) => {\n const ra = TYPE_RANK[a.type] ?? 9\n const rb = TYPE_RANK[b.type] ?? 9\n if (ra !== rb) return ra - rb\n if (a.type === 'text-format' && b.type === 'text-format') {\n // Longer trigger (`***`) before shorter (`**`, `*`).\n return b.tag.length - a.tag.length\n }\n return 0\n })\n}\n\n/** Collect every plugin's transformers (de-duplicated by reference) and order\n * them. The result is passed to `$convertTo/FromMarkdownString` and\n * `registerMarkdownShortcuts`. */\nexport function buildTransformers(plugins: readonly MarkdownPlugin[]): Transformer[] {\n const seen = new Set<Transformer>()\n const collected: Transformer[] = []\n for (const plugin of plugins) {\n for (const transformer of plugin.transformers ?? []) {\n if (!seen.has(transformer)) {\n seen.add(transformer)\n collected.push(transformer)\n }\n }\n }\n return orderTransformers(collected)\n}\n"]}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/transformers/registry.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,kDAAkD;AAKlD,6EAA6E;AAC7E,6EAA6E;AAC7E,mEAAmE;AACnE,MAAM,SAAS,GAA2B;IACxC,mBAAmB,EAAE,CAAC;IACtB,OAAO,EAAE,CAAC;IACV,aAAa,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC;CAChB,CAAA;AAED,+DAA+D;AAC/D,MAAM,UAAU,iBAAiB,CAAC,YAAoC;IACpE,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,EAAE,GAAG,EAAE,CAAA;QAC7B,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YACzD,qDAAqD;YACrD,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAA;QACpC,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;kCAEkC;AAClC,MAAM,UAAU,iBAAiB,CAAC,OAAkC;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAe,CAAA;IACnC,MAAM,SAAS,GAAkB,EAAE,CAAA;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,WAAW,IAAI,MAAM,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;gBACrB,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,iBAAiB,CAAC,SAAS,CAAC,CAAA;AACrC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/markdown-editor",
3
- "version": "0.2.13",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,9 +24,6 @@
24
24
  "./styles/editor.css": "./dist/styles/editor.css"
25
25
  },
26
26
  "peerDependencies": {
27
- "@llui/dom": "^0.11.5",
28
- "@llui/lexical": "^0.2.8",
29
- "@llui/components": "^0.12.2",
30
27
  "lexical": "^0.46.0",
31
28
  "@lexical/markdown": "^0.46.0",
32
29
  "@lexical/rich-text": "^0.46.0",
@@ -35,7 +32,11 @@
35
32
  "@lexical/table": "^0.46.0",
36
33
  "@lexical/selection": "^0.46.0",
37
34
  "@lexical/utils": "^0.46.0",
38
- "@lexical/code-core": "^0.46.0"
35
+ "@lexical/code-core": "^0.46.0",
36
+ "@llui/dom": "^0.12.0",
37
+ "@llui/markdown": "^0.12.0",
38
+ "@llui/lexical": "^0.3.0",
39
+ "@llui/components": "^0.13.0"
39
40
  },
40
41
  "devDependencies": {
41
42
  "lexical": "^0.46.0",
@@ -50,9 +51,10 @@
50
51
  "typescript": "^6.0.0",
51
52
  "vitest": "^4.1.2",
52
53
  "@lexical/code-core": "^0.46.0",
53
- "@llui/dom": "0.11.7",
54
- "@llui/lexical": "0.2.9",
55
- "@llui/components": "0.12.3"
54
+ "@llui/dom": "0.12.0",
55
+ "@llui/markdown": "0.12.0",
56
+ "@llui/components": "0.13.0",
57
+ "@llui/lexical": "0.3.0"
56
58
  },
57
59
  "sideEffects": [
58
60
  "./dist/styles/editor.css"