Selection mapping

Convert between DOM ranges and engine selections.

The browser tracks selection as DOM Range objects anchored at text nodes by offset. The engine tracks selection as a Selection (text, node, or block). The selection mapping layer translates between them.

Modules

packages/dom/src/selection-mapping/:

  • dom-to-model.ts — walk DOM → engine Selection using data-spine-internal-* attributes.
  • model-to-dom.ts — walk engine Selection → DOM Range.
  • selection-mapper.ts — combined entry point used by the runtime.

DOM → model

  1. Locate the nearest ancestor carrying data-spine-internal-node-path.
  2. If inside a text leaf (data-spine-internal-text-leaf), accumulate the offset from data-spine-internal-leaf-start.
  3. Produce a TextSelection, NodeSelection, or BlockSelection as appropriate.

Model → DOM

  1. Resolve the rendered DOM node for the selection's path.
  2. Walk to the text leaf at the given offset.
  3. Construct a DOM Range for the overlay to measure.

Edge cases

  • Empty paragraphs with no text node to anchor on.
  • Media atoms and other boundaries without an inline text run — see frontier.
  • Zero-width inline elements.

Each edge case has a dedicated code path and round-trip test.