@lexical/html 0.44.1-nightly.20260519.0 → 0.45.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/{DOMRenderExtension.d.ts → dist/DOMRenderExtension.d.ts} +12 -1
- package/dist/DOMRenderRuntime.d.ts +51 -0
- package/dist/LexicalHtml.dev.js +3192 -0
- package/dist/LexicalHtml.dev.mjs +3146 -0
- package/{LexicalHtml.js.flow → dist/LexicalHtml.js.flow} +16 -16
- package/dist/LexicalHtml.mjs +56 -0
- package/dist/LexicalHtml.node.mjs +54 -0
- package/dist/LexicalHtml.prod.js +9 -0
- package/dist/LexicalHtml.prod.mjs +9 -0
- package/dist/RenderContext.d.ts +68 -0
- package/{compileDOMRenderConfigOverrides.d.ts → dist/compileDOMRenderConfigOverrides.d.ts} +1 -1
- package/{constants.d.ts → dist/constants.d.ts} +2 -0
- package/dist/domOverride.d.ts +23 -0
- package/dist/import/CoreImportExtension.d.ts +11 -0
- package/dist/import/DOMImportExtension.d.ts +82 -0
- package/dist/import/HorizontalRuleImportExtension.d.ts +27 -0
- package/dist/import/ImportContext.d.ts +208 -0
- package/dist/import/compileImportRules.d.ts +50 -0
- package/dist/import/coreImportRules.d.ts +25 -0
- package/dist/import/defineImportRule.d.ts +32 -0
- package/dist/import/defineOverlayRules.d.ts +66 -0
- package/dist/import/index.d.ts +38 -0
- package/dist/import/inlineStylesFromStyleSheets.d.ts +28 -0
- package/dist/import/parseCss.d.ts +18 -0
- package/dist/import/runImport.d.ts +19 -0
- package/dist/import/schemas.d.ts +91 -0
- package/dist/import/sel.d.ts +74 -0
- package/dist/import/types.d.ts +394 -0
- package/dist/index.d.ts +44 -0
- package/{types.d.ts → dist/types.d.ts} +96 -8
- package/package.json +33 -18
- package/src/ContextRecord.ts +243 -0
- package/src/DOMRenderExtension.ts +96 -0
- package/src/DOMRenderRuntime.ts +265 -0
- package/src/RenderContext.ts +168 -0
- package/src/compileDOMRenderConfigOverrides.ts +416 -0
- package/src/constants.ts +18 -0
- package/src/domOverride.ts +46 -0
- package/src/import/CoreImportExtension.ts +26 -0
- package/src/import/DOMImportExtension.ts +221 -0
- package/src/import/HorizontalRuleImportExtension.ts +53 -0
- package/src/import/ImportContext.ts +339 -0
- package/src/import/compileImportRules.ts +178 -0
- package/src/import/coreImportRules.ts +485 -0
- package/src/import/defineImportRule.ts +40 -0
- package/src/import/defineOverlayRules.ts +105 -0
- package/src/import/index.ts +96 -0
- package/src/import/inlineStylesFromStyleSheets.ts +104 -0
- package/src/import/parseCss.ts +219 -0
- package/src/import/runImport.ts +245 -0
- package/src/import/schemas.ts +236 -0
- package/src/import/sel.ts +314 -0
- package/src/import/types.ts +471 -0
- package/src/index.ts +555 -0
- package/src/types.ts +470 -0
- package/LexicalHtml.dev.js +0 -914
- package/LexicalHtml.dev.mjs +0 -900
- package/LexicalHtml.mjs +0 -24
- package/LexicalHtml.node.mjs +0 -22
- package/LexicalHtml.prod.js +0 -9
- package/LexicalHtml.prod.mjs +0 -9
- package/RenderContext.d.ts +0 -32
- package/domOverride.d.ts +0 -18
- package/index.d.ts +0 -32
- /package/{ContextRecord.d.ts → dist/ContextRecord.d.ts} +0 -0
- /package/{LexicalHtml.js → dist/LexicalHtml.js} +0 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { DOMImportContextSymbol } from '../constants';
|
|
9
|
+
import type { AnyContextConfigPairOrUpdater, ContextConfig, ContextRecord } from '../types';
|
|
10
|
+
import type { CompiledOverlayRules } from './defineOverlayRules';
|
|
11
|
+
import type { LexicalNode } from 'lexical';
|
|
12
|
+
/**
|
|
13
|
+
* Phantom-typed branding so consumers cannot construct or mutate a
|
|
14
|
+
* {@link CompiledSelector} directly; the only way to obtain one is via the
|
|
15
|
+
* {@link sel} builder or {@link parseSelector}. The actual runtime shape is
|
|
16
|
+
* an internal implementation detail (see `./sel`).
|
|
17
|
+
*
|
|
18
|
+
* @experimental
|
|
19
|
+
*/
|
|
20
|
+
export declare const NodeBrand: unique symbol;
|
|
21
|
+
/** @experimental */
|
|
22
|
+
export declare const CaptureBrand: unique symbol;
|
|
23
|
+
/**
|
|
24
|
+
* An opaque, compiled selector used as the `match` field of a
|
|
25
|
+
* {@link DOMImportRule}. The two phantom type parameters carry the matched
|
|
26
|
+
* Node subtype (`N`) and a record of named regex captures (`C`) so the
|
|
27
|
+
* importer body gets correctly-typed `ctx` and `node` arguments without
|
|
28
|
+
* casts.
|
|
29
|
+
*
|
|
30
|
+
* @experimental
|
|
31
|
+
*/
|
|
32
|
+
export interface CompiledSelector<N extends Node = Node, C extends Record<string, RegExpMatchArray> = Record<string, RegExpMatchArray>> {
|
|
33
|
+
readonly [NodeBrand]?: N;
|
|
34
|
+
readonly [CaptureBrand]?: C;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The Node subtype matched by a selector (e.g. `HTMLAnchorElement` for
|
|
38
|
+
* `sel.tag('a')`, `Text` for `sel.text()`).
|
|
39
|
+
*
|
|
40
|
+
* @experimental
|
|
41
|
+
*/
|
|
42
|
+
export type NodeOfSelector<S> = S extends CompiledSelector<infer N, Record<string, RegExpMatchArray>> ? N : Node;
|
|
43
|
+
/**
|
|
44
|
+
* The named-capture map for a selector.
|
|
45
|
+
*
|
|
46
|
+
* @experimental
|
|
47
|
+
*/
|
|
48
|
+
export type CapturesOfSelector<S> = S extends CompiledSelector<Node, infer C> ? C : Record<string, never>;
|
|
49
|
+
/**
|
|
50
|
+
* Options bag for {@link ElementSelectorBuilder.attr} when the value is a
|
|
51
|
+
* regex. Future options will be added here without breaking existing
|
|
52
|
+
* call-sites.
|
|
53
|
+
*
|
|
54
|
+
* @experimental
|
|
55
|
+
*/
|
|
56
|
+
export interface AttrMatchOptions<K extends string = string> {
|
|
57
|
+
/**
|
|
58
|
+
* If provided, the {@link RegExpMatchArray} from the successful match is
|
|
59
|
+
* stored on `ctx.captures[capture]` for the importer to consume — saving
|
|
60
|
+
* a second regex execution.
|
|
61
|
+
*/
|
|
62
|
+
readonly capture?: K;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Options bag for {@link ElementSelectorBuilder.styleAny} when the value is a
|
|
66
|
+
* regex. See {@link AttrMatchOptions} for capture semantics.
|
|
67
|
+
*
|
|
68
|
+
* @experimental
|
|
69
|
+
*/
|
|
70
|
+
export interface StyleMatchOptions<K extends string = string> {
|
|
71
|
+
readonly capture?: K;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Fluent builder for an element selector. The two type parameters carry the
|
|
75
|
+
* matched element type and the named-capture map; each call refines them.
|
|
76
|
+
*
|
|
77
|
+
* The builder itself implements {@link CompiledSelector} so it can be used
|
|
78
|
+
* directly as the `match` field of a rule — no `.build()` call needed.
|
|
79
|
+
*
|
|
80
|
+
* @experimental
|
|
81
|
+
*/
|
|
82
|
+
export interface ElementSelectorBuilder<E extends HTMLElement, C extends Record<string, RegExpMatchArray> = Record<string, never>> extends CompiledSelector<E, C> {
|
|
83
|
+
/** Require every listed class to be present on the element. */
|
|
84
|
+
classAll(...classes: readonly string[]): ElementSelectorBuilder<E, C>;
|
|
85
|
+
/** Require at least one of the listed classes to be present. */
|
|
86
|
+
classAny(...classes: readonly string[]): ElementSelectorBuilder<E, C>;
|
|
87
|
+
/** Require the attribute to be present (any value). */
|
|
88
|
+
attr(name: string, value: true): ElementSelectorBuilder<E, C>;
|
|
89
|
+
/** Require the attribute to equal the given string. */
|
|
90
|
+
attr(name: string, value: string): ElementSelectorBuilder<E, C>;
|
|
91
|
+
/**
|
|
92
|
+
* Require the attribute to match the given regex. With
|
|
93
|
+
* `{capture: 'name'}` the match result is exposed on
|
|
94
|
+
* `ctx.captures.name`.
|
|
95
|
+
*/
|
|
96
|
+
attr<const O extends AttrMatchOptions>(name: string, value: RegExp, options?: O): ElementSelectorBuilder<E, O extends {
|
|
97
|
+
capture: infer K;
|
|
98
|
+
} ? C & Record<K & string, RegExpMatchArray> : C>;
|
|
99
|
+
/** Require the inline-style declaration to equal `value`. */
|
|
100
|
+
styleAny(prop: string, value: string): ElementSelectorBuilder<E, C>;
|
|
101
|
+
/** Require the inline-style declaration to match `value`. */
|
|
102
|
+
styleAny<const O extends StyleMatchOptions>(prop: string, value: RegExp, options?: O): ElementSelectorBuilder<E, O extends {
|
|
103
|
+
capture: infer K;
|
|
104
|
+
} ? C & Record<K & string, RegExpMatchArray> : C>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Argument to {@link DOMImportContext.branch} / `$importChildren({context})`
|
|
108
|
+
* — see {@link ContextConfigPair} / {@link ContextConfigUpdater}.
|
|
109
|
+
*
|
|
110
|
+
* @experimental
|
|
111
|
+
*/
|
|
112
|
+
export type ImportContextPairOrUpdater = AnyContextConfigPairOrUpdater<typeof DOMImportContextSymbol>;
|
|
113
|
+
/**
|
|
114
|
+
* A typed context-state key for the import pipeline. Create with
|
|
115
|
+
* {@link createImportState}.
|
|
116
|
+
*
|
|
117
|
+
* @experimental
|
|
118
|
+
*/
|
|
119
|
+
export type ImportStateConfig<V> = ContextConfig<typeof DOMImportContextSymbol, V>;
|
|
120
|
+
/**
|
|
121
|
+
* A mutable, document-order-shared store for the import pipeline. Lets a
|
|
122
|
+
* rule visited early in the document write information that rules visited
|
|
123
|
+
* later can read — e.g. parse `<style>` or `<meta>` and influence
|
|
124
|
+
* subsequent matching.
|
|
125
|
+
*
|
|
126
|
+
* Implemented as the root-layer {@link ContextRecord} of the import walk:
|
|
127
|
+
* `ctx.session.set(cfg, v)` mutates the slot on that root record, and
|
|
128
|
+
* every unshadowed `ctx.get(cfg)` read in any branch picks it up. A
|
|
129
|
+
* `$importChildren({context: [...]})` branch that explicitly writes the
|
|
130
|
+
* same slot shadows the session value for the duration of that branch.
|
|
131
|
+
*
|
|
132
|
+
* @experimental
|
|
133
|
+
*/
|
|
134
|
+
export interface ImportSession {
|
|
135
|
+
/** Read the current value, returning the config's default if unset. */
|
|
136
|
+
get<V>(cfg: ImportStateConfig<V>): V;
|
|
137
|
+
/** Write `value` into the slot. */
|
|
138
|
+
set<V>(cfg: ImportStateConfig<V>, value: V): void;
|
|
139
|
+
/** Read-modify-write. */
|
|
140
|
+
update<V>(cfg: ImportStateConfig<V>, updater: (prev: V) => V): void;
|
|
141
|
+
/** Returns `true` if the slot has been written since session creation. */
|
|
142
|
+
has<V>(cfg: ImportStateConfig<V>): boolean;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Context exposed to a rule's `$import` function. Mirrors the existing render
|
|
146
|
+
* context (see {@link RenderContext}) but is import-scoped.
|
|
147
|
+
*
|
|
148
|
+
* @experimental
|
|
149
|
+
*/
|
|
150
|
+
export interface DOMImportContext<C extends Record<string, RegExpMatchArray> = Record<string, never>> {
|
|
151
|
+
/** Captures from this rule's selector. Fresh per rule invocation. */
|
|
152
|
+
readonly captures: Readonly<C>;
|
|
153
|
+
/**
|
|
154
|
+
* Mutable, document-order-shared store. Use to make information from
|
|
155
|
+
* earlier-visited nodes available to later-visited ones (e.g. a
|
|
156
|
+
* `<style>` or `<meta>` at the top of the document influencing how
|
|
157
|
+
* later elements are interpreted). One {@link ImportSession} instance
|
|
158
|
+
* is created per top-level `$generateNodesFromDOM` call and is shared
|
|
159
|
+
* across all recursive `$importChildren` / `$importOne` invocations.
|
|
160
|
+
*/
|
|
161
|
+
readonly session: ImportSession;
|
|
162
|
+
/** Read a typed context value. */
|
|
163
|
+
get<V>(cfg: ImportStateConfig<V>): V;
|
|
164
|
+
/**
|
|
165
|
+
* Recursively import every child of `parent` and return the produced
|
|
166
|
+
* lexical nodes, optionally enforcing a {@link ChildSchema} and/or
|
|
167
|
+
* branching the import context for the duration of the call (via
|
|
168
|
+
* `opts.context`).
|
|
169
|
+
*/
|
|
170
|
+
$importChildren(parent: ParentNode, opts?: ImportChildrenOpts): LexicalNode[];
|
|
171
|
+
/**
|
|
172
|
+
* Recursively import a single DOM node.
|
|
173
|
+
*/
|
|
174
|
+
$importOne(node: Node, opts?: ImportNodeOpts): LexicalNode[];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Options accepted by {@link DOMImportContext.$importChildren}. The combination
|
|
178
|
+
* of `schema`, `$onChild`, and `$after` is sufficient to express every
|
|
179
|
+
* child-handling pattern in the legacy `forChild` / `after` / wrap-continuous
|
|
180
|
+
* machinery.
|
|
181
|
+
*
|
|
182
|
+
* @experimental
|
|
183
|
+
*/
|
|
184
|
+
export interface ImportChildrenOpts {
|
|
185
|
+
/**
|
|
186
|
+
* How to validate and (re)package produced children. Defaults to whichever
|
|
187
|
+
* schema the parent's importer passed; the top-level entry uses
|
|
188
|
+
* {@link BlockSchema}.
|
|
189
|
+
*/
|
|
190
|
+
readonly schema?: ChildSchema;
|
|
191
|
+
/**
|
|
192
|
+
* Called for each produced lexical child immediately after its rule
|
|
193
|
+
* returned, with the chance to substitute or drop it. Equivalent to the
|
|
194
|
+
* old `forChild` hook but scoped to one `$importChildren` call.
|
|
195
|
+
*/
|
|
196
|
+
readonly $onChild?: (child: LexicalNode) => LexicalNode | null | undefined;
|
|
197
|
+
/**
|
|
198
|
+
* Called once with the full child array after all DOM children have been
|
|
199
|
+
* recursively imported but before {@link ChildSchema.$packageRun} is
|
|
200
|
+
* applied. Equivalent to the old `after` hook.
|
|
201
|
+
*/
|
|
202
|
+
readonly $after?: (children: LexicalNode[]) => LexicalNode[];
|
|
203
|
+
/** Context overrides scoped to the children traversal. */
|
|
204
|
+
readonly context?: readonly ImportContextPairOrUpdater[];
|
|
205
|
+
/**
|
|
206
|
+
* Additional {@link DOMImportRule}s active only for this children
|
|
207
|
+
* traversal (and any nested `$importChildren` calls that don't push
|
|
208
|
+
* their own overlay). The overlay is checked BEFORE the main
|
|
209
|
+
* dispatcher, so its rules take precedence; calling `$next()` from an
|
|
210
|
+
* overlay rule falls through to the next overlay-or-main rule.
|
|
211
|
+
*
|
|
212
|
+
* Use this to scope cost-bearing rules to where they apply. For
|
|
213
|
+
* example, a GitHub code-table rule installs an overlay that
|
|
214
|
+
* unwraps `<tr>` / `<td>` inside the table, without paying that
|
|
215
|
+
* predicate cost on every other `<tr>` / `<td>` paste.
|
|
216
|
+
*
|
|
217
|
+
* The value must be produced by
|
|
218
|
+
* {@link defineOverlayRules}; this forces the dispatcher to be
|
|
219
|
+
* compiled once at module scope and reused across
|
|
220
|
+
* `$importChildren` calls, instead of being recompiled per invocation.
|
|
221
|
+
*/
|
|
222
|
+
readonly rules?: CompiledOverlayRules;
|
|
223
|
+
}
|
|
224
|
+
/** @experimental */
|
|
225
|
+
export interface ImportNodeOpts {
|
|
226
|
+
readonly context?: readonly ImportContextPairOrUpdater[];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* A {@link ChildSchema} encodes which lexical nodes a parent accepts as
|
|
230
|
+
* children and how to package or reject the rest. The legacy
|
|
231
|
+
* `wrapContinuousInlines` / `ArtificialNode__DO_NOT_USE` logic is the
|
|
232
|
+
* `BlockSchema` and `NestedBlockSchema` cases of this primitive.
|
|
233
|
+
*
|
|
234
|
+
* A schema only controls how the *children* are assembled before being
|
|
235
|
+
* appended to the parent the calling rule already chose. It cannot
|
|
236
|
+
* change the parent itself. Cases where the parent's shape needs to
|
|
237
|
+
* change in response to its children — e.g. an inline `<a>` that
|
|
238
|
+
* encloses a block `<h1>`, which must be lifted so the heading takes
|
|
239
|
+
* the link's place and the link is redistributed onto the heading's
|
|
240
|
+
* inline contents — belong in the rule body, not the schema. See the
|
|
241
|
+
* "Lifting blocks out of an inline parent" section of the docs.
|
|
242
|
+
*
|
|
243
|
+
* @experimental
|
|
244
|
+
*/
|
|
245
|
+
export interface ChildSchema {
|
|
246
|
+
/** Optional name for debug output. */
|
|
247
|
+
readonly name?: string;
|
|
248
|
+
/**
|
|
249
|
+
* Returns `true` if `child` is a valid child of `parent` in this position.
|
|
250
|
+
*/
|
|
251
|
+
$accepts(child: LexicalNode, parent: LexicalNode | null): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Package a maximal run of non-accepted siblings into zero or more
|
|
254
|
+
* accepted nodes. The returned nodes replace the rejected run at the
|
|
255
|
+
* same position in the child list and are not re-checked against
|
|
256
|
+
* `$accepts` — the caller is trusted to return valid children. If
|
|
257
|
+
* omitted, or if it returns an empty array, {@link ChildSchema.onReject}
|
|
258
|
+
* is consulted instead.
|
|
259
|
+
*/
|
|
260
|
+
$packageRun?(rejected: LexicalNode[], parent: LexicalNode | null, domParent: Node | null): LexicalNode[];
|
|
261
|
+
/**
|
|
262
|
+
* Fallback strategy for a run of non-accepted children when
|
|
263
|
+
* `$packageRun` is missing or returns an empty array:
|
|
264
|
+
*
|
|
265
|
+
* - `'drop'` (default) — silently discards the run. Use when the
|
|
266
|
+
* schema is strict and rejected content is meaningless in this
|
|
267
|
+
* position (e.g. text between table rows).
|
|
268
|
+
* - `'hoist'` — emits the rejected nodes unchanged at the same
|
|
269
|
+
* position in the assembled child list. The caller's parent then
|
|
270
|
+
* receives them as-is, which is only useful if the calling rule
|
|
271
|
+
* intends to surface mixed content to *its* parent (a less common
|
|
272
|
+
* pattern; usually `$packageRun` should re-shape the run first).
|
|
273
|
+
*
|
|
274
|
+
* `'hoist'` does NOT lift the run all the way up out of the calling
|
|
275
|
+
* rule's parent — that requires the rule itself to detect the
|
|
276
|
+
* situation and emit a different parent structure (see the
|
|
277
|
+
* "Lifting blocks out of an inline parent" section).
|
|
278
|
+
*/
|
|
279
|
+
readonly onReject?: 'hoist' | 'drop';
|
|
280
|
+
/**
|
|
281
|
+
* Final pass over the assembled child list (after `$packageRun`). Returns
|
|
282
|
+
* the children to actually attach. Use to enforce structural invariants
|
|
283
|
+
* (e.g. drop empty runs, pad short table rows).
|
|
284
|
+
*/
|
|
285
|
+
$finalize?(children: LexicalNode[], parent: LexicalNode | null): LexicalNode[];
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* The middleware signature of an import rule. Call `$next()` to delegate to
|
|
289
|
+
* the next-matching rule for this node (returning its result, which may then
|
|
290
|
+
* be inspected or wrapped); return `[]` to drop the node.
|
|
291
|
+
*
|
|
292
|
+
* @experimental
|
|
293
|
+
*/
|
|
294
|
+
export type DOMImportFn<E extends Node, C extends Record<string, RegExpMatchArray> = Record<string, never>> = (ctx: DOMImportContext<C>, node: E, $next: () => readonly LexicalNode[]) => readonly LexicalNode[];
|
|
295
|
+
/**
|
|
296
|
+
* An importer for a DOM node, dispatched by `match` and implemented by
|
|
297
|
+
* `$import`.
|
|
298
|
+
*
|
|
299
|
+
* @experimental
|
|
300
|
+
*/
|
|
301
|
+
export interface DOMImportRule<S extends CompiledSelector = CompiledSelector> {
|
|
302
|
+
/**
|
|
303
|
+
* Optional identifier surfaced in dev-mode logs, error messages, and
|
|
304
|
+
* introspection devtools. Convention: `'@scope/package/rule-id'` for
|
|
305
|
+
* library rules.
|
|
306
|
+
*/
|
|
307
|
+
readonly name?: string;
|
|
308
|
+
/** A {@link CompiledSelector} produced by the {@link sel} builder. */
|
|
309
|
+
readonly match: S;
|
|
310
|
+
/** Middleware that converts the matched DOM node into lexical nodes. */
|
|
311
|
+
readonly $import: DOMImportFn<NodeOfSelector<S>, CapturesOfSelector<S>>;
|
|
312
|
+
}
|
|
313
|
+
/** @experimental */
|
|
314
|
+
export type AnyDOMImportRule = DOMImportRule<any>;
|
|
315
|
+
/**
|
|
316
|
+
* Context exposed to a {@link DOMPreprocessFn}. Lets the preprocessor:
|
|
317
|
+
*
|
|
318
|
+
* - Write to the per-import {@link ImportSession} (the same
|
|
319
|
+
* `ctx.session` rules see during the walk). Writes mutate the
|
|
320
|
+
* root-layer context record, so they are visible to every scoped
|
|
321
|
+
* `ctx.get(cfg)` read that hasn't been shadowed by a branch.
|
|
322
|
+
*
|
|
323
|
+
* @experimental
|
|
324
|
+
*/
|
|
325
|
+
export interface DOMPreprocessContext {
|
|
326
|
+
/**
|
|
327
|
+
* Document-order-shared store, same instance as `ctx.session` in
|
|
328
|
+
* rules. Use to pass info from the DOM preprocess phase (e.g.
|
|
329
|
+
* inspected `<meta>` tags, collected `<style>` text) to the
|
|
330
|
+
* importer rules.
|
|
331
|
+
*/
|
|
332
|
+
readonly session: ImportSession;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* A middleware step in the DOM-preprocess chain. Runs before walking
|
|
336
|
+
* begins and may:
|
|
337
|
+
*
|
|
338
|
+
* - Mutate the input DOM in place (e.g. inline stylesheets, strip
|
|
339
|
+
* unsafe elements, normalize attributes).
|
|
340
|
+
* - Write to {@link DOMPreprocessContext.session} for rules to read
|
|
341
|
+
* (and for unshadowed scoped reads to pick up).
|
|
342
|
+
* - Call `$next()` to defer to the next-lower preprocessor in the
|
|
343
|
+
* stack; omit the call to short-circuit and skip the rest.
|
|
344
|
+
*
|
|
345
|
+
* The preprocess phase runs inside the same editor read / update
|
|
346
|
+
* context as the walk that follows, so a preprocess function may call
|
|
347
|
+
* `$`-prefixed Lexical APIs (e.g. `$getState`, `$getRoot`) as needed.
|
|
348
|
+
* The `$next` parameter is named with a `$` prefix to make that
|
|
349
|
+
* editor-context expectation visible to readers and lints.
|
|
350
|
+
*
|
|
351
|
+
* Append-style merge applies: an extension's preprocessors are appended
|
|
352
|
+
* to the existing stack, so later-registered preprocessors run first
|
|
353
|
+
* and may delegate to earlier (lower-priority) ones via `$next()`. Same
|
|
354
|
+
* convention as {@link ExportMimeTypeFunction} on the export side.
|
|
355
|
+
*
|
|
356
|
+
* @experimental
|
|
357
|
+
*/
|
|
358
|
+
export type DOMPreprocessFn = (dom: Document | ParentNode, ctx: DOMPreprocessContext, $next: () => void) => void;
|
|
359
|
+
/**
|
|
360
|
+
* Per-call options to the extension's `$generateNodesFromDOM`.
|
|
361
|
+
*
|
|
362
|
+
* @experimental
|
|
363
|
+
*/
|
|
364
|
+
export interface GenerateNodesFromDOMOptions {
|
|
365
|
+
/**
|
|
366
|
+
* Context pairs/updaters applied for the duration of this import only —
|
|
367
|
+
* use to communicate per-call info such as the {@link ImportSource}.
|
|
368
|
+
*/
|
|
369
|
+
readonly context?: readonly ImportContextPairOrUpdater[];
|
|
370
|
+
/**
|
|
371
|
+
* Additional preprocessors to run on this call only, on top of the
|
|
372
|
+
* extension's configured {@link DOMImportConfig.preprocess}. Per-call
|
|
373
|
+
* preprocessors run AFTER the configured ones.
|
|
374
|
+
*/
|
|
375
|
+
readonly preprocess?: readonly DOMPreprocessFn[];
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Output of {@link DOMImportExtension}.
|
|
379
|
+
*
|
|
380
|
+
* @experimental
|
|
381
|
+
*/
|
|
382
|
+
export interface DOMImportExtensionOutput {
|
|
383
|
+
/**
|
|
384
|
+
* Convert a {@link Document} or {@link ParentNode} into lexical nodes,
|
|
385
|
+
* using the dispatcher compiled from this extension's configured
|
|
386
|
+
* {@link DOMImportRule}s.
|
|
387
|
+
*
|
|
388
|
+
* Must be called within an `editor.update()` or `editor.read()` because
|
|
389
|
+
* the importers may invoke `$create...` helpers.
|
|
390
|
+
*/
|
|
391
|
+
$generateNodesFromDOM(dom: Document | ParentNode, options?: GenerateNodesFromDOMOptions): LexicalNode[];
|
|
392
|
+
/** @internal */
|
|
393
|
+
readonly defaults: undefined | ContextRecord<typeof DOMImportContextSymbol>;
|
|
394
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { BaseSelection, LexicalEditor, LexicalNode } from 'lexical';
|
|
9
|
+
export { contextUpdater, contextValue } from './ContextRecord';
|
|
10
|
+
export { domOverride } from './domOverride';
|
|
11
|
+
export { DOMRenderExtension } from './DOMRenderExtension';
|
|
12
|
+
export type { AnyDOMImportRule, AttrMatchOptions, CapturesOfSelector, ChildSchema, CompiledOverlayRules, CompiledSelector, DOMImportContext, DOMImportExtensionOutput, DOMImportFn, DOMImportRule, DOMImportRuleEntry, DOMPreprocessContext, DOMPreprocessFn, ElementSelectorBuilder, GenerateNodesFromDOMOptions, ImportChildrenOpts, ImportContextPairOrUpdater, ImportNodeOpts, ImportSession, ImportStateConfig, NodeOfSelector, StyleMatchOptions, } from './import';
|
|
13
|
+
export { $distributeInlineWrapper, $generateNodesFromDOMViaExtension, $getImportContextValue, $inlineStylesFromStyleSheets, $isBlockLevel, $withImportContext, BlockSchema, CoreImportExtension, CoreImportRules, createImportState, defaultIsInline, defaultPreservesWhitespace, defineImportRule, defineOverlayRules, type DOMImportConfig, DOMImportExtension, HorizontalRuleImportExtension, HorizontalRuleImportRules, ImportOverlays, ImportSource, ImportSourceDataTransfer, type ImportSourceKind, ImportTextFormat, ImportTextStyle, ImportWhitespaceConfig, InlineSchema, isElementOfTag, type IsInlineForWhitespace, type IsPreserveWhitespaceDom, NestedBlockSchema, parseSelector, RootSchema, sel, type WhitespaceImportConfig, } from './import';
|
|
14
|
+
export { $getRenderContextValue, $getSessionDOMRenderConfig, $setRenderContextValue, $updateRenderContextValue, $withRenderContext, createRenderState, RenderContextExport, RenderContextRoot, } from './RenderContext';
|
|
15
|
+
export type { AnyDOMRenderMatch, AnyRenderStateConfig, AnyRenderStateConfigPairOrUpdater, ContextPairOrUpdater, DOMOverrideOptions, DOMRenderConfig, DOMRenderExtensionOutput, DOMRenderMatch, DOMRenderMatchConfig, NodeMatch, RenderContextReader, } from './types';
|
|
16
|
+
/**
|
|
17
|
+
* How you parse your html string to get a document is left up to you. In the browser you can use the native
|
|
18
|
+
* DOMParser API to generate a document (see clipboard.ts), but to use in a headless environment you can use JSDom
|
|
19
|
+
* or an equivalent library and pass in the document here.
|
|
20
|
+
*/
|
|
21
|
+
export declare function $generateNodesFromDOM(editor: LexicalEditor, dom: Document | ParentNode): Array<LexicalNode>;
|
|
22
|
+
/**
|
|
23
|
+
* Generate DOM nodes from the editor state into the given container element,
|
|
24
|
+
* using the editor's {@link EditorDOMRenderConfig}.
|
|
25
|
+
* @experimental
|
|
26
|
+
*/
|
|
27
|
+
export declare function $generateDOMFromNodes<T extends HTMLElement | DocumentFragment>(container: T, selection?: null | BaseSelection, editor?: LexicalEditor): T;
|
|
28
|
+
/**
|
|
29
|
+
* Generate DOM nodes from a root node into the given container element,
|
|
30
|
+
* including the root node itself. Uses the editor's {@link EditorDOMRenderConfig}.
|
|
31
|
+
* @experimental
|
|
32
|
+
*/
|
|
33
|
+
export declare function $generateDOMFromRoot<T extends HTMLElement | DocumentFragment>(container: T, root?: LexicalNode): T;
|
|
34
|
+
/**
|
|
35
|
+
* Generate an HTML string from the editor's current state (or `selection`
|
|
36
|
+
* if provided).
|
|
37
|
+
*
|
|
38
|
+
* Must be called inside an active editor scope — i.e. `editor.update(...)`,
|
|
39
|
+
* `editor.read(...)`, or `editor.getEditorState().read(callback, {editor})`.
|
|
40
|
+
* The legacy `editor.getEditorState().read(callback)` call (without the
|
|
41
|
+
* `{editor}` option) does not set an active editor and is not supported;
|
|
42
|
+
* `editor.read(...)` is the drop-in replacement.
|
|
43
|
+
*/
|
|
44
|
+
export declare function $generateHtmlFromNodes(editor: LexicalEditor, selection?: BaseSelection | null): string;
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
|
-
import type { DOMRenderContextSymbol } from './constants';
|
|
9
|
-
import type { BaseSelection, DOMExportOutput,
|
|
8
|
+
import type { DOMImportContextSymbol, DOMRenderContextSymbol } from './constants';
|
|
9
|
+
import type { BaseSelection, DOMExportOutput, DOMSlotForNode, EditorDOMRenderConfig, Klass, LexicalEditor, LexicalNode, StateConfig } from 'lexical';
|
|
10
10
|
/**
|
|
11
11
|
* @experimental
|
|
12
12
|
*
|
|
13
|
-
* Any ContextSymbol for {@link ContextConfig} (
|
|
13
|
+
* Any ContextSymbol for {@link ContextConfig} (DOM render or DOM import).
|
|
14
14
|
*/
|
|
15
|
-
export type AnyContextSymbol = typeof DOMRenderContextSymbol;
|
|
15
|
+
export type AnyContextSymbol = typeof DOMRenderContextSymbol | typeof DOMImportContextSymbol;
|
|
16
16
|
/**
|
|
17
17
|
* @experimental
|
|
18
18
|
*
|
|
@@ -68,6 +68,73 @@ export type AnyContextConfigPairOrUpdater<Ctx extends AnyContextSymbol> = Contex
|
|
|
68
68
|
export interface DOMRenderExtensionOutput {
|
|
69
69
|
/** @internal */
|
|
70
70
|
defaults: undefined | ContextRecord<typeof DOMRenderContextSymbol>;
|
|
71
|
+
/** @internal */
|
|
72
|
+
runtime: DOMRenderRuntime;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* @experimental
|
|
76
|
+
*
|
|
77
|
+
* A read-only view of a render context layer, passed to the
|
|
78
|
+
* {@link DOMOverrideOptions} predicates so they can decide whether an
|
|
79
|
+
* override should be installed based only on context values.
|
|
80
|
+
*/
|
|
81
|
+
export interface RenderContextReader {
|
|
82
|
+
get<V>(cfg: RenderStateConfig<V>): V;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* @experimental
|
|
86
|
+
* @internal
|
|
87
|
+
*
|
|
88
|
+
* Per-editor runtime state for {@link DOMRenderExtension} that backs the
|
|
89
|
+
* imperative editor context ({@link createRenderState} writes via
|
|
90
|
+
* `$setRenderContextValue`) and the conditional install of overrides.
|
|
91
|
+
*/
|
|
92
|
+
export interface DOMRenderRuntime {
|
|
93
|
+
/**
|
|
94
|
+
* The mutable, persistent editor-level context record. Reads of a
|
|
95
|
+
* {@link RenderStateConfig} during reconciliation (and as the base layer
|
|
96
|
+
* during a session) fall through to this record. It is also the layer
|
|
97
|
+
* that {@link DOMOverrideOptions.disabledForEditor} predicates read from.
|
|
98
|
+
*/
|
|
99
|
+
readonly editorContext: ContextRecord<typeof DOMRenderContextSymbol>;
|
|
100
|
+
/**
|
|
101
|
+
* Imperatively set a value in the editor context. If the change flips any
|
|
102
|
+
* override's `disabledForEditor` result, the resident render config is
|
|
103
|
+
* recompiled and the affected nodes are re-rendered (recreating DOM for
|
|
104
|
+
* structural overrides).
|
|
105
|
+
*/
|
|
106
|
+
setContextValue<V>(cfg: RenderStateConfig<V>, value: V): void;
|
|
107
|
+
/**
|
|
108
|
+
* Resolve the {@link EditorDOMRenderConfig} for the current export/generate
|
|
109
|
+
* session, applying any {@link DOMOverrideOptions.disabledForSession}
|
|
110
|
+
* predicates against the active session context. Returns the resident
|
|
111
|
+
* config when no session gating applies.
|
|
112
|
+
*/
|
|
113
|
+
getSessionConfig(): EditorDOMRenderConfig;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* @experimental
|
|
117
|
+
*
|
|
118
|
+
* Options for {@link domOverride} controlling *whether* an override is
|
|
119
|
+
* installed, based only on render context. Both predicates default to
|
|
120
|
+
* "not disabled".
|
|
121
|
+
*/
|
|
122
|
+
export interface DOMOverrideOptions {
|
|
123
|
+
/**
|
|
124
|
+
* Gate residency in the editor's render config (used by reconciliation and
|
|
125
|
+
* as the base for export/generate). Evaluated against the persistent editor
|
|
126
|
+
* context at compile time, and re-evaluated when that context changes via
|
|
127
|
+
* `$setRenderContextValue`; a change recompiles the config and re-renders
|
|
128
|
+
* affected nodes. Return `true` to remove the override. Default: not disabled.
|
|
129
|
+
*/
|
|
130
|
+
disabledForEditor?: (ctx: RenderContextReader) => boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Gate participation in a single export/generate session. Evaluated once at
|
|
133
|
+
* the start of each session against that session's context. Has no effect on
|
|
134
|
+
* live reconciliation (which is not a session). Return `true` to remove the
|
|
135
|
+
* override for that session. Default: not disabled.
|
|
136
|
+
*/
|
|
137
|
+
disabledForSession?: (ctx: RenderContextReader) => boolean;
|
|
71
138
|
}
|
|
72
139
|
/**
|
|
73
140
|
* @experimental
|
|
@@ -157,16 +224,19 @@ export interface DOMRenderMatch<T extends LexicalNode> {
|
|
|
157
224
|
* after the children. The root of the node returned by createDOM must
|
|
158
225
|
* still be exactly one HTMLElement.
|
|
159
226
|
*
|
|
160
|
-
* Generally you will call `$next()` to get
|
|
161
|
-
*
|
|
227
|
+
* Generally you will call `$next()` to get a slot and then use its methods
|
|
228
|
+
* to create a new one. The slot type is narrowed via {@link DOMSlotForNode}:
|
|
229
|
+
* for `ElementNode` it resolves to {@link ElementDOMSlot} with
|
|
230
|
+
* children-management semantics; for non-Element nodes the base
|
|
231
|
+
* {@link DOMSlot} pointing at the keyed DOM.
|
|
162
232
|
*
|
|
163
233
|
* @param node The LexicalNode
|
|
164
234
|
* @param dom The rendered HTMLElement
|
|
165
235
|
* @param $next Call the next implementation
|
|
166
236
|
* @param editor The editor
|
|
167
|
-
* @returns The
|
|
237
|
+
* @returns The slot for this node
|
|
168
238
|
*/
|
|
169
|
-
$getDOMSlot?:
|
|
239
|
+
$getDOMSlot?: (node: T, dom: HTMLElement, $next: () => DOMSlotForNode<T>, editor: LexicalEditor) => DOMSlotForNode<T>;
|
|
170
240
|
/**
|
|
171
241
|
* Called during the reconciliation process to determine which nodes
|
|
172
242
|
* to insert into the DOM for this Lexical Node. This is also the default
|
|
@@ -290,4 +360,22 @@ export interface DOMRenderMatch<T extends LexicalNode> {
|
|
|
290
360
|
* @returns true if this
|
|
291
361
|
*/
|
|
292
362
|
$extractWithChild?: (node: T, childNode: LexicalNode, selection: null | BaseSelection, destination: 'clone' | 'html', $next: () => boolean, editor: LexicalEditor) => boolean;
|
|
363
|
+
/**
|
|
364
|
+
* Set via {@link domOverride}'s options argument, not directly. See
|
|
365
|
+
* {@link DOMOverrideOptions.disabledForEditor}.
|
|
366
|
+
*/
|
|
367
|
+
disabledForEditor?: (ctx: RenderContextReader) => boolean;
|
|
368
|
+
/**
|
|
369
|
+
* Set via {@link domOverride}'s options argument, not directly. See
|
|
370
|
+
* {@link DOMOverrideOptions.disabledForSession}.
|
|
371
|
+
*/
|
|
372
|
+
disabledForSession?: (ctx: RenderContextReader) => boolean;
|
|
293
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* @experimental
|
|
376
|
+
*
|
|
377
|
+
* The hook fields of a {@link DOMRenderMatch} — i.e. without `nodes` or the
|
|
378
|
+
* {@link DOMOverrideOptions} predicates, which are passed separately to
|
|
379
|
+
* {@link domOverride}.
|
|
380
|
+
*/
|
|
381
|
+
export type DOMRenderMatchConfig<T extends LexicalNode> = Omit<DOMRenderMatch<T>, 'nodes' | keyof DOMOverrideOptions>;
|
package/package.json
CHANGED
|
@@ -8,37 +8,52 @@
|
|
|
8
8
|
"html"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.
|
|
12
|
-
"main": "LexicalHtml.js",
|
|
13
|
-
"types": "index.d.ts",
|
|
11
|
+
"version": "0.45.0",
|
|
12
|
+
"main": "./dist/LexicalHtml.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
16
|
"url": "git+https://github.com/facebook/lexical.git",
|
|
17
17
|
"directory": "packages/lexical-html"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@lexical/extension": "0.
|
|
21
|
-
"@lexical/
|
|
22
|
-
"@lexical/
|
|
23
|
-
"lexical": "0.
|
|
20
|
+
"@lexical/extension": "0.45.0",
|
|
21
|
+
"@lexical/internal": "0.45.0",
|
|
22
|
+
"@lexical/selection": "0.45.0",
|
|
23
|
+
"@lexical/utils": "0.45.0",
|
|
24
|
+
"lexical": "0.45.0"
|
|
24
25
|
},
|
|
25
|
-
"module": "LexicalHtml.mjs",
|
|
26
|
+
"module": "./dist/LexicalHtml.mjs",
|
|
26
27
|
"sideEffects": false,
|
|
27
28
|
"exports": {
|
|
28
29
|
".": {
|
|
30
|
+
"source": "./src/index.ts",
|
|
29
31
|
"import": {
|
|
30
|
-
"types": "./index.d.ts",
|
|
31
|
-
"development": "./LexicalHtml.dev.mjs",
|
|
32
|
-
"production": "./LexicalHtml.prod.mjs",
|
|
33
|
-
"node": "./LexicalHtml.node.mjs",
|
|
34
|
-
"default": "./LexicalHtml.mjs"
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"development": "./dist/LexicalHtml.dev.mjs",
|
|
34
|
+
"production": "./dist/LexicalHtml.prod.mjs",
|
|
35
|
+
"node": "./dist/LexicalHtml.node.mjs",
|
|
36
|
+
"default": "./dist/LexicalHtml.mjs"
|
|
35
37
|
},
|
|
36
38
|
"require": {
|
|
37
|
-
"types": "./index.d.ts",
|
|
38
|
-
"development": "./LexicalHtml.dev.js",
|
|
39
|
-
"production": "./LexicalHtml.prod.js",
|
|
40
|
-
"default": "./LexicalHtml.js"
|
|
39
|
+
"types": "./dist/index.d.ts",
|
|
40
|
+
"development": "./dist/LexicalHtml.dev.js",
|
|
41
|
+
"production": "./dist/LexicalHtml.prod.js",
|
|
42
|
+
"default": "./dist/LexicalHtml.js"
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
|
-
}
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"dist",
|
|
48
|
+
"src",
|
|
49
|
+
"!src/__tests__",
|
|
50
|
+
"!src/__bench__",
|
|
51
|
+
"!src/__mocks__",
|
|
52
|
+
"!src/**/*.test.ts",
|
|
53
|
+
"!src/**/*.test.tsx",
|
|
54
|
+
"!src/**/*.bench.ts",
|
|
55
|
+
"!src/**/*.bench.tsx",
|
|
56
|
+
"README.md",
|
|
57
|
+
"LICENSE"
|
|
58
|
+
]
|
|
44
59
|
}
|