@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.
- package/dist/editor.d.ts +7 -0
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +66 -11
- package/dist/editor.js.map +1 -1
- package/dist/effects.d.ts +5 -4
- package/dist/effects.d.ts.map +1 -1
- package/dist/effects.js +11 -6
- package/dist/effects.js.map +1 -1
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/paste.d.ts.map +1 -1
- package/dist/paste.js +5 -0
- package/dist/paste.js.map +1 -1
- package/dist/plugins/_preview.js.map +1 -1
- package/dist/plugins/callout.d.ts.map +1 -1
- package/dist/plugins/callout.js +37 -45
- package/dist/plugins/callout.js.map +1 -1
- package/dist/plugins/context-menu.js.map +1 -1
- package/dist/plugins/core.js.map +1 -1
- package/dist/plugins/emoji.js.map +1 -1
- package/dist/plugins/floating-toolbar.js.map +1 -1
- package/dist/plugins/hr.d.ts.map +1 -1
- package/dist/plugins/hr.js +4 -7
- package/dist/plugins/hr.js.map +1 -1
- package/dist/plugins/image.d.ts.map +1 -1
- package/dist/plugins/image.js +28 -20
- package/dist/plugins/image.js.map +1 -1
- package/dist/plugins/inline.js.map +1 -1
- package/dist/plugins/link.d.ts.map +1 -1
- package/dist/plugins/link.js +16 -9
- package/dist/plugins/link.js.map +1 -1
- package/dist/plugins/math.d.ts.map +1 -1
- package/dist/plugins/math.js +25 -34
- package/dist/plugins/math.js.map +1 -1
- package/dist/plugins/mention.js.map +1 -1
- package/dist/plugins/mermaid.d.ts.map +1 -1
- package/dist/plugins/mermaid.js +25 -34
- package/dist/plugins/mermaid.js.map +1 -1
- package/dist/plugins/overlay.js.map +1 -1
- package/dist/plugins/single-block.js.map +1 -1
- package/dist/plugins/slash.js.map +1 -1
- package/dist/plugins/table.d.ts.map +1 -1
- package/dist/plugins/table.js +84 -19
- package/dist/plugins/table.js.map +1 -1
- package/dist/plugins/types.js.map +1 -1
- package/dist/plugins/ui.js.map +1 -1
- package/dist/security.d.ts +26 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +87 -0
- package/dist/security.js.map +1 -0
- package/dist/state.js.map +1 -1
- package/dist/styles/editor.css +0 -6
- package/dist/surfaces/link-dialog.js.map +1 -1
- package/dist/surfaces/toolbar.js.map +1 -1
- package/dist/theme.d.ts +2 -5
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +15 -11
- package/dist/theme.js.map +1 -1
- package/dist/transformers/gfm.d.ts +9 -1
- package/dist/transformers/gfm.d.ts.map +1 -1
- package/dist/transformers/gfm.js +9 -2
- package/dist/transformers/gfm.js.map +1 -1
- package/dist/transformers/registry.js.map +1 -1
- package/package.json +10 -8
- package/src/editor.ts +92 -11
- package/src/effects.ts +11 -7
- package/src/index.ts +3 -8
- package/src/paste.ts +5 -0
- package/src/plugins/callout.ts +44 -59
- package/src/plugins/hr.ts +4 -14
- package/src/plugins/image.ts +32 -29
- package/src/plugins/link.ts +20 -10
- package/src/plugins/math.ts +27 -41
- package/src/plugins/mermaid.ts +26 -45
- package/src/plugins/table.ts +94 -17
- package/src/security.ts +89 -0
- package/src/styles/editor.css +0 -6
- package/src/theme.ts +15 -11
- package/src/transformers/gfm.ts +10 -2
- package/dist/__llui_deps.json +0 -274
package/dist/editor.d.ts
CHANGED
|
@@ -62,6 +62,13 @@ export interface EditorParts {
|
|
|
62
62
|
/** Reactive format signal for `connect`-style toolbars. */
|
|
63
63
|
format: Signal<FormatState>;
|
|
64
64
|
}
|
|
65
|
+
/** Swallow the underline text-format command. `registerRichText` wires Cmd+U to
|
|
66
|
+
* FORMAT_TEXT 'underline', but the GFM markdown dialect this editor serializes
|
|
67
|
+
* has no underline representation, so an applied underline would be silently
|
|
68
|
+
* stripped on save. Intercepting at CRITICAL priority (ahead of rich-text) keeps
|
|
69
|
+
* the WYSIWYG surface and the serialized dialect in lock-step: underline can be
|
|
70
|
+
* neither applied nor lost. Returns a disposer. */
|
|
71
|
+
export declare function blockUnderlineFormat(editor: LexicalEditor): () => void;
|
|
65
72
|
/**
|
|
66
73
|
* Build the markdown editor component. Embed it with `mountApp(el, markdownEditor(...))`
|
|
67
74
|
* or compose it inside a larger component.
|
package/dist/editor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAMA,OAAO,
|
|
1
|
+
{"version":3,"file":"editor.d.ts","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"AAMA,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAA;AAMhB,OAAO,EAAmC,KAAK,MAAM,EAAE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAYjG,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAMrE,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,SAAS,EAEd,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,YAAY;IAC3B;2FACuF;IACvF,OAAO,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;IACnC,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACtB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,kBAAkB,CAAA;IAC1B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,uEAAuE;IACvE,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IAC9C,mFAAmF;IACnF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAA;IACzC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;+EAE2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;wEAIoE;IACpE,MAAM,CAAC,EAAE,aAAa,CAAA;CACvB;AAED;;iEAEiE;AACjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,MAAM,IAAI,CAAA;CAChD;AAED;;;yEAGyE;AACzE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAA;IACrC,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED,gEAAgE;AAChE,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,aAAa,CAAA;AAEjE,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;IAC7B,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAA;CAC5B;AAOD;;;;;mDAKmD;AACnD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,IAAI,CAMtE;AAeD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,GAAE,YAAiB,GACxB,kBAAkB,CAAC,WAAW,EAAE,SAAS,EAAE,YAAY,CAAC,CAwO1D"}
|
package/dist/editor.js
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
// surfaces the format state for the chrome, routes command intents back to the
|
|
4
4
|
// live editor through effects, and COMPOSES plugin UI extensions (each plugin's
|
|
5
5
|
// state slice + reducer + view + effects) into the single component.
|
|
6
|
-
import { $getRoot, $setSelection } from 'lexical';
|
|
6
|
+
import { $getRoot, $setSelection, COMMAND_PRIORITY_CRITICAL, FORMAT_TEXT_COMMAND, } from 'lexical';
|
|
7
7
|
import { $convertFromMarkdownString, $convertToMarkdownString, registerMarkdownShortcuts, } from '@lexical/markdown';
|
|
8
8
|
import { component, div } from '@llui/dom';
|
|
9
9
|
import { lexicalForeign, registerDecoratorBridges, PROGRAMMATIC_TAG, } from '@llui/lexical';
|
|
10
10
|
import { corePlugin } from './plugins/core.js';
|
|
11
11
|
import { linkPlugin } from './plugins/link.js';
|
|
12
12
|
import { registerMarkdownPaste } from './paste.js';
|
|
13
|
+
import { registerLinkSanitizer } from './security.js';
|
|
13
14
|
import { toolbar as renderToolbar } from './surfaces/toolbar.js';
|
|
14
15
|
import { buildTransformers } from './transformers/registry.js';
|
|
15
16
|
import { mergeTheme } from './theme.js';
|
|
@@ -20,6 +21,15 @@ import { countWords, init, update, } from './state.js';
|
|
|
20
21
|
function defaultPlugins() {
|
|
21
22
|
return [corePlugin(), linkPlugin()];
|
|
22
23
|
}
|
|
24
|
+
/** Swallow the underline text-format command. `registerRichText` wires Cmd+U to
|
|
25
|
+
* FORMAT_TEXT 'underline', but the GFM markdown dialect this editor serializes
|
|
26
|
+
* has no underline representation, so an applied underline would be silently
|
|
27
|
+
* stripped on save. Intercepting at CRITICAL priority (ahead of rich-text) keeps
|
|
28
|
+
* the WYSIWYG surface and the serialized dialect in lock-step: underline can be
|
|
29
|
+
* neither applied nor lost. Returns a disposer. */
|
|
30
|
+
export function blockUnderlineFormat(editor) {
|
|
31
|
+
return editor.registerCommand(FORMAT_TEXT_COMMAND, (payload) => payload === 'underline', COMMAND_PRIORITY_CRITICAL);
|
|
32
|
+
}
|
|
23
33
|
/**
|
|
24
34
|
* Build the markdown editor component. Embed it with `mountApp(el, markdownEditor(...))`
|
|
25
35
|
* or compose it inside a larger component.
|
|
@@ -37,11 +47,26 @@ export function markdownEditor(config = {}) {
|
|
|
37
47
|
.filter((p) => p.ui !== undefined)
|
|
38
48
|
.map((p) => ({ name: p.name, ui: p.ui }));
|
|
39
49
|
const pluginUIByName = new Map(pluginUIs.map((p) => [p.name, p.ui]));
|
|
40
|
-
//
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
// Per-MOUNT live-editor context, keyed by the mount's stable `send` closure —
|
|
51
|
+
// the SAME object the runtime hands to both `view` and `onEffect`. A single
|
|
52
|
+
// definition can be mounted more than once (or re-mounted); each mount gets its
|
|
53
|
+
// own editor reference here, so effects and plugin handlers dispatch to their
|
|
54
|
+
// own editor and unmount clears only that mount's reference (no cross-wiring,
|
|
55
|
+
// no leaked disposed editor). Entries are collected with their `send` key.
|
|
56
|
+
const mountContexts = new WeakMap();
|
|
57
|
+
const contextFor = (send) => {
|
|
58
|
+
let ctx = mountContexts.get(send);
|
|
59
|
+
if (!ctx) {
|
|
60
|
+
ctx = { editor: null, lastChange: undefined };
|
|
61
|
+
mountContexts.set(send, ctx);
|
|
62
|
+
}
|
|
63
|
+
return ctx;
|
|
64
|
+
};
|
|
65
|
+
const baseOnEffect = makeOnEffect((api) => contextFor(api.send).editor, itemsById, {
|
|
66
|
+
// NB: consumer `onChange` is delivered DIRECTLY from the foreign onChange
|
|
67
|
+
// wrapper (see `view` below), NOT through this effect path — the dispose-time
|
|
68
|
+
// debounce flush runs after the TEA loop is disposed, and a `send` from a
|
|
69
|
+
// disposed loop is dropped, so effect-routed delivery loses the final edit.
|
|
45
70
|
onFormatChange: config.onFormatChange,
|
|
46
71
|
applyValue: (editor, value) => editor.update(() => {
|
|
47
72
|
$convertFromMarkdownString(value, transformers);
|
|
@@ -85,9 +110,10 @@ export function markdownEditor(config = {}) {
|
|
|
85
110
|
};
|
|
86
111
|
const composedOnEffect = (effect, api) => {
|
|
87
112
|
if (effect.type === 'pluginEffect') {
|
|
113
|
+
const mount = contextFor(api.send);
|
|
88
114
|
const ui = pluginUIByName.get(effect.name);
|
|
89
115
|
ui?.onEffect?.(effect.effect, {
|
|
90
|
-
editor:
|
|
116
|
+
editor: () => mount.editor,
|
|
91
117
|
send: (msg) => api.send({ type: 'plugin', name: effect.name, msg }),
|
|
92
118
|
emit: (msg) => api.send(msg),
|
|
93
119
|
});
|
|
@@ -96,6 +122,9 @@ export function markdownEditor(config = {}) {
|
|
|
96
122
|
baseOnEffect(effect, api);
|
|
97
123
|
};
|
|
98
124
|
const view = ({ state, send, }) => {
|
|
125
|
+
// This mount's live-editor slot (keyed by this mount's `send`). `onReady`
|
|
126
|
+
// fills it; effects/plugins read it through `contextFor(api.send)`.
|
|
127
|
+
const mount = contextFor(send);
|
|
99
128
|
// Build the collab binding (once, at mount) from the consumer's factory,
|
|
100
129
|
// injecting the markdown seed + status sinks that mirror into `state.collab`.
|
|
101
130
|
const collabBinding = config.collab
|
|
@@ -129,7 +158,17 @@ export function markdownEditor(config = {}) {
|
|
|
129
158
|
? { changeDebounceMs: config.changeDebounceMs }
|
|
130
159
|
: {}),
|
|
131
160
|
register: (editor) => {
|
|
132
|
-
const disposers = [
|
|
161
|
+
const disposers = [
|
|
162
|
+
// Keep the WYSIWYG surface and the serialized GFM dialect in lock-step:
|
|
163
|
+
// underline (Cmd+U) has no markdown representation, so it is swallowed
|
|
164
|
+
// rather than applied-then-silently-stripped on save.
|
|
165
|
+
blockUnderlineFormat(editor),
|
|
166
|
+
registerMarkdownShortcuts(editor, transformers),
|
|
167
|
+
// Global scheme allowlist for links: the single backstop covering the
|
|
168
|
+
// link dialog, pasted/imported markdown, and the typed `[x](url)`
|
|
169
|
+
// shortcut. Image src is enforced in the image transformer.
|
|
170
|
+
registerLinkSanitizer(editor),
|
|
171
|
+
];
|
|
133
172
|
if (config.pasteMarkdown !== false)
|
|
134
173
|
disposers.push(registerMarkdownPaste(editor, transformers));
|
|
135
174
|
if (decorators.length > 0)
|
|
@@ -139,16 +178,32 @@ export function markdownEditor(config = {}) {
|
|
|
139
178
|
return () => {
|
|
140
179
|
for (const dispose of disposers)
|
|
141
180
|
dispose();
|
|
181
|
+
// Release this mount's editor reference so a disposed editor never
|
|
182
|
+
// leaks and stale effects can't reach a torn-down editor.
|
|
183
|
+
mount.editor = null;
|
|
142
184
|
};
|
|
143
185
|
},
|
|
144
186
|
onReady: (editor) => {
|
|
145
|
-
|
|
187
|
+
mount.editor = editor;
|
|
146
188
|
if (config.placeholder) {
|
|
147
189
|
editor.getRootElement()?.setAttribute('data-placeholder', config.placeholder);
|
|
148
190
|
}
|
|
149
191
|
config.onReady?.(editor);
|
|
150
192
|
},
|
|
151
|
-
onChange: (value) =>
|
|
193
|
+
onChange: (value) => {
|
|
194
|
+
// Deliver to the consumer DIRECTLY, independent of the TEA loop: the
|
|
195
|
+
// dispose-time debounce flush runs AFTER the component is disposed, and a
|
|
196
|
+
// `send` from a disposed loop is dropped — so routing consumer delivery
|
|
197
|
+
// through `send` would lose the last debounce window of typing on unmount.
|
|
198
|
+
// Deduped per mount so the same value isn't delivered twice.
|
|
199
|
+
if (value !== mount.lastChange) {
|
|
200
|
+
mount.lastChange = value;
|
|
201
|
+
config.onChange?.(value);
|
|
202
|
+
}
|
|
203
|
+
// Mirror into TEA state (value/dirty) while the loop is alive; dropped
|
|
204
|
+
// silently after dispose, which is fine — the consumer was already told.
|
|
205
|
+
send({ type: 'markdownChanged', value });
|
|
206
|
+
},
|
|
152
207
|
onSelectionChange: (ctx) => {
|
|
153
208
|
const format = computeFormatState(ctx.editor, ctx);
|
|
154
209
|
const text = ctx.editor.getEditorState().read(() => $getRoot().getTextContent());
|
|
@@ -165,7 +220,7 @@ export function markdownEditor(config = {}) {
|
|
|
165
220
|
const rendered = ui.view({
|
|
166
221
|
state: state.at(`plugins.${name}`),
|
|
167
222
|
send: (msg) => send({ type: 'plugin', name, msg }),
|
|
168
|
-
editor:
|
|
223
|
+
editor: () => mount.editor,
|
|
169
224
|
});
|
|
170
225
|
return Array.isArray(rendered) ? rendered : [rendered];
|
|
171
226
|
});
|
package/dist/editor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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","sourcesContent":["// `markdownEditor(config)` — the high-level component. Lexical owns the live\n// document; this wires the foreign seam to the markdown transformer converters,\n// surfaces the format state for the chrome, routes command intents back to the\n// live editor through effects, and COMPOSES plugin UI extensions (each plugin's\n// state slice + reducer + view + effects) into the single component.\n\nimport { $getRoot, $setSelection, type EditorThemeClasses, type LexicalEditor } from 'lexical'\nimport {\n $convertFromMarkdownString,\n $convertToMarkdownString,\n registerMarkdownShortcuts,\n} from '@lexical/markdown'\nimport { component, div, type Renderable, type Signal, type SignalComponentDef } from '@llui/dom'\nimport {\n lexicalForeign,\n registerDecoratorBridges,\n PROGRAMMATIC_TAG,\n type DecoratorBridge,\n} from '@llui/lexical'\nimport { corePlugin } from './plugins/core.js'\nimport { linkPlugin } from './plugins/link.js'\nimport { registerMarkdownPaste } from './paste.js'\nimport { toolbar as renderToolbar } from './surfaces/toolbar.js'\nimport type { CommandItem, MarkdownPlugin } from './plugins/types.js'\nimport type { PluginUI } from './plugins/ui.js'\nimport { buildTransformers } from './transformers/registry.js'\nimport { mergeTheme } from './theme.js'\nimport { computeFormatState } from './format.js'\nimport { makeOnEffect } from './effects.js'\nimport {\n countWords,\n init,\n update,\n type EditorEffect,\n type EditorMsg,\n type EditorOutMsg,\n type EditorState,\n type FormatState,\n} from './state.js'\n\nexport interface EditorConfig {\n /** Plugins composing the feature set; order defines transformer precedence.\n * Defaults to `[corePlugin(), linkPlugin()]` so the minimal editor has GFM + links. */\n plugins?: readonly MarkdownPlugin[]\n /** Initial markdown (uncontrolled seed). */\n defaultValue?: string\n /** Controlled: the consumer owns this signal; the editor follows it. */\n value?: Signal<string>\n /** Debounced markdown-emission window (ms). Default 300. */\n changeDebounceMs?: number\n placeholder?: string\n readonly?: boolean\n /** Lexical theme class map. */\n theme?: EditorThemeClasses\n /** Editor namespace (instance isolation). */\n namespace?: string\n /** Outbound markdown (after debounce). */\n onChange?: (markdown: string) => void\n /** Outbound format surface (for chrome built outside this package). */\n onFormatChange?: (format: FormatState) => void\n /** Receives the live Lexical editor at mount (imperative access, collab hooks). */\n onReady?: (editor: LexicalEditor) => void\n /** Render the built-in toolbar above the editor. Default false (minimal). */\n toolbar?: boolean\n /** Convert plain-text Markdown to rich content on paste. Default true.\n * Pastes that carry `text/html` are always left to Lexical's HTML import,\n * regardless of this flag. Set false to paste Markdown as literal text. */\n pasteMarkdown?: boolean\n /** Enable collaborative editing. The editor hands you a markdown `seed` and\n * status sinks; return a binding (build it with `yjsCollab` from\n * `@llui/lexical-collab`, wiring your own provider). Mutually exclusive with\n * `value` — the shared CRDT document, not a markdown signal, owns the content.\n * `defaultValue` becomes the seed the bootstrapping peer writes. */\n collab?: CollabFactory\n}\n\n/** Disposer-returning binding the collab layer installs on the live editor.\n * `@llui/lexical-collab`'s `YjsCollab` satisfies this structurally, so\n * `@llui/markdown-editor` needs no Yjs dependency of its own. */\nexport interface CollabBinding {\n register: (editor: LexicalEditor) => () => void\n}\n\n/** Hooks the editor injects into the {@link CollabFactory}: a markdown `seed`\n * (run once by the bootstrapping peer to fill an empty shared doc from\n * `defaultValue`) plus status sinks the editor mirrors into `state.collab`.\n * Spread straight into `yjsCollab({ id, provider, user, ...hooks })`. */\nexport interface CollabHooks {\n seed: (editor: LexicalEditor) => void\n onStatus: (connected: boolean) => void\n onSync: (synced: boolean) => void\n onPeers: (count: number) => void\n}\n\n/** Builds the collab binding from the editor-supplied hooks. */\nexport type CollabFactory = (hooks: CollabHooks) => CollabBinding\n\n/** Hooks the chrome layer (toolbar/menus) uses to compose around the editor. */\nexport interface EditorParts {\n /** The merged, surface-filtered command items. */\n items: readonly CommandItem[]\n /** Reactive format signal for `connect`-style toolbars. */\n format: Signal<FormatState>\n}\n\n/** Default plugin set when the consumer supplies none. */\nfunction defaultPlugins(): MarkdownPlugin[] {\n return [corePlugin(), linkPlugin()]\n}\n\n/**\n * Build the markdown editor component. Embed it with `mountApp(el, markdownEditor(...))`\n * or compose it inside a larger component.\n */\nexport function markdownEditor(\n config: EditorConfig = {},\n): SignalComponentDef<EditorState, EditorMsg, EditorEffect> {\n const plugins = config.plugins && config.plugins.length > 0 ? config.plugins : defaultPlugins()\n const transformers = buildTransformers(plugins)\n\n const items: CommandItem[] = plugins.flatMap((p) => p.items ?? [])\n const itemsById = new Map(items.map((i) => [i.id, i]))\n // Share the merged item list with plugins that want it (e.g. the slash menu).\n for (const plugin of plugins) plugin.onItems?.(items)\n const decorators: DecoratorBridge[] = plugins.flatMap((p) => p.decorators ?? [])\n const pluginUIs: Array<{ name: string; ui: PluginUI }> = plugins\n .filter((p): p is MarkdownPlugin & { ui: PluginUI } => p.ui !== undefined)\n .map((p) => ({ name: p.name, ui: p.ui }))\n const pluginUIByName = new Map(pluginUIs.map((p) => [p.name, p.ui]))\n\n // The live editor, captured at mount; effects dispatch through it.\n let editorRef: LexicalEditor | null = null\n const getEditor = (): LexicalEditor | null => editorRef\n\n const baseOnEffect = makeOnEffect(getEditor, itemsById, {\n onChange: config.onChange,\n onFormatChange: config.onFormatChange,\n applyValue: (editor, value) =>\n editor.update(\n () => {\n $convertFromMarkdownString(value, transformers)\n // Clear selection so the reconciler doesn't pull DOM focus into the\n // editor on an external push (e.g. typing in a bound source textarea).\n $setSelection(null)\n },\n { tag: PROGRAMMATIC_TAG },\n ),\n })\n\n if (config.collab && config.value) {\n throw new Error(\n 'markdownEditor: `collab` and `value` are mutually exclusive — in a collaborative ' +\n 'session the shared CRDT document owns the content, not a markdown signal. ' +\n 'Use `defaultValue` as the bootstrap seed instead.',\n )\n }\n\n const collabEnabled = !!config.collab\n const seedValue = config.value ? config.value.peek() : (config.defaultValue ?? '')\n\n // ── Composed TEA: core + plugin UI slices ──────────────────────────────────\n const composedInit = (): [EditorState, EditorEffect[]] => {\n const [core, effects] = init({\n value: seedValue,\n readonly: config.readonly ?? false,\n collab: collabEnabled,\n })\n const slices: Record<string, unknown> = {}\n for (const { name, ui } of pluginUIs) slices[name] = ui.init()\n return [{ ...core, plugins: slices }, effects]\n }\n\n const composedUpdate = (state: EditorState, msg: EditorMsg): [EditorState, EditorEffect[]] => {\n if (msg.type === 'plugin') {\n const ui = pluginUIByName.get(msg.name)\n if (!ui?.update) return [state, []]\n const result = ui.update(state.plugins[msg.name], msg.msg)\n const [slice, effects] = (Array.isArray(result) ? result : [result, []]) as [\n unknown,\n unknown[],\n ]\n return [\n { ...state, plugins: { ...state.plugins, [msg.name]: slice } },\n effects.map((effect) => ({ type: 'pluginEffect' as const, name: msg.name, effect })),\n ]\n }\n return update(state, msg)\n }\n\n const composedOnEffect = (\n effect: EditorEffect,\n api: { send: (msg: EditorMsg) => void; state: Signal<EditorState> },\n ): void => {\n if (effect.type === 'pluginEffect') {\n const ui = pluginUIByName.get(effect.name)\n ui?.onEffect?.(effect.effect, {\n editor: getEditor,\n send: (msg) => api.send({ type: 'plugin', name: effect.name, msg }),\n emit: (msg) => api.send(msg as EditorMsg),\n })\n return\n }\n baseOnEffect(effect, api)\n }\n\n const view = ({\n state,\n send,\n }: {\n state: Signal<EditorState>\n send: (msg: EditorMsg) => void\n }): Renderable => {\n // Build the collab binding (once, at mount) from the consumer's factory,\n // injecting the markdown seed + status sinks that mirror into `state.collab`.\n const collabBinding: CollabBinding | null = config.collab\n ? config.collab({\n seed: () => {\n $convertFromMarkdownString(seedValue, transformers)\n $setSelection(null)\n },\n onStatus: (connected) => send({ type: 'collabStatus', connected }),\n onSync: (synced) => send({ type: 'collabSync', synced }),\n onPeers: (peers) => send({ type: 'collabPeers', peers }),\n })\n : null\n\n const host = lexicalForeign<EditorOutMsg>({\n namespace: config.namespace ?? 'llui-markdown',\n theme: mergeTheme(config.theme),\n plugins,\n serialize: (editor) =>\n editor.getEditorState().read(() => $convertToMarkdownString(transformers)),\n deserialize: (_editor, value) => {\n $convertFromMarkdownString(value, transformers)\n $setSelection(null)\n },\n // In collab mode the shared CRDT owns the document: the local undo stack\n // and the boot-time seed are disabled — the binding supplies a scoped undo\n // manager and a sync-gated bootstrap instead.\n ...(collabBinding ? { history: false, seedMode: 'deferred' as const } : {}),\n defaultValue: collabBinding || config.value ? undefined : (config.defaultValue ?? ''),\n ...(config.value && !collabBinding ? { value: config.value } : {}),\n readonly: state.at('readonly'),\n ...(config.changeDebounceMs !== undefined\n ? { changeDebounceMs: config.changeDebounceMs }\n : {}),\n register: (editor) => {\n const disposers = [registerMarkdownShortcuts(editor, transformers)]\n if (config.pasteMarkdown !== false)\n disposers.push(registerMarkdownPaste(editor, transformers))\n if (decorators.length > 0) disposers.push(registerDecoratorBridges(editor, decorators))\n if (collabBinding) disposers.push(collabBinding.register(editor))\n return () => {\n for (const dispose of disposers) dispose()\n }\n },\n onReady: (editor) => {\n editorRef = editor\n if (config.placeholder) {\n editor.getRootElement()?.setAttribute('data-placeholder', config.placeholder)\n }\n config.onReady?.(editor)\n },\n onChange: (value) => send({ type: 'markdownChanged', value }),\n onSelectionChange: (ctx) => {\n const format = computeFormatState(ctx.editor, ctx)\n const text = ctx.editor.getEditorState().read(() => $getRoot().getTextContent())\n // Toggle an empty marker so CSS can show the placeholder.\n ctx.editor.getRootElement()?.setAttribute('data-empty', text === '' ? 'true' : 'false')\n send({ type: 'formatChanged', format, wordCount: countWords(text), charCount: text.length })\n },\n emit: (msg) => send(msg),\n })\n\n // Plugin view contributions (overlays/panels) — each gets its own slice + send.\n const pluginViews: Renderable = pluginUIs.flatMap(({ name, ui }) => {\n if (!ui.view) return []\n const rendered = ui.view({\n state: state.at(`plugins.${name}`),\n send: (msg) => send({ type: 'plugin', name, msg }),\n editor: getEditor,\n })\n return Array.isArray(rendered) ? rendered : [rendered]\n })\n\n if (!config.toolbar) return [host, ...pluginViews]\n return [\n div({ 'data-scope': 'md-editor', 'data-part': 'root' }, [\n renderToolbar({ format: state.at('format'), send, items, collab: state.at('collab') }),\n div({ 'data-scope': 'md-editor', 'data-part': 'surface' }, [host]),\n ]),\n ...pluginViews,\n ]\n }\n\n return component<EditorState, EditorMsg, EditorEffect>({\n name: 'MarkdownEditor',\n init: composedInit,\n update: composedUpdate,\n view,\n onEffect: composedOnEffect,\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"editor.js","sourceRoot":"","sources":["../src/editor.ts"],"names":[],"mappings":"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"}
|
package/dist/effects.d.ts
CHANGED
|
@@ -6,12 +6,13 @@ export interface EffectApi {
|
|
|
6
6
|
send: (msg: EditorMsg) => void;
|
|
7
7
|
}
|
|
8
8
|
export interface EffectConfig {
|
|
9
|
-
onChange?: (markdown: string) => void;
|
|
10
9
|
onFormatChange?: (format: FormatState) => void;
|
|
11
10
|
/** Push markdown into the live editor (deserialize), without echoing onChange. */
|
|
12
11
|
applyValue: (editor: LexicalEditor, value: string) => void;
|
|
13
12
|
}
|
|
14
|
-
/** Build the component's `onEffect`. `
|
|
15
|
-
*
|
|
16
|
-
|
|
13
|
+
/** Build the component's `onEffect`. `resolveEditor` maps the per-mount effect
|
|
14
|
+
* `api` (whose `send` identifies the mount) to that mount's live editor — so two
|
|
15
|
+
* mounts of one definition dispatch to their own editors; `items` is the merged
|
|
16
|
+
* id → command map. */
|
|
17
|
+
export declare function makeOnEffect(resolveEditor: (api: EffectApi) => LexicalEditor | null, items: ReadonlyMap<string, CommandItem>, config: EffectConfig): (effect: EditorEffect, api: EffectApi) => void;
|
|
17
18
|
//# sourceMappingURL=effects.d.ts.map
|
package/dist/effects.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effects.d.ts","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEtE,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,
|
|
1
|
+
{"version":3,"file":"effects.d.ts","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEtE,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAA;CAC/B;AAED,MAAM,WAAW,YAAY;IAC3B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IAC9C,kFAAkF;IAClF,UAAU,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3D;AAED;;;uBAGuB;AACvB,wBAAgB,YAAY,CAC1B,aAAa,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,aAAa,GAAG,IAAI,EACvD,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,EACvC,MAAM,EAAE,YAAY,GACnB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,KAAK,IAAI,CA2BhD"}
|
package/dist/effects.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
// Effect handler: the only place TEA reaches back into the live Lexical editor.
|
|
2
2
|
// `execCommand` looks an id up in the merged command-item map and runs it on the
|
|
3
3
|
// editor captured at mount; emit* forward to the consumer's callbacks.
|
|
4
|
-
/** Build the component's `onEffect`. `
|
|
5
|
-
*
|
|
6
|
-
|
|
4
|
+
/** Build the component's `onEffect`. `resolveEditor` maps the per-mount effect
|
|
5
|
+
* `api` (whose `send` identifies the mount) to that mount's live editor — so two
|
|
6
|
+
* mounts of one definition dispatch to their own editors; `items` is the merged
|
|
7
|
+
* id → command map. */
|
|
8
|
+
export function makeOnEffect(resolveEditor, items, config) {
|
|
7
9
|
return (effect, api) => {
|
|
8
10
|
switch (effect.type) {
|
|
9
11
|
case 'execCommand': {
|
|
10
|
-
const editor =
|
|
12
|
+
const editor = resolveEditor(api);
|
|
11
13
|
const item = items.get(effect.id);
|
|
12
14
|
if (editor && item)
|
|
13
15
|
item.run(editor, { send: api.send });
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
18
|
case 'applyValue': {
|
|
17
|
-
const editor =
|
|
19
|
+
const editor = resolveEditor(api);
|
|
18
20
|
if (editor)
|
|
19
21
|
config.applyValue(editor, effect.value);
|
|
20
22
|
return;
|
|
21
23
|
}
|
|
22
24
|
case 'emitChange': {
|
|
23
|
-
|
|
25
|
+
// Consumer `onChange` delivery moved to the foreign onChange wrapper (see
|
|
26
|
+
// editor.ts) so it survives dispose — the loop is torn down before the
|
|
27
|
+
// dispose-time debounce flush runs, and a `send`-routed effect would be
|
|
28
|
+
// dropped. This effect now only signals that state changed; no side effect.
|
|
24
29
|
return;
|
|
25
30
|
}
|
|
26
31
|
case 'emitFormat': {
|
package/dist/effects.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effects.js","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,uEAAuE;
|
|
1
|
+
{"version":3,"file":"effects.js","sourceRoot":"","sources":["../src/effects.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,uEAAuE;AAiBvE;;;uBAGuB;AACvB,MAAM,UAAU,YAAY,CAC1B,aAAuD,EACvD,KAAuC,EACvC,MAAoB;IAEpB,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACrB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,aAAa,CAAC,CAAC,CAAC;gBACnB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;gBACjC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;gBACjC,IAAI,MAAM,IAAI,IAAI;oBAAE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;gBACxD,OAAM;YACR,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAA;gBACjC,IAAI,MAAM;oBAAE,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;gBACnD,OAAM;YACR,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,0EAA0E;gBAC1E,uEAAuE;gBACvE,wEAAwE;gBACxE,4EAA4E;gBAC5E,OAAM;YACR,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBACtC,OAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
|
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8EAA8E;AAC9E,mEAAmE;AAEnE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAsB,MAAM,SAAS,CAAA;AAC9E,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAC3E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAoC,MAAM,YAAY,CAAA;AAE3E,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAChC,MAAqB,EACrB,OAAsD;IAEtD,OAAO,MAAM,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACvC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAA;QAC9B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAA;QAChF,CAAC;QAED,IAAI,SAAS,GAAc,IAAI,CAAC,SAAS,CAAA;QACzC,IAAI,IAAI,GAAG,KAAK,CAAA;QAEhB,MAAM,SAAS,GAAG,aAAa,EAAE,CAAA;QACjC,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;YAC7C,IAAI,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAA;YAE5E,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAA;gBACjF,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,IAAI,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;oBACxD,IAAI,IAAI;wBAAE,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;gBAC1C,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAA;oBACnF,IAAI,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC;wBAAE,SAAS,GAAG,MAAM,CAAA;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI;YACJ,SAAS;YACT,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,8EAA8E;AAC9E,mEAAmE;AAEnE,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAsB,MAAM,SAAS,CAAA;AAC9E,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAC3E,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,YAAY,EAAoC,MAAM,YAAY,CAAA;AAE3E,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAChC,MAAqB,EACrB,OAAsD;IAEtD,OAAO,MAAM,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;QACvC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAA;QAC9B,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,EAAE,GAAG,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAA;QAChF,CAAC;QAED,IAAI,SAAS,GAAc,IAAI,CAAC,SAAS,CAAA;QACzC,IAAI,IAAI,GAAG,KAAK,CAAA;QAEhB,MAAM,SAAS,GAAG,aAAa,EAAE,CAAA;QACjC,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;YAC7C,IAAI,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,CAAA;YAE5E,IAAI,IAAI,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAA;gBACjF,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,IAAI,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;oBACxD,IAAI,IAAI;wBAAE,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;gBAC1C,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAA;oBACnF,IAAI,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC;wBAAE,SAAS,GAAG,MAAM,CAAA;gBACjD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI;YACJ,SAAS;YACT,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;SACzB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type EditorConfig, type EditorParts, type CollabBinding, type CollabHooks, type CollabFactory, markdownEditor, } from './editor.js';
|
|
1
|
+
export { type EditorConfig, type EditorParts, type CollabBinding, type CollabHooks, type CollabFactory, markdownEditor, blockUnderlineFormat, } from './editor.js';
|
|
2
2
|
export { type BlockType, type FormatState, type OverlayKind, type CollabStatus, type EditorState, type EditorMsg, type EditorOutMsg, type EditorEffect, type InitOptions, EMPTY_FORMAT, COLLAB_OFF, init, update, countWords, } from './state.js';
|
|
3
3
|
export { type ItemSurface, type CommandItem, type CommandContext, type MarkdownPlugin, } from './plugins/types.js';
|
|
4
4
|
export { type PluginUI, type PluginUISpec, type PluginViewArgs, type PluginEffectContext, definePluginUI, } from './plugins/ui.js';
|
|
@@ -17,10 +17,10 @@ export { type EmojiPluginOptions, DEFAULT_EMOJI, emojiPlugin } from './plugins/e
|
|
|
17
17
|
export { type ImagePluginOptions, imagePlugin } from './plugins/image.js';
|
|
18
18
|
export { tablePlugin } from './plugins/table.js';
|
|
19
19
|
export { $insertMarkdownAtSelection, registerMarkdownPaste } from './paste.js';
|
|
20
|
-
export { GFM_NODES, GFM_TRANSFORMERS } from './transformers/gfm.js';
|
|
20
|
+
export { GFM_NODES, GFM_TRANSFORMERS, HIGHLIGHT_TRANSFORMER } from './transformers/gfm.js';
|
|
21
21
|
export { buildTransformers, orderTransformers } from './transformers/registry.js';
|
|
22
22
|
export { computeFormatState } from './format.js';
|
|
23
|
-
export { STRIKETHROUGH_CLASS,
|
|
23
|
+
export { STRIKETHROUGH_CLASS, defaultTheme, mergeTheme } from './theme.js';
|
|
24
24
|
export { type ToolbarItemParts, type ToolbarParts, type ToolbarOptions, DEFAULT_GLYPHS, connectToolbar, toolbar, } from './surfaces/toolbar.js';
|
|
25
25
|
export { type LinkDialogOptions, linkDialog } from './surfaces/link-dialog.js';
|
|
26
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,wBAAwB,EAC7B,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,oBAAoB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAE9E,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE1E,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `@llui/markdown-editor` — WYSIWYG Markdown editor for LLui, built on Lexical.
|
|
2
|
-
export { markdownEditor, } from './editor.js';
|
|
2
|
+
export { markdownEditor, blockUnderlineFormat, } from './editor.js';
|
|
3
3
|
export { EMPTY_FORMAT, COLLAB_OFF, init, update, countWords, } from './state.js';
|
|
4
4
|
export {} from './plugins/types.js';
|
|
5
5
|
export { definePluginUI, } from './plugins/ui.js';
|
|
@@ -18,10 +18,10 @@ export { DEFAULT_EMOJI, emojiPlugin } from './plugins/emoji.js';
|
|
|
18
18
|
export { imagePlugin } from './plugins/image.js';
|
|
19
19
|
export { tablePlugin } from './plugins/table.js';
|
|
20
20
|
export { $insertMarkdownAtSelection, registerMarkdownPaste } from './paste.js';
|
|
21
|
-
export { GFM_NODES, GFM_TRANSFORMERS } from './transformers/gfm.js';
|
|
21
|
+
export { GFM_NODES, GFM_TRANSFORMERS, HIGHLIGHT_TRANSFORMER } from './transformers/gfm.js';
|
|
22
22
|
export { buildTransformers, orderTransformers } from './transformers/registry.js';
|
|
23
23
|
export { computeFormatState } from './format.js';
|
|
24
|
-
export { STRIKETHROUGH_CLASS,
|
|
24
|
+
export { STRIKETHROUGH_CLASS, defaultTheme, mergeTheme } from './theme.js';
|
|
25
25
|
export { DEFAULT_GLYPHS, connectToolbar, toolbar, } from './surfaces/toolbar.js';
|
|
26
26
|
export { linkDialog } from './surfaces/link-dialog.js';
|
|
27
27
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,EAML,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAEhF,OAAO,EAML,cAAc,EACd,oBAAoB,GACrB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAUL,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,OAAO,EAKN,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAKL,cAAc,GACf,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAGL,iBAAiB,GAClB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAIL,aAAa,EACb,cAAc,GACf,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,OAAO,EAA0B,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAA6B,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAA2C,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,EAA2B,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACxF,OAAO,EAA2B,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAE9E,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC1F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAEjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE1E,OAAO,EAIL,cAAc,EACd,cAAc,EACd,OAAO,GACR,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAA0B,UAAU,EAAE,MAAM,2BAA2B,CAAA"}
|
package/dist/paste.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste.d.ts","sourceRoot":"","sources":["../src/paste.ts"],"names":[],"mappings":"AAMA,OAAO,EAUL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAA;AAChB,OAAO,EAA8B,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"paste.d.ts","sourceRoot":"","sources":["../src/paste.ts"],"names":[],"mappings":"AAMA,OAAO,EAUL,KAAK,aAAa,EACnB,MAAM,SAAS,CAAA;AAChB,OAAO,EAA8B,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAGhF;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,GAC/B,OAAO,CAqBT;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,KAAK,CAAC,WAAW,CAAC,GAC/B,MAAM,IAAI,CA6BZ"}
|
package/dist/paste.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// per-editor via the `pasteMarkdown: false` config option.
|
|
6
6
|
import { $createParagraphNode, $getSelection, $insertNodes, $isRangeSelection, $setSelection, COMMAND_PRIORITY_HIGH, PASTE_COMMAND, isDOMNode, isSelectionCapturedInDecoratorInput, } from 'lexical';
|
|
7
7
|
import { $convertFromMarkdownString } from '@lexical/markdown';
|
|
8
|
+
import { $sanitizeLinkNodes } from './security.js';
|
|
8
9
|
/**
|
|
9
10
|
* Parse `markdown` with `transformers` and insert the produced nodes at the
|
|
10
11
|
* current range selection. The document is parsed into a detached scratch
|
|
@@ -24,6 +25,10 @@ export function $insertMarkdownAtSelection(markdown, transformers) {
|
|
|
24
25
|
// touches the scratch node, not the live document.
|
|
25
26
|
const scratch = $createParagraphNode();
|
|
26
27
|
$convertFromMarkdownString(markdown, transformers, scratch);
|
|
28
|
+
// Untrusted source: neutralize any `javascript:`/`data:` link the markdown
|
|
29
|
+
// carried BEFORE the nodes are spliced into the live document. (Image src is
|
|
30
|
+
// enforced in the image transformer; links go through here.)
|
|
31
|
+
$sanitizeLinkNodes(scratch);
|
|
27
32
|
const nodes = scratch.getChildren();
|
|
28
33
|
if (nodes.length === 0)
|
|
29
34
|
return false;
|
package/dist/paste.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste.js","sourceRoot":"","sources":["../src/paste.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,2DAA2D;AAE3D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,mCAAmC,GAEpC,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,0BAA0B,EAAoB,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"paste.js","sourceRoot":"","sources":["../src/paste.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,2DAA2D;AAE3D,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,mCAAmC,GAEpC,MAAM,SAAS,CAAA;AAChB,OAAO,EAAE,0BAA0B,EAAoB,MAAM,mBAAmB,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAElD;;;;;;;;;GASG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAgB,EAChB,YAAgC;IAEhC,MAAM,SAAS,GAAG,aAAa,EAAE,CAAA;IACjC,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAA;IAC/C,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,EAAE,CAAA;IAE/B,kFAAkF;IAClF,mDAAmD;IACnD,MAAM,OAAO,GAAG,oBAAoB,EAAE,CAAA;IACtC,0BAA0B,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAA;IAC3D,2EAA2E;IAC3E,6EAA6E;IAC7E,6DAA6D;IAC7D,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAA;IACnC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IAEpC,6EAA6E;IAC7E,4EAA4E;IAC5E,aAAa,CAAC,KAAK,CAAC,CAAA;IACpB,YAAY,CAAC,KAAK,CAAC,CAAA;IACnB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAqB,EACrB,YAAgC;IAEhC,OAAO,MAAM,CAAC,eAAe,CAC3B,aAAa,EACb,CAAC,KAAqB,EAAE,EAAE;QACxB,qEAAqE;QACrE,wCAAwC;QACxC,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,mCAAmC,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAA;QAC9F,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,CAAA;QACrC,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAA;QAC5B,wEAAwE;QACxE,IAAI,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC;YAAE,OAAO,KAAK,CAAA;QACvD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC5C,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAA;QAEvB,qEAAqE;QACrE,sEAAsE;QACtE,wEAAwE;QACxE,sEAAsE;QACtE,wBAAwB;QACxB,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;QAErD,KAAK,CAAC,cAAc,EAAE,CAAA;QACtB,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE;YACjB,0BAA0B,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;QAChD,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC,EACD,qBAAqB,CACtB,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_preview.js","sourceRoot":"","sources":["../../src/plugins/_preview.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,qEAAqE;AACrE,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,oCAAoC;AACpC,mEAAmE;AACnE,wEAAwE;AACxE,yEAAyE;AACzE,2DAA2D;AAE3D,OAAO,EAAE,OAAO,EAA+B,MAAM,WAAW,CAAA;AAShE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,MAAqB,EACrB,GAAG,GAAG,KAAK;IAEX,OAAO,OAAO,CAA8C;QAC1D,GAAG;QACH,KAAK,EAAE,EAAE,MAAM,EAAE;QACjB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YACvB,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YACvC,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;YAC3C,MAAM,KAAK,GAAG,CAAC,KAAa,EAAQ,EAAE;gBACpC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;gBACzB,IAAI,OAAO,GAAG,KAAK,QAAQ;oBAAE,EAAE,CAAC,SAAS,GAAG,GAAG,CAAA;;oBAC1C,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC,CAAA;YACD,mEAAmE;YACnE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACvC,OAAO,EAAE,MAAM,EAAE,CAAA;QACnB,CAAC;QACD,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE;KACzC,CAAC,CAAA;AACJ,CAAC"
|
|
1
|
+
{"version":3,"file":"_preview.js","sourceRoot":"","sources":["../../src/plugins/_preview.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,qEAAqE;AACrE,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,oCAAoC;AACpC,mEAAmE;AACnE,wEAAwE;AACxE,yEAAyE;AACzE,2DAA2D;AAE3D,OAAO,EAAE,OAAO,EAA+B,MAAM,WAAW,CAAA;AAShE;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAsB,EACtB,MAAqB,EACrB,GAAG,GAAG,KAAK;IAEX,OAAO,OAAO,CAA8C;QAC1D,GAAG;QACH,KAAK,EAAE,EAAE,MAAM,EAAE;QACjB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;YACvB,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YACvC,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAA;YAC3C,MAAM,KAAK,GAAG,CAAC,KAAa,EAAQ,EAAE;gBACpC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;gBACzB,IAAI,OAAO,GAAG,KAAK,QAAQ;oBAAE,EAAE,CAAC,SAAS,GAAG,GAAG,CAAA;;oBAC1C,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;YAC9B,CAAC,CAAA;YACD,mEAAmE;YACnE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACvC,OAAO,EAAE,MAAM,EAAE,CAAA;QACnB,CAAC;QACD,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE;KACzC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../src/plugins/callout.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,iBAAiB,EAElB,MAAM,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE/D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;
|
|
1
|
+
{"version":3,"file":"callout.d.ts","sourceRoot":"","sources":["../../src/plugins/callout.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,iBAAiB,EAElB,MAAM,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE/D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,WAAW,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb;AA+FD,iFAAiF;AACjF,wBAAgB,cAAc,CAC5B,IAAI,GAAE,WAAoB,EAC1B,SAAS,SAAgB,GACxB,iBAAiB,CAEnB;AAyBD,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,oBAAyB,GAAG,cAAc,CA0B7E"}
|
package/dist/plugins/callout.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import {} from 'lexical';
|
|
6
6
|
import { $insertNodeToNearestRoot } from '@lexical/utils';
|
|
7
7
|
import { $createLLuiDecoratorNode, $isLLuiDecoratorNode, LLuiDecoratorNode, decoratorBridge, } from '@llui/lexical';
|
|
8
|
-
import { button,
|
|
8
|
+
import { button, div, span, text } from '@llui/dom';
|
|
9
9
|
const KIND_CYCLE = ['note', 'tip', 'warning', 'danger'];
|
|
10
10
|
const KIND_LABEL = {
|
|
11
11
|
note: 'Note',
|
|
@@ -29,50 +29,42 @@ function isCalloutData(value) {
|
|
|
29
29
|
const stop = (e) => e.stopPropagation();
|
|
30
30
|
/** The LLui sub-view rendered inside a callout DecoratorNode. The badge cycles
|
|
31
31
|
* the kind; the text is an editable island that persists into the Lexical node
|
|
32
|
-
* on blur (both round-trip to markdown).
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
contenteditable: 'true',
|
|
69
|
-
role: 'textbox',
|
|
70
|
-
'aria-label': 'Callout text',
|
|
71
|
-
onBlur: (e) => send({ type: 'commitText', text: e.target.textContent ?? '' }),
|
|
72
|
-
}, [text(state.at('text'))]),
|
|
73
|
-
]),
|
|
74
|
-
],
|
|
75
|
-
}));
|
|
32
|
+
* on blur (both round-trip to markdown). `data` is a reactive signal fed by the
|
|
33
|
+
* bridge, so a data commit updates the view IN PLACE — the editable island keeps
|
|
34
|
+
* its focus/caret instead of the whole sub-app remounting. */
|
|
35
|
+
const calloutBridge = decoratorBridge(BRIDGE_TYPE, (data, api) => [
|
|
36
|
+
div({
|
|
37
|
+
'data-scope': 'md-callout',
|
|
38
|
+
'data-part': 'root',
|
|
39
|
+
'data-kind': data.at('kind'),
|
|
40
|
+
contenteditable: 'false',
|
|
41
|
+
onKeyDown: stop,
|
|
42
|
+
onBeforeInput: stop,
|
|
43
|
+
onPaste: stop,
|
|
44
|
+
}, [
|
|
45
|
+
button({
|
|
46
|
+
type: 'button',
|
|
47
|
+
'data-part': 'badge',
|
|
48
|
+
'aria-label': 'Change callout kind',
|
|
49
|
+
onClick: () => {
|
|
50
|
+
const cur = data.peek();
|
|
51
|
+
api.update({ kind: nextKind(cur.kind), text: cur.text });
|
|
52
|
+
},
|
|
53
|
+
}, [text(data.at('kind').map((k) => KIND_LABEL[k]))]),
|
|
54
|
+
span({
|
|
55
|
+
'data-part': 'text',
|
|
56
|
+
contenteditable: 'true',
|
|
57
|
+
role: 'textbox',
|
|
58
|
+
'aria-label': 'Callout text',
|
|
59
|
+
onBlur: (e) => {
|
|
60
|
+
const cur = data.peek();
|
|
61
|
+
const value = e.target.textContent ?? '';
|
|
62
|
+
if (value !== cur.text)
|
|
63
|
+
api.update({ kind: cur.kind, text: value });
|
|
64
|
+
},
|
|
65
|
+
}, [text(data.at('text'))]),
|
|
66
|
+
]),
|
|
67
|
+
]);
|
|
76
68
|
/** `:::kind text` element transformer (single-line admonition). */
|
|
77
69
|
const CALLOUT_TRANSFORMER = {
|
|
78
70
|
dependencies: [LLuiDecoratorNode],
|