Skip to content

feat(rust): the core nodes' DOM hooks and @lexical/html's HTML export and import - #154

Open
tmm wants to merge 1 commit into
rust-domfrom
rust-html
Open

tmm wants to merge 1 commit into
rust-domfrom
rust-html

Conversation

@tmm

@tmm tmm commented Nov 14, 2026

Copy link
Copy Markdown
Member

Description

The Rust port's html feature had a DOM (lexical_editor::dom) but no
node rendered into it, so html/export and html/import had no suite.

This adds, behind the same feature:

  • createDOM, exportDOM and the static importDOM as LexicalNode
    hooks, with ElementNode.exportDOM (indent and direction) and
    TextNode's behavior as their defaults, and the types they exchange
    (DOMExportOutput, DOMConversionOutput, DOMConversionMap, ...) in
    lexical_editor::lexical_dom, ported from LexicalNode.ts,
    LexicalEditor.ts and the DOM helpers of LexicalUtils.ts.
  • createEditor's theme (always) and html config (export overrides
    and extra import conversions), editor._config, the conversion cache,
    and DEFAULT_EDITOR_DOM_CONFIG.
  • The DOM code of the core nodes: TextNode (createDOM with the theme's
    class names and the style, exportDOM, and the #text, b, span and
    format-element conversions), TabNode, LineBreakNode,
    ParagraphNode (with its extractWithChild), and
    ArtificialNode__DO_NOT_USE, which the core now registers as JS does.
  • LexicalNode.isSelected.
  • lexical_editor::html, ported from packages/lexical-html/src/index.ts:
    generate_html_from_nodes, generate_dom_from_nodes,
    generate_dom_from_root, append_node_to_html (with
    $sliceSelectedTextNodeContent for a selection) and
    generate_nodes_from_dom.
  • Conformance suites for html/export and html/import.

$inlineStylesFromStyleSheets and the DOMImportExtension and
DOMRenderExtension pipelines are not ported (rust/PARITY.md); no vector
needs them. The node packages' DOM parts come next.

Test plan

Before

$ cargo run -q -p lexical-conformance --release -- html/
| `html/entities` | 2125 | 2125 | 0 | 0 | 0 | pass |
| `html/export` | – | – | – | – | – | not implemented |
| `html/import` | – | – | – | – | – | not implemented |
| `html/parse` | 37 | 37 | 0 | 0 | 0 | pass |
| **Total** | 2162 | 2162 | 0 | 0 | 0 | |

After

$ cargo run -q -p lexical-conformance --release -- html/
| `html/entities` | 2125 | 2125 | 0 | 0 | 0 | pass |
| `html/export` | 42 | 42 | 0 | 0 | 0 | pass |
| `html/import` | 68 | 68 | 0 | 0 | 0 | pass |
| `html/parse` | 37 | 37 | 0 | 0 | 0 | pass |
| **Total** | 2272 | 2272 | 0 | 0 | 0 | |

$ cargo run -q -p lexical-conformance --release
| **Total** | 3643 | 3643 | 0 | 0 | 0 | |

cargo fmt --all --check, cargo clippy --workspace --all-targets --all-features --locked -- -D warnings, cargo test --workspace --all-features --locked, cargo doc with -D warnings, and
cargo check -p lexical-editor --no-default-features --features <f> for
each feature are clean.

… and import

## Description

The Rust port's `html` feature had a DOM (`lexical_editor::dom`) but no
node rendered into it, so `html/export` and `html/import` had no suite.

This adds, behind the same feature:

- `createDOM`, `exportDOM` and the static `importDOM` as `LexicalNode`
  hooks, with `ElementNode.exportDOM` (indent and direction) and
  `TextNode`'s behavior as their defaults, and the types they exchange
  (`DOMExportOutput`, `DOMConversionOutput`, `DOMConversionMap`, ...) in
  `lexical_editor::lexical_dom`, ported from `LexicalNode.ts`,
  `LexicalEditor.ts` and the DOM helpers of `LexicalUtils.ts`.
- `createEditor`'s `theme` (always) and `html` config (export overrides
  and extra import conversions), `editor._config`, the conversion cache,
  and `DEFAULT_EDITOR_DOM_CONFIG`.
- The DOM code of the core nodes: `TextNode` (`createDOM` with the theme's
  class names and the style, `exportDOM`, and the `#text`, `b`, `span` and
  format-element conversions), `TabNode`, `LineBreakNode`,
  `ParagraphNode` (with its `extractWithChild`), and
  `ArtificialNode__DO_NOT_USE`, which the core now registers as JS does.
- `LexicalNode.isSelected`.
- `lexical_editor::html`, ported from `packages/lexical-html/src/index.ts`:
  `generate_html_from_nodes`, `generate_dom_from_nodes`,
  `generate_dom_from_root`, `append_node_to_html` (with
  `$sliceSelectedTextNodeContent` for a selection) and
  `generate_nodes_from_dom`.
- Conformance suites for `html/export` and `html/import`.

`$inlineStylesFromStyleSheets` and the `DOMImportExtension` and
`DOMRenderExtension` pipelines are not ported (rust/PARITY.md); no vector
needs them. The node packages' DOM parts come next.

## Test plan

### Before

```
$ cargo run -q -p lexical-conformance --release -- html/
| `html/entities` | 2125 | 2125 | 0 | 0 | 0 | pass |
| `html/export` | – | – | – | – | – | not implemented |
| `html/import` | – | – | – | – | – | not implemented |
| `html/parse` | 37 | 37 | 0 | 0 | 0 | pass |
| **Total** | 2162 | 2162 | 0 | 0 | 0 | |
```

### After

```
$ cargo run -q -p lexical-conformance --release -- html/
| `html/entities` | 2125 | 2125 | 0 | 0 | 0 | pass |
| `html/export` | 42 | 42 | 0 | 0 | 0 | pass |
| `html/import` | 68 | 68 | 0 | 0 | 0 | pass |
| `html/parse` | 37 | 37 | 0 | 0 | 0 | pass |
| **Total** | 2272 | 2272 | 0 | 0 | 0 | |

$ cargo run -q -p lexical-conformance --release
| **Total** | 3643 | 3643 | 0 | 0 | 0 | |
```

`cargo fmt --all --check`, `cargo clippy --workspace --all-targets
--all-features --locked -- -D warnings`, `cargo test --workspace
--all-features --locked`, `cargo doc` with `-D warnings`, and
`cargo check -p lexical-editor --no-default-features --features <f>` for
each feature are clean.

Amp-Thread-ID: https://ampcode.com/threads/T-506c8fa1-4309-40f1-9810-732b311eaeab

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants