Back to Plate

Inline link harvest rows need link policy boundaries

docs/solutions/best-practices/2026-05-09-inline-link-harvest-rows-need-link-policy-boundaries.md

53.0.62.8 KB
Original Source

Inline link harvest rows need link policy boundaries

Problem

Lexical link tests are tempting to copy directly, but several rows are product or link-plugin policy rather than generic editor behavior. Porting all of them would make Slate core encode a link-specific paste rule that belongs in an app or plugin.

Symptoms

  • Link-boundary rows, partial-link copy rows, toolbar rows, autolink rows, and paste-inside-link rows appear in the same upstream file.
  • The raw Slate owner is split across inlines.test.ts, clipboard-contract.ts, and future link-plugin policy.
  • A direct copy would imply pasted text inside a link should always lose link affinity.

What Didn't Work

  • Treating every Lexical link row as raw editor behavior.
  • Treating paste-inside-link splitting as a generic inline-fragment law.
  • Closing the source file as covered because Slate already had inline typing, cut, and mention navigation rows.

Solution

Split the rows by ownership:

  • Browser-owned raw behavior: paste before or after an inline link must not expand the link.
  • Model-owned raw behavior: partial inline-link fragment copy/paste preserves link attributes.
  • Link-plugin policy: paste text, formatted HTML, another link, or multiple blocks inside an existing link may split the link only if the link plugin accepts that behavior.
  • Product policy: toolbar link conversion, image linking, and autolink URL paste do not belong in generic Slate proof.

The Slate coverage added:

  • .tmp/slate-v2/playwright/integration/examples/inlines.test.ts: browser proof for plain-text and rich-HTML paste at inline-link boundaries.
  • .tmp/slate-v2/packages/slate/test/clipboard-contract.ts: package proof for partial inline-link fragment copy/paste.

Why This Works

Slate core owns inline structure, fragment insertion, and browser boundary behavior. It does not own a universal "links should stop absorbing pasted content" rule because link is schema/plugin meaning, not a primitive text law.

This keeps generic coverage strong without hardcoding app-level link semantics.

Prevention

  • For harvested link tests, classify rows as boundary behavior, fragment behavior, link-plugin policy, or product shell before writing code.
  • Add browser proof when the claim is about the real paste transport or DOM boundary.
  • Add package proof when the claim is about fragment shape and model selection.
  • Do not make generic Slate transforms branch on type: 'link' unless a public link-plugin owner is explicitly accepted.