@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
@@ -1 +1 @@
1
- {"version":3,"file":"callout.js","sourceRoot":"","sources":["../../src/plugins/callout.ts"],"names":[],"mappings":"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","sourcesContent":["// Callout (admonition) plugin — the custom-rendering showcase. A callout is a\n// block decorator: it stores `{ kind, text }`, renders an LLui sub-view (its own\n// TEA loop) with a clickable kind badge, and round-trips to `:::kind text`\n// markdown via a contributed element transformer.\n\nimport { type ElementNode, type LexicalEditor, type LexicalNode } from 'lexical'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { ElementTransformer } from '@lexical/markdown'\nimport {\n $createLLuiDecoratorNode,\n $isLLuiDecoratorNode,\n LLuiDecoratorNode,\n decoratorBridge,\n} from '@llui/lexical'\nimport { button, component, div, span, text, type Signal } from '@llui/dom'\nimport type { MarkdownPlugin } from './types.js'\n\nexport type CalloutKind = 'note' | 'tip' | 'warning' | 'danger'\n\nexport interface CalloutData {\n kind: CalloutKind\n text: string\n}\n\nconst KIND_CYCLE: readonly CalloutKind[] = ['note', 'tip', 'warning', 'danger']\nconst KIND_LABEL: Readonly<Record<CalloutKind, string>> = {\n note: 'Note',\n tip: 'Tip',\n warning: 'Warning',\n danger: 'Danger',\n}\n\nconst BRIDGE_TYPE = 'callout'\n\nfunction nextKind(kind: CalloutKind): CalloutKind {\n const idx = KIND_CYCLE.indexOf(kind)\n return KIND_CYCLE[(idx + 1) % KIND_CYCLE.length]!\n}\n\nfunction isCalloutData(value: unknown): value is CalloutData {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as CalloutData).kind === 'string' &&\n typeof (value as CalloutData).text === 'string'\n )\n}\n\ntype CalloutMsg = { type: 'cycle' } | { type: 'commitText'; text: string }\n\n// Keep keyboard/input/paste events from bubbling to the outer Lexical editor so\n// the nested editable text island edits natively without Lexical intercepting.\nconst stop = (e: Event): void => e.stopPropagation()\n\n/** The LLui sub-view rendered inside a callout DecoratorNode. The badge cycles\n * the kind; the text is an editable island that persists into the Lexical node\n * on blur (both round-trip to markdown). */\nconst calloutBridge = decoratorBridge<CalloutData, CalloutData, CalloutMsg, never>(\n BRIDGE_TYPE,\n (data, api) =>\n component<CalloutData, CalloutMsg, never>({\n name: 'Callout',\n init: () => ({ kind: data.kind, text: data.text }),\n update: (state, msg) => {\n if (msg.type === 'cycle') {\n const kind = nextKind(state.kind)\n api.update({ kind, text: state.text })\n return { ...state, kind }\n }\n if (msg.type === 'commitText') {\n if (msg.text === state.text) return state\n api.update({ kind: state.kind, text: msg.text })\n return { ...state, text: msg.text }\n }\n return state\n },\n view: ({ state, send }) => [\n div(\n {\n 'data-scope': 'md-callout',\n 'data-part': 'root',\n 'data-kind': state.at('kind') as Signal<string>,\n contenteditable: 'false',\n onKeyDown: stop,\n onBeforeInput: stop,\n onPaste: stop,\n },\n [\n button(\n {\n type: 'button',\n 'data-part': 'badge',\n 'aria-label': 'Change callout kind',\n onClick: () => send({ type: 'cycle' }),\n },\n [text(state.at('kind').map((k) => KIND_LABEL[k]))],\n ),\n span(\n {\n 'data-part': 'text',\n contenteditable: 'true',\n role: 'textbox',\n 'aria-label': 'Callout text',\n onBlur: (e: FocusEvent) =>\n send({ type: 'commitText', text: (e.target as HTMLElement).textContent ?? '' }),\n },\n [text(state.at('text') as Signal<string>)],\n ),\n ],\n ),\n ],\n }),\n)\n\n/** `:::kind text` element transformer (single-line admonition). */\nconst CALLOUT_TRANSFORMER: ElementTransformer = {\n dependencies: [LLuiDecoratorNode],\n export: (node: LexicalNode): string | null => {\n if (!$isLLuiDecoratorNode(node) || node.getBridgeType() !== BRIDGE_TYPE) return null\n const data = node.getData()\n if (!isCalloutData(data)) return null\n return `:::${data.kind} ${data.text}`\n },\n regExp: /^:::(note|tip|warning|danger)[ \\t]+(.+)$/,\n replace: (parentNode: ElementNode, _children, match): void => {\n const kind = match[1] as CalloutKind\n const callout = $createLLuiDecoratorNode(BRIDGE_TYPE, { kind, text: match[2] ?? '' })\n parentNode.replace(callout)\n },\n type: 'element',\n}\n\n/** Insert a fresh callout at the current selection; returns the created node. */\nexport function $insertCallout(\n kind: CalloutKind = 'note',\n textValue = 'New callout',\n): LLuiDecoratorNode {\n return $insertNodeToNearestRoot($createLLuiDecoratorNode(BRIDGE_TYPE, { kind, text: textValue }))\n}\n\n/** Move focus into a callout's editable text island once it has decorated, and\n * select its placeholder text so the next keystroke replaces it. */\nfunction focusCalloutText(editor: LexicalEditor, key: string, attempt = 0): void {\n if (typeof requestAnimationFrame !== 'function') return\n requestAnimationFrame(() => {\n const span = editor.getElementByKey(key)?.querySelector('[data-part=\"text\"]')\n if (span instanceof HTMLElement) {\n span.focus()\n try {\n const range = document.createRange()\n range.selectNodeContents(span)\n const sel = window.getSelection()\n sel?.removeAllRanges()\n sel?.addRange(range)\n } catch {\n /* selection API unavailable */\n }\n } else if (attempt < 3) {\n focusCalloutText(editor, key, attempt + 1)\n }\n })\n}\n\nexport interface CalloutPluginOptions {\n /** Default kind for the toolbar/slash insert action. */\n defaultKind?: CalloutKind\n}\n\nexport function calloutPlugin(opts: CalloutPluginOptions = {}): MarkdownPlugin {\n const defaultKind = opts.defaultKind ?? 'note'\n return {\n name: 'callout',\n nodes: [LLuiDecoratorNode],\n decorators: [calloutBridge],\n transformers: [CALLOUT_TRANSFORMER],\n items: [\n {\n id: 'callout',\n label: 'Callout',\n icon: 'callout',\n group: 'insert',\n keywords: ['note', 'admonition', 'aside', 'tip', 'warning'],\n run: (editor) => {\n let key = ''\n editor.update(() => {\n key = $insertCallout(defaultKind).getKey()\n })\n // Land the caret inside the new callout's text, not after the block.\n focusCalloutText(editor, key)\n },\n surfaces: ['toolbar', 'slash', 'context'],\n },\n ],\n }\n}\n"]}
1
+ {"version":3,"file":"callout.js","sourceRoot":"","sources":["../../src/plugins/callout.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../src/plugins/context-menu.ts"],"names":[],"mappings":"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","sourcesContent":["// Right-click context menu — a plugin-UI overlay. `register` installs a\n// `contextmenu` listener on the editor root and opens the menu at the pointer;\n// the plugin-UI renders the menu and runs the chosen command.\n\nimport { div, each, text, type Signal } from '@llui/dom'\nimport { definePluginUI } from './ui.js'\nimport { OVERLAY_Z, hideOverlay, overlayRoot } from './overlay.js'\nimport type { CommandItem, MarkdownPlugin } from './types.js'\n\ninterface MenuItem {\n id: string\n label: string\n}\n\ninterface ContextState {\n open: boolean\n x: number\n y: number\n items: MenuItem[]\n}\n\ntype ContextMsg =\n | { type: 'open'; x: number; y: number; items: MenuItem[] }\n | { type: 'close' }\n | { type: 'choose'; index: number }\n\ntype ContextEffect = { type: 'run'; id: string }\n\nexport function contextMenuPlugin(): MarkdownPlugin {\n let contextItems: CommandItem[] = []\n\n return {\n name: 'contextMenu',\n onItems: (items) => {\n // Curated: only items that explicitly opt into the context menu (insert\n // actions, links, history). Inline formatting lives in the floating bar.\n contextItems = items.filter((i) => i.surfaces?.includes('context') ?? false)\n },\n register: (editor, ctx) => {\n const onContext = (e: Event): void => {\n const me = e as MouseEvent\n e.preventDefault()\n ctx.emit({\n type: 'plugin',\n name: 'contextMenu',\n msg: {\n type: 'open',\n x: me.clientX,\n y: me.clientY,\n items: contextItems.map((i) => ({ id: i.id, label: i.label })),\n },\n })\n }\n const root = editor.getRootElement()\n root?.addEventListener('contextmenu', onContext)\n return () => {\n editor.getRootElement()?.removeEventListener('contextmenu', onContext)\n }\n },\n ui: definePluginUI<ContextState, ContextMsg, ContextEffect>({\n init: () => ({ open: false, x: 0, y: 0, items: [] }),\n update: (state, msg) => {\n switch (msg.type) {\n case 'open':\n return { open: msg.items.length > 0, x: msg.x, y: msg.y, items: msg.items }\n case 'close':\n return hideOverlay(state)\n case 'choose': {\n const item = state.items[msg.index]\n if (!item) return hideOverlay(state)\n return [{ ...state, open: false }, [{ type: 'run', id: item.id }]]\n }\n }\n },\n onEffect: (effect, ctx) => {\n ctx.emit({ type: 'runCommand', id: effect.id })\n },\n view: ({ state, send }) =>\n overlayRoot({\n open: state.at('open'),\n x: state.at('x'),\n y: state.at('y'),\n zIndex: OVERLAY_Z.contextMenu,\n attrs: { 'data-scope': 'md-context', 'data-part': 'root' },\n // Backdrop closes the menu on any outside interaction.\n before: () => [\n div({\n 'data-scope': 'md-context',\n 'data-part': 'backdrop',\n onMouseDown: () => send({ type: 'close' }),\n onContextMenu: (e: Event) => {\n e.preventDefault()\n send({ type: 'close' })\n },\n }),\n ],\n children: () => [\n each(state.at('items') as Signal<MenuItem[]>, {\n key: (it) => it.id,\n render: (item, index) => [\n div(\n {\n 'data-scope': 'md-context',\n 'data-part': 'option',\n onMouseDown: (e: MouseEvent) => {\n e.preventDefault()\n send({ type: 'choose', index: index.peek() })\n },\n },\n [text(item.map((it) => it.label))],\n ),\n ],\n }),\n ],\n }),\n }),\n }\n}\n"]}
1
+ {"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../src/plugins/context-menu.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"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","sourcesContent":["// The core plugin: the GFM superset of nodes, transformers, command items, and\n// shortcuts. This is the default plugin when none are supplied, so the minimal\n// `markdownEditor()` one-liner still has full keyboard formatting.\n\nimport {\n $createParagraphNode,\n $getSelection,\n $isRangeSelection,\n REDO_COMMAND,\n UNDO_COMMAND,\n type ElementNode,\n type LexicalEditor,\n} from 'lexical'\nimport { mergeRegister } from '@lexical/utils'\nimport { $setBlocksType } from '@lexical/selection'\nimport { $createHeadingNode, $createQuoteNode, type HeadingTagType } from '@lexical/rich-text'\nimport { $createCodeNode } from '@lexical/code-core'\nimport {\n INSERT_CHECK_LIST_COMMAND,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n registerCheckList,\n registerList,\n} from '@lexical/list'\nimport type { CommandContext, CommandItem, MarkdownPlugin } from './types.js'\nimport { inlineItems } from './inline.js'\nimport { GFM_NODES, GFM_TRANSFORMERS } from '../transformers/gfm.js'\n\nconst NOOP_CTX: CommandContext = { send: () => {} }\n\n/** Wrap a node-factory into an editor action that converts the selected blocks. */\nfunction block(create: () => ElementNode): (editor: LexicalEditor) => void {\n return (editor) =>\n editor.update(() => {\n const selection = $getSelection()\n if ($isRangeSelection(selection)) $setBlocksType(selection, create)\n })\n}\n\nfunction heading(tag: HeadingTagType): (editor: LexicalEditor) => void {\n return block(() => $createHeadingNode(tag))\n}\n\nexport interface CorePluginOptions {\n /** Reserved for future core options. */\n readonly _?: never\n}\n\nexport function corePlugin(_opts: CorePluginOptions = {}): MarkdownPlugin {\n const items: CommandItem[] = [\n ...inlineItems(),\n {\n id: 'paragraph',\n label: 'Text',\n icon: 'paragraph',\n group: 'block',\n keywords: ['body', 'normal'],\n run: block(() => $createParagraphNode()),\n isActive: (f) => f.blockType === 'paragraph',\n },\n {\n id: 'h1',\n label: 'Heading 1',\n icon: 'h1',\n group: 'block',\n keywords: ['title'],\n run: heading('h1'),\n isActive: (f) => f.blockType === 'h1',\n },\n {\n id: 'h2',\n label: 'Heading 2',\n icon: 'h2',\n group: 'block',\n run: heading('h2'),\n isActive: (f) => f.blockType === 'h2',\n },\n {\n id: 'h3',\n label: 'Heading 3',\n icon: 'h3',\n group: 'block',\n run: heading('h3'),\n isActive: (f) => f.blockType === 'h3',\n },\n {\n id: 'quote',\n label: 'Quote',\n icon: 'quote',\n group: 'block',\n keywords: ['blockquote'],\n run: block(() => $createQuoteNode()),\n isActive: (f) => f.blockType === 'quote',\n },\n {\n id: 'codeBlock',\n label: 'Code block',\n icon: 'code-block',\n group: 'block',\n keywords: ['fence', 'pre'],\n run: block(() => $createCodeNode()),\n isActive: (f) => f.blockType === 'code',\n },\n {\n id: 'bulletList',\n label: 'Bulleted list',\n icon: 'list-bullet',\n group: 'list',\n keywords: ['unordered', 'ul'],\n run: (e) => e.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'bullet',\n },\n {\n id: 'numberList',\n label: 'Numbered list',\n icon: 'list-number',\n group: 'list',\n keywords: ['ordered', 'ol'],\n run: (e) => e.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'number',\n },\n {\n id: 'checkList',\n label: 'Task list',\n icon: 'list-check',\n group: 'list',\n keywords: ['todo', 'checkbox'],\n run: (e) => e.dispatchCommand(INSERT_CHECK_LIST_COMMAND, undefined),\n isActive: (f) => f.blockType === 'check',\n },\n {\n id: 'undo',\n label: 'Undo',\n icon: 'undo',\n group: 'history',\n run: (e) => e.dispatchCommand(UNDO_COMMAND, undefined),\n isDisabled: (f) => !f.canUndo,\n surfaces: ['toolbar', 'context'],\n },\n {\n id: 'redo',\n label: 'Redo',\n icon: 'redo',\n group: 'history',\n run: (e) => e.dispatchCommand(REDO_COMMAND, undefined),\n isDisabled: (f) => !f.canRedo,\n surfaces: ['toolbar', 'context'],\n },\n ]\n\n const byId = new Map(items.map((i) => [i.id, i]))\n const shortcut =\n (id: string) =>\n (editor: LexicalEditor): boolean => {\n const item = byId.get(id)\n if (!item) return false\n item.run(editor, NOOP_CTX)\n return true\n }\n\n return {\n name: 'core',\n nodes: GFM_NODES,\n transformers: GFM_TRANSFORMERS,\n items,\n // registerList wires list commands/indentation; registerCheckList adds the\n // click-to-toggle on task items. (Linking is handled by the editor's link\n // dialog via $toggleLink — see commitLink in editor.ts.)\n register: (editor) => mergeRegister(registerList(editor), registerCheckList(editor)),\n shortcuts: [\n { combo: 'Mod-Alt-1', run: shortcut('h1') },\n { combo: 'Mod-Alt-2', run: shortcut('h2') },\n { combo: 'Mod-Alt-3', run: shortcut('h3') },\n { combo: 'Mod-Shift-7', run: shortcut('numberList') },\n { combo: 'Mod-Shift-8', run: shortcut('bulletList') },\n { combo: 'Mod-Shift-9', run: shortcut('quote') },\n ],\n }\n}\n"]}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/plugins/core.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"emoji.js","sourceRoot":"","sources":["../../src/plugins/emoji.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,uEAAuE;AAEvE,OAAO,EAAE,eAAe,EAAiB,MAAM,SAAS,CAAA;AAIxD,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAqC;IAC7D,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,IAAI;IACT,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,CAAC,EAAE,GAAG;IACN,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,GAAG;IACb,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;CACf,CAAA;AAED,SAAS,WAAW,CAAC,GAAqC;IACxD,OAAO;QACL,YAAY,EAAE,EAAE;QAChB,0EAA0E;QAC1E,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI;QAClB,YAAY,EAAE,kBAAkB;QAChC,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,GAAG;QACZ,OAAO,EAAE,CAAC,IAAc,EAAE,KAAuB,EAAQ,EAAE;YACzD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACjC,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,EAAE,YAAY;KACnB,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,WAAW,CAAC,OAA2B,EAAE;IACvD,MAAM,GAAG,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAA;IACvD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,YAAY,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;KACjC,CAAA;AACH,CAAC","sourcesContent":["// Emoji plugin — replace `:shortcode:` with the emoji while typing or on import,\n// via a text-match transformer. Unknown shortcodes are left untouched.\n\nimport { $createTextNode, type TextNode } from 'lexical'\nimport type { TextMatchTransformer } from '@lexical/markdown'\nimport type { MarkdownPlugin } from './types.js'\n\n/** A small default shortcode → emoji map. Extend via `emojiPlugin({ emoji })`. */\nexport const DEFAULT_EMOJI: Readonly<Record<string, string>> = {\n smile: '😄',\n grin: '😁',\n joy: '😂',\n wink: '😉',\n heart: '❤️',\n thumbsup: '👍',\n '+1': '👍',\n thumbsdown: '👎',\n fire: '🔥',\n tada: '🎉',\n rocket: '🚀',\n star: '⭐',\n check: '✅',\n x: '❌',\n warning: '⚠️',\n bulb: '💡',\n eyes: '👀',\n sparkles: '✨',\n '100': '💯',\n thinking: '🤔',\n}\n\nfunction transformer(map: Readonly<Record<string, string>>): TextMatchTransformer {\n return {\n dependencies: [],\n // `null` keeps the emoji as a unicode character in the exported markdown.\n export: () => null,\n importRegExp: /:([a-z0-9_+-]+):/,\n regExp: /:([a-z0-9_+-]+):$/,\n trigger: ':',\n replace: (node: TextNode, match: RegExpMatchArray): void => {\n const emoji = map[match[1] ?? '']\n if (emoji) node.replace($createTextNode(emoji))\n },\n type: 'text-match',\n }\n}\n\nexport interface EmojiPluginOptions {\n /** Extra/override shortcode → emoji entries (merged over the defaults). */\n emoji?: Readonly<Record<string, string>>\n}\n\nexport function emojiPlugin(opts: EmojiPluginOptions = {}): MarkdownPlugin {\n const map = { ...DEFAULT_EMOJI, ...(opts.emoji ?? {}) }\n return {\n name: 'emoji',\n transformers: [transformer(map)],\n }\n}\n"]}
1
+ {"version":3,"file":"emoji.js","sourceRoot":"","sources":["../../src/plugins/emoji.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,uEAAuE;AAEvE,OAAO,EAAE,eAAe,EAAiB,MAAM,SAAS,CAAA;AAIxD,kFAAkF;AAClF,MAAM,CAAC,MAAM,aAAa,GAAqC;IAC7D,KAAK,EAAE,IAAI;IACX,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,IAAI;IACT,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,CAAC,EAAE,GAAG;IACN,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,QAAQ,EAAE,GAAG;IACb,KAAK,EAAE,IAAI;IACX,QAAQ,EAAE,IAAI;CACf,CAAA;AAED,SAAS,WAAW,CAAC,GAAqC;IACxD,OAAO;QACL,YAAY,EAAE,EAAE;QAChB,0EAA0E;QAC1E,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI;QAClB,YAAY,EAAE,kBAAkB;QAChC,MAAM,EAAE,mBAAmB;QAC3B,OAAO,EAAE,GAAG;QACZ,OAAO,EAAE,CAAC,IAAc,EAAE,KAAuB,EAAQ,EAAE;YACzD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;YACjC,IAAI,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,EAAE,YAAY;KACnB,CAAA;AACH,CAAC;AAOD,MAAM,UAAU,WAAW,CAAC,OAA2B,EAAE;IACvD,MAAM,GAAG,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAA;IACvD,OAAO;QACL,IAAI,EAAE,OAAO;QACb,YAAY,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;KACjC,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"floating-toolbar.js","sourceRoot":"","sources":["../../src/plugins/floating-toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["// Floating selection toolbar — a bubble of inline-format actions that appears\n// above a non-collapsed text selection. A plugin-UI overlay: `register` watches\n// selection changes and positions/fills the bar; clicking a button runs the\n// command on the still-live selection.\n\nimport { $getSelection, $isRangeSelection } from 'lexical'\nimport { $findMatchingParent, mergeRegister } from '@lexical/utils'\nimport { $isLinkNode } from '@lexical/link'\nimport { button, each, span, text, unsafeHtml, type Signal } from '@llui/dom'\nimport { definePluginUI } from './ui.js'\nimport { OVERLAY_Z, hideOverlay, onViewportChange, overlayRoot } from './overlay.js'\nimport { DEFAULT_GLYPHS } from '../surfaces/toolbar.js'\nimport type { CommandItem, MarkdownPlugin } from './types.js'\n\ninterface BarItem {\n id: string\n label: string\n glyph: string\n active: boolean\n}\n\ninterface FloatState {\n open: boolean\n x: number\n y: number\n items: BarItem[]\n}\n\ntype FloatMsg =\n | { type: 'show'; x: number; y: number; items: BarItem[] }\n | { type: 'hide' }\n | { type: 'run'; index: number }\n\ntype FloatEffect = { type: 'run'; id: string }\n\ninterface InlineFormat {\n bold: boolean\n italic: boolean\n strikethrough: boolean\n code: boolean\n link: boolean\n}\n\nfunction readFormat(editor: import('lexical').LexicalEditor): InlineFormat {\n return editor.getEditorState().read(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) {\n return { bold: false, italic: false, strikethrough: false, code: false, link: false }\n }\n return {\n bold: selection.hasFormat('bold'),\n italic: selection.hasFormat('italic'),\n strikethrough: selection.hasFormat('strikethrough'),\n code: selection.hasFormat('code'),\n link: $findMatchingParent(selection.anchor.getNode(), (n) => $isLinkNode(n)) !== null,\n }\n })\n}\n\nfunction activeFor(id: string, fmt: InlineFormat): boolean {\n switch (id) {\n case 'bold':\n return fmt.bold\n case 'italic':\n return fmt.italic\n case 'strikethrough':\n return fmt.strikethrough\n case 'code':\n return fmt.code\n case 'link':\n return fmt.link\n default:\n return false\n }\n}\n\nexport function floatingToolbarPlugin(): MarkdownPlugin {\n let floatingItems: CommandItem[] = []\n\n return {\n name: 'floatingToolbar',\n onItems: (items) => {\n floatingItems = items.filter((i) =>\n i.surfaces ? i.surfaces.includes('floating') : i.group === 'inline',\n )\n },\n register: (editor, ctx) => {\n const refresh = (): void => {\n const collapsed = editor.getEditorState().read(() => {\n const s = $getSelection()\n return !$isRangeSelection(s) || s.isCollapsed()\n })\n const dom = typeof window !== 'undefined' ? window.getSelection() : null\n if (collapsed || !dom || dom.rangeCount === 0) {\n ctx.emit({ type: 'plugin', name: 'floatingToolbar', msg: { type: 'hide' } })\n return\n }\n const rect = dom.getRangeAt(0).getBoundingClientRect()\n if (rect.width === 0 && rect.height === 0) {\n ctx.emit({ type: 'plugin', name: 'floatingToolbar', msg: { type: 'hide' } })\n return\n }\n const fmt = readFormat(editor)\n const items: BarItem[] = floatingItems.map((i) => ({\n id: i.id,\n label: i.label,\n glyph: DEFAULT_GLYPHS[i.id] ?? i.label,\n active: activeFor(i.id, fmt),\n }))\n ctx.emit({\n type: 'plugin',\n name: 'floatingToolbar',\n msg: { type: 'show', x: rect.left + rect.width / 2, y: rect.top, items },\n })\n }\n return mergeRegister(\n editor.registerUpdateListener(() => refresh()),\n // Keep the bubble glued to the selection while the page scrolls.\n onViewportChange(refresh),\n )\n },\n ui: definePluginUI<FloatState, FloatMsg, FloatEffect>({\n init: () => ({ open: false, x: 0, y: 0, items: [] }),\n update: (state, msg) => {\n switch (msg.type) {\n case 'show':\n return { open: msg.items.length > 0, x: msg.x, y: msg.y, items: msg.items }\n case 'hide':\n return hideOverlay(state)\n case 'run': {\n const item = state.items[msg.index]\n return item ? [state, [{ type: 'run', id: item.id }]] : state\n }\n }\n },\n onEffect: (effect, ctx) => {\n ctx.emit({ type: 'runCommand', id: effect.id })\n },\n // `x` is the selection's horizontal centre; the transform centres the bar on\n // it and lifts it above the selection.\n view: ({ state, send }) =>\n overlayRoot({\n open: state.at('open'),\n x: state.at('x'),\n y: state.at('y'),\n zIndex: OVERLAY_Z.floatingToolbar,\n transform: 'transform:translate(-50%,-115%)',\n attrs: { 'data-scope': 'md-floating', 'data-part': 'bar' },\n children: () => [\n each(state.at('items') as Signal<BarItem[]>, {\n key: (it) => it.id,\n render: (item, index) => [\n button(\n {\n type: 'button',\n 'data-scope': 'md-floating',\n 'data-part': 'item',\n 'data-active': item.map((it) => (it.active ? '' : undefined)),\n 'aria-label': item.map((it) => it.label),\n onMouseDown: (e: MouseEvent) => {\n e.preventDefault()\n send({ type: 'run', index: index.peek() })\n },\n },\n [span({ 'data-part': 'glyph', 'aria-hidden': 'true' }, [renderGlyph(item)])],\n ),\n ],\n }),\n ],\n }),\n }),\n }\n}\n\n/** Render an item's glyph (SVG markup → unsafeHtml, otherwise text). */\nfunction renderGlyph(item: Signal<BarItem>): import('@llui/dom').Mountable {\n // The glyph value is stable per row; reading once is fine.\n const glyph = item.peek().glyph\n return glyph.trimStart().startsWith('<svg') ? unsafeHtml(glyph) : text(item.map((it) => it.glyph))\n}\n"]}
1
+ {"version":3,"file":"floating-toolbar.js","sourceRoot":"","sources":["../../src/plugins/floating-toolbar.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hr.d.ts","sourceRoot":"","sources":["../../src/plugins/hr.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AA6BhD,yDAAyD;AACzD,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,QAAQ,IAAI,cAAc,CAkBzC"}
1
+ {"version":3,"file":"hr.d.ts","sourceRoot":"","sources":["../../src/plugins/hr.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAmBhD,yDAAyD;AACzD,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED,wBAAgB,QAAQ,IAAI,cAAc,CAkBzC"}
@@ -3,14 +3,11 @@
3
3
  import {} from 'lexical';
4
4
  import { $insertNodeToNearestRoot } from '@lexical/utils';
5
5
  import { $createLLuiDecoratorNode, $isLLuiDecoratorNode, LLuiDecoratorNode, decoratorBridge, } from '@llui/lexical';
6
- import { component, hr } from '@llui/dom';
6
+ import { hr } from '@llui/dom';
7
7
  const BRIDGE_TYPE = 'hr';
8
- const hrBridge = decoratorBridge(BRIDGE_TYPE, () => component({
9
- name: 'HorizontalRule',
10
- init: () => ({}),
11
- update: (state) => state,
12
- view: () => [hr({ 'data-md-hr': '', contenteditable: 'false' })],
13
- }));
8
+ const hrBridge = decoratorBridge(BRIDGE_TYPE, () => [
9
+ hr({ 'data-md-hr': '', contenteditable: 'false' }),
10
+ ]);
14
11
  const HR_TRANSFORMER = {
15
12
  dependencies: [LLuiDecoratorNode],
16
13
  export: (node) => $isLLuiDecoratorNode(node) && node.getBridgeType() === BRIDGE_TYPE ? '---' : null,
@@ -1 +1 @@
1
- {"version":3,"file":"hr.js","sourceRoot":"","sources":["../../src/plugins/hr.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,sDAAsD;AAEtD,OAAO,EAAsC,MAAM,SAAS,CAAA;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAEzD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AAGzC,MAAM,WAAW,GAAG,IAAI,CAAA;AAExB,MAAM,QAAQ,GAAG,eAAe,CAK9B,WAAW,EAAE,GAAG,EAAE,CAClB,SAAS,CAAiD;IACxD,IAAI,EAAE,gBAAgB;IACtB,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IACxB,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC,CAAC;CACjE,CAAC,CACH,CAAA;AAED,MAAM,cAAc,GAAuB;IACzC,YAAY,EAAE,CAAC,iBAAiB,CAAC;IACjC,MAAM,EAAE,CAAC,IAAiB,EAAiB,EAAE,CAC3C,oBAAoB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;IACnF,MAAM,EAAE,uBAAuB;IAC/B,OAAO,EAAE,CAAC,UAAuB,EAAQ,EAAE;QACzC,UAAU,CAAC,OAAO,CAAC,wBAAwB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,yDAAyD;AACzD,MAAM,UAAU,qBAAqB;IACnC,wBAAwB,CAAC,wBAAwB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,UAAU,EAAE,CAAC,QAAQ,CAAC;QACtB,YAAY,EAAE,CAAC,cAAc,CAAC;QAC9B,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,gBAAgB;gBACpB,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,IAAI;gBACV,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC;gBAChD,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;gBAC7D,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC;aAC1C;SACF;KACF,CAAA;AACH,CAAC","sourcesContent":["// Horizontal-rule plugin — a thematic break rendered as an `<hr>` via the\n// decorator bridge, round-tripping to `---` markdown.\n\nimport { type ElementNode, type LexicalNode } from 'lexical'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { ElementTransformer } from '@lexical/markdown'\nimport {\n $createLLuiDecoratorNode,\n $isLLuiDecoratorNode,\n LLuiDecoratorNode,\n decoratorBridge,\n} from '@llui/lexical'\nimport { component, hr } from '@llui/dom'\nimport type { MarkdownPlugin } from './types.js'\n\nconst BRIDGE_TYPE = 'hr'\n\nconst hrBridge = decoratorBridge<\n Record<string, never>,\n Record<string, never>,\n { type: 'noop' },\n never\n>(BRIDGE_TYPE, () =>\n component<Record<string, never>, { type: 'noop' }, never>({\n name: 'HorizontalRule',\n init: () => ({}),\n update: (state) => state,\n view: () => [hr({ 'data-md-hr': '', contenteditable: 'false' })],\n }),\n)\n\nconst HR_TRANSFORMER: ElementTransformer = {\n dependencies: [LLuiDecoratorNode],\n export: (node: LexicalNode): string | null =>\n $isLLuiDecoratorNode(node) && node.getBridgeType() === BRIDGE_TYPE ? '---' : null,\n regExp: /^(---|\\*\\*\\*|___)\\s*$/,\n replace: (parentNode: ElementNode): void => {\n parentNode.replace($createLLuiDecoratorNode(BRIDGE_TYPE, {}))\n },\n type: 'element',\n}\n\n/** Insert a horizontal rule at the current selection. */\nexport function $insertHorizontalRule(): void {\n $insertNodeToNearestRoot($createLLuiDecoratorNode(BRIDGE_TYPE, {}))\n}\n\nexport function hrPlugin(): MarkdownPlugin {\n return {\n name: 'hr',\n nodes: [LLuiDecoratorNode],\n decorators: [hrBridge],\n transformers: [HR_TRANSFORMER],\n items: [\n {\n id: 'horizontalRule',\n label: 'Divider',\n icon: 'hr',\n group: 'insert',\n keywords: ['rule', 'divider', 'separator', 'hr'],\n run: (editor) => editor.update(() => $insertHorizontalRule()),\n surfaces: ['toolbar', 'slash', 'context'],\n },\n ],\n }\n}\n"]}
1
+ {"version":3,"file":"hr.js","sourceRoot":"","sources":["../../src/plugins/hr.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,sDAAsD;AAEtD,OAAO,EAAsC,MAAM,SAAS,CAAA;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAA;AAEzD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAA;AAG9B,MAAM,WAAW,GAAG,IAAI,CAAA;AAExB,MAAM,QAAQ,GAAG,eAAe,CAAwB,WAAW,EAAE,GAAG,EAAE,CAAC;IACzE,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,CAAC;CACnD,CAAC,CAAA;AAEF,MAAM,cAAc,GAAuB;IACzC,YAAY,EAAE,CAAC,iBAAiB,CAAC;IACjC,MAAM,EAAE,CAAC,IAAiB,EAAiB,EAAE,CAC3C,oBAAoB,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;IACnF,MAAM,EAAE,uBAAuB;IAC/B,OAAO,EAAE,CAAC,UAAuB,EAAQ,EAAE;QACzC,UAAU,CAAC,OAAO,CAAC,wBAAwB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;IAC/D,CAAC;IACD,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,yDAAyD;AACzD,MAAM,UAAU,qBAAqB;IACnC,wBAAwB,CAAC,wBAAwB,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,CAAC,iBAAiB,CAAC;QAC1B,UAAU,EAAE,CAAC,QAAQ,CAAC;QACtB,YAAY,EAAE,CAAC,cAAc,CAAC;QAC9B,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,gBAAgB;gBACpB,KAAK,EAAE,SAAS;gBAChB,IAAI,EAAE,IAAI;gBACV,KAAK,EAAE,QAAQ;gBACf,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC;gBAChD,GAAG,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;gBAC7D,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC;aAC1C;SACF;KACF,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/plugins/image.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAgFhD,MAAM,WAAW,kBAAkB;IACjC;kDAC8C;IAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACzC;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,cAAc,CA2HzE"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/plugins/image.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AA0EhD,MAAM,WAAW,kBAAkB;IACjC;kDAC8C;IAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CACzC;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,kBAAuB,GAAG,cAAc,CAkIzE"}
@@ -5,8 +5,9 @@
5
5
  import { $getSelection, $setSelection, } from 'lexical';
6
6
  import { $insertNodeToNearestRoot } from '@lexical/utils';
7
7
  import { $createLLuiDecoratorNode, $isLLuiDecoratorNode, LLuiDecoratorNode, decoratorBridge, } from '@llui/lexical';
8
- import { button, component, div, img, input, text } from '@llui/dom';
8
+ import { button, div, img, input, text } from '@llui/dom';
9
9
  import { connect as connectDialog, overlay as overlayDialog, } from '@llui/components/dialog';
10
+ import { sanitizeImageUrl } from '../security.js';
10
11
  import { definePluginUI } from './ui.js';
11
12
  const BRIDGE_TYPE = 'image';
12
13
  function isImageData(value) {
@@ -15,16 +16,11 @@ function isImageData(value) {
15
16
  typeof value.src === 'string' &&
16
17
  typeof value.alt === 'string');
17
18
  }
18
- const imageBridge = decoratorBridge(BRIDGE_TYPE, (data) => component({
19
- name: 'Image',
20
- init: () => ({ src: data.src, alt: data.alt }),
21
- update: (state) => state,
22
- view: ({ state }) => [
23
- div({ 'data-scope': 'md-image', 'data-part': 'root', contenteditable: 'false' }, [
24
- img({ src: state.at('src'), alt: state.at('alt') }),
25
- ]),
26
- ],
27
- }));
19
+ const imageBridge = decoratorBridge(BRIDGE_TYPE, (data) => [
20
+ div({ 'data-scope': 'md-image', 'data-part': 'root', contenteditable: 'false' }, [
21
+ img({ src: data.at('src'), alt: data.at('alt') }),
22
+ ]),
23
+ ]);
28
24
  const IMAGE_TRANSFORMER = {
29
25
  dependencies: [LLuiDecoratorNode],
30
26
  export: (node) => {
@@ -35,7 +31,13 @@ const IMAGE_TRANSFORMER = {
35
31
  },
36
32
  regExp: /^!\[([^\]]*)\]\(([^)]+)\)$/,
37
33
  replace: (parentNode, _children, match) => {
38
- parentNode.replace($createLLuiDecoratorNode(BRIDGE_TYPE, { alt: match[1] ?? '', src: match[2] ?? '' }));
34
+ // Enforce the image-src allowlist on import/paste: a disallowed scheme
35
+ // (e.g. `javascript:`) sanitizes to null → drop the image entirely rather
36
+ // than materialize a decorator node bound to an unsafe src.
37
+ const src = sanitizeImageUrl(match[2] ?? '');
38
+ if (src === null)
39
+ return;
40
+ parentNode.replace($createLLuiDecoratorNode(BRIDGE_TYPE, { alt: match[1] ?? '', src }));
39
41
  },
40
42
  type: 'element',
41
43
  };
@@ -55,7 +57,9 @@ function dialogOpen(msg, current) {
55
57
  }
56
58
  }
57
59
  export function imagePlugin(opts = {}) {
58
- let savedSelection = null;
60
+ // Keyed by the per-mount editor so two mounts never cross-wire the selection
61
+ // saved while the insert dialog is open.
62
+ const savedSelection = new WeakMap();
59
63
  return {
60
64
  name: 'image',
61
65
  nodes: [LLuiDecoratorNode],
@@ -155,20 +159,24 @@ export function imagePlugin(opts = {}) {
155
159
  if (!editor)
156
160
  return;
157
161
  if (effect.type === 'begin') {
158
- savedSelection = editor.getEditorState().read(() => {
162
+ savedSelection.set(editor, editor.getEditorState().read(() => {
159
163
  const selection = $getSelection();
160
164
  return selection ? selection.clone() : null;
161
- });
165
+ }));
162
166
  return;
163
167
  }
164
- if (effect.src.trim() === '')
168
+ // Enforce the image-src allowlist at insert: a disallowed scheme drops
169
+ // the insertion rather than binding the decorator to an unsafe src.
170
+ const src = sanitizeImageUrl(effect.src.trim());
171
+ if (src === null)
165
172
  return;
173
+ const saved = savedSelection.get(editor) ?? null;
166
174
  editor.update(() => {
167
- if (savedSelection)
168
- $setSelection(savedSelection.clone());
169
- $insertNodeToNearestRoot($createLLuiDecoratorNode(BRIDGE_TYPE, { src: effect.src.trim(), alt: effect.alt }));
175
+ if (saved)
176
+ $setSelection(saved.clone());
177
+ $insertNodeToNearestRoot($createLLuiDecoratorNode(BRIDGE_TYPE, { src, alt: effect.alt }));
170
178
  });
171
- savedSelection = null;
179
+ savedSelection.delete(editor);
172
180
  },
173
181
  }),
174
182
  };
@@ -1 +1 @@
1
- {"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/plugins/image.ts"],"names":[],"mappings":"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","sourcesContent":["// Image plugin — a block image rendered via the decorator bridge, round-tripping\n// to `![alt](src)` markdown, inserted through a plugin-UI dialog (URL + alt, with\n// optional file upload). Exercises decorator rendering + a transformer + the\n// plugin-UI extension all at once.\n\nimport {\n $getSelection,\n $setSelection,\n type BaseSelection,\n type ElementNode,\n type LexicalNode,\n} from 'lexical'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { ElementTransformer } from '@lexical/markdown'\nimport {\n $createLLuiDecoratorNode,\n $isLLuiDecoratorNode,\n LLuiDecoratorNode,\n decoratorBridge,\n} from '@llui/lexical'\nimport { button, component, div, img, input, text, type Signal } from '@llui/dom'\nimport {\n connect as connectDialog,\n overlay as overlayDialog,\n type DialogMsg,\n} from '@llui/components/dialog'\nimport { definePluginUI } from './ui.js'\nimport type { MarkdownPlugin } from './types.js'\n\nconst BRIDGE_TYPE = 'image'\n\ninterface ImageData {\n src: string\n alt: string\n}\n\nfunction isImageData(value: unknown): value is ImageData {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as ImageData).src === 'string' &&\n typeof (value as ImageData).alt === 'string'\n )\n}\n\nconst imageBridge = decoratorBridge<ImageData, ImageData, { type: 'noop' }, never>(\n BRIDGE_TYPE,\n (data) =>\n component<ImageData, { type: 'noop' }, never>({\n name: 'Image',\n init: () => ({ src: data.src, alt: data.alt }),\n update: (state) => state,\n view: ({ state }) => [\n div({ 'data-scope': 'md-image', 'data-part': 'root', contenteditable: 'false' }, [\n img({ src: state.at('src') as Signal<string>, alt: state.at('alt') as Signal<string> }),\n ]),\n ],\n }),\n)\n\nconst IMAGE_TRANSFORMER: ElementTransformer = {\n dependencies: [LLuiDecoratorNode],\n export: (node: LexicalNode): string | null => {\n if (!$isLLuiDecoratorNode(node) || node.getBridgeType() !== BRIDGE_TYPE) return null\n const data = node.getData()\n return isImageData(data) ? `![${data.alt}](${data.src})` : null\n },\n regExp: /^!\\[([^\\]]*)\\]\\(([^)]+)\\)$/,\n replace: (parentNode: ElementNode, _children, match): void => {\n parentNode.replace(\n $createLLuiDecoratorNode(BRIDGE_TYPE, { alt: match[1] ?? '', src: match[2] ?? '' }),\n )\n },\n type: 'element',\n}\n\ninterface ImageState {\n dialog: { open: boolean }\n src: string\n alt: string\n}\n\ntype ImageMsg =\n | { type: 'open' }\n | { type: 'setSrc'; src: string }\n | { type: 'setAlt'; alt: string }\n | { type: 'submit' }\n | { type: 'dialog'; msg: DialogMsg }\n\ntype ImageEffect = { type: 'begin' } | { type: 'insert'; src: string; alt: string }\n\nfunction dialogOpen(msg: DialogMsg, current: boolean): boolean {\n switch (msg.type) {\n case 'open':\n return true\n case 'close':\n return false\n case 'toggle':\n return !current\n case 'setOpen':\n return msg.open\n case 'animationEnd':\n case 'transitionEnd':\n return current\n }\n}\n\nexport interface ImagePluginOptions {\n /** Upload a chosen file and resolve to its URL. When omitted, the file picker\n * is hidden and only URL entry is offered. */\n upload?: (file: File) => Promise<string>\n}\n\nexport function imagePlugin(opts: ImagePluginOptions = {}): MarkdownPlugin {\n let savedSelection: BaseSelection | null = null\n\n return {\n name: 'image',\n nodes: [LLuiDecoratorNode],\n decorators: [imageBridge],\n transformers: [IMAGE_TRANSFORMER],\n items: [\n {\n id: 'image',\n label: 'Image',\n icon: 'image',\n group: 'insert',\n keywords: ['img', 'picture', 'photo'],\n run: (_editor, ctx) => ctx.send({ type: 'plugin', name: 'image', msg: { type: 'open' } }),\n surfaces: ['toolbar', 'slash', 'context'],\n },\n ],\n ui: definePluginUI<ImageState, ImageMsg, ImageEffect>({\n init: () => ({ dialog: { open: false }, src: '', alt: '' }),\n update: (state, msg) => {\n switch (msg.type) {\n case 'open':\n return [{ dialog: { open: true }, src: '', alt: '' }, [{ type: 'begin' }]]\n case 'setSrc':\n return { ...state, src: msg.src }\n case 'setAlt':\n return { ...state, alt: msg.alt }\n case 'submit':\n return [\n { ...state, dialog: { open: false } },\n [{ type: 'insert', src: state.src, alt: state.alt }],\n ]\n case 'dialog': {\n const open = dialogOpen(msg.msg, state.dialog.open)\n return open === state.dialog.open ? state : { ...state, dialog: { open } }\n }\n }\n },\n view: ({ state, send }) => {\n const dialogSend = (msg: DialogMsg): void => send({ type: 'dialog', msg })\n const parts = connectDialog(state.at('dialog'), dialogSend, {\n id: 'md-image-dialog',\n closeLabel: 'Cancel',\n })\n return [\n overlayDialog({\n state: state.at('dialog'),\n send: dialogSend,\n parts,\n content: () => [\n div({ ...parts.content, 'data-md-link': 'box' }, [\n div({ ...parts.title, 'data-md-link': 'title' }, [text('Insert image')]),\n input({\n 'data-md-link': 'input',\n type: 'url',\n placeholder: 'https://example.com/image.png',\n value: state.at('src') as Signal<string>,\n onInput: (e: Event) =>\n send({ type: 'setSrc', src: (e.target as HTMLInputElement).value }),\n }),\n input({\n 'data-md-link': 'input',\n 'data-md-image': 'alt',\n type: 'text',\n placeholder: 'Alt text (description)',\n value: state.at('alt') as Signal<string>,\n onInput: (e: Event) =>\n send({ type: 'setAlt', alt: (e.target as HTMLInputElement).value }),\n }),\n ...(opts.upload\n ? [\n input({\n 'data-md-image': 'file',\n type: 'file',\n accept: 'image/*',\n onChange: (e: Event) => {\n const file = (e.target as HTMLInputElement).files?.[0]\n if (file && opts.upload) {\n void opts.upload(file).then((src) => send({ type: 'setSrc', src }))\n }\n },\n }),\n ]\n : []),\n div({ 'data-md-link': 'actions' }, [\n button({ ...parts.closeTrigger, 'data-md-link': 'cancel' }, [text('Cancel')]),\n button(\n {\n type: 'button',\n 'data-md-link': 'apply',\n onClick: () => send({ type: 'submit' }),\n },\n [text('Insert')],\n ),\n ]),\n ]),\n ],\n }),\n ]\n },\n onEffect: (effect, ctx) => {\n const editor = ctx.editor()\n if (!editor) return\n if (effect.type === 'begin') {\n savedSelection = editor.getEditorState().read(() => {\n const selection = $getSelection()\n return selection ? selection.clone() : null\n })\n return\n }\n if (effect.src.trim() === '') return\n editor.update(() => {\n if (savedSelection) $setSelection(savedSelection.clone())\n $insertNodeToNearestRoot(\n $createLLuiDecoratorNode(BRIDGE_TYPE, { src: effect.src.trim(), alt: effect.alt }),\n )\n })\n savedSelection = null\n },\n }),\n }\n}\n"]}
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/plugins/image.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/plugins/inline.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,+EAA+E;AAC/E,kFAAkF;AAClF,gFAAgF;AAChF,uDAAuD;AAEvD,OAAO,EAAE,mBAAmB,EAA2C,MAAM,SAAS,CAAA;AAOtF,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,CAAA;AAUlG,MAAM,IAAI,GAA0C;IAClD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,UAAU,CAAC;QACtB,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM;KAC1B;IACD,aAAa,EAAE;QACb,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC3B,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;KACjC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;CACF,CAAA;AAED,wDAAwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA;AACxE,CAAC;AAED;gFACgF;AAChF,MAAM,UAAU,WAAW,CAAC,UAAmC,cAAc;IAC3E,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;QACpB,OAAO;YACL,EAAE;YACF,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["// Shared inline text-formatting building blocks: the bold / italic /\n// strikethrough / code command items and the `FORMAT_TEXT_COMMAND` dispatcher.\n// Both `corePlugin` (the full GFM superset) and `singleBlockPlugin` (inline-only)\n// derive their inline surface from here, so the canonical inline-format set and\n// its labels/icons/keywords live in exactly one place.\n\nimport { FORMAT_TEXT_COMMAND, type LexicalEditor, type TextFormatType } from 'lexical'\nimport type { FormatState } from '../state.js'\nimport type { CommandItem } from './types.js'\n\n/** An inline text-format surfaced as a toolbar command item. */\nexport type InlineFormat = 'bold' | 'italic' | 'strikethrough' | 'code'\n\n/** The full inline-format set, in toolbar order. */\nexport const INLINE_FORMATS: readonly InlineFormat[] = ['bold', 'italic', 'strikethrough', 'code']\n\ninterface InlineFormatDef {\n label: string\n icon: string\n keywords: readonly string[]\n format: TextFormatType\n isActive: (f: FormatState) => boolean\n}\n\nconst DEFS: Record<InlineFormat, InlineFormatDef> = {\n bold: {\n label: 'Bold',\n icon: 'bold',\n keywords: ['strong'],\n format: 'bold',\n isActive: (f) => f.bold,\n },\n italic: {\n label: 'Italic',\n icon: 'italic',\n keywords: ['emphasis'],\n format: 'italic',\n isActive: (f) => f.italic,\n },\n strikethrough: {\n label: 'Strikethrough',\n icon: 'strikethrough',\n keywords: ['strike', 'del'],\n format: 'strikethrough',\n isActive: (f) => f.strikethrough,\n },\n code: {\n label: 'Inline code',\n icon: 'code',\n keywords: ['mono'],\n format: 'code',\n isActive: (f) => f.code,\n },\n}\n\n/** Dispatch a text-format toggle on the live editor. */\nexport function inlineFormatCommand(format: TextFormatType): (editor: LexicalEditor) => void {\n return (editor) => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format)\n}\n\n/** Build the inline `CommandItem`s for `formats` (default: all four), grouped\n * under `'inline'`. Surfaces are left unset (item appears in every surface). */\nexport function inlineItems(formats: readonly InlineFormat[] = INLINE_FORMATS): CommandItem[] {\n return formats.map((id) => {\n const def = DEFS[id]\n return {\n id,\n label: def.label,\n icon: def.icon,\n group: 'inline',\n keywords: def.keywords,\n run: inlineFormatCommand(def.format),\n isActive: def.isActive,\n }\n })\n}\n"]}
1
+ {"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/plugins/inline.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,+EAA+E;AAC/E,kFAAkF;AAClF,gFAAgF;AAChF,uDAAuD;AAEvD,OAAO,EAAE,mBAAmB,EAA2C,MAAM,SAAS,CAAA;AAOtF,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAA4B,CAAC,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,CAAC,CAAA;AAUlG,MAAM,IAAI,GAA0C;IAClD,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,QAAQ,CAAC;QACpB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;IACD,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,UAAU,CAAC;QACtB,MAAM,EAAE,QAAQ;QAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM;KAC1B;IACD,aAAa,EAAE;QACb,KAAK,EAAE,eAAe;QACtB,IAAI,EAAE,eAAe;QACrB,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC;QAC3B,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa;KACjC;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI;KACxB;CACF,CAAA;AAED,wDAAwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAA;AACxE,CAAC;AAED;gFACgF;AAChF,MAAM,UAAU,WAAW,CAAC,UAAmC,cAAc;IAC3E,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAA;QACpB,OAAO;YACL,EAAE;YACF,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/plugins/link.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AA4C7D,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,cAAc,CAkEvE"}
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/plugins/link.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,YAAY,CAAA;AA4C7D,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,cAAc,CA2EvE"}
@@ -6,6 +6,7 @@ import { $getSelection, $isRangeSelection, $setSelection, } from 'lexical';
6
6
  import { $findMatchingParent } from '@lexical/utils';
7
7
  import { $isLinkNode, $toggleLink } from '@lexical/link';
8
8
  import { linkDialog } from '../surfaces/link-dialog.js';
9
+ import { sanitizeLinkUrl } from '../security.js';
9
10
  import { definePluginUI } from './ui.js';
10
11
  const PLUGIN = 'link';
11
12
  /** Read the URL of the link wrapping the current selection (empty if none). */
@@ -35,8 +36,9 @@ function dialogOpen(msg, current) {
35
36
  }
36
37
  export function linkPlugin(opts = {}) {
37
38
  // Selection saved when the dialog opens (the modal steals focus/selection),
38
- // restored on commit. Encapsulated in the plugin instance not the core editor.
39
- let savedSelection = null;
39
+ // restored on commit. Keyed by the per-mount editor so two mounts of the same
40
+ // plugin instance never cross-wire their saved selection.
41
+ const savedSelection = new WeakMap();
40
42
  const item = {
41
43
  id: 'link',
42
44
  label: 'Link',
@@ -82,20 +84,25 @@ export function linkPlugin(opts = {}) {
82
84
  if (!editor)
83
85
  return;
84
86
  if (effect.type === 'begin') {
85
- savedSelection = editor.getEditorState().read(() => {
87
+ savedSelection.set(editor, editor.getEditorState().read(() => {
86
88
  const selection = $getSelection();
87
89
  return selection ? selection.clone() : null;
88
- });
90
+ }));
89
91
  ctx.send({ type: 'show', url: readLinkUrl(editor) });
90
92
  return;
91
93
  }
92
- const url = effect.url.trim();
94
+ // Enforce the URL-scheme allowlist at commit: a `javascript:`/`data:`
95
+ // href sanitizes to null → no link is created (unlink). The global
96
+ // LinkNode transform is the backstop, but blocking here avoids ever
97
+ // materializing the unsafe link.
98
+ const safe = sanitizeLinkUrl(effect.url.trim());
99
+ const saved = savedSelection.get(editor) ?? null;
93
100
  editor.update(() => {
94
- if (savedSelection)
95
- $setSelection(savedSelection.clone());
96
- $toggleLink(url === '' ? null : url);
101
+ if (saved)
102
+ $setSelection(saved.clone());
103
+ $toggleLink(safe === null || safe === '' ? null : safe);
97
104
  });
98
- savedSelection = null;
105
+ savedSelection.delete(editor);
99
106
  },
100
107
  }),
101
108
  };
@@ -1 +1 @@
1
- {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/plugins/link.ts"],"names":[],"mappings":"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","sourcesContent":["// The link plugin — a stateful, UI-bearing feature built entirely as a plugin\n// (no core editor changes). It owns its dialog state, its view (the modal), and\n// its effects (save/restore selection + toggle the link). This is the proof that\n// the plugin-UI extension makes such features pluggable rather than built-in.\n\nimport {\n $getSelection,\n $isRangeSelection,\n $setSelection,\n type BaseSelection,\n type LexicalEditor,\n} from 'lexical'\nimport { $findMatchingParent } from '@lexical/utils'\nimport { $isLinkNode, $toggleLink } from '@lexical/link'\nimport type { DialogMsg, DialogState } from '@llui/components/dialog'\nimport { linkDialog } from '../surfaces/link-dialog.js'\nimport { definePluginUI } from './ui.js'\nimport type { CommandItem, MarkdownPlugin } from './types.js'\n\nconst PLUGIN = 'link'\n\ninterface LinkState {\n dialog: DialogState\n url: string\n}\n\ntype LinkMsg =\n | { type: 'open' }\n | { type: 'show'; url: string }\n | { type: 'setUrl'; url: string }\n | { type: 'submit' }\n | { type: 'dialog'; msg: DialogMsg }\n\ntype LinkEffect = { type: 'begin' } | { type: 'commit'; url: string }\n\n/** Read the URL of the link wrapping the current selection (empty if none). */\nfunction readLinkUrl(editor: LexicalEditor): string {\n return editor.getEditorState().read(() => {\n const selection = $getSelection()\n if (!$isRangeSelection(selection)) return ''\n const link = $findMatchingParent(selection.anchor.getNode(), (node) => $isLinkNode(node))\n return $isLinkNode(link) ? link.getURL() : ''\n })\n}\n\nfunction dialogOpen(msg: DialogMsg, current: boolean): boolean {\n switch (msg.type) {\n case 'open':\n return true\n case 'close':\n return false\n case 'toggle':\n return !current\n case 'setOpen':\n return msg.open\n case 'animationEnd':\n case 'transitionEnd':\n return current\n }\n}\n\nexport interface LinkPluginOptions {\n /** Default URL pre-filled when there's no existing link (default ''). */\n defaultUrl?: string\n}\n\nexport function linkPlugin(opts: LinkPluginOptions = {}): MarkdownPlugin {\n // Selection saved when the dialog opens (the modal steals focus/selection),\n // restored on commit. Encapsulated in the plugin instance — not the core editor.\n let savedSelection: BaseSelection | null = null\n\n const item: CommandItem = {\n id: 'link',\n label: 'Link',\n icon: 'link',\n group: 'inline',\n keywords: ['url', 'href'],\n run: (_editor, ctx) => ctx.send({ type: 'plugin', name: PLUGIN, msg: { type: 'open' } }),\n isActive: (f) => f.link,\n surfaces: ['toolbar', 'floating', 'context'],\n }\n\n return {\n name: PLUGIN,\n items: [item],\n ui: definePluginUI<LinkState, LinkMsg, LinkEffect>({\n init: () => ({ dialog: { open: false }, url: opts.defaultUrl ?? '' }),\n update: (state, msg) => {\n switch (msg.type) {\n case 'open':\n return [state, [{ type: 'begin' }]]\n case 'show':\n return { dialog: { open: true }, url: msg.url }\n case 'setUrl':\n return { ...state, url: msg.url }\n case 'submit':\n return [{ ...state, dialog: { open: false } }, [{ type: 'commit', url: state.url }]]\n case 'dialog': {\n const open = dialogOpen(msg.msg, state.dialog.open)\n return open === state.dialog.open ? state : { ...state, dialog: { open } }\n }\n }\n },\n view: ({ state, send }) => [\n linkDialog({\n dialog: state.at('dialog'),\n url: state.at('url'),\n onInput: (url) => send({ type: 'setUrl', url }),\n onSubmit: () => send({ type: 'submit' }),\n onDialog: (msg) => send({ type: 'dialog', msg }),\n }),\n ],\n onEffect: (effect, ctx) => {\n const editor = ctx.editor()\n if (!editor) return\n if (effect.type === 'begin') {\n savedSelection = editor.getEditorState().read(() => {\n const selection = $getSelection()\n return selection ? selection.clone() : null\n })\n ctx.send({ type: 'show', url: readLinkUrl(editor) })\n return\n }\n const url = effect.url.trim()\n editor.update(() => {\n if (savedSelection) $setSelection(savedSelection.clone())\n $toggleLink(url === '' ? null : url)\n })\n savedSelection = null\n },\n }),\n }\n}\n"]}
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/plugins/link.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/plugins/math.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAgBnE,MAAM,WAAW,iBAAiB;IAChC;gCAC4B;IAC5B;;;0CAGsC;IACtC,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,cAAc,CA0EvE"}
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../../src/plugins/math.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAcnE,MAAM,WAAW,iBAAiB;IAChC;gCAC4B;IAC5B;;;0CAGsC;IACtC,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB;AAED,wBAAgB,UAAU,CAAC,IAAI,GAAE,iBAAsB,GAAG,cAAc,CA8DvE"}
@@ -4,7 +4,7 @@
4
4
  import {} from 'lexical';
5
5
  import { $insertNodeToNearestRoot } from '@lexical/utils';
6
6
  import { $createLLuiDecoratorNode, $isLLuiDecoratorNode, LLuiDecoratorNode, decoratorBridge, } from '@llui/lexical';
7
- import { component, div, span, text } from '@llui/dom';
7
+ import { div, span, text } from '@llui/dom';
8
8
  import { renderedPreview } from './_preview.js';
9
9
  const BRIDGE_TYPE = 'math';
10
10
  function isMathData(value) {
@@ -12,39 +12,30 @@ function isMathData(value) {
12
12
  }
13
13
  const stop = (e) => e.stopPropagation();
14
14
  export function mathPlugin(opts = {}) {
15
- const bridge = decoratorBridge(BRIDGE_TYPE, (data, api) => component({
16
- name: 'Math',
17
- init: () => ({ tex: data.tex }),
18
- update: (state, msg) => {
19
- if (msg.type === 'commit') {
20
- if (msg.tex === state.tex)
21
- return state;
22
- api.update({ tex: msg.tex });
23
- return { tex: msg.tex };
24
- }
25
- return state;
26
- },
27
- view: ({ state, send }) => {
28
- const children = [
29
- span({
30
- 'data-part': 'source',
31
- contenteditable: 'true',
32
- role: 'textbox',
33
- 'aria-label': 'TeX source',
34
- onKeyDown: stop,
35
- onBeforeInput: stop,
36
- onPaste: stop,
37
- onBlur: (e) => send({ type: 'commit', tex: e.target.textContent ?? '' }),
38
- }, [text(state.at('tex'))]),
39
- ];
40
- if (opts.render) {
41
- children.push(renderedPreview(state.at('tex'), opts.render, 'span'));
42
- }
43
- return [
44
- div({ 'data-scope': 'md-math', 'data-part': 'root', contenteditable: 'false' }, children),
45
- ];
46
- },
47
- }));
15
+ const bridge = decoratorBridge(BRIDGE_TYPE, (data, api) => {
16
+ const children = [
17
+ span({
18
+ 'data-part': 'source',
19
+ contenteditable: 'true',
20
+ role: 'textbox',
21
+ 'aria-label': 'TeX source',
22
+ onKeyDown: stop,
23
+ onBeforeInput: stop,
24
+ onPaste: stop,
25
+ onBlur: (e) => {
26
+ const tex = e.target.textContent ?? '';
27
+ if (tex !== data.peek().tex)
28
+ api.update({ tex });
29
+ },
30
+ }, [text(data.at('tex'))]),
31
+ ];
32
+ if (opts.render) {
33
+ children.push(renderedPreview(data.at('tex'), opts.render, 'span'));
34
+ }
35
+ return [
36
+ div({ 'data-scope': 'md-math', 'data-part': 'root', contenteditable: 'false' }, children),
37
+ ];
38
+ });
48
39
  const transformer = {
49
40
  dependencies: [LLuiDecoratorNode],
50
41
  export: (node) => {
@@ -1 +1 @@
1
- {"version":3,"file":"math.js","sourceRoot":"","sources":["../../src/plugins/math.ts"],"names":[],"mappings":"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","sourcesContent":["// Math plugin — a block math node ($$…$$) rendered via the decorator bridge. The\n// TeX source is editable inline (persists on blur); an optional `render` callback\n// (e.g. KaTeX) turns it into a typeset preview. Round-trips to `$$tex$$`.\n\nimport { type ElementNode, type LexicalNode } from 'lexical'\nimport { $insertNodeToNearestRoot } from '@lexical/utils'\nimport type { ElementTransformer } from '@lexical/markdown'\nimport {\n $createLLuiDecoratorNode,\n $isLLuiDecoratorNode,\n LLuiDecoratorNode,\n decoratorBridge,\n} from '@llui/lexical'\nimport { component, div, span, text, type Mountable, type Signal } from '@llui/dom'\nimport type { MarkdownPlugin } from './types.js'\nimport { renderedPreview, type PreviewRender } from './_preview.js'\n\nconst BRIDGE_TYPE = 'math'\n\ninterface MathData {\n tex: string\n}\n\nfunction isMathData(value: unknown): value is MathData {\n return typeof value === 'object' && value !== null && typeof (value as MathData).tex === 'string'\n}\n\ntype MathMsg = { type: 'commit'; tex: string }\n\nconst stop = (e: Event): void => e.stopPropagation()\n\nexport interface MathPluginOptions {\n /** Typeset TeX to an HTML string (e.g. via KaTeX). When omitted, the raw TeX is\n * shown in a styled box. */\n /** Render the TeX source to a preview. Return a DOM `Node` (mounted\n * directly, no sanitization) or a **trusted HTML string** (injected as-is\n * — sanitize it yourself, e.g. via DOMPurify, since it carries document\n * content). See `renderedPreview`. */\n render?: PreviewRender\n}\n\nexport function mathPlugin(opts: MathPluginOptions = {}): MarkdownPlugin {\n const bridge = decoratorBridge<MathData, MathData, MathMsg, never>(BRIDGE_TYPE, (data, api) =>\n component<MathData, MathMsg, never>({\n name: 'Math',\n init: () => ({ tex: data.tex }),\n update: (state, msg) => {\n if (msg.type === 'commit') {\n if (msg.tex === state.tex) return state\n api.update({ tex: msg.tex })\n return { tex: msg.tex }\n }\n return state\n },\n view: ({ state, send }) => {\n const children: Mountable[] = [\n span(\n {\n 'data-part': 'source',\n contenteditable: 'true',\n role: 'textbox',\n 'aria-label': 'TeX source',\n onKeyDown: stop,\n onBeforeInput: stop,\n onPaste: stop,\n onBlur: (e: FocusEvent) =>\n send({ type: 'commit', tex: (e.target as HTMLElement).textContent ?? '' }),\n },\n [text(state.at('tex') as Signal<string>)],\n ),\n ]\n if (opts.render) {\n children.push(renderedPreview(state.at('tex') as Signal<string>, opts.render, 'span'))\n }\n return [\n div({ 'data-scope': 'md-math', 'data-part': 'root', contenteditable: 'false' }, children),\n ]\n },\n }),\n )\n\n const transformer: ElementTransformer = {\n dependencies: [LLuiDecoratorNode],\n export: (node: LexicalNode): string | null => {\n if (!$isLLuiDecoratorNode(node) || node.getBridgeType() !== BRIDGE_TYPE) return null\n const data = node.getData()\n return isMathData(data) ? `$$${data.tex}$$` : null\n },\n regExp: /^\\$\\$(.+)\\$\\$$/,\n replace: (parentNode: ElementNode, _children, match): void => {\n parentNode.replace($createLLuiDecoratorNode(BRIDGE_TYPE, { tex: match[1] ?? '' }))\n },\n type: 'element',\n }\n\n return {\n name: 'math',\n nodes: [LLuiDecoratorNode],\n decorators: [bridge],\n transformers: [transformer],\n items: [\n {\n id: 'math',\n label: 'Math block',\n icon: 'math',\n group: 'insert',\n keywords: ['latex', 'tex', 'equation', 'formula'],\n run: (editor) =>\n editor.update(() =>\n $insertNodeToNearestRoot($createLLuiDecoratorNode(BRIDGE_TYPE, { tex: 'e = mc^2' })),\n ),\n surfaces: ['slash', 'context'],\n },\n ],\n }\n}\n"]}
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../../src/plugins/math.ts"],"names":[],"mappings":"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"}