DocumentEditor
DocumentEditor is the paginated rich-text surface for DOCX-compatible
documents, reports, and long-form content. TipTap owns the logical document and
selection model; the A3S Office kernel owns deterministic pagination, shaping,
and file semantics.
Large-document DOM measurement is cooperative. The editor measures canonical top-level blocks in bounded 32 ms slices, yields between blocks, and aborts a stale pass when the controlled document changes. Only a complete pass updates the reusable pagination snapshot; Worker/WASM layout remains authoritative.
Large-document performance
A3S Office keeps the canonical TipTap document and model positions intact while
windowing the live ProseMirror tree, physical page sheets, and pagination
widgets for eligible structurally plain DOCX imports. It does not replace the
document with a presentation-only virtual list. Search, selection, editing,
undo, export, and Ctrl+Home / Ctrl+End therefore continue to address the
complete model even when most document DOM is not mounted.
The reference measurements below were captured on 2026-08-19 on an Apple M2 Pro with 16 GB of memory, Playwright 1.61.1, headless Chrome 149, and a 1,440 × 1,000 viewport. Cold-open and scroll values are the median and complete range of three fresh browser processes. Controlled-edit values use five fresh processes. These figures describe the measured reference environment; they are not a cross-device service-level guarantee.
Cold open and pagination
Editor visible is the first frame containing editable document content.
Pagination ready means the complete physical-page map is available; it does
not mean every page sheet has been mounted. A Long Task is a browser main-thread
task of at least 50 ms.
Scroll, retained state, and mounted work
The scroll profile advances through the complete scroll range over 120
requestAnimationFrame samples. FPS reflects the 120 Hz reference display, so
p95 frame interval and Long Tasks are the more portable responsiveness
indicators. Retained state is collected after an explicit diagnostic V8 garbage
collection and includes the complete canonical model, not only mounted DOM.
At readiness, the text fixture mounted 1 of 782 content chunks and 4 of 3,125 page sheets. End navigation mounted 2 content chunks. The table fixture mounted 4 of 6,250 row leaves and 4 of 2,381 page sheets at readiness; end navigation left 1 row leaf mounted. The complete table model remained available through 196 outer geometry containers.
Controlled tail edits
Wall starts at the browser beforeinput event and ends when the host-facing
controlled publication count changes. Publish CPU covers construction of the
complete html and model values. All 20 measured publications used the
indexed lazy-chunk path, retained both edit markers at the exact final
paragraph or row, and produced no browser, page, or console error.
Reproduce the measurements
Build and start the production Playground in one terminal:
Run the benchmarks and deterministic a3s-test windowing gate in another:
Each benchmark writes its raw JSON report under
.a3s-test/performance/results/; fixtures and results are intentionally ignored
by Git. See the
complete methodology and current boundaries
for Worker phases, measurement definitions, spreadsheet comparison, and the
rich-DOCX fallback. Documents with unsupported tags, relationships, tracked
structures, drawings, or other rich features deliberately use the complete
compatibility importer and are not covered by these 100,000-unit figures.
Properties
Content contract
IME and controlled updates
Chinese, Japanese, Korean, and other composition-based input remains owned by
the browser while composition is active. DocumentEditor does not publish
phonetic pre-edit text through onChange; after ProseMirror has settled the
compositionend DOM update, it publishes the complete committed document once.
If the host supplies a different controlled content value during composition,
the editor defers that replacement until the composition has settled. The
committed local value is reported first, then the still-authoritative host value
is reconciled. Hosts do not need an IME-specific debounce or event filter.
Native text-case effects
The Home ribbon's Text case effects menu applies Normal, All caps, or Small
caps as one mutually exclusive character-format state. Cmd/Ctrl+Shift+A
toggles All caps and Cmd/Ctrl+Shift+K toggles Small caps. The same TipTap
commands, metadata, and Undo path are used by body text, headers, footers,
Format Painter, and character-formatting revisions.
The editor keeps the semantic source text unchanged. CSS renders All caps with
text-transform: uppercase and Small caps with font-variant-caps: small-caps.
DOCX import, export, and reopen preserve native w:caps and w:smallCaps
properties, including explicit resets and prior values inside w:rPrChange.
A paragraph containing either effect intentionally uses browser line measurement. Uppercase conversion can change the rendered glyph count relative to the source UTF-16 offsets, and small caps changes font metrics. Keeping the browser authoritative for those paragraphs avoids inaccurate pagination; other eligible paragraphs continue through Worker/WASM shaping.
Native script-specific fonts
Writer retains the four independent WordprocessingML w:rFonts slots:
ascii, hAnsi, eastAsia, and cs. Each slot keeps its exact direct family,
optional theme reference, and separately resolved browser family; w:hint
remains native metadata. Style inheritance resolves the effective set without
rewriting untouched direct or theme identity. A mixed-script run is divided
into bounded TextStyle spans for Latin ASCII, high ANSI, East Asian, and
complex-script text, while neutral punctuation stays with the surrounding
script.
Cmd/Ctrl+D or the Home ribbon opens Advanced Font Settings with separate
Latin, East Asian, and complex-text controls. The Latin control intentionally
updates both ascii and hAnsi; the Home font picker intentionally expresses
an all-text choice and updates all four slots. Each control has independent
mixed-selection state and Follow style. A script-aware preview uses the
selected family for each text segment. Applying any combination of fonts,
scale, spacing, kerning, emphasis, hidden text, character border, outline,
shadow, emboss, imprint, or position restores the captured selection and creates one
transaction and one Undo record.
Body text, headers, footers, footnotes, endnotes, Format Painter, formatting
revisions, strict/transitional DOCX import, exact export, and reopen share the
same typed representation. Unchanged theme references survive an edit to a
different slot. Duplicate or misplaced elements, extra or spoofed attributes,
child-bearing or text-bearing leaves, unknown values, and font names longer
than 127 characters fail closed and appear in compatibility diagnostics. The
DOM stores validated JSON in data-office-script-fonts and the active segment
in data-office-script-font-slot; CSS uses only the resolved family, so browser
font substitution does not mutate native file identity.
Native OpenType typography
Writer uses one closed Office 2010 OpenType model for ordinary text and
structured equations. It retains all 16 native w14:ligatures combinations,
w14:numForm values default, lining, or oldStyle, w14:numSpacing
values default, proportional, or tabular, canonical
w14:stylisticSets IDs 1 through 20, and explicit w14:cntxtAlts enable or
reset values. Each property inherits
independently and malformed, duplicated, misplaced, child-bearing,
text-bearing, out-of-range, or namespace-spoofed values fail closed.
Cmd/Ctrl+D or the Home ribbon opens Advanced Font Settings with separate
controls for ligatures, number form, number spacing, stylistic sets, and
contextual alternates. Every control reports its own mixed-selection state and
Follow style value. Apply changes only touched properties on each selected run,
preserves the other direct OpenType settings, restores the captured selection,
and combines OpenType, script fonts, and the other advanced character settings
into one transaction and one Undo record. The live preview uses the same
canonical CSS projection as the document.
Body text, headers, footers, footnotes, endnotes, comments, Format Painter,
formatting revisions, and reject restoration share the same representation.
DOCX export emits ordered w14 properties, declares the required namespace
and mc:Ignorable token, and retains current and prior values through reopen.
Compatibility diagnostics identify unsupported or invalid source values. The
DOM stores canonical JSON in data-office-opentype-features; CSS projects
font-feature-settings, font-variant-ligatures, and
font-variant-numeric. Paragraphs with active shaping use
browser-authoritative line measurement so glyph substitution cannot desync
source UTF-16 offsets from pagination.
Native character spacing
Writer keeps character spacing as one signed native w:spacing value from
-31,680 through 31,680 twips, where 20 twips equal one point. Cmd/Ctrl+D or
the Home ribbon opens Advanced Font Settings with Normal, Expanded, and
Condensed modes plus an exact 0.05–1,584 point magnitude. A mixed selection is
left unchanged until a mode is chosen. Apply restores the captured selection
and creates one Undo record; Cancel and Escape leave the document unchanged and
return focus to the editor.
Body text and header/footer editors use the same TipTap command and preserve an
explicit zero separately from inherited spacing. Format Painter, tracked
character-format changes, Undo, DOCX import/export/reopen, and old formatting
inside w:rPrChange retain the exact signed value. The DOM stores
data-office-character-spacing-twips; CSS projects it as letter-spacing
without rewriting text. Eligible paragraphs remain on the Worker/WASM layout
path because the kernel applies the same linear advance adjustment.
Native horizontal character scale
Writer stores horizontal character scale as one native w:w integer from 1%
through 600%. A missing property still inherits, an explicit 100% remains a
direct reset, and an empty <w:w/> uses the native 100% default. Strict and
transitional WordprocessingML use the same bounded integer model; malformed,
fractional, duplicated, child-bearing, out-of-range, or namespace-spoofed
properties fail closed.
Cmd/Ctrl+D or the Home ribbon opens Advanced Font Settings, where the
Scale field accepts the exact integer range. Scale, spacing, and baseline
position track mixed selections independently. Editing any combination and
choosing Apply restores the captured selection and creates one transaction and
one Undo record. Character scale has no separate standard shortcut, so Writer
does not claim one.
Body text, headers, footers, Format Painter, tracked formatting, reject
restoration, DOCX import/export/reopen, and old formatting inside w:rPrChange
all retain the exact value. The DOM stores
data-office-character-scale-percent and projects it through CSS
font-stretch. Non-100% runs deliberately use browser line measurement until
the Worker/WASM text-layout protocol carries exact horizontal run scaling;
other eligible paragraphs remain on the deterministic kernel path.
Native pair kerning
Writer stores pair kerning as one native w:kern threshold from 0 through
3,277 half-points. A positive value enables kerning when the effective w:sz
font size is greater than or equal to that threshold; 24 therefore means 12
points. An explicit zero enables kerning at every font size. A missing direct
property continues through the style hierarchy, while a document with no
w:kern anywhere keeps kerning disabled.
The shared Cmd/Ctrl+D Advanced Font Settings dialog provides a Kerning
checkbox and an exact 0–1,638.5 point field in 0.5-point increments. New direct
formatting starts at 12 points. Scale, spacing, kerning, emphasis mark, and
baseline position track mixed selections independently and commit together through one
transaction. Clearing the checkbox removes only direct kerning; Apply restores
the captured selection and creates one Undo record. Pair kerning has no
separate standard shortcut, so Writer does not claim one.
Body text, headers, footers, footnotes, endnotes, inherited styles, Format
Painter, tracked formatting, reject restoration, DOCX import/export/reopen,
and prior formatting inside w:rPrChange retain exact half-points. Strict and
transitional documents reject missing values, duplicate or nested elements,
text-bearing properties, extra attributes, fractions, negative or out-of-range
values, and namespace spoofing. Compatibility diagnostics report valid and
rejected properties separately.
The DOM stores data-office-kerning-threshold-half-points and projects the
effective state as CSS font-kerning: normal or none. Editing, preview, and
PDF surfaces start with kerning disabled and share that projection. The same
effective boolean reaches the Worker/WASM text-layout path, so pagination and
paint do not disagree about pair advances.
Native East Asian emphasis marks
Writer stores emphasis as one closed native w:em state: none, dot,
comma, circle, or underDot. A missing direct property continues through
the run, character-style, paragraph-style, and document-default hierarchy.
Explicit none is different from removing direct formatting: it intentionally
suppresses an inherited mark.
The shared Cmd/Ctrl+D Advanced Font Settings dialog offers Follow style,
None, Dot above, Comma above, Circle above, and Dot below. Emphasis, scale,
spacing, kerning, and baseline position keep independent mixed-selection state.
Choosing Follow style removes only the direct property; choosing None writes the
native reset. Apply restores the captured selection and focus and commits every
touched character property through one transaction and one Undo record. There
is no separate standard Writer shortcut, so the command catalog does not claim
one.
Body text, headers, footers, footnotes, endnotes, inherited styles, Format
Painter, tracked character formatting, reject restoration, strict or
transitional DOCX import/export/reopen, and prior formatting inside
w:rPrChange retain the exact value. Missing values, unknown tokens, duplicate
or nested elements, text-bearing leaves, extra attributes, and namespace
spoofing fail closed and appear in compatibility diagnostics.
The DOM stores data-office-emphasis-mark. CSS text-emphasis-style and
text-emphasis-position project a filled dot, literal comma, or open circle
above the text, or a filled dot below it. Paragraphs with a visible mark use
browser-authoritative line measurement so glyphs outside the normal line box
are included. An explicit none stays on the Worker/WASM path only when the final
computed standard and WebKit emphasis styles are both absent or none, so a
host CSS override cannot create a pagination disagreement.
Native hidden text
Writer stores hidden text as one three-state TextStyle property. Removing the
direct property continues through run, character-style, paragraph-style, and
document-default inheritance. true writes native w:vanish; false writes
an explicit w:vanish w:val="0" reset so inherited hidden formatting stays
visible after export and reopen.
The shared Cmd/Ctrl+D Advanced Font Settings dialog keeps hidden text
independent from scale, spacing, kerning, emphasis, and baseline position. A
mixed selection remains untouched until the Hidden text checkbox is changed.
Apply restores the captured selection and commits every touched property in one
transaction and one Undo record. The standard Cmd/Ctrl+Shift+H shortcut
toggles the same typed command; TipTap's conflicting Highlight binding is
disabled.
Body text, headers, footers, footnotes, endnotes, inherited styles, Format
Painter, tracked formatting, reject restoration, strict/transitional DOCX
import/export/reopen, and prior formatting inside w:rPrChange retain the exact
state. Empty properties or exact lowercase 1, 0, on, off, true, and
false values are accepted. Unknown casing or tokens, duplicates, children,
text, extra attributes, misplaced elements, and namespace spoofing fail closed
and appear in compatibility diagnostics. Unchanged comment XML remains
source-preserved; this boundary is not a claim of rich comment-text editing.
The DOM stores data-office-hidden-text="true|false". Hidden text is suppressed
by default. The View ribbon's Show hidden text command reveals it only on an
editable Writer surface and adds the conventional dotted underline. Read-only
preview and detached PDF capture always keep it suppressed. Paragraphs that
contain hidden text use browser-authoritative line measurement so invisible
glyphs cannot enter the Worker/WASM advance model.
Native outline, shadow, emboss, and imprint
Writer stores four independent nullable TextStyle properties for native
w:outline, w:shadow, w:emboss, and w:imprint. Removing a direct
property continues through run, character-style, paragraph-style, and
document-default inheritance. true writes the native enabled property and
false writes an explicit w:val="0" reset, so inherited effects remain off
after export and reopen.
Outline and shadow may be enabled together. Emboss is mutually exclusive with
outline, shadow, and imprint; imprint is mutually exclusive with outline,
shadow, and emboss. The shared Cmd/Ctrl+D Advanced Font Settings dialog
keeps all four mixed-selection states independent. Enabling an exclusive
effect clears every conflicting checkbox and marks those clears as touched, so
Apply commits the complete conflict-safe result through one transaction and
one Undo record. There is no dedicated standard Writer shortcut for these four
effects, so the command catalog does not invent one.
Body text, headers, footers, footnotes, endnotes, document defaults, inherited
styles, Format Painter, tracked character formatting, reject restoration,
strict or transitional DOCX import/export/reopen, and prior formatting inside
w:rPrChange retain the exact values. Empty properties and exact lowercase
1, 0, on, off, true, and false values are accepted. Unknown casing
or tokens, duplicates, nested or text-bearing leaves, extra attributes,
misplaced elements, namespace spoofing, and conflicting enabled sets fail
closed and appear in compatibility diagnostics.
The DOM stores data-office-legacy-text-outline,
data-office-legacy-text-shadow, data-office-legacy-text-emboss, and
data-office-legacy-text-imprint as explicit true|false values. CSS projects
outline with a bounded stroke, shadow with a bounded offset, and emboss or
imprint with opposite light/dark offsets. Browser and PDF output therefore
provide a controlled visual approximation rather than claiming desktop-engine
pixel identity. These effects change paint only, so otherwise eligible
paragraphs remain on the Worker/WASM layout path. Open the Playground's
文字效果 template to inspect all four states and switch the valid
outline-shadow pair to an exclusive effect.
Native character borders
Writer stores character borders as one typed native w:bdr value. The model
retains all 25 visible WordprocessingML line styles plus the explicit nil and
none resets, direct or theme colors with tint and shade, widths from 2
through 96 eighth-points, text spacing from 0 through 31 points, and explicit
shadow and frame flags. Imported nil and none remain distinct even though
both suppress paint.
The Home Font group provides a direct Character Border toggle. The shared
Cmd/Ctrl+D Advanced Font Settings dialog keeps mixed selections untouched
until edited and distinguishes Follow style, explicit no-border, and an
editable border. Line style, color, exact 0.25–12 point width in 0.125-point
increments, integer spacing, shadow, and frame commit with every other touched
character property through one transaction and one Undo record. Format Painter
uses the same mark. There is no dedicated standard Writer shortcut, so the
command catalog does not claim one.
Document defaults, paragraph and character styles, body text, headers,
footers, footnotes, endnotes, formatting revisions, strict or transitional
DOCX import, exact export, and reopen preserve the semantic value. Malformed,
duplicated, misplaced, namespace-spoofed, child- or text-bearing,
extra-attribute, art-style, out-of-range, and unresolved-theme input fails
closed and appears in compatibility diagnostics. Prior formatting inside
w:rPrChange uses the same bounded parser and exporter.
The DOM stores validated JSON in data-office-run-border and projects all
four edges, spacing, shadow, and fragment cloning through CSS. Visible borders
use browser-authoritative line measurement because border and padding change
inline geometry. Explicit nil and none remain eligible for Worker/WASM
layout. Browser and PDF paint are bounded visual approximations of line styles;
the OOXML semantics remain exact. Open the Playground's 字符边框 template
to exercise the complete authoring and one-step Undo flow.
Native character shading
Writer stores character shading as one typed native w:shd value instead of
flattening it into a browser background color. The model retains every
WordprocessingML pattern, direct or automatic foreground and background
colors, independent themeColor and themeFill references with tint and
shade, and an explicit nil reset. A tint and shade can coexist on the same
theme channel: browser paint follows native tint precedence while export keeps
both attributes.
The shared Cmd/Ctrl+D Advanced Font Settings dialog treats shading as an
independently mixed property. It distinguishes Follow style, explicit no
shading, and an editable value with pattern, foreground, and background
controls. Theme identity survives while its resolved color remains unchanged;
choosing a direct color intentionally replaces only that channel. The complete
patch commits with the other touched font properties in one transaction and
one Undo record, and Format Painter copies the same semantic TextStyle value.
Document defaults, paragraph and character styles, conditional table styles,
body text, headers, footers, footnotes, endnotes, formatting revisions, strict
or transitional DOCX import, exact export, and reopen share the resolver.
Malformed, duplicated, misplaced, namespace-spoofed, child- or text-bearing,
extra-attribute, and unresolved-theme leaves fail closed to explicit nil and
appear in compatibility diagnostics. Prior values inside w:rPrChange use the
same bounded model.
The DOM stores validated JSON in data-office-run-shading. CSS provides a
bounded projection for solid, striped, crossed, thin-line, and percentage
patterns with cloned inline fragments. Shading changes paint only, so eligible
paragraphs stay on the Worker/WASM layout path. Native w:highlight remains a
separate mark and takes visual precedence without deleting the underlying
shading semantics. Open the Playground's 字符底纹 template to edit the
complete model and verify one-step Undo.
Native proofing languages
Writer retains the three independent native w:lang slots: Latin w:val,
East Asian w:eastAsia, and bidi w:bidi. Native w:noProof remains a
separate three-state value. Removing the direct value follows the current
style, false explicitly includes text in proofing, and true excludes it.
The model does not flatten those states into the document-wide browser
spellcheck switch.
Review exposes 设置校对语言 beside Spelling Check. Its accessible dialog accepts bounded BCP 47 tags, reports mixed values independently, leaves every untouched slot unchanged, and offers Follow style for each language and for the proofing state. Apply restores the captured selection and focus and commits all touched fields through one TipTap transaction and one Undo record. Header and footer editing invokes the same model.
Document defaults, paragraph and character styles, body text, headers,
footers, footnotes, endnotes, tracked character formatting, rejection restore,
strict or transitional DOCX import/export/reopen, and prior formatting inside
w:rPrChange preserve the exact slots and explicit state. Malformed,
duplicated, misplaced, nested, text-bearing, extra-attribute,
namespace-spoofed, invalid-tag, and invalid on/off input fails closed and is
reported by compatibility diagnostics.
The DOM stores canonical language JSON in
data-office-proofing-languages, stores explicit state in
data-office-no-proof="true|false", and projects the effective lang and
spellcheck attributes. Valid effective languages also travel with each
Worker text-layout run and are set on the RustyBuzz buffer before Rust/WASM
shaping. This preserves language-sensitive shaping without claiming bundled
spelling dictionaries, grammar, or translation. Open the Playground's
校对语言 template to inspect Latin, East Asian, bidi, explicitly checked,
and excluded examples.
Native character baseline position
The same Advanced Font Settings dialog stores Normal, Raised, or Lowered
text as one signed native w:position value from -3,168 through 3,168
half-points. One half-point equals 0.5 point, so the numeric field accepts an
exact 0.5–1,584 point magnitude. Scale, position, and spacing track mixed
selections independently; changing all three and choosing Apply still creates
one transaction and one Undo record.
Body text, headers, footers, Format Painter, tracked character formatting, and
prior values inside w:rPrChange share the same TipTap attribute. Explicit
zero remains distinct from inheritance. Transitional DOCX accepts signed
integers, while strict DOCX also accepts universal measures that convert to an
exact half-point. Malformed, duplicated, out-of-range, or namespace-spoofed
properties fail closed. Export and reopen write the exact native value,
including w:position w:val="0".
The DOM stores data-office-character-position-half-points and exposes the
exact point value through --work-document-character-position; CSS applies it
as numeric vertical-align. Native subscript or superscript takes visual
precedence when w:position and w:vertAlign coexist, and removing that mark
reveals the retained baseline offset again. Positioned paragraphs deliberately
use browser line measurement until the Worker/WASM text-layout protocol can
carry per-run baseline offsets; other eligible paragraphs remain on the
deterministic kernel path.
Real-time review mode
Pass an initialized Document collaboration session with mode: 'comment' and
an authenticated actor to enable selection comments without text editing. The
reviewer can create a thread, reply, resolve or reopen, and delete only records
owned by that actor. Threads, selection marks, attribution, and detached-anchor
state persist in Yjs/Yrs; remote review changes stay out of local undo history.
See Real-time collaboration
for the browser, CLI/MCP, and A3S Boot authorization workflow.
Real-time suggestion mode
Pass an initialized Document collaboration session with mode: 'suggest' and
an authenticated actor to enable attributed insertion, deletion, and
replacement proposals. The editor forces tracked text changes on, omits normal
formatting/comment/final-decision controls, and permits the actor to withdraw
only its own proposals. Canonical text, structure, non-suggestion formatting,
options, comments, and another actor's proposals remain protected.
An edit participant accepts or rejects proposals from the review panel. The
visible change and one immutable WorkDocumentChangeDecision are committed in
the same Yjs transaction. The record keeps proposal and decision actor/name/time
attribution and appears in content.changeDecisions; a second conflicting
decision fails closed. The A3S Boot reference service repeats the semantic
authorization in Yrs before persistence and broadcast. See
Suggest changes to a Document
for the complete browser/backend contract and the current native CLI/MCP limit.
Character-formatting revisions
With tracked changes enabled, applying direct character formatting to existing
text creates one formatting revision. The bounded model covers bold, italic,
underline, strike, subscript, superscript, font family, font size, text color,
highlight, character scale, spacing, kerning threshold, emphasis mark, hidden
text, character border, outline, shadow, emboss, imprint, baseline position,
all-caps and small-caps effects, and Word grid state. Formatting applied to text that is still a
pending insertion remains part of that insertion
instead of creating a nested revision.
The revision stores the exact prior direct marks while the selected text renders with the new marks. Accept removes only the revision wrapper and keeps the new formatting. Reject restores the prior marks and removes the wrapper without changing any character. Both paths are single transactions, and clearing direct formatting never removes comment or revision marks.
Supported strict or transitional DOCX w:rPrChange records import into the same
review card with author, optional date, current formatting, and prior formatting.
Export writes a native w:rPrChange again. Unsupported, malformed, duplicated,
or namespace-spoofed run-property changes remain on the structural diagnostic
path rather than being interpreted as editable state.
In collaboration, the mark and an accept/reject audit record travel through the
standard Yjs v1 update. Yrs validates the bounded formatting snapshot and reads
formatting decision records, while authenticated suggest sessions must
preserve existing formatting revisions and cannot create or rewrite them. See
Synchronize character-formatting revisions
and the complete A3S Boot backend.
In the Playground, choose 体验格式修订, open 审阅, then
查看修订(3) to review the Formatting card.
To inspect paired native move semantics without importing a file, choose 体验移动修订, then open 审阅. The demo presents the source and destination as one 移动 card; accepting keeps the destination text, rejecting keeps the source, and the same review surface becomes modal at phone width.
Native underline formatting
Writer authors and reopens all 18 native WordprocessingML underline values:
none, single, words, double, thick, dotted, dottedHeavy, dash,
dashedHeavy, dashLong, dashLongHeavy, dotDash, dashDotHeavy,
dotDotDash, dashDotDotHeavy, wave, wavyHeavy, and wavyDouble.
The Home ribbon, selection toolbar, and header/footer surface share an
accessible split control. Underline color supports Automatic Color, direct RGB,
and preserved theme/tint/shade identity.
Cmd/Ctrl+U disables any active underline style or enables single from the
off state. Cmd/Ctrl+Shift+D toggles double, and Cmd/Ctrl+Shift+W toggles
words-only underline. Format Painter, tracked character-format changes, Undo,
DOCX export, and reopen preserve the exact typed state, including explicit
none used to override inherited formatting.
Native strikethrough formatting
Writer keeps strikethrough as one typed none | single | double mark. The
Home ribbon, selection toolbar, and header/footer ribbon expose the same
accessible split control, while the compact page-chrome toolbar provides a
direct toggle. Body text, page chrome, Format Painter, tracked character-format
changes, Undo, DOCX export, and reopen preserve the exact style, including an
explicit none that overrides inherited formatting.
DOCX import tracks w:strike and w:dstrike independently at every style and
direct-format layer, then resolves double above single. Export writes both
properties so switching from an inherited double strike to single, or clearing
either inherited state, cannot revive stale formatting after reopen. CSS
projects solid or double line-through without changing the text or excluding an
otherwise eligible paragraph from Worker/WASM layout.
Traditional Office does not define a direct Writer shortcut for this command,
so the command catalog advertises none. The editor also disables TipTap's
unrelated Mod+Shift+S binding; use the ribbon or selection toolbar instead.
Selection toolbar controls
The floating Writer selection toolbar uses the same compact, theme-aware button tokens as its surrounding actions. Underline and strikethrough split controls explicitly reset browser-native button appearance, keep a single-pixel divider between the primary action and its disclosure, and retain the same hover, pressed, focus, and keyboard semantics as the Home ribbon. This prevents a browser's default outset border from changing the toolbar's density or making the two controls look like unrelated widgets.
Paragraph-formatting revisions
Tracked paragraph commands now create a separate paragraph-formatting
revision on each affected paragraph or heading. The bounded snapshot covers
alignment, writing direction, left/right/first-line or hanging indentation,
space before/after, line height and rule, keep-lines/keep-next/page-break/widow
controls, contextual spacing, outline level, tab stops, borders, shading, and
the default-collapsed flag. One multi-paragraph command shares a stable
revision identity, and later formatting edits keep the original pre-change
snapshot instead of rebasing the pending review.
Accept keeps the current paragraph properties and removes only the review metadata. Reject restores the complete prior paragraph properties without changing text or inline marks. Either decision and the original formatting command form independent undo boundaries; a malformed or non-canonical prior snapshot fails closed instead of applying a partial restoration.
Supported strict or transitional DOCX w:pPrChange records import as
Paragraph Formatting cards with author, optional date, current properties, and
the complete supported prior-property snapshot. Export emits native
w:pPrChange again and removes every private transport marker. Duplicated,
malformed, namespace-spoofed, or unsupported paragraph-property changes remain
on the structural diagnostic path.
The node metadata and immutable changeKind: "paragraph-formatting" decision
record use the standard Yjs v1 document update. Yrs reads the decision kind,
retains browser-created revisions across restart and duplicate/reordered
delivery, and rejects suggest updates that create or rewrite paragraph review
metadata. See
Synchronize paragraph-formatting revisions.
The Playground's second review card is 段落格式; rejecting it restores the
original alignment, indentation, spacing, and line height while preserving the
paragraph text and the separate character-formatting revision.
Ordered-list numbering revisions
With tracked changes enabled, changing an ordered list's decimal, lower/upper
letter, or lower/upper Roman style, or changing its starting number, creates one
numbering revision for the complete list range. The first edit stores a
canonical bounded snapshot of the original style, start value, nesting level,
and retained Office numbering identity; later edits keep that baseline rather
than rebasing the pending review.
Accept keeps the current list properties and removes only the review metadata. Reject restores the complete original numbering snapshot without changing list text. The original command and each decision remain independent one-step Undo boundaries. The review panel presents one 编号格式 card, so a native record per list item is not exposed as a misleading stack of paragraph changes.
Supported strict or transitional DOCX w:numberingChange records import for
unambiguous single-level and bounded multi-level decimal, letter, Roman, and
bullet (nfc 23) definitions at the current w:ilvl. Sibling levels in
w:original may carry other ST_NumberFormat values as opaque prior text.
Consecutive per-item records become one atomic list intent only when author,
date, numbering identity, level, format, suffix, and original sequence agree.
Export writes native sequential records back under w:numPr, enables
w:trackRevisions, and removes every private marker. Malformed, duplicated,
conflicting, unsupported current-level picture formats, or namespace-spoofed
records remain structural diagnostics.
The snapshot is capped at 64 KiB and native import/export at 65,536 records.
Tracking first checks for a structural ReplaceAroundStep, so ordinary typing
does not scan ordered lists. The list metadata and immutable
changeKind: "numbering" decision use standard Yjs v1 updates; Yrs projects
them after persistence and restart and rejects suggest updates that remove or
rewrite the revision. See
Synchronize ordered-list numbering revisions.
The Playground's third card is 编号格式; rejecting it restores the original
Roman numbering while preserving every list item, and Undo restores the pending
revision.
Whole-paragraph mark revisions
Word records an inserted or deleted whole paragraph with both a direct body
w:ins or w:del wrapper and a matching paragraph-mark record under
w:pPr/w:rPr. A3S Office imports this bounded text-only shape as one insertion
or deletion review item when the kind, author, UTC date, namespace, and direct
paragraph structure agree. Transitional and strict Word namespaces are
supported. The numeric body and paragraph-mark IDs are validated independently
and may differ, matching native producer behavior, while duplicate browser
identities are allocated safely.
The Changes pane shows one card rather than a misleading body change plus an empty structural revision. Accepting an inserted paragraph or rejecting a deleted paragraph preserves the complete block; rejecting an insertion or accepting a deletion removes it. Each decision is one transaction and one Undo boundary. Export writes the body revision and a separate native paragraph-mark revision, enables tracked changes, removes private markers, and reopening the DOCX restores the same atomic semantics. Import and export admit at most 65,536 records.
An isolated paragraph-mark change can mean a paragraph-break merge or split.
When the adjacent sibling is also an eligible text-only paragraph, Work imports
a reviewable paragraph-break change with accept/reject join semantics and
mark-only DOCX export. Otherwise it is not guessed as a whole-paragraph change.
Untracked text-only sibling runs (including empty/rPr-only) may sit beside
matching body wrappers and still import as one atomic whole-paragraph revision.
Safe relationship-bound external hyperlinks (http/https/mailto with a
resolved r:id) are admitted alongside relationship-free internal links.
Supported inline DrawingML pictures (wp:inline with a resolved image
r:embed) are admitted alongside visible text, or as picture-only paragraph
bodies for whole-paragraph mark wrappers and paragraph-break neighbors when
that is the only content. Untracked supported inline DrawingML picture siblings
may sit beside matching body wrappers, mirroring untracked text siblings.
Floating anchors, empty or malformed drawings, unresolved embeds, unresolved
or unsafe hyperlinks, mismatched kind/author/date, malformed or
namespace-spoofed attributes, unsupported nodes, and over-limit input stay on
the structural compatibility path with explicit diagnostics.
Move revisions
Word represents a moved text range with a paired w:moveFrom and w:moveTo
record. A3S Office imports the bounded text-only subset as one move review
identity when both sides use the same numeric ID, author, date, and text. The
transitional and strict Word namespaces are accepted, and each side keeps its
from or to role in the browser mark. The review pane shows one 移动 card
and uses the destination range for navigation, so selecting a move never sweeps
up unrelated text between the two positions.
Accepting a move removes the source text and keeps the destination text;
rejecting it removes the destination and keeps the source. Both operations are
one atomic transaction across the pair, one Undo boundary, and one immutable
changeKind: "move" collaboration decision. A destination whose wording
differs from the source is still displayed with a source → destination summary
for diagnostics, but resolution fails closed until the pair is valid.
DOCX export first gives the docx writer transient negative IDs, then rewrites
those wrappers to native w:moveFrom and w:moveTo elements with the shared
positive ID, author, and UTC date. Companion w:move*Range* bookmarks that
uniquely sandwich each supported side also round-trip, including when the
destination lives in a later section than the source, when body-level
Start/End enclose one w:tbl with a supported text-only move in exactly one
w:tc (single-cell tables, or multi-cell tables whose sibling cells hold only
untracked text-only content), when at most one simple w:sdt (with
w:sdtPr chrome) contains the move's paragraph or table, or when move ancestry
is at most two w:tbl elements that both contain the supported text-only
move. Reopening therefore returns the same one-card review identity without
data-document-change leakage or transient IDs. The bounded import/export
budget is 65,536 move sides and 1,000,000 characters per move. Rich runs
outside ordinary text, deeper nested tables, nested tables beside the move,
SDT combined with nested tables, nested or sibling SDT sandwiches, tracked
revisions in sibling cells, section-sandwiching range markers, unpaired
markers, relationship-bound objects, malformed metadata, and duplicate
identities remain on the structural compatibility path and are reported rather
than flattened into an inexact editable move. Compare / same-document
text-only inferred moves also emit companion w:move*Range* bookmarks on
export with deterministic rangeId / rangeName; section-crossing and
table/complex Compare moves stay fail-closed.
Compare can infer a move inside a simple paragraph or heading, and can pair a range across aligned simple text blocks when both blocks belong to the same document section. In either case the unique lexical range must appear once in each aligned delete/insert chunk, with matching marks and safely carried separators. Those admitted inferred pairs export the same companion range bookmarks as native moves. Arbitrary source/destination edits, duplicate or mark-mismatched candidates, rich runs, section-boundary ranges, tables, and over-limit text continue to produce deterministic insertion/deletion or diagnostic results. Use a native paired move or an explicit browser move mark when broader exact move-review semantics are required.
The Playground's 体验移动修订 button provides a repeatable text-only fixture for checking this atomic accept/reject interaction without a file import.
Document compare and combine
The Review ribbon now exposes 比较文档 and 合并文档 as first-class
Writer workflows. Compare treats the mounted controlled document as the
original and imports a .docx, .html, .htm, or .txt file as the revised
version. A deterministic section/block alignment and token diff generates the
existing reviewable insertion, deletion, character-formatting, and
paragraph-formatting revisions. When a lexical range appears exactly once in a
delete chunk and once in an insert chunk within the same simple paragraph or
heading, or across aligned simple text blocks in the same document section,
Compare additionally emits one paired move review item. Matching marks and
safely carried separators are required; ambiguous duplicates, mark mismatches,
rich runs, section-boundary ranges, tables, and over-limit text remain ordinary
revisions or explicit diagnostics. Admitted inferred pairs export companion
w:move*Range* bookmarks with deterministic rangeId / rangeName alongside
native w:moveFrom / w:moveTo. The selected author is attached to every generated
revision, the source name is bounded transaction metadata, the whole result
publishes through one controlled onChange, and Undo restores the
pre-comparison document in one step. After a successful comparison, the
Changes pane opens automatically so each generated revision can be located,
accepted, or rejected with the existing review commands.
Combine is a different, fail-closed operation. The imported reviewed copy must already contain revisions, the current document must contain none, and rejecting every imported revision on an immutable snapshot must reproduce the current baseline exactly. The current bounded path admits inline insertion/deletion, character-formatting, and paragraph-formatting revisions while retaining the current paragraph identities. A missing revision set, malformed prior-format snapshot, baseline mismatch, or structural block revision leaves the current document untouched and returns a localized diagnostic.
Comparison accepts at most 1,024 blocks in each version and 1,000,000 combined text characters. Block alignment and each inline diff allocate at most about 1.1 million matrix cells. The two documents must have the same section count and page-layout attributes. Unchanged complex blocks may pass through, but a changed table, list, image, equation, content control, empty structural block, or other complex tree is never flattened into a misleading text diff. Existing revisions in either comparison input, unsupported review marks, and layout changes also fail closed.
Generated inline revisions export as native w:ins and w:del, character
format revisions as w:rPrChange, and paragraph-format revisions as
w:pPrChange; export and reopen retain their author, date, text, and prior
format snapshot. A browser-created inserted or deleted paragraph additionally
uses block-container metadata so rejecting an inserted block or accepting a
deleted block removes the whole container. When that container is one exact
text-only paragraph whose text is entirely owned by the matching insertion or
deletion, export now maps it to the native paragraph-mark shape described
above, and reopen preserves the atomic block decision. Isolated paragraph-break
merge/split semantics, mixed content, and other structural changes still fail
closed and are reported rather than presented as complete structural
comparison fidelity.
Open the Playground's 文档比较 template, choose Review → 比较文档,
and import a revised file to exercise the public path. The local A3S Test suite
also imports a dedicated cross-paragraph fixture and verifies one move card,
both scoped marks, and atomic rejection. Focused component tests, DOCX reopen
coverage, responsive Playwright, and the local-only
word-document-comparison.acl suite cover controlled publication, review
decisions, focus restoration, accessibility, and empty browser diagnostics.
A3S Test is not installed or invoked by Actions or Pages.
Controlled review conflicts
An incoming controlled content value remains authoritative and is applied
without adding an undo entry or echoing it through onChange. When the update
targets the same artifactId, the editor compares comment anchors and tracked
changes before and after replacement. Position-only movement and newly added
review items are safe. Removed ranges, changed reviewed text, or a reused
revision ID with a different insertion/deletion kind emit
onReviewConflict and show an accessible warning.
Removing a comment thread and its anchor together is treated as an intentional
host deletion. Removing only the thread while its body anchor remains reports a
record-removed conflict. If a host update removes only the anchor, the thread
record is retained through later local edits until the host removes the record
or restores its original anchor. Changing artifactId establishes a new
document boundary and clears prior conflicts; hosts that switch documents
should therefore provide stable artifact IDs.
Each DocumentReviewConflictEvent contains the current artifactId and the
newly detected conflicts. A conflict identifies its review kind, id,
reason, and previousText, with nextText or nextKind when available.
The same review identity emits once while unresolved and keeps its original
recovery baseline even if later host updates change it again. Dismissal hides
the warning but does not reinterpret or merge the authoritative host value.
Source-backed DOCX export
importOfficeFile registers the original DOCX Blob against the imported
artifact. createArtifactBlob regenerates the editable core document, then
copies safe source-only OPC parts byte-for-byte and reconnects their content
types and relationships. Generated document, style, numbering, header, footer,
and settings semantics remain authoritative. In word/settings.xml, passive
ignorable attributes and elements plus structurally valid, non-conflicting
mc:AlternateContent blocks are merged from strict or transitional UTF-8 or
UTF-16 sources. Relationship-bound and behavior-changing source settings are
not restored. Passive, relationship-free extension trees at the roots and
uniquely matched nodes of word/styles.xml and word/numbering.xml are also
retained. Styles match by type plus style ID. Imported abstract-numbering,
concrete-numbering, and level metadata follows regenerated IDs; duplicate,
source-only, malformed, or ambiguous one-to-many mappings are dropped.
Generated Word style and numbering semantics still win. Relationship-free
passive extensions from non-OOXML ignorable namespaces also follow uniquely
matched picture drawings in regenerated document, header, footer, footnote, and
endnote parts. The match uses normalized anchor plus drawing-property IDs,
which body, page-chrome, and note import retains in sanitized editable HTML.
Native note pictures also retain layout, wrapping, crop, bounded rotation/reflection,
and layer metadata;
export repairs missing note-part image relationships and validates every media
target. Source-only, changed, duplicate, namespace-spoofed,
relationship-bound, Microsoft/OOXML semantic, and ambiguous drawing branches
are dropped; generated image geometry and media stay authoritative. Legacy
VML, shapes, SmartArt, and drawing-bearing content-control wrappers normalize.
Passive extensions also follow uniquely matched, unchanged paragraphs and their
paragraph properties by native w14:paraId plus w14:textId. Both IDs survive
sanitized body and page-chrome HTML. Text edits rotate textId, formatting-only
edits and moves retain it, and copies or splits receive new paragraph IDs.
Changed text versions, duplicate identities, relationship-bound content, and
Microsoft/OOXML semantic branches are dropped; generated paragraph semantics
stay authoritative. Stable tables retain equivalent passive extensions on the
table, row, and cell scopes and their property nodes. Native row w14:paraId
plus w14:textId survives body and page-chrome HTML; tables and cells derive
conservative identities from directly owned row and paragraph IDs. Row content
or structure changes rotate the version, copies receive independent IDs, and
nested rows or cells remain isolated from outer-table export. Ambiguous,
cross-kind, unsafe, or semantic branches are dropped while generated table
geometry wins. Unsupported math, note/comment wrappers, and other inline markup
may still normalize. Source font-table metadata and source-only internal
obfuscated-font payloads survive with relationship IDs rewritten to the final
package graph. External references, mismatched relationship or content types,
duplicate identities, and generated-path collisions are disconnected. Native
DOCX applications can use the retained embedded fonts, but browser editing,
preview, and PDF output continue to use registered A3S fonts or substitution
and may wrap text differently.
Persist the source Blob with the artifact and call registerSourceBlob after a
browser reload. Export fails explicitly when an artifact declares a source but
that Blob is unavailable. Imported source metadata includes a SHA-256
fingerprint, and export rejects a different Blob registered under the same
artifact ID. Digital signatures are invalid after editing, and VBA, ActiveX,
and custom-ribbon content is deliberately omitted from the macro-free DOCX
output. Compatibility diagnostics report these boundaries before export.
DOCX text and grid fidelity
Imported section layouts retain an optional WorkDocumentGrid with its OOXML
grid type and point-based line pitch. Imported runs retain explicit
snapToGrid values. Both properties survive editing and DOCX export; a
gridless source remains gridless instead of receiving the document generator's
default grid.
For automatic Word line spacing, the browser combines the original paragraph multiple with a measured Traditional Office advance for the resolved run font. These render metrics are internal compatibility data: export continues to use the original OOXML paragraph multiple, so a browser-only calibration cannot rewrite the document's line-spacing semantics.
Office 2013 w15:collapsed paragraph metadata round-trips through body and
page-chrome HTML as data-office-default-collapsed. Import accepts only an
empty leaf or the exact core Word w:val lexicals true, on, 1, false,
off, and 0; an omitted value means true, while a malformed or duplicated
direct value fails closed instead of inheriting stale state. Export emits
canonical 1 or 0, declares the Word 2012 namespace, and adds its prefix to
mc:Ignorable. The browser deliberately keeps the content expanded and
editable because this native property controls Word's initial document view,
not content visibility or the editor's navigation-pane state.
Paragraph shading round-trips as structured data-office-paragraph-shading
metadata plus a browser preview. Import resolves w:shd through document
defaults, based-on paragraph styles, conditional table styles, and direct
formatting. It preserves every Word pattern mask, direct or automatic
foreground/background colors, explicit nil resets, and independent
themeColor/themeFill references with tint or shade. Export restores both
theme channels and the native pattern. When tint and shade are both present on
one channel, preview follows Word's tint precedence while export retains both
attributes. A direct browser background edit keeps
the pattern but intentionally replaces the edited theme-bound channel with
direct RGB. Malformed, duplicated, namespace-spoofed, relationship-bound, or
unresolved theme values fail closed rather than exposing inherited stale
formatting. Direct page-chrome shading uses the same editor model and export
path.
Paragraph borders round-trip as structured data-office-paragraph-borders
metadata plus a bounded CSS preview. Import applies document defaults,
based-on paragraph styles, conditional table styles, and direct formatting in
that order. The model retains schema-ordered top, left, bottom, right,
between, and facing-page bar edges; all 197 Word line and art border styles;
direct, automatic, or theme colors with tint and shade; native widths and
spacing; shadow; and frame flags. Physical edges are directly editable in the
browser. Art borders, between-paragraph grouping, and facing-page placement use
an explicit preview approximation while export restores exact native w:pBdr
children and attributes. A direct CSS change removes the theme reference only
from the edited physical edge. Strict and transitional WordprocessingML are
accepted; malformed ordering, duplicate containers or edges, namespace
spoofing, relationship-bound attributes, invalid measures, and unresolved
themes fail closed. Page-chrome paragraphs share the same edit and export
model.
Native table of contents
Writer represents a Table of Contents as a selectable, non-editable typed block instead of flattening generated rows into ordinary text. Insert and Customize in the References ribbon read the existing shared outline, accept semantic headings and native outline-level paragraphs across levels 1 through 9, and preserve hyperlinks, page-number visibility, right alignment, and dot, dash, underline, or no leader. Each insert or option change is one TipTap transaction and one Undo record. No shortcut is advertised because the conventional Writer surface does not define a separate direct shortcut for this command.
Every entry stores a bounded title, level, page number, and stable target. An included outline item without a native paragraph identity receives one in the same insert/update transaction, so inserting the TOC cannot invalidate its own links and Undo restores both changes together. Page values come from the same live Worker/WASM pagination resolver used by PAGE fields. The explicit Update Table of Contents action recomputes every block from those two sources in one transaction, so changing a heading or pagination never creates a second heading or page-number model. A document stores at most 512 cached entries per block; additional matches are reported as truncated rather than producing an unbounded node attribute.
DOCX export emits a native w:sdt Table of Contents with a live TOC field,
cached entries, internal heading bookmarks, and the selected leader semantics.
Import and reopen preserve the common TOC \\o "1-3" \\h \\z \\u subset,
complete-range page suppression, and the space separator used for non-right-
aligned page numbers. Custom \\t style mappings, partial page ranges,
malformed ranges, and separators that cannot be represented exactly are not
silently approximated; compatibility diagnostics report them. Each imported
TOC resolves cached rows independently, so multiple TOCs can target the same
heading. Open the
Playground's 可更新目录 template to edit, navigate, refresh, export, and
reopen the complete path.
Native document index
Writer keeps every marked index term as a selectable inline atom and keeps the generated index as a separate selectable, non-editable block. In References, Mark Index Entry captures selected text and can author a primary term, secondary term, cross-reference, or bold/italic page-number intent. Insert or Customize Index controls one through four columns, indented or run-in layout, page-number alignment, and dot, dash, underline, or no leader. The conventional Writer surface does not define separate direct shortcuts for these commands, so the command catalog does not invent any.
The generated block sorts normalized terms, combines duplicate terms on the same page, and retains every stable marker target behind the merged page link. Clicking a page selects its source marker. Page values come from the same live Worker/WASM field resolver used by PAGE fields; a page break or reflow therefore does not create a second pagination model. Marking, editing, inserting, customizing, and explicitly refreshing every index each create one TipTap transaction and one Undo record. A document reads at most 2,048 markers and caches at most 512 generated rows; exceeding either limit produces an explicit truncated state instead of an unbounded node attribute.
DOCX export emits native w:fldSimple XE entries and a real w:sdt content
control containing a live INDEX field plus cached Index1 and Index2 rows.
Primary and secondary terms, cross-references, bold/italic page runs, columns,
run-in layout, alignment, and leader semantics survive export, import, reopen,
and a second export. Import accepts the lossless common XE \\b, \\i, and
\\t switches and the INDEX \\c, \\e, and \\r subset. Entry ranges,
custom entry types, locale switches, malformed fields, and other unsupported
switches stay on the explicit compatibility-diagnostic path rather than being
silently approximated. Open the Playground's 原生索引 template to mark,
navigate, refresh, export, and reopen the complete path.
Built-in navigation
The View ribbon opens a persistent heading outline on wide layouts and a focus-contained drawer on compact layouts. Searching the pane scans body text as well as headings, groups each result under its current section, highlights all matches, and moves the editor selection without adding a history entry. Selecting a compact result closes the drawer before restoring the body focus and exact text range.
The Pages view renders live physical-page thumbnails. Documents above 48 pages mount a window of at most 24 buttons plus the current and keyboard-roving pages when needed. Physical scroll spacers retain the document distance, and Home or End makes the first or last page reachable without mounting every page.
Heading and full-text collections use the same window contract above 48 rows. They mount at most 32 contiguous rows, plus sparse active, selected, and keyboard-roving rows when those fall outside the window. Native scroll distance, global list positions, Arrow traversal, Home/End, and exact search selection are preserved. Long-distance result jumps use an instant programmatic scroll for the selection frame and then restore the editor's normal scroll style.
Built-in references
The References ribbon inserts and refreshes typed tables of contents and native
indexes, and inserts captions, cross-references, footnotes, endnotes, page
fields, dates, and citations in the controlled TipTap document. Caption
numbers are part of each caption's accessible name. Caption deletion and
reordering update every linked cross-reference in the same transaction: valid
targets are renumbered and a dangling field renders as Missing reference
instead of retaining a stale number. Undo restores the caption and its linked
field state together.
Common live fields
The Insert ribbon also exposes Word's bounded common field subset: PAGE,
NUMPAGES, SECTION, SECTIONPAGES, DATE, TIME, NUMWORDS, and
NUMCHARS. Numeric page and section fields resolve from the measured physical
page that contains the atom. Word-count fields count visible body text while
excluding generated field results; character counts include spaces and ignore
line-break separators. Refresh and F9 update every eligible field in one
controlled transaction, so a reflow never leaves a stale mixture of values.
Page, section, and bookmark page-reference fields also accept the deterministic
numeric switches emitted by WPS: Arabic, uppercase/lowercase Roman,
uppercase/lowercase alphabetic, and Ordinal. WPS complex fields commonly append
\\* MERGEFORMAT; that tail stays in the native instruction and does not alter
the live result. The wps-fields-probe Commander command captures the exact
installed WPS field instructions for a local compatibility review. The
wps-ui-probe --profile shell|fields|all command separately captures the
installed Writer shell and native field command IDs as UI/UX reference JSON;
it is isolated evidence rather than a product runtime dependency.
The Insert ribbon field launcher is a command menu (Popover + menuitem),
not an OfficeSelect: the closed label stays 插入域 while choosing a field
kind inserts immediately without fake select state.
The Field settings button beside the quick field menu opens the same
bounded model for insertion and editing. Page and section fields offer Arabic,
upper/lower Roman, upper/lower alphabetic, and Ordinal formats. Date and time
fields offer the supported Chinese, ISO, English-long, 24-hour, and 12-hour
presets. Editing a bookmark page reference keeps its stable target identity and
can explicitly toggle the WPS hyperlink switch. Existing MERGEFORMAT tails
are retained, and an imported clock format outside the preset list is shown as
a source-preserved choice until the user selects a new format. Apply is one
controlled document update and returns focus to the document; the same dialog
is reachable after the compact Insert ribbon is scrolled.
Selecting a bookmark in the Cross-reference dialog can insert a live
PAGEREF field instead of a static reference. The field stores both the
bookmark's stable identity and its current name, follows identity-preserving
bookmark normalization, and displays Missing reference when the target is
gone. The native DOCX boundary accepts only the deterministic inline subset
(\\h, the bounded numeric switches, and \\* MERGEFORMAT where applicable);
nested, malformed, unsupported,
or missing-target instructions remain cached text and are reported through the
compatibility diagnostics rather than being presented as editable semantics.
Built-in picture properties
Selecting a body image opens the contextual Picture ribbon. Fast wrapping, alignment, 90-degree rotation, and horizontal/vertical reflection commands remain available, while Picture Properties edits width and height in centimeters, a per-image aspect-ratio lock, wrapping, alignment, text distance, rotation, reflection, and alternative text in one responsive dialog.
Apply creates one undo entry and changes only fields edited by the user. An
imported pixel dimension that was merely displayed as a rounded centimeter
value therefore remains exact. Cancel or Escape leaves the document unchanged,
keeps the image selected, and restores keyboard focus to the Picture Properties
button. Rotation is intentionally limited to quarter turns so the editor,
preview, PDF capture, and native DOCX a:xfrm projection share one predictable
model. Arbitrary-angle or malformed DrawingML transforms are reported by
compatibility diagnostics and normalized instead of being exposed as an
inexact editable value.
Built-in editable text boxes
The Insert ribbon adds a bounded Text Box block. Selecting it opens a contextual Text Box ribbon with the same predictable controls on desktop and compact Web: inline or floating layout, width and height in millimeters, page/column/margin or paragraph-relative offsets, fill and outline, padding, top/center/bottom vertical alignment, and five explicit shape presets: rectangle, rounded rectangle, ellipse, diamond, and triangle. Every accepted change is one typed document update and one Undo step. The selected shape is visible in the control label and on the page, remains discoverable after a compact-ribbon scroll, and survives Undo/Redo. A text box keeps its rich inline text and line breaks, remains selectable as an isolated block, and is kept together by the pagination resolver so a box is not split across physical pages.
The native file boundary is deliberately small and explicit. Supported DOCX
WordprocessingML text boxes use wps:wsp with txBox="1" or a text-bearing
body, and WPS commonly wraps them in mc:AlternateContent. Isolated drawings
with one of the five supported preset geometries preserve geometry,
inline/floating placement, offsets, fill, outline, body padding, vertical
anchor, text, and stable drawing-property IDs through the same editable model.
The generated shape is also consumed by the live page, read-only preview, and
PDF capture projections. An isolated text-box drawing in a paragraph is
converted to editable content. A paragraph that mixes the drawing with other
runs, a VML-only connector, an arbitrary or unsupported preset, malformed shape
content, or another unsupported DrawingML branch stays on the normal
compatibility path and is reported by docx.text-boxes diagnostics rather than
being silently presented as a lossless edit.
The import-to-editor boundary is covered separately: data-text-box-*
attributes are parsed into the structured TipTap model before the live page is
mounted, so a valid WPS shape cannot silently fall back to default rectangle
dimensions. The release fixtures and browser tests exercise all five presets,
desktop and compact discovery, accessibility, viewport containment, and clean
console/page-error evidence.
The bounded connector slice now owns isolated straight, elbow, and curved connectors as editable content. The contextual Connector ribbon exposes one typed connector-kind control alongside solid, dash, dot, and dash-dot line styles, color, width, typed none/triangle/stealth/diamond/oval/open endpoint arrows, layout, offsets, and endpoint percentages. The kind drives a live SVG line, routed polyline, or quadratic path, while the same model drives compact controls, Undo/Redo, WPS VML import, and native DrawingML export/reopen.
The WPS boundary remains explicit. The installed WPS 12.0 COM probe writes
Shapes.AddConnector as a legacy VML v:shape with o:spt="32", 33, or
37 (#_x0000_t32, 33, or 37) for straight, elbow, or curved shapes,
and reports native DashStyle=4 for a dashed line plus the bounded COM 3/4
arrow reference. It is not a text-bearing wps:wsp. VML dashstyle,
startarrow/endarrow, and DrawingML a:prstDash/a:headEnd/a:tailEnd
values map into the same bounded model (classic maps to stealth; unknown
values normalize to none). Arbitrary route-point editing, long-tail dash or
arrow styles, mixed
paragraphs, arbitrary or malformed drawings, and endpoint/routing semantics
outside the typed three-kind model remain fail-closed compatibility boundaries rather
than being presented as exact edits. The deterministic fixture,
word-connector-editor.acl, word-wps-connector-boundary.acl, and
word-wps-connector-kinds.acl cover the authoring/import path with screenshots,
accessibility, console, and page-error evidence; the docx.connectors
diagnostic keeps unsupported source branches visible to hosts.
Built-in content controls
The Insert ribbon adds a bounded inline Content Control workflow for document templates and review forms. The responsive dialog keeps the control's intent together: choose plain text or rich text, give it a display name and program tag, allow multiline text where appropriate, choose a border, tag, or hidden appearance, and optionally set a theme-independent color. Selecting an existing control opens the same dialog for its metadata, while the control's accessible textbox name follows its alias or tag.
Content and shell locks are enforced by the editor transaction boundary rather than by styling alone. A content lock rejects typing, paste, and generic metadata writes; a shell lock prevents replacement or deletion while still allowing the declared editable content path. Typed commands must explicitly request an unlock-sensitive deletion or property change. Insertion, property changes, and deletion each remain one document transaction and one Undo step.
The native DOCX contract is intentionally narrow. Direct paragraph w:sdt
controls in transitional or strict WordprocessingML can round-trip plain or
rich inline runs, aliases, tags, native lock values, multiline text,
collision-free IDs, and Word 2012 appearance and color. Empty controls are
preserved as empty editable spans. Data bindings, placeholders, repeating
regions, date/dropdown/picture/form controls, block or nested controls, and
relationship-bound semantics are not represented by this model. They remain
safe editable text (or a fail-closed import) and receive
docx.content-controls.unsupported diagnostics instead of an inexact editable
promise.
Host-defined selection menu
The menu factory receives an immutable selection snapshot with exact selected text, a structured fragment, adjacent context, complete plain text, synchronized HTML, and the current controlled content value. The callback also receives conflict-aware editing commands.
Return or await asynchronous work so the editor can map the original range
through unrelated transactions. If the selected text itself changes, a later
replaceText returns stale-selection instead of modifying unrelated content.
For an open-ended action such as “Ask AI”, collect the user's question in the
host UI before dispatching a request. The Playground demonstrates this with a
focused question composer and keeps the attached document context collapsed
after submission instead of filling the assistant with raw context.
Extensions
extensions accepts TipTap extensions. Keep the array identity stable and use
unique extension names. A custom Node or Mark also needs DOCX import/export
semantics if it must survive a file round trip. See the
extension model.
