Contenteditable is still your document surface, and that is fine
Contenteditable is still your document surface, and that is fine
TLDR: the industry line is "never build on contenteditable, use ProseMirror or Lexical". That advice assumes you control the document model. When your document is arbitrary HTML produced by a parser, a structured editor forces a lossy re-parse, and a disciplined contenteditable is the honest choice. You give up undo, collaboration, and IME correctness, so the default advice stays right for greenfield docs.
The position
If your editing surface must render unknown, machine-produced HTML with spatial layout, tables, and inline formatting, and your export path reads the same HTML back as a semantic tree, then contenteditable plus a small set of hard rules is a better fit than adopting a structured editor framework.
What the industry does and why
The consensus is loud and correct for its use case. Contenteditable is underspecified, browser behavior diverges, undo is per-browser and unreliable, and collaborative editing is impossible. ProseMirror and Lexical solve this by refusing to treat the DOM as the source of truth. They maintain a transaction-based document model and render it to the DOM, so the editor can undo, collaborate, and validate every state change. That is the right architecture for a document editor.
Why it fails for this problem class
Every one of those benefits depends on owning the document model. This project's document is the extracted HTML: per-page regions, spatial wrappers, tables with row and column spans, callouts, image placeholders. Loading that into a structured editor means parsing it into the editor's schema. Anything outside the schema is dropped, flattened, or mangled, and the export pipeline reads the very markup the editor would have re-modeled. You would need to teach the editor schema to understand a parser's output better than the parser does.
The extraction tool does not need the editor to understand the document. It needs the editor to leave the document alone except where the user explicitly formats it. That is a much weaker contract, and contenteditable is the only browser primitive that offers it directly.
The better approach
Keep contenteditable, and make the discipline load-bearing:
- Route commands by type. Force
styleWithCSStrue only around color commands so colors become inline styles, and false everywhere else so bold and italic keep producing semantic tags a parser reads. - Name your surfaces and their authority. The document surfaces may sync back to the store; a per-page editable overlay may not.
- Verify serialized output, not pixels. Browser commands like
hiliteColorleave transparent-style noise behind; assert the DOM after formatting, not the screenshot.
What you give up
Real undo. The toolbar keeps its own snapshot stack, which is a fraction of a framework's transaction history. Collaboration. There is no operational transform layer, so two people editing one extracted document is out of scope. IME and caret edge cases, where frameworks have spent years ironing out the exact bugs contenteditable is known for. For an extraction tool whose primary users are single-editor automation runs, those are acceptable.
When the common pattern is right
When you control the document from the start, when users will collaborate, or when the document has a small closed schema, adopt the structured editor and never look back. The industry default is correct there. It is wrong only when the value of your product is preserving a document shape you did not design, which is exactly the case where the model breaks down first.