Skip to content

Add docs pending inline style at collapsed caret#316

Merged
hackerwins merged 7 commits into
mainfrom
docs-pending-inline-style
May 30, 2026
Merged

Add docs pending inline style at collapsed caret#316
hackerwins merged 7 commits into
mainfrom
docs-pending-inline-style

Conversation

@hackerwins

@hackerwins hackerwins commented May 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a transient pending inline style to the docs editor — toggling bold/italic/color/etc. at a collapsed caret now records the request and applies it to the next typed characters, matching ProseMirror "stored marks" / Google Docs behaviour.
  • Drops the pending state on any non-typing caret move (click, arrow keys, blur, undo/redo, copy/cut/paste, image insert, Tab cell nav, select-all, snapshot restore). Enter (block split) preserves it across the new block.
  • Wires both surfaces uniformly: the toolbar (editor.applyStyle) and the keyboard shortcuts (Cmd+B/I/U/X/./, and Cmd+\) both write through the new PendingStyle controller on collapsed selection.
  • View-local only — no changes to DocStore, the Yorkie schema, or the document model. Slides text-box editor (which also instantiates TextEditor) is opt-in and unchanged.

Design doc: `docs/design/docs/docs-pending-inline-style.md`
Plan + lessons: `docs/tasks/active/20260530-docs-pending-inline-style-{todo,lessons}.md`

Test plan

  • `pnpm verify:fast` exit 0 (54 docs test files / 855 tests + 1 skipped passing)
  • Controller unit tests — 10 tests in `pending-style.test.ts` (set/has/get/clear/consume + anchor mismatch + rewind clamp + rebind)
  • Doc-level integration scenarios — 6 tests in `pending-style-integration.test.ts` (typing pickup, caret-move discard, Enter rebind, IME composing cycle, layered toggles, anchor mismatch clear)
  • Editor-level wiring spec — 9 tests in `pending-style-editor.test.ts` covering both surfaces (toolbar `applyStyle` + keyboard `Cmd+B/I\`) end-to-end via the public `EditorAPI`, plus the cancellation triggers (`resetAfterDocumentReplace`, undo, redo, non-collapsed isolation)
  • Manual browser smoke in `pnpm dev`:
    • Empty paragraph, Cmd+B, type "Hello" → bold
    • Empty paragraph, Cmd+B, click elsewhere, type → plain
    • Empty paragraph, Cmd+B, Enter, type → new line is bold
    • Empty paragraph, Cmd+B, right-arrow, type → plain
    • Empty paragraph, Cmd+I, IME-type "안녕" → both syllables italic, including during composing
    • Empty paragraph, toolbar color picker, type → typed text picks up color
    • Cmd+B twice (toggle off) — verified by automated test, re-confirm visually

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@hackerwins, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 19 minutes and 39 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6d27d1e0-c052-490e-bf9e-05e75cc45191

📥 Commits

Reviewing files that changed from the base of the PR and between 49df83a and 35783d2.

📒 Files selected for processing (10)
  • docs/design/README.md
  • docs/design/docs/docs-pending-inline-style.md
  • docs/tasks/active/20260530-docs-pending-inline-style-lessons.md
  • docs/tasks/active/20260530-docs-pending-inline-style-todo.md
  • packages/docs/src/view/editor.ts
  • packages/docs/src/view/pending-style.ts
  • packages/docs/src/view/text-editor.ts
  • packages/docs/test/view/pending-style-editor.test.ts
  • packages/docs/test/view/pending-style-integration.test.ts
  • packages/docs/test/view/pending-style.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs-pending-inline-style

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Verification: verify:self

Result: ✅ PASS in 255.8s

Lane Status Duration
tokens:build ✅ pass 2.5s
sheets:build ✅ pass 14.0s
docs:build ✅ pass 12.8s
slides:build ✅ pass 14.5s
verify:fast ✅ pass 166.5s
frontend:build ✅ pass 19.2s
verify:frontend:chunks ✅ pass 0.3s
backend:build ✅ pass 5.0s
cli:build ✅ pass 2.1s
verify:entropy ✅ pass 18.9s

Verification: verify:integration

Result: ✅ PASS

@codecov

codecov Bot commented May 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 46.70659% with 89 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/docs/src/view/text-editor.ts 18.94% 77 Missing ⚠️
packages/docs/src/view/editor.ts 66.66% 12 Missing ⚠️

📢 Thoughts on this report? Let us know!

The docs editor currently ignores inline-style toolbar actions when
the selection is collapsed. Document the proposal to record a pending
style at the caret, apply it to the next inserted run, and drop it on
non-typing caret moves — matching ProseMirror stored marks and Google
Docs behaviour. The change is view-local; data model and Yorkie schema
are untouched.
The docs editor currently drops inline-style toolbar actions when no
text is selected. Introduce a small view-local controller that holds
a pending style anchored to a caret position. Subsequent edits in
the editor / text-editor will consume this state to apply the style
to typed characters and clear it on non-typing caret moves.
Wire the PendingStyle controller into the docs editor input pipeline.
applyStyle and clearInlineFormatting now record a pending style on a
collapsed caret, getSelectionStyle merges it so toolbar buttons reflect
the toggle, and the text editor consumes the style on each insertText
via small docInsertText / docDeleteText / docSplitBlock helpers that
wrap doc mutations with the pending hooks. IME composing and Hangul
cycles preserve the anchor via rewindAnchor; Enter splits via
rebindAnchor. Non-typing caret moves (mouse, arrow keys, Home/End,
clipboard ops, blur, undo, redo, inline image insert) clear the
pending state. Integration scenarios cover collapsed toggle, caret
move discard, Enter preservation, IME composing, layered toggles,
and anchor-mismatch clearing.
Record implementation notes and deviations from the written plan
(setPendingStyle setter instead of constructor option; centralized
helpers instead of per-call-site wiring; bundled Task 2+3 commit
because the unused field tripped the pre-commit typecheck) so the
next contributor in this area has the why, not just the what.
Wire pending.clear() at four caret-moving sites the first pass missed:
validateCursorPosition (cursor reset after remote block delete),
resetAfterDocumentReplace (snapshot restore from peer), image-body
mousedown (capture-phase handler runs before text-editor sees the
click), Tab cell navigation, and handleKeyDown's remote-block-deleted
fallback. Anchor-mismatch covered these functionally, but the design
doc lists each one as an explicit cancellation trigger and skipping
them left a brief window where the toolbar would show a stale toggle
after a remote edit or image click. Add an editor-level wiring spec
(`pending-style-editor.test.ts`) that exercises the public EditorAPI
so future refactors that drop a clear() call fail a test.
The toolbar path (editor.applyStyle) was wired for pending, but the
keyboard shortcut path goes through text-editor.toggleStyle /
clearFormatting which both early-returned on a collapsed selection.
That meant Cmd+B with no selection did nothing — and re-pressing
Cmd+B never toggled off because the first press was a no-op. Route
both methods through pending.set when collapsed, reading the visual
style (caret style + any existing pending) so re-toggles operate on
the displayed state rather than the stale doc-level style.

Add keyboard-path coverage to pending-style-editor.test.ts:
collapsed Cmd+B sets bold, Cmd+B twice toggles off, Cmd+B + Cmd+I
accumulates, and Cmd+\ clears.
Second-pass review surfaced that the design doc never mentioned the
keyboard-shortcut entry point (text-editor.toggleStyle /
clearFormatting), which is exactly why the original implementation
shipped without it wired and required a follow-up after browser
smoke. Capture the missed-surface lesson in the lessons file and
update the design doc's Architecture section to list both surfaces
explicitly. Add a defense-in-depth comment to toggleStyle explaining
that the unguarded visual merge depends on selection-creating paths
having cleared pending, and wire pending.clear() at the one such
path (selectAll) that was still missing it.
@hackerwins
hackerwins force-pushed the docs-pending-inline-style branch from 3d78e8f to 35783d2 Compare May 30, 2026 16:30
@hackerwins hackerwins changed the title Docs: pending inline style at collapsed caret Add docs pending inline style at collapsed caret May 30, 2026
@hackerwins
hackerwins merged commit aa9d283 into main May 30, 2026
4 checks passed
@hackerwins
hackerwins deleted the docs-pending-inline-style branch May 30, 2026 16:40
hackerwins added a commit that referenced this pull request May 31, 2026
PRs #257/#301/#303/#304/#305/#306/#307/#309/#315/#316/#317/#321/#322
shipped between v0.4.2 and the v0.4.3 cut, leaving their paired todo
files in active with the process checkboxes still open. Flip the
remaining boxes for the work that landed, then move the paired
todo/lessons into docs/tasks/archive/2026/05/ via pnpm tasks:archive.
Active count drops from 17 to 6; archive count grows by 21 files.

Patch release covering 29 commits since v0.4.2. Headline theme is
Slides editing & UX polish toward Google Slides / PowerPoint parity:
smart guides (equal-spacing / distance / size), Shift drag modifiers,
text inside shapes, a Format options right panel, tier-1 universal
toolbar controls, text autofit (shrink + grow), group-selection
visuals, and several smaller text-box / selection fixes. PPTX import
gained paragraph-level bullet styles, body anchor (vertical
alignment), and stretched blipFill cover-crop.

Docs added a pending-inline-style at collapsed caret, a caret that
tracks the resolved text color, bullet indent on Tab / Shift+Tab,
font / size / line-spacing / clear formatting toolbar controls, an
inline-style-attribute clear that actually lands in the CRDT, and a
polished toolbar trigger / color swatch pass shared across docs /
sheets / slides. Sheets gained .xlsx import.

Infrastructure: Docker images now build on native arm64 runners,
fixing the release hang seen on v0.4.2. No Prisma migration, no new
backend env vars — the devops bump is a routine image-tag change.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
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