@llui/markdown-editor 0.3.0 → 0.5.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 (54) hide show
  1. package/dist/editor.d.ts +15 -2
  2. package/dist/editor.d.ts.map +1 -1
  3. package/dist/editor.js +12 -2
  4. package/dist/editor.js.map +1 -1
  5. package/dist/index.d.ts +6 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +15 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugins/block-drag.d.ts +74 -0
  10. package/dist/plugins/block-drag.d.ts.map +1 -0
  11. package/dist/plugins/block-drag.js +983 -0
  12. package/dist/plugins/block-drag.js.map +1 -0
  13. package/dist/plugins/code-language.d.ts +60 -0
  14. package/dist/plugins/code-language.d.ts.map +1 -0
  15. package/dist/plugins/code-language.js +308 -0
  16. package/dist/plugins/code-language.js.map +1 -0
  17. package/dist/plugins/frontmatter.d.ts +45 -0
  18. package/dist/plugins/frontmatter.d.ts.map +1 -0
  19. package/dist/plugins/frontmatter.js +281 -0
  20. package/dist/plugins/frontmatter.js.map +1 -0
  21. package/dist/plugins/overlay.d.ts +1 -0
  22. package/dist/plugins/overlay.d.ts.map +1 -1
  23. package/dist/plugins/overlay.js +7 -0
  24. package/dist/plugins/overlay.js.map +1 -1
  25. package/dist/plugins/wikilink.d.ts +110 -0
  26. package/dist/plugins/wikilink.d.ts.map +1 -0
  27. package/dist/plugins/wikilink.js +692 -0
  28. package/dist/plugins/wikilink.js.map +1 -0
  29. package/dist/styles/block-drag.css +118 -0
  30. package/dist/styles/editor.css +112 -0
  31. package/dist/transformers/code.d.ts +24 -0
  32. package/dist/transformers/code.d.ts.map +1 -0
  33. package/dist/transformers/code.js +167 -0
  34. package/dist/transformers/code.js.map +1 -0
  35. package/dist/transformers/gfm.d.ts.map +1 -1
  36. package/dist/transformers/gfm.js +7 -2
  37. package/dist/transformers/gfm.js.map +1 -1
  38. package/dist/transformers/registry.d.ts +3 -0
  39. package/dist/transformers/registry.d.ts.map +1 -1
  40. package/dist/transformers/registry.js +26 -0
  41. package/dist/transformers/registry.js.map +1 -1
  42. package/package.json +42 -28
  43. package/src/editor.ts +27 -4
  44. package/src/index.ts +58 -1
  45. package/src/plugins/block-drag.ts +1175 -0
  46. package/src/plugins/code-language.ts +378 -0
  47. package/src/plugins/frontmatter.ts +324 -0
  48. package/src/plugins/overlay.ts +7 -0
  49. package/src/plugins/wikilink.ts +843 -0
  50. package/src/styles/block-drag.css +118 -0
  51. package/src/styles/editor.css +112 -0
  52. package/src/transformers/code.ts +174 -0
  53. package/src/transformers/gfm.ts +6 -2
  54. package/src/transformers/registry.ts +27 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/markdown-editor",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -21,43 +21,57 @@
21
21
  "types": "./dist/surfaces/toolbar.d.ts",
22
22
  "import": "./dist/surfaces/toolbar.js"
23
23
  },
24
- "./styles/editor.css": "./dist/styles/editor.css"
24
+ "./plugins/block-drag": {
25
+ "types": "./dist/plugins/block-drag.d.ts",
26
+ "import": "./dist/plugins/block-drag.js"
27
+ },
28
+ "./plugins/code-language": {
29
+ "types": "./dist/plugins/code-language.d.ts",
30
+ "import": "./dist/plugins/code-language.js"
31
+ },
32
+ "./plugins/wikilink": {
33
+ "types": "./dist/plugins/wikilink.d.ts",
34
+ "import": "./dist/plugins/wikilink.js"
35
+ },
36
+ "./styles/editor.css": "./dist/styles/editor.css",
37
+ "./styles/block-drag.css": "./dist/styles/block-drag.css"
25
38
  },
26
39
  "peerDependencies": {
27
- "lexical": "^0.46.0",
28
- "@lexical/markdown": "^0.46.0",
29
- "@lexical/rich-text": "^0.46.0",
30
- "@lexical/list": "^0.46.0",
31
- "@lexical/link": "^0.46.0",
32
- "@lexical/table": "^0.46.0",
33
- "@lexical/selection": "^0.46.0",
34
- "@lexical/utils": "^0.46.0",
35
- "@lexical/code-core": "^0.46.0",
40
+ "lexical": "^0.48.0",
41
+ "@lexical/markdown": "^0.48.0",
42
+ "@lexical/rich-text": "^0.48.0",
43
+ "@lexical/list": "^0.48.0",
44
+ "@lexical/link": "^0.48.0",
45
+ "@lexical/table": "^0.48.0",
46
+ "@lexical/selection": "^0.48.0",
47
+ "@lexical/utils": "^0.48.0",
48
+ "@lexical/code-core": "^0.48.0",
49
+ "@llui/lexical": "^0.4.0",
50
+ "@llui/components": "^0.13.0",
36
51
  "@llui/dom": "^0.12.0",
37
- "@llui/markdown": "^0.12.0",
38
- "@llui/lexical": "^0.3.0",
39
- "@llui/components": "^0.13.0"
52
+ "@llui/markdown": "^0.12.0"
40
53
  },
41
54
  "devDependencies": {
42
- "lexical": "^0.46.0",
43
- "@lexical/headless": "^0.46.0",
44
- "@lexical/markdown": "^0.46.0",
45
- "@lexical/rich-text": "^0.46.0",
46
- "@lexical/list": "^0.46.0",
47
- "@lexical/link": "^0.46.0",
48
- "@lexical/table": "^0.46.0",
49
- "@lexical/selection": "^0.46.0",
50
- "@lexical/utils": "^0.46.0",
55
+ "lexical": "^0.48.0",
56
+ "@lexical/headless": "^0.48.0",
57
+ "@lexical/markdown": "^0.48.0",
58
+ "@lexical/rich-text": "^0.48.0",
59
+ "@lexical/list": "^0.48.0",
60
+ "@lexical/link": "^0.48.0",
61
+ "@lexical/table": "^0.48.0",
62
+ "@lexical/selection": "^0.48.0",
63
+ "@lexical/utils": "^0.48.0",
51
64
  "typescript": "^6.0.0",
52
65
  "vitest": "^4.1.2",
53
- "@lexical/code-core": "^0.46.0",
66
+ "@lexical/code-core": "^0.48.0",
54
67
  "@llui/dom": "0.12.0",
68
+ "@llui/lexical": "0.4.0",
55
69
  "@llui/markdown": "0.12.0",
56
- "@llui/components": "0.13.0",
57
- "@llui/lexical": "0.3.0"
70
+ "@llui/components": "0.13.0"
58
71
  },
59
72
  "sideEffects": [
60
- "./dist/styles/editor.css"
73
+ "./dist/styles/editor.css",
74
+ "./dist/styles/block-drag.css"
61
75
  ],
62
76
  "description": "WYSIWYG Markdown editor for LLui — hides Markdown behind a rich, pluggable editing widget built on Lexical",
63
77
  "keywords": [
@@ -87,7 +101,7 @@
87
101
  "access": "public"
88
102
  },
89
103
  "scripts": {
90
- "build": "tsc -p tsconfig.build.json && mkdir -p dist/styles && cp src/styles/editor.css dist/styles/",
104
+ "build": "tsc -p tsconfig.build.json && mkdir -p dist/styles && cp src/styles/*.css dist/styles/",
91
105
  "check": "tsc --noEmit -p tsconfig.check.json",
92
106
  "lint": "eslint src",
93
107
  "test": "vitest run"
package/src/editor.ts CHANGED
@@ -83,10 +83,23 @@ export interface EditorConfig {
83
83
  }
84
84
 
85
85
  /** Disposer-returning binding the collab layer installs on the live editor.
86
- * `@llui/lexical-collab`'s `YjsCollab` satisfies this structurally, so
87
- * `@llui/markdown-editor` needs no Yjs dependency of its own. */
86
+ * `@llui/lexical-collab`'s `YjsCollab` and `@llui/lexical-loro`'s `LoroCollab`
87
+ * both satisfy this structurally, so `@llui/markdown-editor` needs neither a Yjs
88
+ * nor a Loro dependency of its own. */
88
89
  export interface CollabBinding {
89
90
  register: (editor: LexicalEditor) => () => void
91
+ /**
92
+ * A CRDT-aware undo owner, if the binding provides one SEPARATELY from
93
+ * `register`. When present it is handed to `lexicalForeign({ externalUndo })`,
94
+ * which forces the built-in `@lexical/history` stack off so the two can never
95
+ * both be live — this is what gives collab mode real, peer-scoped undo.
96
+ *
97
+ * Optional because not every binding splits undo out this way: `yjsCollab`
98
+ * installs its own undo commands INSIDE `register`, so it leaves this unset and
99
+ * still owns undo. A binding that sets neither would leave the editor with no
100
+ * undo at all — see `@llui/lexical-loro`, which sets this.
101
+ */
102
+ externalUndo?: (editor: LexicalEditor) => () => void
90
103
  }
91
104
 
92
105
  /** Hooks the editor injects into the {@link CollabFactory}: a markdown `seed`
@@ -291,8 +304,18 @@ export function markdownEditor(
291
304
  },
292
305
  // In collab mode the shared CRDT owns the document: the local undo stack
293
306
  // and the boot-time seed are disabled — the binding supplies a scoped undo
294
- // manager and a sync-gated bootstrap instead.
295
- ...(collabBinding ? { history: false, seedMode: 'deferred' as const } : {}),
307
+ // manager and a sync-gated bootstrap instead. A binding that owns undo via
308
+ // a SEPARATE `externalUndo` (Loro) has it wired here; one that owns undo
309
+ // inside its own `register` (Yjs) leaves the field unset. Either way the
310
+ // built-in history is off, so a binding that forgot both would show as "no
311
+ // undo" rather than fighting a local stack.
312
+ ...(collabBinding
313
+ ? {
314
+ history: false as const,
315
+ seedMode: 'deferred' as const,
316
+ ...(collabBinding.externalUndo ? { externalUndo: collabBinding.externalUndo } : {}),
317
+ }
318
+ : {}),
296
319
  defaultValue: collabBinding || config.value ? undefined : (config.defaultValue ?? ''),
297
320
  ...(config.value && !collabBinding ? { value: config.value } : {}),
298
321
  readonly: state.at('readonly'),
package/src/index.ts CHANGED
@@ -57,6 +57,17 @@ export {
57
57
  $insertCallout,
58
58
  } from './plugins/callout.js'
59
59
  export { hrPlugin, $insertHorizontalRule } from './plugins/hr.js'
60
+ export {
61
+ type FrontmatterData,
62
+ type FrontmatterPluginOptions,
63
+ FRONTMATTER_BRIDGE_TYPE,
64
+ FRONTMATTER_TRANSFORMER,
65
+ frontmatterPlugin,
66
+ serializeFrontmatter,
67
+ splitFrontmatter,
68
+ $getFrontmatter,
69
+ $setFrontmatter,
70
+ } from './plugins/frontmatter.js'
60
71
  export { slashPlugin } from './plugins/slash.js'
61
72
  export { contextMenuPlugin } from './plugins/context-menu.js'
62
73
  export { floatingToolbarPlugin } from './plugins/floating-toolbar.js'
@@ -66,11 +77,57 @@ export { type Mention, type MentionPluginOptions, mentionPlugin } from './plugin
66
77
  export { type EmojiPluginOptions, DEFAULT_EMOJI, emojiPlugin } from './plugins/emoji.js'
67
78
  export { type ImagePluginOptions, imagePlugin } from './plugins/image.js'
68
79
  export { tablePlugin } from './plugins/table.js'
80
+ export {
81
+ type CodeLanguagePluginOptions,
82
+ type CodeLanguageState,
83
+ type CodeLanguageMsg,
84
+ type CodeLanguageEffect,
85
+ CODE_LANGUAGE_PLUGIN,
86
+ codeLanguagePlugin,
87
+ } from './plugins/code-language.js'
88
+ export {
89
+ type WikiLink,
90
+ type WikiLinkPluginOptions,
91
+ type SerializedWikiLinkNode,
92
+ WikiLinkNode,
93
+ $createWikiLinkNode,
94
+ $isWikiLinkNode,
95
+ parseWikiLinkInner,
96
+ formatWikiLink,
97
+ // The representability guards that make `formatWikiLink` the true inverse of
98
+ // `parseWikiLinkInner`; exported so a host resolving/creating targets can
99
+ // apply the same normalization before it hands one to `$createWikiLinkNode`.
100
+ sanitizeWikiLinkTarget,
101
+ sanitizeWikiLinkAlias,
102
+ wikilinkPlugin,
103
+ } from './plugins/wikilink.js'
104
+ export {
105
+ type BlockDragOptions,
106
+ type BlockRect,
107
+ type DropTarget,
108
+ type IndicatorRect,
109
+ type Place,
110
+ BLOCK_DRAG_Z,
111
+ blockAtPoint,
112
+ findDropTarget,
113
+ indicatorRect,
114
+ blockDragPlugin,
115
+ } from './plugins/block-drag.js'
69
116
 
70
117
  export { $insertMarkdownAtSelection, registerMarkdownPaste } from './paste.js'
71
118
 
72
119
  export { GFM_NODES, GFM_TRANSFORMERS, HIGHLIGHT_TRANSFORMER } from './transformers/gfm.js'
73
- export { buildTransformers, orderTransformers } from './transformers/registry.js'
120
+ // The CommonMark-correct fenced-code transformer. Already part of
121
+ // `GFM_TRANSFORMERS`; exported for consumers assembling a transformer set by hand.
122
+ export { CODE_INFO_TRANSFORMER, normalizeCodeInfo } from './transformers/code.js'
123
+ // `setTransformerPrecedence` breaks ties between SAME-rank transformers, so a
124
+ // collision (e.g. wikilink vs upstream LINK, which both match at the same index)
125
+ // is resolved structurally instead of by the order a consumer lists plugins in.
126
+ export {
127
+ buildTransformers,
128
+ orderTransformers,
129
+ setTransformerPrecedence,
130
+ } from './transformers/registry.js'
74
131
 
75
132
  export { computeFormatState } from './format.js'
76
133