Developer tools · HTML WYSIWYG editor
Why execCommand Is Deprecated and What Browser Editors Use Instead
· How it works
html contenteditable developer-workflow
Covers the rise and fall of document.execCommand, why its output was inconsistent, and how modern editors build on Selection, Range and beforeinput instead.
The one-line bold button that stopped being safe — opens with execCommand('bold') and the deprecation warning
A bold button can be one call: focus the editing surface, then ask `document.execCommand` to apply `bold` to the current selection. ToolAcre still uses that path because the browser owns the caret and selected range inside its contenteditable element. The compact call is convenient, but convenience does not make its resulting tree predictable.
The code treats refusal as an ordinary possibility. Its command wrapper catches an exception, announces that the browser declined the action, and directs the writer to source mode. That fallback is more honest than promising that one toolbar click always produces one particular element or works identically in every engine.
What execCommand did and where it came from — explains its origin in early Internet Explorer and its adoption by every browser
The same wrapper drives bold, italic, unordered and ordered lists, formatting removal, undo, redo, block formatting, links and unlinking. Those are the commands actually present in the toolbar; this article does not extend the list with alignment, colors, fonts, tables, images or other familiar rich-text features that the implementation never exposes.
Every command runs against the live editable DOM. Afterward, the panel refreshes its source, preview, word count and removal report from the current innerHTML. The saved result is therefore not a command log. It is a filtered serialization of whatever structure the browser left behind after performing or refusing the requested operation.
Why the command API is deprecated: browsers can produce different DOM shapes
Deprecation matters because the API does not give an editor author a precise structural contract for each mutation. The ToolAcre limitations explicitly warn that behavior differs between engines, particularly around nested lists. A visible list may be acceptable while its nesting or wrapper choices differ from the markup another browser produced.
No repository source supports a claim that every browser, version or command has a particular compatibility result. The safe statement is narrower: this implementation calls the deprecated API, catches refusal, and offers direct source editing as an escape hatch. Test the browser and operation you intend to use rather than extrapolating a matrix.
Selection and Range are relevant alternatives, but this tool does not implement them
Selection and Range can describe selected DOM boundaries and support explicit tree manipulation, but ToolAcre does not implement a replacement formatting engine with them. Naming those APIs as if they were the current code path would misdescribe the product. Here, the browser command remains the mutator and the sanitizer remains the output boundary.
A custom model could own marks, blocks, transactions and selection mapping, but that is a different product architecture with different tests. This lightweight editor deliberately avoids claiming such machinery. Its reviewable contract is that visual actions may create browser-dependent DOM, while source mode reveals the filtered markup that will actually be copied or downloaded.
beforeinput is not part of this editor’s formatting path
The implementation also does not intercept `beforeinput` to translate editing intentions into custom transactions. Input events merely trigger a refresh after the browser has changed the surface. Paste and drop are exceptions: those events are prevented, their clipboard or transfer payload is filtered, and only the resulting HTML or plain text is inserted.
That distinction prevents a broad architectural claim. ToolAcre owns the paste gate but not every keystroke mutation. Ordinary typing, deletion, Enter behavior and toolbar commands remain browser editing operations. The sanitizer reviews their serialized output; it does not turn the editor into a beforeinput-driven framework or normalize every intermediate DOM mutation.
Worked example: inspect the legacy command output this editor actually produces
For a concrete check, type two short sentences, select one phrase and press Bold. Switch to HTML source and inspect the element around that phrase. ToolAcre maps legacy `b` to `strong` during sanitization, so the filtered result can be semantic even when the live editing command initially chose a legacy tag.
Repeat with a list and then undo. The toolbar sends `insertUnorderedList` and `undo`; it does not maintain a separate application history. If the browser refuses, the status region says so. If the nesting looks odd, source mode is the supported correction path. The observed output, not the button label, is the evidence.
What this does not cover: no replacement editor architecture is implemented here
This article does not claim support for a modern replacement command system, collaborative transactions, deterministic cross-browser trees or a custom undo stack. It also does not infer behavior for keyboard shortcuts because the source defines toolbar actions, not a shortcut registry. Unsupported features remain omissions rather than implied capabilities.
Security is separate from command choice. The allowlist filters emitted markup and the preview is sandboxed without scripts, but the sanitizer explicitly disclaims use as a general hostile-input XSS filter. A server accepting untrusted publication content still needs an appropriate server-side HTML5-parser sanitizer and destination-specific policy.
Takeaway: own the DOM, not the command — summarises the migration path and how the resulting markup is what you inspect in a WYSIWYG-to-HTML tool
Own the result you can inspect. In this editor, a command asks the browser to mutate a contenteditable tree, then the allowlist rewrites that tree’s serialization into the supported subset. Source mode exposes the handoff and provides a practical repair surface when browser editing behavior is inconvenient or inconsistent.
Use a disposable sample in the same browser as your real work. Exercise only the shipped commands, inspect links and nesting, test undo before relying on it, and copy the filtered HTML only after reading it. That workflow respects deprecation without pretending ToolAcre has already replaced the underlying editing API.