feat: publish edited page models

Add PreparedEdit::page: diff an edited page::Page against the stored page
and lower the difference onto the typed writers (text replacement, character
formatting, paragraph insertion, split, join, move and deletion, outline
insertion, deletion, position, width and saved collapse state), then squash
their transactions into one revision per changed space while renaming the
writer-allocated identities to the ones the model carries. Content the
model cannot express (tables, images, lists, tags, fields, definitions,
unsupported objects) must be unchanged and is otherwise untouched. A split at
the end of a paragraph is distinguished from an appended paragraph by the
copied paragraph style; a join needs a nonempty right side.

Validation: a twelve-case oracle compares every active revision the typed
writers produce with the page writer's result for the same edit, ignoring
only writer-allocated styles, authors and reorder attribution; composed edits
publish one transaction; direct model edits round-trip and leave unrelated
objects byte-identical; unsupported edits fail before writing. Clippy and
fmt pass.

Assisted-by: claude-fable-5.1
3283203e9fclover caruso committed on 9/11/2026, 6:05:38 AMparentc5acf4f
7 files changedLine totals unavailable