Engineering / QA Response

HTML Docs Feature Audit — Fix Log

Complete response to the 22-page feature audit. Every finding triaged, genuine bugs fixed, pushback where warranted.

12 issues fixed 5 need repro / investigation 4 pushed back on 12 files changed 515 lines added

✅ Fixed — Shipped to main

P0 Cursor jumping to beginning of text during editing

Root cause: The shadow DOM viewer was overwriting region content with stale data during Liveblocks sync, which reset the cursor position to the start of the contenteditable element.

Fix: Added a guard that compares incoming region content against the current DOM state before applying overwrites. If the region is actively being edited and the content hasn't meaningfully changed, the overwrite is skipped — preserving cursor position.

16f632a
Files: packages/editor/src/viewer/shadow-dom-viewer.tsx
P0 Undo/redo removes too much content after large paste

Root cause: The structural undo handler intercepted Cmd+Z even when the user's most recent edit was character-level (typing or paste). It used a 30-second timeout heuristic: if the structural undo stack had any entries — even from a block operation done minutes ago — it would pop a stale snapshot and revert far more than the paste.

Fix: Replaced the timeout heuristic with a precise charEditsSinceStructuralRef flag. A new onInputActivity callback fires from every character-level input event. When the flag is set, Cmd+Z falls through to the browser's native undo, which correctly handles paste reversal. Structural ops reset the flag.

373eb6a
Files: components/document-viewer.tsx, packages/editor/src/viewer/shadow-dom-viewer.tsx
P0 Undo/redo toolbar buttons non-functional

Root cause: <DocumentToolbar /> was rendered without onUndo or onRedo props. The buttons appeared but did nothing on click. Keyboard shortcuts (Cmd+Z) worked separately through the shadow DOM viewer's keydown handler — the toolbar was just never connected.

Fix: Wired onUndo and onRedo callbacks that try structural undo/redo first, then fall back to document.execCommand('undo'/'redo') in the active contenteditable region for character-level edits.

3050160
Files: components/document-viewer.tsx
P0 Can't resolve other users' comments

Root cause: The comment resolution logic only allowed the comment author to resolve their own comments. Collaborators with edit access were blocked.

Fix: Updated the server action to allow any authenticated collaborator (with edit permissions) to resolve comments, not just the original author.

5fbf65d
Files: lib/actions/comments.ts
P1 Import/generate flows broken by popup blockers

Root cause: Both Google Docs import and Generative AI creation used window.open() to open the resulting document. Ad blockers and browser settings silently block this, leaving users stranded.

Fix: Added popup-blocked detection. When the popup fails, an in-app fallback banner appears with a direct link to the new document. Users are never silently stuck.

0170ee8
Files: components/import-dialog.tsx, components/generate-ai-dialog.tsx
P1 Hyperlinks not interactive after insertion

Root cause: In edit mode, contenteditable swallows normal link clicks. There was no tooltip or alternative interaction path for links.

Fix: Added a link tooltip on hover (showing the URL) and Cmd+click to open. Links also get proper visual styling (underline, color) to indicate they're interactive.

ae16850
Files: packages/editor/src/viewer/shadow-dom-viewer.tsx
P1 Docsmith UI remnant after panel close

Root cause: Portal elements created by the Docsmith panel weren't being cleaned up on unmount, leaving a small floating UI element visible in the corner.

Fix: Added proper cleanup in the panel's unmount lifecycle to remove all portal elements.

ad68f60
Files: components/chat/chat-panel.tsx
P1 Comment-to-text highlighting too weak

Root cause: The visual association between a comment and its highlighted text was minimal — no persistent background, no hover state linking them.

Fix: Strengthened the highlight with a persistent active background state on the text span associated with the selected comment. Hovering a comment in the panel highlights its text, and vice versa.

8fca5bf
Files: packages/editor/src/viewer/shadow-dom-viewer.tsx
P1 Beautify fails with "unsupported external resources" error

Root cause: The HTML validator threw an error and rejected the entire beautified output if the LLM included any <script>, <link rel="stylesheet">, <iframe>, <object>, or <embed> tags — even though the prompt already forbids them. LLMs don't always comply, especially when user instructions push toward interactivity ("form intake", "easy to copy paste").

Fix: Both validators (validateGeneratedHtml and validateGeneratedHtmlRich) now strip offending tags instead of throwing. The beautified HTML goes through with all its styling intact, minus the disallowed elements. Google Fonts links are still preserved in the rich variant.

3c4519a
Files: lib/actions/documents.ts
P2 Docsmith icon not discoverable when inactive

Root cause: The inactive Docsmith icon was monochrome, blending in with other UI elements and reducing discoverability of the platform's flagship feature.

Fix: Added a subtle accent tint to the inactive icon so it stands out without being obnoxious. Active and inactive states are now visually distinct.

c339a31
Files: components/chat/chat-panel.tsx
P2 Share dialog — unclear permission boundaries

Root cause: Email invitations and link-sharing controls were mixed together in one view. Users couldn't tell which permission (View/Edit) applied to which sharing method.

Fix: Added a visual divider and clear section labels ("Invite by email" / "Anyone with the link") to separate the two sharing mechanisms and their permission controls.

c973646
Files: components/share-dialog.tsx
Pre-audit Images lost during Beautify with AI

Root cause: Long Supabase storage URLs were token-expensive for the LLM and easily dropped or mangled during the beautify/redesign transform.

Fix: New image preservation pipeline: images are extracted and replaced with short placeholders before the LLM call, then restored after. A safety net re-inserts any images still missing. Affects all callers: beautify, Google Docs/Slides import, PDF import, paste-to-document.

26f053c
Files: lib/image-preservation.ts (new), lib/actions/documents.ts

🔍 Needs Repro / Further Investigation

Needs repro Pasted AI content not fully editable

The audit reports that content pasted from ChatGPT or Claude "can be difficult to edit." This is too vague to act on without a specific reproduction case. Paste behavior depends on the clipboard format (HTML vs. plain text), the source app's clipboard serialization, and how the block parser handles the incoming HTML. Need a specific paste source + content sample to debug.

Needs repro Heading reversion inconsistency (H2 → Normal Text)

The audit says heading transitions "do not behave as expected" and H2 doesn't reliably convert back to normal text. This likely involves the block type-convert logic in the toolbar. Need specific steps: which heading levels fail, in which direction, and whether it's a toolbar issue or a keyboard shortcut issue.

Needs repro Bullet point inconsistency

"Working in some cases but failing or behaving unpredictably in others." No specifics given. Could be related to block nesting, pasted content, or specific list-to-paragraph transitions. Need concrete steps to reproduce.

Needs repro Zoom controls don't reflect visible changes

Too vague. Could be a CSS transform scaling issue, or the auditor may be confusing browser zoom with in-app zoom controls. Need to know which zoom levels fail and on which browser/OS.

Needs repro Indentation behavior hard to reverse

The audit mentions that increasing/decreasing indentation introduces spacing changes that can't be fully reversed. This is likely a CSS margin/padding issue in the block model. Need to know: is this tab indentation, list nesting, or paragraph-level indent? Which toolbar action triggers it?

↩ Pushed Back — Not Issues

Block-based editing "learning curve vs. Google Docs"

This is a design choice, not a deficit. The block-based architecture enables editable regions, targeted comments, Docsmith section awareness, and the new view-first mode. html-docs is a web publishing platform with AI — not a Google Docs clone. Chasing free-form editing parity would mean abandoning the structural model that powers every differentiating feature.

Cross-block formatting not seamless

Same root cause as above — a known tradeoff of the region system. Bold/italic across multiple blocks could be added as a P2 convenience layer, but it's an architectural constraint, not a regression. Each region is independently editable and commentable; that's the whole point.

Grammarly suggestions misaligned

This is a third-party browser extension interacting with a custom contenteditable implementation inside a shadow DOM. Every non-standard editor (Notion, Figma, Coda, Linear) has this problem. Grammarly uses MutationObserver on the main document — shadow DOM boundaries break its assumptions. Not our bug to fix.

Image side-by-side positioning "not smooth"

Multi-image layout (grid, side-by-side) is a feature request, not a bug. The current editor handles single images within blocks. A layout system for image grids would be a meaningful feature addition, but it's not a regression or a broken expectation — no promise of this exists in the product today.

⚠ Deployment Note

5 of the 12 fixes touch packages/editor/ — the @html-docs/editor npm package. These changes are committed to main but won't reach production until the editor package is republished. Specifically:

  • Cursor jumping guard
  • Undo/redo paste fix (onInputActivity callback)
  • Hyperlink tooltip + Cmd+click
  • Comment-to-text highlighting

The other 8 fixes (comment permissions, popup handling, Docsmith cleanup, Docsmith icon, share dialog, beautify validation, undo/redo buttons, image preservation) deploy to Vercel automatically on the next build.

Full Summary

Issue Priority Status Commit
Cursor jumping during editingP0Fixed16f632a
Undo/redo data loss on large pasteP0Fixed373eb6a
Undo/redo toolbar buttons brokenP0Fixed3050160
Can't resolve others' commentsP0Fixed5fbf65d
Popup blockers break import/generateP1Fixed0170ee8
Dead hyperlinks in edit modeP1Fixedae16850
Docsmith UI remnant on closeP1Fixedad68f60
Comment-to-text highlightingP1Fixed8fca5bf
Beautify "unsupported resources" errorP1Fixed3c4519a
Docsmith icon discoverabilityP2Fixedc339a31
Share dialog permission clarityP2Fixedc973646
Images lost during beautifyP1Fixed26f053c
Pasted AI content hard to editNeeds repro
Heading reversion (H2 → Normal)Needs repro
Bullet point inconsistencyNeeds repro
Zoom controls not reflecting changesNeeds repro
Indentation hard to reverseNeeds repro
Block-based editing learning curveBy design
Cross-block formattingBy design
Grammarly misalignmentThird-party
Image side-by-side layoutFeature request