@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.
- package/dist/editor.d.ts +15 -2
- package/dist/editor.d.ts.map +1 -1
- package/dist/editor.js +12 -2
- package/dist/editor.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/block-drag.d.ts +74 -0
- package/dist/plugins/block-drag.d.ts.map +1 -0
- package/dist/plugins/block-drag.js +983 -0
- package/dist/plugins/block-drag.js.map +1 -0
- package/dist/plugins/code-language.d.ts +60 -0
- package/dist/plugins/code-language.d.ts.map +1 -0
- package/dist/plugins/code-language.js +308 -0
- package/dist/plugins/code-language.js.map +1 -0
- package/dist/plugins/frontmatter.d.ts +45 -0
- package/dist/plugins/frontmatter.d.ts.map +1 -0
- package/dist/plugins/frontmatter.js +281 -0
- package/dist/plugins/frontmatter.js.map +1 -0
- package/dist/plugins/overlay.d.ts +1 -0
- package/dist/plugins/overlay.d.ts.map +1 -1
- package/dist/plugins/overlay.js +7 -0
- package/dist/plugins/overlay.js.map +1 -1
- package/dist/plugins/wikilink.d.ts +110 -0
- package/dist/plugins/wikilink.d.ts.map +1 -0
- package/dist/plugins/wikilink.js +692 -0
- package/dist/plugins/wikilink.js.map +1 -0
- package/dist/styles/block-drag.css +118 -0
- package/dist/styles/editor.css +112 -0
- package/dist/transformers/code.d.ts +24 -0
- package/dist/transformers/code.d.ts.map +1 -0
- package/dist/transformers/code.js +167 -0
- package/dist/transformers/code.js.map +1 -0
- package/dist/transformers/gfm.d.ts.map +1 -1
- package/dist/transformers/gfm.js +7 -2
- package/dist/transformers/gfm.js.map +1 -1
- package/dist/transformers/registry.d.ts +3 -0
- package/dist/transformers/registry.d.ts.map +1 -1
- package/dist/transformers/registry.js +26 -0
- package/dist/transformers/registry.js.map +1 -1
- package/package.json +42 -28
- package/src/editor.ts +27 -4
- package/src/index.ts +58 -1
- package/src/plugins/block-drag.ts +1175 -0
- package/src/plugins/code-language.ts +378 -0
- package/src/plugins/frontmatter.ts +324 -0
- package/src/plugins/overlay.ts +7 -0
- package/src/plugins/wikilink.ts +843 -0
- package/src/styles/block-drag.css +118 -0
- package/src/styles/editor.css +112 -0
- package/src/transformers/code.ts +174 -0
- package/src/transformers/gfm.ts +6 -2
- package/src/transformers/registry.ts +27 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// YAML frontmatter plugin — the leading `---` … `---` metadata block.
|
|
2
|
+
//
|
|
3
|
+
// ## Why the block is an OPAQUE STRING, not parsed YAML
|
|
4
|
+
//
|
|
5
|
+
// Deliberate choice, and the requirement that drove it is round-trip fidelity:
|
|
6
|
+
// what the author wrote must come back out byte-for-byte. Two options exist —
|
|
7
|
+
// parse YAML properly, or don't parse it at all — and only the second is
|
|
8
|
+
// achievable here:
|
|
9
|
+
//
|
|
10
|
+
// - Parsing correctly means a real YAML 1.2 implementation (anchors, aliases,
|
|
11
|
+
// tags, flow/block collections, the five scalar styles, folded/literal block
|
|
12
|
+
// scalars with their indentation-indicator and chomping rules). Nothing
|
|
13
|
+
// smaller is *correct*, and a correct parser is not enough by itself: a
|
|
14
|
+
// round-trip also needs a comment- and style-preserving EMITTER, because
|
|
15
|
+
// `parse` → `stringify` normalizes quoting, key order, indentation and drops
|
|
16
|
+
// comments outright. That is a large dependency (this package deliberately
|
|
17
|
+
// dropped Prism from `@lexical/code` for exactly this reason — see
|
|
18
|
+
// `code-language.ts`) to buy a feature the editor does not need: it never
|
|
19
|
+
// interprets frontmatter, it only has to preserve it.
|
|
20
|
+
//
|
|
21
|
+
// - The naive middle ground — split each line on the first `:` into a
|
|
22
|
+
// `Record<string, string>` — is what the reference implementation this was
|
|
23
|
+
// modelled on does, and it is strictly WORSE than not parsing. Nested maps,
|
|
24
|
+
// sequences, block scalars, quoted values containing `:`, comments and blank
|
|
25
|
+
// lines are all silently flattened or destroyed. A lossy parse presented as
|
|
26
|
+
// structured data is a data-loss bug wearing a feature's clothes.
|
|
27
|
+
//
|
|
28
|
+
// So the block is stored verbatim as a single `source` string and re-emitted
|
|
29
|
+
// between two fences. Consumers that *want* structure own that choice: hand
|
|
30
|
+
// `$getFrontmatter()` to whatever YAML library they already ship, or supply
|
|
31
|
+
// `render` to draw a preview. The editor stays honest about not understanding it.
|
|
32
|
+
//
|
|
33
|
+
// The one unavoidable deviation from byte-for-byte: `$convertFromMarkdownString`
|
|
34
|
+
// runs `normalizeMarkdown`, which `trimEnd()`s every line BEFORE any transformer
|
|
35
|
+
// is consulted, so trailing whitespace inside the block is lost. That happens
|
|
36
|
+
// upstream of every transformer and cannot be intercepted from one. YAML treats
|
|
37
|
+
// trailing spaces as insignificant, so nothing meaningful changes. Likewise a
|
|
38
|
+
// body that is empty or only blank lines normalizes to the canonical `---\n---`.
|
|
39
|
+
//
|
|
40
|
+
// ## The `---` collision with `hrPlugin`
|
|
41
|
+
//
|
|
42
|
+
// `hrPlugin`'s ELEMENT transformer matches `/^(---|\*\*\*|___)\s*$/`, so before
|
|
43
|
+
// this plugin existed a leading frontmatter block parsed as a horizontal rule
|
|
44
|
+
// followed by loose prose. Telling consumers to drop `hrPlugin` is not a fix:
|
|
45
|
+
// `---` is legitimately both things, and which one it is depends on POSITION and
|
|
46
|
+
// CLOSURE, not on which plugin is loaded.
|
|
47
|
+
//
|
|
48
|
+
// The resolution is structural, not ordering-based. `@lexical/markdown`'s
|
|
49
|
+
// importer tries EVERY multiline-element transformer on a line before ANY
|
|
50
|
+
// element transformer (`$importMultiline` runs first in `$importMarkdownNodes`;
|
|
51
|
+
// export mirrors it with `[...multilineElement, ...element]`). This is therefore
|
|
52
|
+
// a `multiline-element` transformer, which means it is consulted ahead of the
|
|
53
|
+
// `hr` element transformer no matter where the two plugins sit in the array —
|
|
54
|
+
// plugin ORDER cannot change the outcome, and neither can loading or omitting
|
|
55
|
+
// `hrPlugin`.
|
|
56
|
+
//
|
|
57
|
+
// Claiming the line is then narrowed by `handleImportAfterStartMatch`, which
|
|
58
|
+
// returns `null` — "not mine, try the next transformer" — unless BOTH hold:
|
|
59
|
+
//
|
|
60
|
+
// 1. the fence is on line 0 (frontmatter is only frontmatter at the very top
|
|
61
|
+
// of the document), and
|
|
62
|
+
// 2. a closing `---` line exists somewhere below it.
|
|
63
|
+
//
|
|
64
|
+
// Declining falls through to `hrPlugin` (when loaded), so a `---` that is
|
|
65
|
+
// genuinely a thematic break — mid-document, or an unclosed one on line 1 —
|
|
66
|
+
// still becomes an `<hr>`. `replace` returns `false` so that TYPING `---` in the
|
|
67
|
+
// editor is likewise left to the hr shortcut; frontmatter is only ever created
|
|
68
|
+
// by importing markdown or by calling `$setFrontmatter`.
|
|
69
|
+
//
|
|
70
|
+
// The block closes at the FIRST subsequent line that is exactly `---`, which is
|
|
71
|
+
// the rule Jekyll / gray-matter / Hugo apply. A `---` *inside* a value (e.g.
|
|
72
|
+
// `title: a --- b`) is not a whole line and is preserved untouched.
|
|
73
|
+
import { $getRoot } from 'lexical';
|
|
74
|
+
import { $createLLuiDecoratorNode, $isLLuiDecoratorNode, LLuiDecoratorNode, decoratorBridge, } from '@llui/lexical';
|
|
75
|
+
import { div, textarea } from '@llui/dom';
|
|
76
|
+
import { renderedPreview } from './_preview.js';
|
|
77
|
+
/** The decorator bridge id for the frontmatter block. */
|
|
78
|
+
export const FRONTMATTER_BRIDGE_TYPE = 'frontmatter';
|
|
79
|
+
function isFrontmatterData(value) {
|
|
80
|
+
return (typeof value === 'object' &&
|
|
81
|
+
value !== null &&
|
|
82
|
+
typeof value.source === 'string');
|
|
83
|
+
}
|
|
84
|
+
/** A line consisting solely of `---` (trailing tabs/spaces tolerated — they are
|
|
85
|
+
* not content, and `normalizeMarkdown` has usually already trimmed them). */
|
|
86
|
+
const FENCE = /^---[ \t]*$/;
|
|
87
|
+
/** Render the fences back around an opaque body. An empty (or blank-only) body
|
|
88
|
+
* collapses to the canonical two-line form so the result stays idempotent. */
|
|
89
|
+
export function serializeFrontmatter(source) {
|
|
90
|
+
return source === '' ? '---\n---' : `---\n${source}\n---`;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The index of the closing fence, or `-1` when `lines` does not open a
|
|
94
|
+
* frontmatter block (no fence on line 0) or never closes one.
|
|
95
|
+
*
|
|
96
|
+
* The single definition of "is this frontmatter?", shared by the importer and
|
|
97
|
+
* {@link splitFrontmatter} so the two can never disagree. A returned index is
|
|
98
|
+
* always `>= 1`, which is the property the importer's anti-rewind invariant
|
|
99
|
+
* rests on (see `handleImportAfterStartMatch`).
|
|
100
|
+
*/
|
|
101
|
+
function closingFenceIndex(lines) {
|
|
102
|
+
const first = lines[0];
|
|
103
|
+
if (first === undefined || !FENCE.test(first))
|
|
104
|
+
return -1;
|
|
105
|
+
for (let i = 1; i < lines.length; i++) {
|
|
106
|
+
const line = lines[i];
|
|
107
|
+
if (line !== undefined && FENCE.test(line))
|
|
108
|
+
return i;
|
|
109
|
+
}
|
|
110
|
+
return -1;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Split a leading frontmatter block off a markdown string: `[body, rest]`, or
|
|
114
|
+
* `null` when the document has none (no line-0 fence, or no closing fence).
|
|
115
|
+
* Exported because a consumer often needs the metadata BEFORE building an
|
|
116
|
+
* editor — the same predicate the importer uses, so the two never disagree.
|
|
117
|
+
*/
|
|
118
|
+
export function splitFrontmatter(markdown) {
|
|
119
|
+
const lines = markdown.split('\n');
|
|
120
|
+
const end = closingFenceIndex(lines);
|
|
121
|
+
if (end === -1)
|
|
122
|
+
return null;
|
|
123
|
+
return [lines.slice(1, end).join('\n'), lines.slice(end + 1).join('\n')];
|
|
124
|
+
}
|
|
125
|
+
// ── Document accessors (run inside `editor.read` / `editor.update`) ──────────
|
|
126
|
+
/** The frontmatter node, if the document starts with one. */
|
|
127
|
+
function $frontmatterNode() {
|
|
128
|
+
const first = $getRoot().getFirstChild();
|
|
129
|
+
return $isLLuiDecoratorNode(first) && first.getBridgeType() === FRONTMATTER_BRIDGE_TYPE
|
|
130
|
+
? first
|
|
131
|
+
: null;
|
|
132
|
+
}
|
|
133
|
+
/** The document's frontmatter body, or `null` when it has none. */
|
|
134
|
+
export function $getFrontmatter() {
|
|
135
|
+
const node = $frontmatterNode();
|
|
136
|
+
if (!node || !$isLLuiDecoratorNode(node))
|
|
137
|
+
return null;
|
|
138
|
+
const data = node.getData();
|
|
139
|
+
return isFrontmatterData(data) ? data.source : null;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Set (or, with `null`, remove) the document's frontmatter. The block is always
|
|
143
|
+
* kept as the FIRST child of the root — it is only frontmatter there, and the
|
|
144
|
+
* exporter relies on that position (see the transformer's `export`).
|
|
145
|
+
*/
|
|
146
|
+
export function $setFrontmatter(source) {
|
|
147
|
+
const existing = $frontmatterNode();
|
|
148
|
+
if (source === null) {
|
|
149
|
+
existing?.remove();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (existing && $isLLuiDecoratorNode(existing)) {
|
|
153
|
+
existing.setData({ source });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const node = $createLLuiDecoratorNode(FRONTMATTER_BRIDGE_TYPE, { source });
|
|
157
|
+
const root = $getRoot();
|
|
158
|
+
const first = root.getFirstChild();
|
|
159
|
+
if (first)
|
|
160
|
+
first.insertBefore(node);
|
|
161
|
+
else
|
|
162
|
+
root.append(node);
|
|
163
|
+
}
|
|
164
|
+
// ── Transformer ─────────────────────────────────────────────────────────────
|
|
165
|
+
const FRONTMATTER_TRANSFORMER = {
|
|
166
|
+
dependencies: [LLuiDecoratorNode],
|
|
167
|
+
export: (node) => {
|
|
168
|
+
if (!$isLLuiDecoratorNode(node) || node.getBridgeType() !== FRONTMATTER_BRIDGE_TYPE)
|
|
169
|
+
return null;
|
|
170
|
+
const data = node.getData();
|
|
171
|
+
if (!isFrontmatterData(data))
|
|
172
|
+
return null;
|
|
173
|
+
// Only the document's FIRST block can be emitted as fences: `---` anywhere
|
|
174
|
+
// else re-imports as a thematic break, which would silently destroy the
|
|
175
|
+
// metadata on the next round-trip. A stray block (dragged out of position,
|
|
176
|
+
// pasted into a quote, …) degrades to a visible ```yaml code fence instead —
|
|
177
|
+
// lossy in node type, but the text survives and the author can see why.
|
|
178
|
+
if ($getRoot().getFirstChild() !== node)
|
|
179
|
+
return '```yaml\n' + data.source + '\n```';
|
|
180
|
+
return serializeFrontmatter(data.source);
|
|
181
|
+
},
|
|
182
|
+
regExpStart: FENCE,
|
|
183
|
+
// Never consulted: `handleImportAfterStartMatch` below always returns a
|
|
184
|
+
// decision, so the default open/close scan is not reached. Declared because
|
|
185
|
+
// the shape requires the pair to be meaningful together.
|
|
186
|
+
regExpEnd: FENCE,
|
|
187
|
+
handleImportAfterStartMatch: ({ lines, rootNode, startLineIndex }) => {
|
|
188
|
+
// Frontmatter exists only at the very top of the document. Anywhere else a
|
|
189
|
+
// `---` is a thematic break — decline so `hrPlugin` (or plain prose) gets it.
|
|
190
|
+
//
|
|
191
|
+
// INVARIANT — do not relax this guard without also fixing the scan below.
|
|
192
|
+
// `$importMarkdownNodes` assigns `i = shiftedIndex` from the returned tuple,
|
|
193
|
+
// so a returned index <= `startLineIndex` REWINDS its loop and the importer
|
|
194
|
+
// spins forever (not a wrong parse — a hang). The scan starts at line 1, so
|
|
195
|
+
// pinning `startLineIndex` to 0 is what makes every returned index strictly
|
|
196
|
+
// greater. A positional relaxation must start the scan at `startLineIndex + 1`.
|
|
197
|
+
if (startLineIndex !== 0)
|
|
198
|
+
return null;
|
|
199
|
+
const end = closingFenceIndex(lines);
|
|
200
|
+
if (end !== -1) {
|
|
201
|
+
// Verbatim body: no trimming, no interpretation, blank lines preserved.
|
|
202
|
+
const source = lines.slice(1, end).join('\n');
|
|
203
|
+
rootNode.append($createLLuiDecoratorNode(FRONTMATTER_BRIDGE_TYPE, { source }));
|
|
204
|
+
return [true, end];
|
|
205
|
+
}
|
|
206
|
+
// Unclosed: this is a lone `---` on line 1, i.e. a horizontal rule.
|
|
207
|
+
return null;
|
|
208
|
+
},
|
|
209
|
+
// Typing `---` must never produce frontmatter — returning false hands the
|
|
210
|
+
// markdown shortcut back to `hrPlugin`. Use `$setFrontmatter` to create one.
|
|
211
|
+
replace: () => false,
|
|
212
|
+
type: 'multiline-element',
|
|
213
|
+
};
|
|
214
|
+
export { FRONTMATTER_TRANSFORMER };
|
|
215
|
+
/** Keep editor-level key/paste handling out of the frontmatter island. */
|
|
216
|
+
const stop = (e) => e.stopPropagation();
|
|
217
|
+
export function frontmatterPlugin(opts = {}) {
|
|
218
|
+
const editable = opts.editable ?? true;
|
|
219
|
+
const bridge = decoratorBridge(FRONTMATTER_BRIDGE_TYPE, (data, api) => {
|
|
220
|
+
const children = [];
|
|
221
|
+
if (editable) {
|
|
222
|
+
children.push(
|
|
223
|
+
// A <textarea>, NOT a contenteditable div: newlines are load-bearing in
|
|
224
|
+
// YAML, and a contenteditable's `textContent` drops the <br>/<div> line
|
|
225
|
+
// structure the browser inserts, so committing from one silently
|
|
226
|
+
// flattens a multi-line block into a single line.
|
|
227
|
+
textarea({
|
|
228
|
+
'data-scope': 'md-frontmatter',
|
|
229
|
+
'data-part': 'source',
|
|
230
|
+
'aria-label': opts.label ?? 'Frontmatter',
|
|
231
|
+
placeholder: opts.placeholder ?? 'key: value',
|
|
232
|
+
spellcheck: 'false',
|
|
233
|
+
autocapitalize: 'off',
|
|
234
|
+
autocomplete: 'off',
|
|
235
|
+
value: data.at('source'),
|
|
236
|
+
// Grow with the content so the whole block stays visible.
|
|
237
|
+
rows: data.at('source').map((source) => String(Math.max(1, source.split('\n').length))),
|
|
238
|
+
onKeyDown: stop,
|
|
239
|
+
onBeforeInput: stop,
|
|
240
|
+
onPaste: stop,
|
|
241
|
+
// Commit on blur only: while the caret is inside, the node data is
|
|
242
|
+
// deliberately stale so the reactive `value` binding cannot rewrite
|
|
243
|
+
// what is being typed.
|
|
244
|
+
onBlur: (e) => {
|
|
245
|
+
const source = e.target.value;
|
|
246
|
+
if (source !== data.peek().source)
|
|
247
|
+
api.update({ source });
|
|
248
|
+
},
|
|
249
|
+
}));
|
|
250
|
+
}
|
|
251
|
+
if (opts.render) {
|
|
252
|
+
children.push(renderedPreview(data.at('source'), opts.render));
|
|
253
|
+
}
|
|
254
|
+
return [
|
|
255
|
+
div({ 'data-scope': 'md-frontmatter', 'data-part': 'root', contenteditable: 'false' }, children),
|
|
256
|
+
];
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
name: 'frontmatter',
|
|
260
|
+
nodes: [LLuiDecoratorNode],
|
|
261
|
+
decorators: [bridge],
|
|
262
|
+
transformers: [FRONTMATTER_TRANSFORMER],
|
|
263
|
+
items: [
|
|
264
|
+
{
|
|
265
|
+
id: 'frontmatter',
|
|
266
|
+
label: 'Frontmatter',
|
|
267
|
+
icon: 'frontmatter',
|
|
268
|
+
group: 'insert',
|
|
269
|
+
keywords: ['frontmatter', 'yaml', 'metadata', 'front matter'],
|
|
270
|
+
// Idempotent: a document already carrying frontmatter is left alone
|
|
271
|
+
// rather than having its metadata blanked.
|
|
272
|
+
run: (editor) => editor.update(() => {
|
|
273
|
+
if ($getFrontmatter() === null)
|
|
274
|
+
$setFrontmatter('');
|
|
275
|
+
}),
|
|
276
|
+
surfaces: ['slash', 'context'],
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/plugins/frontmatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/plugins/overlay.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../src/plugins/overlay.ts"],"names":[],"mappings":"AAwBA,OAAO,EAOL,KAAK,UAAU,EACf,KAAK,MAAM,EACZ,MAAM,WAAW,CAAA;AAGlB,eAAO,MAAM,SAAS;;;;;;CAUZ,CAAA;AAWV,MAAM,WAAW,iBAAiB;IAChC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IACrB,2CAA2C;IAC3C,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACjB,2CAA2C;IAC3C,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACjB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,UAAU,CAAA;IACzB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,UAAU,CAAA;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,UAAU,CA2B9D;AAED;mDACmD;AACnD,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAEpE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAoB5D"}
|
package/dist/plugins/overlay.js
CHANGED
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
// 61 — context menu — pointer-anchored
|
|
19
19
|
// 62 — floating selection toolbar — selection-anchored bubble
|
|
20
20
|
// 63 — table tools — element-anchored, sits over a table
|
|
21
|
+
// 64 — code-block language badge — element-anchored, may sit INSIDE a
|
|
22
|
+
// table cell, so it must clear 63
|
|
21
23
|
// The values live with each plugin's view; this comment is the source of truth.
|
|
22
24
|
import { div, derived, onMount, portal, show, } from '@llui/dom';
|
|
23
25
|
import { registerNestedLayer } from '@llui/components/utils';
|
|
@@ -26,6 +28,11 @@ export const OVERLAY_Z = {
|
|
|
26
28
|
contextMenu: 61,
|
|
27
29
|
floatingToolbar: 62,
|
|
28
30
|
tableTools: 63,
|
|
31
|
+
// Strictly above `tableTools`: a fenced code block can live inside a table
|
|
32
|
+
// cell, in which case both surfaces are open at once. At an equal z-index the
|
|
33
|
+
// clickable one was decided by portal insertion order — i.e. by plugin array
|
|
34
|
+
// order — which is exactly the no-tie rule this scale exists to prevent.
|
|
35
|
+
codeLanguage: 64,
|
|
29
36
|
};
|
|
30
37
|
const toMountables = (r) => [...r];
|
|
31
38
|
// Unique marker per overlay instance so its portal root can be located while
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/plugins/overlay.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,iFAAiF;AACjF,8EAA8E;AAC9E,+EAA+E;AAC/E,mDAAmD;AACnD,EAAE;AACF,kFAAkF;AAClF,gFAAgF;AAChF,6EAA6E;AAC7E,kFAAkF;AAClF,sFAAsF;AACtF,EAAE;AACF,8BAA8B;AAC9B,0EAA0E;AAC1E,qEAAqE;AACrE,gEAAgE;AAChE,yEAAyE;AACzE,mFAAmF;AACnF,gFAAgF;AAEhF,OAAO,EACL,GAAG,EACH,OAAO,EACP,OAAO,EACP,MAAM,EACN,IAAI,GAIL,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAE5D,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,SAAS,EAAE,EAAE;IACb,WAAW,EAAE,EAAE;IACf,eAAe,EAAE,EAAE;IACnB,UAAU,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../../src/plugins/overlay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { TextNode, type EditorConfig, type LexicalEditor, type LexicalNode, type LexicalUpdateJSON, type NodeKey, type SerializedTextNode, type Spread } from 'lexical';
|
|
2
|
+
import type { MarkdownPlugin } from './types.js';
|
|
3
|
+
/** A parsed wikilink. `alias` is `null` when the target is shown verbatim. */
|
|
4
|
+
export interface WikiLink {
|
|
5
|
+
target: string;
|
|
6
|
+
alias: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Parse the content BETWEEN the brackets. Returns `null` when the content is not
|
|
10
|
+
* a valid wikilink body.
|
|
11
|
+
*
|
|
12
|
+
* Deliberate choices, each load-bearing for exact round-tripping:
|
|
13
|
+
* * split on the FIRST `|` only, so `[[a|b|c]]` has alias `b|c` and re-exports
|
|
14
|
+
* byte-identically;
|
|
15
|
+
* * an EMPTY alias (`[[a|]]`) normalizes to no alias — the alternative
|
|
16
|
+
* (keeping `alias: ''`) would render a zero-width, unclickable node;
|
|
17
|
+
* * NO trimming. `[[ a ]]` keeps its spaces, because trimming would make
|
|
18
|
+
* import→export lossy. Presentation trimming is the host's call in
|
|
19
|
+
* `onNavigate`/`resolve`, not the document's.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseWikiLinkInner(inner: string): WikiLink | null;
|
|
22
|
+
/** Sanitize a target. Returns `null` when nothing usable survives. */
|
|
23
|
+
export declare function sanitizeWikiLinkTarget(raw: string): string | null;
|
|
24
|
+
/** Sanitize an alias. Returns `null` when nothing usable survives. */
|
|
25
|
+
export declare function sanitizeWikiLinkAlias(raw: string | null): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Serialize a wikilink back to markdown. Inverse of {@link parseWikiLinkInner}
|
|
28
|
+
* for every link built through this module's constructors — see
|
|
29
|
+
* {@link sanitizeWikiLinkTarget} for why that qualifier is load-bearing.
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatWikiLink(link: WikiLink): string;
|
|
32
|
+
export type SerializedWikiLinkNode = Spread<{
|
|
33
|
+
target: string;
|
|
34
|
+
alias: string | null;
|
|
35
|
+
}, SerializedTextNode>;
|
|
36
|
+
/**
|
|
37
|
+
* An atomic inline wikilink. Extends `TextNode` so the caret, selection and
|
|
38
|
+
* text formats behave exactly as they do for prose, while `token` mode keeps it
|
|
39
|
+
* indivisible: the user can delete it or move past it, but never edit its
|
|
40
|
+
* interior into a state where the visible alias disagrees with `__target`.
|
|
41
|
+
*/
|
|
42
|
+
export declare class WikiLinkNode extends TextNode {
|
|
43
|
+
__target: string;
|
|
44
|
+
__alias: string | null;
|
|
45
|
+
static getType(): string;
|
|
46
|
+
static clone(node: WikiLinkNode): WikiLinkNode;
|
|
47
|
+
constructor(target: string, alias: string | null, text?: string, key?: NodeKey);
|
|
48
|
+
static importJSON(serializedNode: SerializedWikiLinkNode): WikiLinkNode;
|
|
49
|
+
updateFromJSON(serializedNode: LexicalUpdateJSON<SerializedWikiLinkNode>): this;
|
|
50
|
+
exportJSON(): SerializedWikiLinkNode;
|
|
51
|
+
createDOM(config: EditorConfig, editor?: LexicalEditor): HTMLElement;
|
|
52
|
+
updateDOM(prevNode: this, dom: HTMLElement, config: EditorConfig): boolean;
|
|
53
|
+
getTarget(): string;
|
|
54
|
+
/**
|
|
55
|
+
* Repoint the link. The display text follows only when there is no alias.
|
|
56
|
+
* The value is sanitized (see {@link sanitizeWikiLinkTarget}); a target with
|
|
57
|
+
* nothing representable in it leaves the link untouched rather than producing
|
|
58
|
+
* one that corrupts the document on export.
|
|
59
|
+
*/
|
|
60
|
+
setTarget(target: string): this;
|
|
61
|
+
getAlias(): string | null;
|
|
62
|
+
/** Set (or clear, with `null`) the alias; the display text follows. */
|
|
63
|
+
setAlias(alias: string | null): this;
|
|
64
|
+
getLink(): WikiLink;
|
|
65
|
+
canInsertTextBefore(): boolean;
|
|
66
|
+
canInsertTextAfter(): boolean;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build a wikilink node. `target`/`alias` are sanitized to values the `[[…]]`
|
|
70
|
+
* syntax can express (see {@link sanitizeWikiLinkTarget}); a target with nothing
|
|
71
|
+
* usable left falls back to the literal text `Page` rather than yielding an
|
|
72
|
+
* invisible token.
|
|
73
|
+
*/
|
|
74
|
+
export declare function $createWikiLinkNode(target: string, alias?: string | null): WikiLinkNode;
|
|
75
|
+
export declare function $isWikiLinkNode(node: LexicalNode | null | undefined): node is WikiLinkNode;
|
|
76
|
+
/** A document the host offers as a link target while the user types `[[…`. */
|
|
77
|
+
export interface DocCandidate {
|
|
78
|
+
/** The link target written into the document (`[[target]]`). */
|
|
79
|
+
readonly target: string;
|
|
80
|
+
/** Human-facing title shown in the results list (defaults to `target`). */
|
|
81
|
+
readonly title?: string;
|
|
82
|
+
/** A short one-line snippet shown under the title. */
|
|
83
|
+
readonly snippet?: string;
|
|
84
|
+
/** A longer content excerpt shown in the reference/preview pane. */
|
|
85
|
+
readonly preview?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface WikiLinkPluginOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Called when the user activates a wikilink. This is the host's resolution
|
|
90
|
+
* seam: `@llui/markdown-editor` knows nothing about what a target names.
|
|
91
|
+
*
|
|
92
|
+
* The notification travels the same route as every other plugin event —
|
|
93
|
+
* `ctx.emit` → the editor's update loop → this plugin's reducer → an effect —
|
|
94
|
+
* rather than a raw DOM event, so an activation is an ordinary TEA message
|
|
95
|
+
* that shows up in devtools, replay and agent traces.
|
|
96
|
+
*/
|
|
97
|
+
onNavigate?: (link: WikiLink) => void;
|
|
98
|
+
/** Text used as the target when the insert command runs with no selection. */
|
|
99
|
+
placeholderTarget?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Document-search seam: as the user types `[[query`, resolve matching
|
|
102
|
+
* documents to offer as link targets, with an optional content preview shown in
|
|
103
|
+
* the panel's reference pane. Sync or async (async is debounced; a stale
|
|
104
|
+
* response for a superseded query is dropped). When omitted, the panel never
|
|
105
|
+
* opens and `[[target]]` still works by typing the closing `]]`.
|
|
106
|
+
*/
|
|
107
|
+
search?: (query: string) => readonly DocCandidate[] | Promise<readonly DocCandidate[]>;
|
|
108
|
+
}
|
|
109
|
+
export declare function wikilinkPlugin(opts?: WikiLinkPluginOptions): MarkdownPlugin;
|
|
110
|
+
//# sourceMappingURL=wikilink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wikilink.d.ts","sourceRoot":"","sources":["../../src/plugins/wikilink.ts"],"names":[],"mappings":"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"}
|