@lexical/html 0.45.0 → 0.45.1-dev.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/LexicalHtml.dev.js +308 -211
- package/dist/LexicalHtml.dev.mjs +309 -213
- package/dist/LexicalHtml.mjs +1 -0
- package/dist/LexicalHtml.node.mjs +1 -0
- package/dist/LexicalHtml.prod.js +1 -1
- package/dist/LexicalHtml.prod.mjs +1 -1
- package/dist/import/HorizontalRuleImportExtension.d.ts +6 -5
- package/dist/import/coreImportRules.d.ts +1 -1
- package/dist/import/index.d.ts +1 -1
- package/dist/import/schemas.d.ts +15 -0
- package/dist/index.d.ts +1 -1
- package/package.json +6 -6
- package/src/import/HorizontalRuleImportExtension.ts +6 -7
- package/src/import/coreImportRules.ts +61 -1
- package/src/import/index.ts +1 -0
- package/src/import/schemas.ts +44 -0
- package/src/index.ts +6 -0
package/dist/LexicalHtml.dev.js
CHANGED
|
@@ -1671,6 +1671,249 @@ function $getImportContextValue(cfg, editor = lexical.$getEditor()) {
|
|
|
1671
1671
|
*/
|
|
1672
1672
|
const $withImportContext = $withContext(DOMImportContextSymbol, getDefaultImportContext);
|
|
1673
1673
|
|
|
1674
|
+
/**
|
|
1675
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1676
|
+
*
|
|
1677
|
+
* This source code is licensed under the MIT license found in the
|
|
1678
|
+
* LICENSE file in the root directory of this source tree.
|
|
1679
|
+
*
|
|
1680
|
+
*/
|
|
1681
|
+
|
|
1682
|
+
|
|
1683
|
+
/**
|
|
1684
|
+
* True if the node fills a block slot at the root or inside another
|
|
1685
|
+
* block — covers both ElementNode-style blocks (paragraph, heading,
|
|
1686
|
+
* quote) and block-level DecoratorNodes (HorizontalRuleNode,
|
|
1687
|
+
* ImageNode-as-block, etc.). Used by {@link BlockSchema},
|
|
1688
|
+
* {@link RootSchema}, and {@link NestedBlockSchema}.
|
|
1689
|
+
*
|
|
1690
|
+
* @experimental
|
|
1691
|
+
*/
|
|
1692
|
+
function $isBlockLevel(node) {
|
|
1693
|
+
return lexical.$isBlockElementNode(node) || lexical.$isDecoratorNode(node) && !node.isInline();
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
/**
|
|
1697
|
+
* Distribute an inline wrapper (`LinkNode`, `MarkNode`, …) across a
|
|
1698
|
+
* heterogeneous run of children produced by `$importChildren`, lifting
|
|
1699
|
+
* any block children to the top level while keeping the wrapper around
|
|
1700
|
+
* the leaf inline content.
|
|
1701
|
+
*
|
|
1702
|
+
* Use from a rule whose DOM source is an inline element that the
|
|
1703
|
+
* browser permitted to enclose block elements — the canonical case is
|
|
1704
|
+
* `<a href="…"><h1>title</h1><div>body</div></a>`, which a link rule
|
|
1705
|
+
* wants to surface as two block siblings (heading + paragraph), each
|
|
1706
|
+
* with its own link wrapping the original inline content. Schemas
|
|
1707
|
+
* can't express this because they reason about a parent's children
|
|
1708
|
+
* only — they cannot lift the parent out of itself.
|
|
1709
|
+
*
|
|
1710
|
+
* For each top-level child:
|
|
1711
|
+
* - **Inline children** are collected into runs; each run is wrapped
|
|
1712
|
+
* in a single fresh wrapper (from `$makeWrapper()`).
|
|
1713
|
+
* - **Block children** are descended into: their own children are
|
|
1714
|
+
* recursively distributed with `$makeWrapper`, then re-attached so
|
|
1715
|
+
* the block keeps its position at the top level.
|
|
1716
|
+
*
|
|
1717
|
+
* The returned list will contain a mix of blocks and wrapped inline
|
|
1718
|
+
* runs. The enclosing schema (typically {@link BlockSchema}) will
|
|
1719
|
+
* then package those inline wrappers into paragraphs as usual.
|
|
1720
|
+
*
|
|
1721
|
+
* @experimental
|
|
1722
|
+
*/
|
|
1723
|
+
function $distributeInlineWrapper(children, $makeWrapper) {
|
|
1724
|
+
const out = [];
|
|
1725
|
+
let inlineRun = [];
|
|
1726
|
+
const flushInline = () => {
|
|
1727
|
+
if (inlineRun.length === 0) {
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
out.push($makeWrapper().splice(0, 0, inlineRun));
|
|
1731
|
+
inlineRun = [];
|
|
1732
|
+
};
|
|
1733
|
+
for (const child of children) {
|
|
1734
|
+
if ($isBlockLevel(child)) {
|
|
1735
|
+
flushInline();
|
|
1736
|
+
// Recursively distribute the wrapper into the block's own
|
|
1737
|
+
// children. A block DecoratorNode (no children) is left alone.
|
|
1738
|
+
if (lexical.$isElementNode(child)) {
|
|
1739
|
+
const wrapped = $distributeInlineWrapper(child.getChildren(), $makeWrapper);
|
|
1740
|
+
child.splice(0, child.getChildrenSize(), wrapped);
|
|
1741
|
+
}
|
|
1742
|
+
out.push(child);
|
|
1743
|
+
} else {
|
|
1744
|
+
inlineRun.push(child);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
flushInline();
|
|
1748
|
+
return out;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
/**
|
|
1752
|
+
* Apply a {@link ChildSchema} to a flat list of children produced by
|
|
1753
|
+
* `$importChildren`. Walks the list once, partitions into accepted vs.
|
|
1754
|
+
* rejected runs, packages or drops rejected runs, then runs `$finalize`.
|
|
1755
|
+
*
|
|
1756
|
+
* @internal
|
|
1757
|
+
*/
|
|
1758
|
+
function $applySchema(schema, children, parent, domParent) {
|
|
1759
|
+
const out = [];
|
|
1760
|
+
let run = null;
|
|
1761
|
+
const flushRun = () => {
|
|
1762
|
+
if (run === null) {
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
const rejected = run;
|
|
1766
|
+
run = null;
|
|
1767
|
+
if (schema.$packageRun) {
|
|
1768
|
+
const packaged = schema.$packageRun(rejected, parent, domParent);
|
|
1769
|
+
if (packaged.length > 0) {
|
|
1770
|
+
for (const n of packaged) {
|
|
1771
|
+
out.push(n);
|
|
1772
|
+
}
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
// No $packageRun (or it returned []) — apply onReject. 'drop' (default)
|
|
1777
|
+
// discards the run. 'hoist' lets it through unchanged at this level.
|
|
1778
|
+
if (schema.onReject === 'hoist') {
|
|
1779
|
+
for (const n of rejected) {
|
|
1780
|
+
out.push(n);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
};
|
|
1784
|
+
for (const child of children) {
|
|
1785
|
+
if (schema.$accepts(child, parent)) {
|
|
1786
|
+
flushRun();
|
|
1787
|
+
out.push(child);
|
|
1788
|
+
} else {
|
|
1789
|
+
if (run === null) {
|
|
1790
|
+
run = [];
|
|
1791
|
+
}
|
|
1792
|
+
run.push(child);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
flushRun();
|
|
1796
|
+
return schema.$finalize ? schema.$finalize(out, parent) : out;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* Apply a parent DOM element's `text-align` (when set to one of the
|
|
1801
|
+
* supported {@link ElementFormatType} values) to each block-level child
|
|
1802
|
+
* Lexical node that does not yet have its own format.
|
|
1803
|
+
*
|
|
1804
|
+
* Mirrors the part of the legacy `wrapContinuousInlines` that wrote
|
|
1805
|
+
* `node.setFormat(textAlign)` onto pre-existing block children when the
|
|
1806
|
+
* DOM parent carried `style.textAlign`. Pair with
|
|
1807
|
+
* {@link $paragraphPackageRun} (which carries the same propagation onto
|
|
1808
|
+
* paragraphs synthesized around inline runs) to fully replicate the
|
|
1809
|
+
* legacy behavior on a run of mixed children.
|
|
1810
|
+
*
|
|
1811
|
+
* @experimental
|
|
1812
|
+
*/
|
|
1813
|
+
function $propagateTextAlignToBlockChildren(children, domParent) {
|
|
1814
|
+
if (!lexical.isHTMLElement(domParent)) {
|
|
1815
|
+
return children;
|
|
1816
|
+
}
|
|
1817
|
+
const textAlign = domParent.style.textAlign;
|
|
1818
|
+
if (!isAlignmentValue(textAlign)) {
|
|
1819
|
+
return children;
|
|
1820
|
+
}
|
|
1821
|
+
for (const child of children) {
|
|
1822
|
+
if (lexical.$isBlockElementNode(child) && child.getFormatType() === '') {
|
|
1823
|
+
child.setFormat(textAlign);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
return children;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* Wrap a run of inline lexical nodes in a fresh paragraph, propagating the
|
|
1831
|
+
* `text-align` of `domParent` as the paragraph's format type (matching the
|
|
1832
|
+
* legacy `wrapContinuousInlines` behavior).
|
|
1833
|
+
*/
|
|
1834
|
+
function $paragraphPackageRun(run, _parent, domParent) {
|
|
1835
|
+
// Mirror the legacy `$wrapInlineNodes` (driven by
|
|
1836
|
+
// `selection.insertNodes`) shortcut where a lone `<br>` at this
|
|
1837
|
+
// level (a `LineBreakNode` is the only thing in the rejected run)
|
|
1838
|
+
// becomes an *empty* paragraph rather than a paragraph wrapping a
|
|
1839
|
+
// visible line break — that's the form clipboard pastes ending in a
|
|
1840
|
+
// trailing `<br>` (Google Docs, Gmail, …) rely on for the editor's
|
|
1841
|
+
// "extra trailing empty line" expectation.
|
|
1842
|
+
if (run.length === 1 && lexical.$isLineBreakNode(run[0])) {
|
|
1843
|
+
run = [];
|
|
1844
|
+
}
|
|
1845
|
+
const paragraph = lexical.$createParagraphNode();
|
|
1846
|
+
if (lexical.isHTMLElement(domParent)) {
|
|
1847
|
+
const textAlign = domParent.style.textAlign;
|
|
1848
|
+
if (isAlignmentValue(textAlign)) {
|
|
1849
|
+
paragraph.setFormat(textAlign);
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
return [paragraph.splice(0, 0, run)];
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
/**
|
|
1856
|
+
* Default schema for block-level positions (root of the document, the body
|
|
1857
|
+
* of a block element node). Accepts block lexical nodes; packages runs of
|
|
1858
|
+
* inline children into fresh paragraph nodes.
|
|
1859
|
+
*
|
|
1860
|
+
* @experimental
|
|
1861
|
+
*/
|
|
1862
|
+
const BlockSchema = {
|
|
1863
|
+
$accepts: $isBlockLevel,
|
|
1864
|
+
$packageRun: $paragraphPackageRun,
|
|
1865
|
+
name: 'BlockSchema'
|
|
1866
|
+
};
|
|
1867
|
+
|
|
1868
|
+
/**
|
|
1869
|
+
* Schema for inline-only positions (the body of an inline lexical node such
|
|
1870
|
+
* as a link). Accepts non-block lexical nodes; runs of block children are
|
|
1871
|
+
* dropped (`onReject: 'drop'` is the default).
|
|
1872
|
+
*
|
|
1873
|
+
* @experimental
|
|
1874
|
+
*/
|
|
1875
|
+
const InlineSchema = {
|
|
1876
|
+
$accepts: child => !$isBlockLevel(child),
|
|
1877
|
+
name: 'InlineSchema'
|
|
1878
|
+
};
|
|
1879
|
+
|
|
1880
|
+
/**
|
|
1881
|
+
* Schema for nested block positions — the equivalent of the legacy
|
|
1882
|
+
* `ArtificialNode__DO_NOT_USE` flow used when a block DOM element appears
|
|
1883
|
+
* inside another block lexical ancestor. Accepts block nodes; runs of inline
|
|
1884
|
+
* children are emitted with a line break between consecutive runs (instead
|
|
1885
|
+
* of being wrapped in a paragraph, which would introduce an extra level of
|
|
1886
|
+
* nesting).
|
|
1887
|
+
*
|
|
1888
|
+
* @experimental
|
|
1889
|
+
*/
|
|
1890
|
+
const NestedBlockSchema = {
|
|
1891
|
+
$accepts: $isBlockLevel,
|
|
1892
|
+
/**
|
|
1893
|
+
* Pass an inline run through unchanged. Because the schema iterator only
|
|
1894
|
+
* groups *maximal* rejected runs (each separated from the next by an
|
|
1895
|
+
* accepted block child), the legacy "linebreak between adjacent inline
|
|
1896
|
+
* groups" case never arises — adjacent inline siblings are already
|
|
1897
|
+
* coalesced into one run.
|
|
1898
|
+
*/
|
|
1899
|
+
$packageRun: run => run,
|
|
1900
|
+
name: 'NestedBlockSchema'
|
|
1901
|
+
};
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* Schema for the topmost level of `$generateNodesFromDOM`. Identical to
|
|
1905
|
+
* {@link BlockSchema}; aliased for clarity at the entry point and so it can
|
|
1906
|
+
* be overridden separately in the future (e.g. to synthesize a `ListNode`
|
|
1907
|
+
* around runs of orphan `ListItemNode`s).
|
|
1908
|
+
*
|
|
1909
|
+
* @experimental
|
|
1910
|
+
*/
|
|
1911
|
+
const RootSchema = {
|
|
1912
|
+
$accepts: $isBlockLevel,
|
|
1913
|
+
$packageRun: $paragraphPackageRun,
|
|
1914
|
+
name: 'RootSchema'
|
|
1915
|
+
};
|
|
1916
|
+
|
|
1674
1917
|
/**
|
|
1675
1918
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
1676
1919
|
*
|
|
@@ -2024,7 +2267,13 @@ const IgnoreScriptStyleRule = defineImportRule({
|
|
|
2024
2267
|
name: '@lexical/html/script-style-ignore'
|
|
2025
2268
|
});
|
|
2026
2269
|
const LineBreakRule = defineImportRule({
|
|
2027
|
-
|
|
2270
|
+
// Mirror the legacy LineBreakNode.importDOM filter: stray `<br>` that
|
|
2271
|
+
// are the sole or trailing child of a block parent (e.g. Apple's
|
|
2272
|
+
// `<br class="Apple-interchange-newline">` clipboard sentinel, or the
|
|
2273
|
+
// trailing `<br>` browsers insert after the last text in a `<div>`)
|
|
2274
|
+
// would otherwise survive as a LineBreakNode and tack an extra blank
|
|
2275
|
+
// line onto the imported content.
|
|
2276
|
+
$import: (_ctx, el) => lexical.isOnlyChildInBlockNode(el) || lexical.isLastChildInBlockNode(el) ? [] : [lexical.$createLineBreakNode()],
|
|
2028
2277
|
match: sel$1.tag('br'),
|
|
2029
2278
|
name: '@lexical/html/br'
|
|
2030
2279
|
});
|
|
@@ -2054,6 +2303,51 @@ const ParagraphRule = defineImportRule({
|
|
|
2054
2303
|
name: '@lexical/html/p'
|
|
2055
2304
|
});
|
|
2056
2305
|
|
|
2306
|
+
/**
|
|
2307
|
+
* Transparent block-container rule for any unconverted block-level DOM
|
|
2308
|
+
* element — `<div>`, but also `<section>`, `<article>`, `<header>`,
|
|
2309
|
+
* `<figure>`, … (everything {@link isBlockDomNode} recognizes via the
|
|
2310
|
+
* legacy `BLOCK_TAG_RE`). Without it these would fall through to the
|
|
2311
|
+
* dispatcher's `$hoistChildrenOf` / `DefaultHoistRule` fallback, which
|
|
2312
|
+
* transparently lifts children up to the enclosing context. That works
|
|
2313
|
+
* structurally, but (a) two sibling `<section>`s collapse into a single
|
|
2314
|
+
* paragraph instead of two, and (b) any `text-align` set on the element
|
|
2315
|
+
* is lost because the synthesized paragraph (built by the enclosing
|
|
2316
|
+
* schema) sees the *grandparent* as `domParent`.
|
|
2317
|
+
*
|
|
2318
|
+
* The rule is registered as a `sel.any()` wildcard and defers (via
|
|
2319
|
+
* `$next()`) for non-block elements so inline tags still reach the inline
|
|
2320
|
+
* rules. Higher-priority tag rules (`<p>`, `<li>`, `<td>`, headings, …)
|
|
2321
|
+
* are dispatched first and never reach here.
|
|
2322
|
+
*
|
|
2323
|
+
* The element's children run through {@link BlockSchema} so each inline
|
|
2324
|
+
* run becomes its own `ParagraphNode` (with the element's `text-align`
|
|
2325
|
+
* picked up via {@link $paragraphPackageRun}'s `domParent`), and any
|
|
2326
|
+
* pre-existing block children get the same alignment applied via
|
|
2327
|
+
* {@link $propagateTextAlignToBlockChildren}. The resulting block-level
|
|
2328
|
+
* nodes are what the enclosing context sees — at the root a sibling
|
|
2329
|
+
* paragraph is the natural shape; inside a block lexical container the
|
|
2330
|
+
* container rule (e.g. {@link ListItemRule}) collapses paragraph
|
|
2331
|
+
* children back into inline-with-line-break form. That way both `<p>`
|
|
2332
|
+
* and transparent blocks (`<div>`, `<section>`, …) project to the same
|
|
2333
|
+
* `ParagraphNode` intermediate, and there is no need for a marker node
|
|
2334
|
+
* to distinguish them.
|
|
2335
|
+
*/
|
|
2336
|
+
const TransparentBlockRule = defineImportRule({
|
|
2337
|
+
$import: (ctx, el, $next) => {
|
|
2338
|
+
if (!lexical.isBlockDomNode(el)) {
|
|
2339
|
+
// Inline element with no dedicated rule — let the inline rules (or
|
|
2340
|
+
// the default hoist) handle it.
|
|
2341
|
+
return $next();
|
|
2342
|
+
}
|
|
2343
|
+
return $propagateTextAlignToBlockChildren(ctx.$importChildren(el, {
|
|
2344
|
+
schema: BlockSchema
|
|
2345
|
+
}), el);
|
|
2346
|
+
},
|
|
2347
|
+
match: sel$1.any(),
|
|
2348
|
+
name: '@lexical/html/transparent-block'
|
|
2349
|
+
});
|
|
2350
|
+
|
|
2057
2351
|
/**
|
|
2058
2352
|
* Rules covering the {@link ParagraphNode}, {@link TextNode},
|
|
2059
2353
|
* {@link LineBreakNode}, and {@link TabNode} cases that the legacy
|
|
@@ -2063,7 +2357,7 @@ const ParagraphRule = defineImportRule({
|
|
|
2063
2357
|
*
|
|
2064
2358
|
* @experimental
|
|
2065
2359
|
*/
|
|
2066
|
-
const CoreImportRules = [IgnoreScriptStyleRule, ParagraphRule, TextRule, LineBreakRule, InlineFormatRule];
|
|
2360
|
+
const CoreImportRules = [IgnoreScriptStyleRule, ParagraphRule, TransparentBlockRule, TextRule, LineBreakRule, InlineFormatRule];
|
|
2067
2361
|
|
|
2068
2362
|
/**
|
|
2069
2363
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -2282,209 +2576,6 @@ function defineOverlayRules(entries) {
|
|
|
2282
2576
|
};
|
|
2283
2577
|
}
|
|
2284
2578
|
|
|
2285
|
-
/**
|
|
2286
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2287
|
-
*
|
|
2288
|
-
* This source code is licensed under the MIT license found in the
|
|
2289
|
-
* LICENSE file in the root directory of this source tree.
|
|
2290
|
-
*
|
|
2291
|
-
*/
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
/**
|
|
2295
|
-
* True if the node fills a block slot at the root or inside another
|
|
2296
|
-
* block — covers both ElementNode-style blocks (paragraph, heading,
|
|
2297
|
-
* quote) and block-level DecoratorNodes (HorizontalRuleNode,
|
|
2298
|
-
* ImageNode-as-block, etc.). Used by {@link BlockSchema},
|
|
2299
|
-
* {@link RootSchema}, and {@link NestedBlockSchema}.
|
|
2300
|
-
*
|
|
2301
|
-
* @experimental
|
|
2302
|
-
*/
|
|
2303
|
-
function $isBlockLevel(node) {
|
|
2304
|
-
return lexical.$isBlockElementNode(node) || lexical.$isDecoratorNode(node) && !node.isInline();
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
/**
|
|
2308
|
-
* Distribute an inline wrapper (`LinkNode`, `MarkNode`, …) across a
|
|
2309
|
-
* heterogeneous run of children produced by `$importChildren`, lifting
|
|
2310
|
-
* any block children to the top level while keeping the wrapper around
|
|
2311
|
-
* the leaf inline content.
|
|
2312
|
-
*
|
|
2313
|
-
* Use from a rule whose DOM source is an inline element that the
|
|
2314
|
-
* browser permitted to enclose block elements — the canonical case is
|
|
2315
|
-
* `<a href="…"><h1>title</h1><div>body</div></a>`, which a link rule
|
|
2316
|
-
* wants to surface as two block siblings (heading + paragraph), each
|
|
2317
|
-
* with its own link wrapping the original inline content. Schemas
|
|
2318
|
-
* can't express this because they reason about a parent's children
|
|
2319
|
-
* only — they cannot lift the parent out of itself.
|
|
2320
|
-
*
|
|
2321
|
-
* For each top-level child:
|
|
2322
|
-
* - **Inline children** are collected into runs; each run is wrapped
|
|
2323
|
-
* in a single fresh wrapper (from `$makeWrapper()`).
|
|
2324
|
-
* - **Block children** are descended into: their own children are
|
|
2325
|
-
* recursively distributed with `$makeWrapper`, then re-attached so
|
|
2326
|
-
* the block keeps its position at the top level.
|
|
2327
|
-
*
|
|
2328
|
-
* The returned list will contain a mix of blocks and wrapped inline
|
|
2329
|
-
* runs. The enclosing schema (typically {@link BlockSchema}) will
|
|
2330
|
-
* then package those inline wrappers into paragraphs as usual.
|
|
2331
|
-
*
|
|
2332
|
-
* @experimental
|
|
2333
|
-
*/
|
|
2334
|
-
function $distributeInlineWrapper(children, $makeWrapper) {
|
|
2335
|
-
const out = [];
|
|
2336
|
-
let inlineRun = [];
|
|
2337
|
-
const flushInline = () => {
|
|
2338
|
-
if (inlineRun.length === 0) {
|
|
2339
|
-
return;
|
|
2340
|
-
}
|
|
2341
|
-
out.push($makeWrapper().splice(0, 0, inlineRun));
|
|
2342
|
-
inlineRun = [];
|
|
2343
|
-
};
|
|
2344
|
-
for (const child of children) {
|
|
2345
|
-
if ($isBlockLevel(child)) {
|
|
2346
|
-
flushInline();
|
|
2347
|
-
// Recursively distribute the wrapper into the block's own
|
|
2348
|
-
// children. A block DecoratorNode (no children) is left alone.
|
|
2349
|
-
if (lexical.$isElementNode(child)) {
|
|
2350
|
-
const wrapped = $distributeInlineWrapper(child.getChildren(), $makeWrapper);
|
|
2351
|
-
child.splice(0, child.getChildrenSize(), wrapped);
|
|
2352
|
-
}
|
|
2353
|
-
out.push(child);
|
|
2354
|
-
} else {
|
|
2355
|
-
inlineRun.push(child);
|
|
2356
|
-
}
|
|
2357
|
-
}
|
|
2358
|
-
flushInline();
|
|
2359
|
-
return out;
|
|
2360
|
-
}
|
|
2361
|
-
|
|
2362
|
-
/**
|
|
2363
|
-
* Apply a {@link ChildSchema} to a flat list of children produced by
|
|
2364
|
-
* `$importChildren`. Walks the list once, partitions into accepted vs.
|
|
2365
|
-
* rejected runs, packages or drops rejected runs, then runs `$finalize`.
|
|
2366
|
-
*
|
|
2367
|
-
* @internal
|
|
2368
|
-
*/
|
|
2369
|
-
function $applySchema(schema, children, parent, domParent) {
|
|
2370
|
-
const out = [];
|
|
2371
|
-
let run = null;
|
|
2372
|
-
const flushRun = () => {
|
|
2373
|
-
if (run === null) {
|
|
2374
|
-
return;
|
|
2375
|
-
}
|
|
2376
|
-
const rejected = run;
|
|
2377
|
-
run = null;
|
|
2378
|
-
if (schema.$packageRun) {
|
|
2379
|
-
const packaged = schema.$packageRun(rejected, parent, domParent);
|
|
2380
|
-
if (packaged.length > 0) {
|
|
2381
|
-
for (const n of packaged) {
|
|
2382
|
-
out.push(n);
|
|
2383
|
-
}
|
|
2384
|
-
return;
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
// No $packageRun (or it returned []) — apply onReject. 'drop' (default)
|
|
2388
|
-
// discards the run. 'hoist' lets it through unchanged at this level.
|
|
2389
|
-
if (schema.onReject === 'hoist') {
|
|
2390
|
-
for (const n of rejected) {
|
|
2391
|
-
out.push(n);
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
};
|
|
2395
|
-
for (const child of children) {
|
|
2396
|
-
if (schema.$accepts(child, parent)) {
|
|
2397
|
-
flushRun();
|
|
2398
|
-
out.push(child);
|
|
2399
|
-
} else {
|
|
2400
|
-
if (run === null) {
|
|
2401
|
-
run = [];
|
|
2402
|
-
}
|
|
2403
|
-
run.push(child);
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
flushRun();
|
|
2407
|
-
return schema.$finalize ? schema.$finalize(out, parent) : out;
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
/**
|
|
2411
|
-
* Wrap a run of inline lexical nodes in a fresh paragraph, propagating the
|
|
2412
|
-
* `text-align` of `domParent` as the paragraph's format type (matching the
|
|
2413
|
-
* legacy `wrapContinuousInlines` behavior).
|
|
2414
|
-
*/
|
|
2415
|
-
function $paragraphPackageRun(run, _parent, domParent) {
|
|
2416
|
-
const paragraph = lexical.$createParagraphNode();
|
|
2417
|
-
if (lexical.isHTMLElement(domParent)) {
|
|
2418
|
-
const textAlign = domParent.style.textAlign;
|
|
2419
|
-
if (isAlignmentValue(textAlign)) {
|
|
2420
|
-
paragraph.setFormat(textAlign);
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
|
-
return [paragraph.splice(0, 0, run)];
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
|
-
/**
|
|
2427
|
-
* Default schema for block-level positions (root of the document, the body
|
|
2428
|
-
* of a block element node). Accepts block lexical nodes; packages runs of
|
|
2429
|
-
* inline children into fresh paragraph nodes.
|
|
2430
|
-
*
|
|
2431
|
-
* @experimental
|
|
2432
|
-
*/
|
|
2433
|
-
const BlockSchema = {
|
|
2434
|
-
$accepts: $isBlockLevel,
|
|
2435
|
-
$packageRun: $paragraphPackageRun,
|
|
2436
|
-
name: 'BlockSchema'
|
|
2437
|
-
};
|
|
2438
|
-
|
|
2439
|
-
/**
|
|
2440
|
-
* Schema for inline-only positions (the body of an inline lexical node such
|
|
2441
|
-
* as a link). Accepts non-block lexical nodes; runs of block children are
|
|
2442
|
-
* dropped (`onReject: 'drop'` is the default).
|
|
2443
|
-
*
|
|
2444
|
-
* @experimental
|
|
2445
|
-
*/
|
|
2446
|
-
const InlineSchema = {
|
|
2447
|
-
$accepts: child => !$isBlockLevel(child),
|
|
2448
|
-
name: 'InlineSchema'
|
|
2449
|
-
};
|
|
2450
|
-
|
|
2451
|
-
/**
|
|
2452
|
-
* Schema for nested block positions — the equivalent of the legacy
|
|
2453
|
-
* `ArtificialNode__DO_NOT_USE` flow used when a block DOM element appears
|
|
2454
|
-
* inside another block lexical ancestor. Accepts block nodes; runs of inline
|
|
2455
|
-
* children are emitted with a line break between consecutive runs (instead
|
|
2456
|
-
* of being wrapped in a paragraph, which would introduce an extra level of
|
|
2457
|
-
* nesting).
|
|
2458
|
-
*
|
|
2459
|
-
* @experimental
|
|
2460
|
-
*/
|
|
2461
|
-
const NestedBlockSchema = {
|
|
2462
|
-
$accepts: $isBlockLevel,
|
|
2463
|
-
/**
|
|
2464
|
-
* Pass an inline run through unchanged. Because the schema iterator only
|
|
2465
|
-
* groups *maximal* rejected runs (each separated from the next by an
|
|
2466
|
-
* accepted block child), the legacy "linebreak between adjacent inline
|
|
2467
|
-
* groups" case never arises — adjacent inline siblings are already
|
|
2468
|
-
* coalesced into one run.
|
|
2469
|
-
*/
|
|
2470
|
-
$packageRun: run => run,
|
|
2471
|
-
name: 'NestedBlockSchema'
|
|
2472
|
-
};
|
|
2473
|
-
|
|
2474
|
-
/**
|
|
2475
|
-
* Schema for the topmost level of `$generateNodesFromDOM`. Identical to
|
|
2476
|
-
* {@link BlockSchema}; aliased for clarity at the entry point and so it can
|
|
2477
|
-
* be overridden separately in the future (e.g. to synthesize a `ListNode`
|
|
2478
|
-
* around runs of orphan `ListItemNode`s).
|
|
2479
|
-
*
|
|
2480
|
-
* @experimental
|
|
2481
|
-
*/
|
|
2482
|
-
const RootSchema = {
|
|
2483
|
-
$accepts: $isBlockLevel,
|
|
2484
|
-
$packageRun: $paragraphPackageRun,
|
|
2485
|
-
name: 'RootSchema'
|
|
2486
|
-
};
|
|
2487
|
-
|
|
2488
2579
|
/**
|
|
2489
2580
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2490
2581
|
*
|
|
@@ -2833,20 +2924,21 @@ const HorizontalRuleRule = defineImportRule({
|
|
|
2833
2924
|
const HorizontalRuleImportRules = [HorizontalRuleRule];
|
|
2834
2925
|
|
|
2835
2926
|
/**
|
|
2836
|
-
* Bundles {@link HorizontalRuleImportRules}
|
|
2837
|
-
* {@link
|
|
2838
|
-
*
|
|
2839
|
-
*
|
|
2927
|
+
* Bundles {@link HorizontalRuleImportRules} together with the runtime
|
|
2928
|
+
* {@link HorizontalRuleExtension}. The application is expected to
|
|
2929
|
+
* already have `CoreImportExtension` (or some equivalent) in its
|
|
2930
|
+
* dependency graph — the core/text/paragraph/inline-format rules are a
|
|
2931
|
+
* shared baseline, not something this leaf importer should re-declare.
|
|
2840
2932
|
*
|
|
2841
2933
|
* Lives in `@lexical/html` (not `@lexical/extension`) because
|
|
2842
2934
|
* {@link DOMImportExtension} itself is in `@lexical/html`, and
|
|
2843
2935
|
* `@lexical/extension` is upstream of `@lexical/html` in the dependency
|
|
2844
|
-
* graph
|
|
2936
|
+
* graph.
|
|
2845
2937
|
*
|
|
2846
2938
|
* @experimental
|
|
2847
2939
|
*/
|
|
2848
2940
|
const HorizontalRuleImportExtension = lexical.defineExtension({
|
|
2849
|
-
dependencies: [
|
|
2941
|
+
dependencies: [extension.HorizontalRuleExtension, lexical.configExtension(DOMImportExtension, {
|
|
2850
2942
|
rules: HorizontalRuleImportRules
|
|
2851
2943
|
})],
|
|
2852
2944
|
name: '@lexical/html/HorizontalRuleImport'
|
|
@@ -2954,6 +3046,10 @@ function $generateHtmlFromNodes(editor, selection = null) {
|
|
|
2954
3046
|
formatDevErrorMessage(`To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom or use withDOM from @lexical/headless/dom before calling this function.`);
|
|
2955
3047
|
}
|
|
2956
3048
|
}
|
|
3049
|
+
// BC: $setTextContent now requires an active-editor scope (added in #8519).
|
|
3050
|
+
// If the caller is in a legacy `editorState.read(cb)` scope (no active editor),
|
|
3051
|
+
// establish one via internal API.
|
|
3052
|
+
lexical.$assumeActiveEditor(editor);
|
|
2957
3053
|
return $generateDOMFromNodes(document.createElement('div'), selection, editor).innerHTML;
|
|
2958
3054
|
}
|
|
2959
3055
|
function $appendNodesToHTML(editor, currentNode, parentElementAppend, selection$1 = null, domConfig = lexical.$getEditorDOMRenderConfig(editor)) {
|
|
@@ -3156,6 +3252,7 @@ exports.$getRenderContextValue = $getRenderContextValue;
|
|
|
3156
3252
|
exports.$getSessionDOMRenderConfig = $getSessionDOMRenderConfig;
|
|
3157
3253
|
exports.$inlineStylesFromStyleSheets = $inlineStylesFromStyleSheets;
|
|
3158
3254
|
exports.$isBlockLevel = $isBlockLevel;
|
|
3255
|
+
exports.$propagateTextAlignToBlockChildren = $propagateTextAlignToBlockChildren;
|
|
3159
3256
|
exports.$setRenderContextValue = $setRenderContextValue;
|
|
3160
3257
|
exports.$updateRenderContextValue = $updateRenderContextValue;
|
|
3161
3258
|
exports.$withImportContext = $withImportContext;
|