Skip to content

feat(html): the document editor formats text - #897

Merged
andiwand merged 2 commits into
mainfrom
feat/format-editor
Sep 13, 2026
Merged

feat(html): the document editor formats text#897
andiwand merged 2 commits into
mainfrom
feat/format-editor

Conversation

@andiwand

@andiwand andiwand commented Sep 13, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Step 4 of the inline formatting plan (docs/design/document-editing.md, decisions 15 and 16). Rebased onto main after #896 merged.

Two ways in. odr.editing.format(style) is the host's button: it states any of bold, italic, underline, strikethrough (a bool), highlight (#rrggbb or null), color (#rrggbb) and size (14pt) on the selection, answers false where refused, and the refusal channel says why. formatBold, formatItalic, formatUnderline and formatStrikeThrough, which Chrome raises for ctrl/cmd+B, I and U, leave the refused list and toggle; a mixed selection turns on, as Word does. They are the shortcuts key class, so where a host keeps that class the editor cancels the browser's own mark and does nothing else.

The gate. Formatting sits behind HtmlConfig::editing_scope whole: under paragraph every chord and every format() refuses with outOfScope (1010).

The cut. A run the selection covers in part is cut first (setText plus insertText), and each covered run gets one setTextStyle, which is the shape #895 and #896 replay. A range over a picture marks the text on both sides; one over a text box refuses, as a replace does.

Toggle and the pending mark. odr.editing.toggle("bold") is the chord's rule for a host's button: a mixed selection turns on. A collapsed caret inside a word marks the word, as Word does. At a word boundary, or in a paragraph holding no run, the mark is pending: nothing changes until the next typed text, which is cut into a run of its own and marked, so what follows stays marked on its own. onSelectionChange reports the pending mark meanwhile, and a caret that moves away, a commit or a narrowed scope drops it.

The page stays a fresh render. The editor writes what translate_text_style writes into the run's style attribute. odr.onSelectionChange(style) reports the computed style the covered runs agree on, one key per property and none where they differ, and is quiet while nothing changes. Two marks on one run fold into one op unless an operation naming that run lies between them. Undo restores the style attribute, stating it before removing it, since Chrome serialises a declaration set through style into an empty attribute after a bare removeAttribute.

Verified. The text check page grows from 118 to 172 checks (headless Chrome, 0 failed): the cut and its ops, the chord toggling both ways and folding, the word rule, every property's css, the selection report, undo and redo, a picture, a text box, and both refusals under scope paragraph. The sheet pages (61, 14, 22, 8) and the plaintext page (45) still pass, since editing.js changed. No rendering changes, so no reference output moves.

@andiwand
andiwand force-pushed the feat/set-text-style-ooxml branch from 1454edb to dfafb19 Compare September 13, 2026 16:42
Base automatically changed from feat/set-text-style-ooxml to main September 13, 2026 16:50
`odr.editing.format(style)` states any of bold, italic, underline,
strikethrough, highlight, colour and size on the selection, and ctrl/cmd+B,
I and U toggle through the `formatBold` family of input types. A run the
selection covers in part is cut first, and each covered run gets one
`setTextStyle`. A collapsed caret inside a word marks the word. Formatting
sits behind the scope gate whole: `paragraph` refuses it with `outOfScope`.

The editor writes what `translate_text_style` writes, so an edited page
looks like a fresh render, and `odr.onSelectionChange` reports the computed
style the covered runs agree on. Two marks on one run fold into one op
unless an operation naming that run lies between them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137vd79NGaB8nfLsdPoghM4
`odr.editing.toggle(property)` is the chord's rule for a host's button: a
mixed selection turns on. On a collapsed caret at a word boundary, or in a
paragraph holding no run, the mark is pending: nothing changes until the
next typed text, which is cut into a run of its own and marked, so what
follows stays marked on its own. `onSelectionChange` reports the pending
mark meanwhile; a caret that moves away, a commit and a narrowed scope drop
it.

The text fold steps over a style op on the same run and the style fold over
a text op, since the two are independent, so typing after a pending mark
still folds into the insert that opened the run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137vd79NGaB8nfLsdPoghM4
@andiwand
andiwand merged commit 51b5fcd into main Sep 13, 2026
32 checks passed
@andiwand
andiwand deleted the feat/format-editor branch September 13, 2026 17:15
andiwand added a commit that referenced this pull request Sep 13, 2026
The two editor scripts under `resources/` follow #897 in both repositories;
no page moved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0137vd79NGaB8nfLsdPoghM4
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.

1 participant