What happened?
Typing into a paragraph that contains an inline <w:br/>, a <w:tab/> or a <w:footnoteReference/> is noticeably slower per keystroke than typing into a plain paragraph of the same document — roughly twice the delay between the key press and the character appearing. The number of formatting runs does not matter (paragraphs with 20 and 60 runs but none of those elements behave like a single-run paragraph), and neither do w:jc="distribute", a run with large w:spacing, or a character style on the first word.
Because each keystroke is handled on its own — every key produces its own render, and keys that queue up while one is being rendered are not merged — the extra cost accumulates when typing fast. In a plain Chrome or Edge tab the editor still kept up with ~10 keys/s on the real document; inside our embedding (WebView2 in a Flutter desktop app, on a 2-core laptop) the same paragraphs fell behind and the last characters of a fast burst appeared seconds late, while plain paragraphs in the same document kept up. The host adds its own overhead, but the per-paragraph difference is the same in all three environments.
The real document is a rabbinic-style Hebrew text: every body paragraph opens with a short line, a <w:br/>, a wide-spaced space, then the body, and ends with a <w:tab/> — so every body paragraph is on the slow path, and the sub-headings (single run, no inline elements) are not. That is why it felt like "the two-column section is slow" until the paragraphs were compared one by one.
Expected: the per-keystroke cost of a paragraph should not depend on an inline line break, tab or footnote reference; or, failing that, queued keystrokes should be coalesced so the delay does not grow with typing speed.
Steps to reproduce
The documents are generated (synthetic text, nothing customer-specific) by a self-contained Node script: https://gist.github.com/Nathaniel-260/8e9be315500f89e6ae7b32eb7c89d4e4
node repro-typing-lag-docx.mjs bisect typing-bisect.docx
node repro-typing-lag-docx.mjs full typing-full.docx
- Open
typing-bisect.docx (one page, nine labelled paragraphs A–I; same text and length, eight runs each, one extra inline feature per paragraph).
- Click into A (plain) and type a quick burst of ~20 characters. Then do the same in C (trailing
<w:tab/>), D (<w:br/> after the first run) and G (footnote reference).
- C, D and G respond visibly slower per key than A; B (
jc=distribute), E (wide-spacing run) and F (character style) behave like A. H (all features) and I (all features, single run) are slow too — so it is the inline elements, not the run count.
typing-full.docx has the shape of the real document (heading in a one-column section, then a continuous two-column section with ~45 body paragraphs and footnotes). Typing fast in body paragraph B vs. the one-run sub-heading A makes the difference easy to feel, especially on a slower machine.
The DOM shows the same thing: with the developer tools open, each keystroke in a slow paragraph produces its own DOM update, one at a time, and the caret overlay updates well before the character itself appears.
SuperDoc version
2.12.0 (@superdoc/docx-engine 0.11.0), V2 layout.
Browser
Chrome 152 and Edge 152 (Windows 10), and WebView2 (Edg/152) inside a Flutter desktop host.
Additional context
Found while diagnosing typing latency in the Otzaria Word plugin (open source, SuperDoc-based). We can share our per-keystroke measurements and traces privately with the SuperDoc team on request; they are deliberately not posted here.
What happened?
Typing into a paragraph that contains an inline
<w:br/>, a<w:tab/>or a<w:footnoteReference/>is noticeably slower per keystroke than typing into a plain paragraph of the same document — roughly twice the delay between the key press and the character appearing. The number of formatting runs does not matter (paragraphs with 20 and 60 runs but none of those elements behave like a single-run paragraph), and neither dow:jc="distribute", a run with largew:spacing, or a character style on the first word.Because each keystroke is handled on its own — every key produces its own render, and keys that queue up while one is being rendered are not merged — the extra cost accumulates when typing fast. In a plain Chrome or Edge tab the editor still kept up with ~10 keys/s on the real document; inside our embedding (WebView2 in a Flutter desktop app, on a 2-core laptop) the same paragraphs fell behind and the last characters of a fast burst appeared seconds late, while plain paragraphs in the same document kept up. The host adds its own overhead, but the per-paragraph difference is the same in all three environments.
The real document is a rabbinic-style Hebrew text: every body paragraph opens with a short line, a
<w:br/>, a wide-spaced space, then the body, and ends with a<w:tab/>— so every body paragraph is on the slow path, and the sub-headings (single run, no inline elements) are not. That is why it felt like "the two-column section is slow" until the paragraphs were compared one by one.Expected: the per-keystroke cost of a paragraph should not depend on an inline line break, tab or footnote reference; or, failing that, queued keystrokes should be coalesced so the delay does not grow with typing speed.
Steps to reproduce
The documents are generated (synthetic text, nothing customer-specific) by a self-contained Node script: https://gist.github.com/Nathaniel-260/8e9be315500f89e6ae7b32eb7c89d4e4
typing-bisect.docx(one page, nine labelled paragraphs A–I; same text and length, eight runs each, one extra inline feature per paragraph).<w:tab/>), D (<w:br/>after the first run) and G (footnote reference).jc=distribute), E (wide-spacing run) and F (character style) behave like A. H (all features) and I (all features, single run) are slow too — so it is the inline elements, not the run count.typing-full.docxhas the shape of the real document (heading in a one-column section, then a continuous two-column section with ~45 body paragraphs and footnotes). Typing fast in body paragraph B vs. the one-run sub-heading A makes the difference easy to feel, especially on a slower machine.The DOM shows the same thing: with the developer tools open, each keystroke in a slow paragraph produces its own DOM update, one at a time, and the caret overlay updates well before the character itself appears.
SuperDoc version
2.12.0 (
@superdoc/docx-engine0.11.0), V2 layout.Browser
Chrome 152 and Edge 152 (Windows 10), and WebView2 (Edg/152) inside a Flutter desktop host.
Additional context
Found while diagnosing typing latency in the Otzaria Word plugin (open source, SuperDoc-based). We can share our per-keystroke measurements and traces privately with the SuperDoc team on request; they are deliberately not posted here.