Files
wordcraft/docs/file-format-parity.md
e989fc2b3d Open RTF in its code page, and Word/RTF files whose extension is wrong (#896)
RTF import read every 8-bit byte as Windows-1252, so Cyrillic (and any
other non-Western) RTF came out as mojibake. Bytes now decode in the
current font's code page (\fcharset, \cpg), else the default font's,
else the document's (\ansicpg), for the single-byte Windows code pages
874 and 1250-1258.

A .doc, .docx or .rtf whose content is another of these formats now opens
by its signature, as Word does: RTF saved as .doc (hh.ru résumés and
accounting exports are commonly saved that way), a .docx renamed .doc, a
Word 97-2003 file renamed .docx.

Co-authored-by: Магда М.Г. <mail@mgmagda.ru>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-12 11:36:15 -04:00

36 KiB
Raw Permalink Blame History

File-format parity with Microsoft Word

Last reviewed: 2026-10-11 · Last updated: 2026-10-11 · Change: trivial (symbol-font text exported as Unicode, #776; previously trivial: text-box margins, Resize shape to fit text and freeforms in groups, #743; previously trivial: formatted paste from the system clipboard's HTML and RTF, #687; previously trivial: independent complex-script formatting inheritance and round-trip regression tests; previously trivial: import/export fixes for TXT, RTF, ODT, HTML and LaTeX, #433–#440; previously major: first version; every format Word reads or writes, measured from the readers and writers on origin/main) · Target: Microsoft Word (Microsoft 365) for Mac 16.113.4, plus Word for Windows' extra formats

Every format Word opens or saves, what WordCraft does with it, and how it's tested. Fidelity is the share of a typical real-world file's content and formatting that survives (read: shows correctly; write: Word opens it showing the same). Summary in target-app-parity.md; the work items are in gaps.md.

Dimension: ~60% (estimated), 179–290 h to full (the sum of the rows below). The weighted table gives ~64%; we discount it to ~60% because DOCX fidelity has never been checked on real-world files. DOCX dominates the weight: a Word user sends and receives .docx; everything else is occasional.

Formats

Weights are the share of a Word user's file traffic (estimate). Read/write: ✅ yes, 🟡 partial, ❌ no, — Word doesn't either.

Format Weight Word WordCraft read WordCraft write Fidelity Hours How it's tested Notes
.docx Word Document (ECMA-376 Transitional) 70% R/W ✅ ✅ ~65% 70–110 crates/docx/tests (roundtrip 34, fixtures 29, malformed 8, bidi 5, citations 5); synthetic fixtures only Word opens our files. Untested on a real-world corpus. Details below
.docx Strict Open XML 1% R/W ✅ (namespace mapping in xml.rs) ❌ ~60% 2–4 one fixture Writing Strict is rare
.docm / .dotx / .dotm 3% R/W ✅ ✅ ~65% incl. above macro_packages.rs Macros and signatures kept on save (#172); macros never run
.doc Word 97-2003 (and .dot) 8% R/W 🟡 ❌ ~60% 25–40 crates/docbin/src/tests.rs, tests/drawing.rs (56) Spec-based reader ([MS-DOC]): text, formatting, styles, sections, headers/footers, tables, lists, notes, fields, bookmarks; inline and floating pictures (PNG, JPEG, DIB, TIFF, EMF, WMF; Macintosh PICT as a sized placeholder) with crop, alt text, position and wrap; basic shapes, lines, groups and text boxes ([MS-ODRAW]). Freeform shapes, z-order and Word 6/95 or encrypted files are dropped or refused. No writer
PDF export 8% W — ✅ ~80% 6–10 crates/pdf/src/tests.rs krilla: embedded subsets, selectable text incl. field results (#133), links, outline, tagging. Fonts it can't subset become outlines (#132). Print Markup (#589): comments in balloons beside each page (scaled to its paper) and tracked changes; HTML/Markdown/text copies end with a comment list. No PDF/A option, no "best for printing/online" choice
PDF open (PDF Reflow, Word for Windows) 1% R ❌ — 0% 30–50 — Converting a PDF into an editable document. A sibling app (PdfCraft) may supply the parser
.rtf Rich Text Format 3% R/W 🟡 🟡 ~50% 10–15 crates/formats/src/tests.rs ~1,500 lines: text, character/paragraph formatting, styles, lists, tables, pictures (\shppict, #154), fields, bookmarks. 8-bit text in the document's code page (\ansicpg) or the current font's (\fcharset, \cpg): Cyrillic, Central European, Greek, Turkish, Hebrew, Arabic, Baltic, Vietnamese, Thai (was Windows-1252 only). Pasted from the system clipboard where the platform offers it (Windows, Wayland) when there is no HTML (#687). Thin: comments, notes, revisions, sections, RTL
.odt OpenDocument Text 2% R/W 🟡 🟡 ~50% 8–12 crates/formats/src/tests.rs Styles, lists (#87), tables, pictures, headers/footers, page breaks (#86), page size, orientation and margins (#810). No footnotes, comments, tracked changes, fields or RTL
.txt Plain text 2% R/W ✅ ✅ ~95% 1–2 unit tests Encoding detection. Files with other extensions (.m3u/.m3u8 playlists, logs, config files, no extension) open as text when they are text, Word and RTF files by their signature; binary files are refused (#569). A Word or RTF extension that contradicts the content also opens by signature, as in Word: RTF saved as .doc (hh.ru résumés, accounting exports), a .docx renamed .doc, a Word 97-2003 file renamed .docx. Word's encoding choice dialog and line-ending options missing; such files save only through Save As
.htm/.html Web Page and Web Page, Filtered 1% R/W 🟡 🟡 ~60% 6–10 crates/formats/src/tests.rs Tables (#102), relative pictures embedded (#113), missing </head> tolerated (#154). No Word "Web Page" (with _files folder) round-trip. The same reader takes HTML from the system clipboard: Paste keeps another program's formatting (a Word document, a web page; Windows' "HTML Format" header understood), Merge Formatting keeps its emphasis (#687)
.mht/.mhtml Single File Web Page <1% R/W ❌ ❌ 0% 3–5 —
.xml Word XML Document (Flat OPC) <1% R/W ✅ ✅ ~65% — crates/docx/tests/word_xml.rs, roundtrip.rs (flat_opc_round_trip_equals_docx) The DOCX package in one XML file, read and written by the DOCX code (#548); File › Export › Word XML Document. .xml files are told apart by their root element
.xml Word 2003 XML (WordprocessingML 2003) <1% R/W 🟡 ❌ ~55% 2–3 crates/docx/tests/word_xml.rs Opened by rewriting it as a package for the DOCX reader (#548): styles, default fonts, lists, tables, sections, headers/footers, footnotes/endnotes, comments, bookmarks, tracked insertions/deletions, hyperlinks, w:binData pictures, document properties. Not read: formatting changes, w:docPr settings, smart tags. Saving as 2003 XML is not planned (legacy)
.wps Works 6–9, WordPerfect .wpd (Windows) <1% R ❌ — 0% 10–20 — Windows-only converters; low value
Encrypted/password-protected .docx/.doc 1% R/W ❌ ❌ 0% 6–10 — ECMA-376 Agile Encryption; .doc RC4/XOR detected and refused (docbin fib). Issue #55
.xlsx/.xlsm/.ods as a mail-merge recipient list — R (data source) ✅ — ~90% 1–3 crates/formats/src/sheet.rs, cmd/mailings.rs Read-only, one sheet's cell values (#334): shared/inline/rich strings, numbers, booleans, cached formula results, dates and times as ISO 8601 (yyyy-mm-dd) from the cell's number format, sparse cells; ODS value types, repeated rows/columns, covered cells. Select Table picks the sheet. Capped (64 MiB per part, 100,000 rows, 1,000 columns, 2 M cells, 32,767 characters a cell). Not shown: number formats other than dates (currency, percent, thousands separators) in .xlsx; no .xls, Access or Outlook sources
.md Markdown — (no) ✅ ✅ — — crates/formats/src/tests.rs Beyond Word
.tex LaTeX — — ✅ ✅ — — crates/formats/src/tests.rs Beyond Word (#11), incl. math
Pictures for Insert › Picture, drag-and-drop and paste — R ✅ — — — insert_picture_takes_a_windows_metafile (engine), paste_picture.rs PNG, JPEG, GIF, WebP, BMP, and Windows Metafile .wmf / Enhanced Metafile .emf at their own frame size (#802), drawn by crates/metafile. Not yet: SVG, TIFF, ICO, HEIC
.png page images — (Save as picture, Mac) — ✅ — — io_ext.rs
.json document model — — ✅ ✅ — — engine tests For agents

DOCX in depth

Measured by grepping crates/docx/src/read and src/write for the OOXML elements (2026-10-10).

Feature Read Write Notes
Text, runs, paragraph and character properties, styles, numbering, sections ✅ ✅ Including complex-script props (w:rtl, w:cs, w:szCs, w:bCs…), East Asian fonts kept apart from Latin (#111); independent complex-script formatting inherited through defaults/styles and preserved over repeated saves (complex_script_inheritance.rs), indents in characters (w:firstLineChars, w:hangingChars, w:leftChars, w:rightChars, #534); every ST_NumberFormat value of w:numFmt is kept on save, Chinese/Japanese/Korean, enclosed and full-width formats are drawn, the rest (Hebrew, Arabic, Hindi, Thai…) show decimal (#534). w:beforeLines/w:afterLines not kept (the points are)
Tables incl. floating (w:tblpPr), table styles and conditional formatting ✅ ✅ Custom table styles round-trip (#256); right-to-left tables (w:bidiVisual) and sections (w:bidi) round-trip (#362)
Headers/footers (first, even/odd), page borders, line numbers, gutter, mirror margins ✅ ✅
Hyphenation settings (w:autoHyphenation, w:hyphenationZone, w:doNotHyphenateCaps, w:consecutiveHyphenLimit) ✅ ✅ Zone, capitals and limit kept and honoured by layout (#407)
Footnotes, endnotes, comments ✅ ✅ The document's own note separators and continuation notice (w:type separator, continuationSeparator, continuationNotice) round-trip as ids -1, 0 and 1 (#352); note options (w:pos, w:numFmt, w:numStart, w:numRestart) round-trip in the settings and in each w:sectPr (#385); commentsExtended written; commentsIds, modern threaded comments (w16cex) partly
Tracked insertions and deletions (w:ins/w:del), paragraph-mark revisions ✅ ✅ #125, #244
Formatting revisions (w:rPrChange, w:pPrChange, w:sectPrChange, w:tblPrChange, w:trPrChange, w:tcPrChange, w:numberingChange) ✅ ✅ #41: kept on open and save, schema order (change element last); changes inside styles.xml are dropped. RTF/ODT ignore them
Move tracking (w:moveFrom/w:moveTo, w:moveFromRangeStart/End, w:moveToRangeStart/End), moved paragraph marks ✅ ✅ #400: both ends linked by the range name; ranges rewritten around each moved stretch (ids renumbered); a move missing an end or a range end opens as a plain deletion/insertion. RTF/ODT/PDF export the result (moved-away text hidden like deletions)
Fields (w:fldChar, w:fldSimple), TOC, cross-references, ADDIN citations ✅ ✅ Field codes Word supports but we don't evaluate keep their cached result. Imported TOCs preserve actual result boundaries, formatted entries and nested fields without relying on TOC styles. EQ \o (overstrike, enclosed characters) is drawn; enclosed characters are written as Word stores them, their style in the code's run sizes (#297); a cached picture (INCLUDEPICTURE) stays as the content of a range field (#465)
Content controls (w:sdt) ✅ ✅ Block, inline, row and cell level, nested; title, tag, id, lock, placeholder, temporary, rich/plain text, w14:checkbox, combo box, drop-down list, date, picture, building block gallery, w15 repeating sections; other w:sdtPr children (data binding, appearance) kept verbatim (#381). A TOC's control is rebuilt by the TOC
Restrict Editing (w:documentProtection edit/formatting/enforcement and password hash, w:locked styles, w:permStart/w:permEnd exceptions) ✅ ✅ #412: SHA-512 hash with salt and spin count written; Word's legacy w:cryptAlgorithmSid/w:hash form (SHA-1/-256/-384/-512, ECMA-376 Part 4 §14.8.1) is kept and verified; MD2/MD4/MD5, w:algIdExt and other unsupported forms are refused, never unlocked; w:colFirst/w:colLast table-column ranges read as plain ranges
Legacy form fields (w:ffData), check boxes, drop-downs ❌ ❌
DrawingML pictures inline and anchored (wp:anchor), wrap square/tight/through/top-bottom ✅ ✅ Tight/through read and written with their wp:wrapPolygon (and edited); without one, a shape's outline is written (a picture's rectangle). wrapText (both sides, left, right, largest) read and written for square, tight and through
WordArt text effects (w14:textFill, w14:textOutline, w14:shadow, w14:glow, w14:reflection in w:rPr) ✅ ✅ Solid, gradient (linear) and no fill, outline colour/width, shadow, glow, reflection (#416); w14:scene3d/w14:props3d dropped
DrawingML shapes and text boxes (wps:) ✅ ✅ Preset geometries subset (callouts and flowchart boxes drawn as the nearest shape, #611); fill and outline from the shape or from the theme through its style references (a:fillRef/a:lnRef, #611), scheme, preset, system, scRGB and HSL colours; rotation and flips (a:xfrm rot/flipH/flipV, pictures and groups too, #332), the effect extent covering the rotated bounds; wps:bodyPr vert and anchor, internal margins (lIns/tIns/rIns/bIns) and Resize shape to fit text (a:spAutoFit: the text is never cut, #743), linked text boxes (wps:txbx/@id, wps:linkedTxbx id/seq, #369); text warps (a:prstTxWarp with adjust values, all 41 presets kept; unknown ones dropped), connectors (straightConnector1, bentConnector2–5, curvedConnector2–5 read; 3-segment forms written) with glued ends (wps:cNvCnPr a:stCxn/a:endCxn; the glued shapes keep their drawing ids) and arrowheads (a:headEnd/a:tailEnd, drawn as triangles) (#416)
Freeform shapes (a:custGeom: a:moveTo, a:lnTo, Bézier curves flattened) and WordCraft ink ✅ ✅ Ink is written as a freeform wps:wsp in a wp:anchor (round caps, alpha for highlighter) and recognised again by its drawing name (#307). It is saved as a custom-geometry shape, not as Word's own ink (InkML in w14:contentPart), so Word shows WordCraft ink as a freeform shape it can move and recolour but not erase with its ink eraser; arcs drawn straight
Group shapes (wpg:), drawing canvas (wpc:) ✅ ✅ Groups (#267) and canvases (#344) with pictures, shapes, freeforms (custom geometry, #743) and text boxes; nested groups flattened. The canvas schema has no transform, so a turned or flipped canvas keeps its turn in our own wpc:extLst extension (urn:wordcraft:canvas-xfrm; Word shows it unturned). Legacy VML canvases (v:group editas="canvas") aren't read as canvases
VML (w:pict, v:shape, v:textbox) 🟡 ❌ Pictures, text boxes, lines (with arrowheads), rectangles and ovals, best effort (#242, #611)
Alt text of drawings (wp:docPr/cNvPr descr and title, decorative mark adec:decorative from [MS-ODRAWXML]) and tables (w:tblCaption, w:tblDescription) ✅ ✅ Pictures, shapes, text boxes, groups and their members, charts and SmartArt; OLE objects get theirs written into the kept XML (#386)
Charts (c:chart), SmartArt (dgm) ✅ ✅ Drawn from the chart's cached data and SmartArt's stored drawing (#292), with data labels (c:showVal). Charts made in WordCraft (Insert › Chart, #409) are written as a c:chartSpace part with their data as literals (c:strLit/c:numLit, no embedded workbook, so Word shows them and offers to create a workbook on Edit Data) and read back as editable; a chart part holding anything more (any chart from Word, or one re-saved by Word) stays read-only. Saved back as read, with every part they reach (chart, embedded workbook, colours and style; diagram data, layout, quick style, colours and drawing) and their content types; a moved or resized one keeps its new frame, and a pasted copy gets its own parts (#319). SmartArt made in WordCraft (#497) is written from its model: data (dgm:dataModel points and connections), our own layout, quick-style and colour definitions under the built-in layout identifiers, and a dsp:drawing with every shape placed; it reads back editable only when its data part is exactly what WordCraft writes
OLE objects (w:object: embedded or linked files, ActiveX) 🟡 ✅ Shown as their picture (VML or DrawingML); saved back whole with the embedding and picture parts, at the size, rotation and flips set in WordCraft (#319, #332). Can't be opened or edited
Native Word ink (w14:contentPart, InkML) 🟡 🟡 Drawing-level ink kept opaque with its InkML part, relationship and content type; run-level mc:AlternateContent keeps the native branch and VML picture fallback. Shows the preview or a missing-picture box. Repeated saves, copies, resize, rotation and namespace aliases tested with original fixtures. No native stroke rendering, eraser, conversion or replay; direct run-level content parts and ink nested in groups/canvases remain unsupported
3D models ❌ ❌ Dropped on read, not preserved on save
Equations (OMML m:oMath) ✅ ✅ #191; manual breaks (m:brk) and the settings' m:mathPr wrapping options (#326)
Themes, font table, settings, compatibility mode ✅ ✅ Embedded fonts (w:embedRegular) not used for rendering, but the font table, its relationships and the embedded font parts are written back unchanged (#770); attached template (w:attachedTemplate and its external relationship) and w:linkStyles round-trip (#377). The template path comes from the file, so opening never reads it: styles update from it only on an explicit Update Styles
Custom XML parts, document properties, bibliography sources 🟡 🟡 Custom XML stores reached from the package/main document preserve opaque data, properties and relationships; binding evaluation remains absent. Custom properties round-trip; bibliography model I/O remains separate (#532 open)
Section text direction (w:textDirection in w:sectPr, §17.6.20) ✅ ✅ tbRl, btLr (and tbRlV/tbLrV, read as tbRl); lrTbV and unknown values read as horizontal (#491)
Ruby (w:ruby: w:rubyPr, w:rt, w:rubyBase) ✅ ✅ #288; base and ruby text with their run formatting, alignment, sizes, raise, language
Document grid (w:docGrid: type, line pitch, w:charSpace), paragraph w:snapToGrid ✅ ✅ #391; run-level w:snapToGrid not read
w:eastAsianLayout, w:fitText ❌ ❌ East Asian layout
Glossary document (building blocks), w:altChunk, sub-documents ❌ ❌
Hostile input ✅ — malformed.rs, capped allocations, never-crash standard
Document paragraph defaults (w:pPrDefault) ✅ ✅ Omission and explicit empty defaults remain distinct across repeated saves; nonempty defaults and later default-spacing edits are written

Opening files from the system

Double-clicking a document, Open With, and making WordCraft the default app (#295). The installers register WordCraft for these types but never take over a default; File › Options › General has Make WordCraft the default for Word documents… where the system allows it.

Platform Registered types Default app Notes
Windows (MSI) .docx .docm .dotx .dotm .doc .dot .rtf .odt; .md .txt under Open With only Options button opens Settings › Default apps on WordCraft's page One ProgId per type, OpenWithProgids, Capabilities + RegisteredApplications (packaging/windows/wordcraft.wxs). Not yet tried on a real install
Linux, BSD (deb, rpm, Flatpak, AppImage) Word, ODT, RTF, Markdown, LaTeX, HTML, text (MimeType= in the desktop entry, AppStream mediatype) Options button runs xdg-mime default for the Word, RTF and ODT types Not from inside Flatpak (the sandbox can't change host defaults); a bare AppImage needs desktop integration first
macOS CFBundleDocumentTypes as Alternate handler (Word, ODT, RTF, Markdown, HTML, text) Finder › Get Info › Open with › Change All (the Options page says so) Apple events open the files (#27)

Paragraph-default preservation

The styles reader records whether w:pPrDefault exists. The writer keeps an omitted container omitted when its modeled properties are still empty. An explicitly empty container stays present, and editing document-default spacing writes the new values. New documents and older serialized style sheets keep their explicit defaults. crates/docx/tests/fixtures.rs covers omitted docDefaults, omitted paragraph defaults, empty containers and populated defaults across two save/reopen cycles. This preserves application-defined defaults without assigning inferred Word spacing values to the model. Observed in Word for Mac 16.113.3 (26092714): three synthetic paragraph-default controls (omitted, explicitly empty, populated) and two reduced invoice controls retain identical text, glyph/image geometry, page sizes and embedded font-program hashes through two WordCraft save/reopen cycles. All fifteen variants open without repair warnings. Word PDFs and measurements remain local under ignored plan/word/; they are not fixtures. These checks cover preservation on Word reopen, not WordCraft pagination parity. The public OOXML reference describes omission as leaving paragraph defaults application-defined. Real-world corpus coverage and WordCraft layout matching remain separate gaps.

Custom XML store preservation

A reduced original bound-control DOCX loses its backing data, item properties and relationship on main, both without editing and after unrelated edits. Main's content-control support (#381) preserves control metadata, including binding attributes, while this custom XML path keeps the backing store through the bounded opaque part graph: payload bytes, content types and related-part IDs survive two edited save/reopen cycles. The public dataBinding contract maps a control to a custom XML data part; its item properties identify the store. Keeping displayed text alone does not preserve that mapping. This change preserves stores without evaluating XPath or synchronizing control edits into XML. Focused original tests cover package/main roots, multiple/shared stores, cycles, external schema references, missing parts, UTF-16 payloads, strict relationship types and reserved filenames. The bibliography names used by #532 are reserved; bibliography already loaded into the source model belongs to its writer. Word-derived files are not fixtures. No readiness estimate rises from these synthetic package checks, and native Word rendering/binding behavior remains untested.

Native save-path guarantees

Native io::save_path_with serializes (and, for password-protected DOCX, encrypts) before creating an exclusively owned sibling temporary file. It writes and synchronizes that file, closes it, then replaces the destination. Failed preparation or replacement keeps the original bytes; cleanup removes only the save's temporary file, on a best-effort basis. Existing <name>.tmp files, directories and links are untouched. A new document gets the default mode (0666 less the umask). When replacing an existing regular file, the Unix temporary file starts with mode 0600 and then takes the existing file's basic permissions. Serialization and format support are unchanged. Synthetic CLI cases and engine/tests/safe_save.rs cover occupied names, links, blocked replacement, missing directories, Save As session state, password-protected saves and original-file protection on macOS. Unit tests inject preparation errors and interleave two prepared saves. Independent saves use separate files; the last successful replacement wins. This is not document locking or conflict detection. Windows/Linux runtime behavior, ACLs and extended metadata, real disk-full conditions, power loss and network filesystems are not verified by these tests. The containing directory is not explicitly synchronized. Cleanup can fail when storage or permissions change, and process termination can leave a temporary file. No Word observation was needed for this filesystem change; it makes no new format-fidelity claim.

What decides beta for formats

  1. A real-world DOCX corpus opened, rendered and round-tripped, compared page by page with Word (local only: Word output can't be committed; keep a manifest and our own renders).
  2. Preserve what we can't render: remaining ink forms and unsupported graphics survive a round trip (keep the parts and the run). Charts, SmartArt and OLE objects do (#292, #319); drawing-level native ink now keeps its InkML and optional picture fallback.
  3. Move tracking (w:moveFrom/w:moveTo) read and written (formatting revisions: #41; content controls: #381).
  4. Encrypted .docx opens with a password.

Imported TOC result preservation

Original synthetic TOCs without TOC paragraph styles lose their outer result range on main and #538. Main also flattens a nested page field in a single-paragraph result. Imported TOCs now use the existing range-field markers to retain the actual result boundaries, nested page-reference fields, formatting, links and locks through edited saves.

The public complex-field contract defines begin/separate/end delimiters and permits nested fields. Paragraph styles do not define those boundaries. A complete range is converted to the engine's styled TOC representation only when that writer can reproduce its exact extent; partial or custom-styled ranges stay explicit.

Focused original regressions cover single/multiple paragraphs, partial ranges, adjacent styled text, multiple/simple fields, table cells, section breaks, missing ends and bounded nesting. The existing styled TOC write/read path remains supported. Update Table and Update Fields refresh unlocked top-level body TOC ranges in place through the engine's generator; one undo restores the imported range. Locked, nested and table-cell ranges remain preserved without regeneration. Preservation is separate from field evaluation. Native Word reopening and refresh, full schema validation and company documents remain untested. Synthetic checks do not raise readiness estimates. No Word-derived files are fixtures.

Revision history

Date Change Summary
2026-10-12 trivial Paste keeps the formatting of HTML and RTF on the system clipboard; Paste Special lists them and pictures (#687, #833)
2026-10-12 trivial ODT page size, orientation and margins read back from styles.xml on open, so they survive a save and reopen (#810)
2026-10-12 minor RTF reads 8-bit text in the document's or the font's code page (\ansicpg, \fcharset, \cpg) instead of always Windows-1252; a .doc/.docx/.rtf whose content is another of these formats opens by signature. Found on a private corpus of real Russian documents: 38 of 44 .doc files were RTF, all now open with their Cyrillic text
2026-10-12 trivial w:sym and symbol-font runs keep their stored characters on save; TXT export and copy write their Unicode equivalents (#776)
2026-10-12 trivial Insert › Picture, drag-and-drop and paste take Windows Metafiles and Enhanced Metafiles (#802); new row for picture formats
2026-10-11 trivial Independent complex-script size, bold and italic inherit correctly through defaults and styles; explicit equal values survive; six synthetic multi-generation round-trip tests, including tracked formatting, added
2026-10-11 minor Opening files from the system: file associations and the default-app button (#295)
2026-10-12 trivial DOCX: a table of contents' entry links (Hyperlink-styled runs in hyperlinks inside a TOC field) import without the Hyperlink style, as Word draws them; measured in Word for Windows
2026-10-12 trivial .doc: custom tab stops read from styles and paragraphs (sprmPChgTabsPapx, sprmPChgTabs, with the alignment and leader of each stop; sprmPChgTabs' operand size fixed), and a section mark ends its section's last paragraph instead of becoming a page break, so the sections (continuous breaks, footers) are kept. Found by comparing EPA templates with Word for Windows; two of them now paginate like Word
2026-10-12 trivial DOCX: a style or paragraph w:numPr with a level and no list takes the list of its style chain (Heading 3 based on a numbered Heading 2 numbers 6.4.5, not 6.15), found in NIH's monitoring-plan template against Word for Windows
2026-10-12 trivial DOCX: w:hideMark on table cells read and written
2026-10-12 trivial DOCX text frames (w:framePr other than drop caps) are read and written back; they were dropped on save
2026-10-11 trivial .doc: inline and floating pictures (BLIP store, PNG/JPEG/DIB/TIFF/EMF/WMF), basic shapes, groups and text boxes read from OfficeArt drawings (#551); fidelity ~55% → ~60%
2026-10-11 trivial Word XML Document (Flat OPC) read and written, Word 2003 XML read (#548)
2026-10-11 trivial #534: DOCX indents in characters read and written; .doc first-line indents (sprmPDxaLeft1, its two-byte operand, and sprmPDxaLeft1_80), indents in characters (sprmPDxc*) and exact/at-least line spacing (LSPD) read correctly
2026-10-11 trivial List and page number formats: all ST_NumberFormat values round-trip; Chinese, Japanese and Korean counting, legal and digit formats, stems/branches, kana, hangul, enclosed and full-width numbers drawn; unknown values are decimal; .doc number format codes mapped (#534)
2026-10-11 trivial SmartArt made in WordCraft written as diagram parts (data, layout, quick style, colours, drawing) and read back editable (#497)
2026-10-11 trivial Attached template (w:attachedTemplate, external relationship of the settings part) and w:linkStyles read and written in schema order; opening never reads the template (#377)
2026-10-11 trivial A bookmark (or comment range) ending after the document's last table keeps its end, in the table's last cell (#464); a field whose cached result is a picture (INCLUDEPICTURE) is kept as a range field around the picture, so the picture survives save; the linked file is never read (#465)
2026-10-11 trivial Print Markup: comments exported in PDFs, prints, page images and HTML/Markdown/text copies (#589)
2026-10-11 trivial Files with an extension WordCraft doesn't know open by content: text (.m3u/.m3u8 playlists, logs…) through the encoding-detecting text import, misnamed Word/RTF files by signature, binary files refused with an error (#569)
2026-10-11 trivial Restrict Editing: Word's legacy password hash (w:cryptAlgorithmSid, w:hash, w:salt, w:cryptSpinCount) verified per ECMA-376 Part 4 §14.8.1; unsupported hash forms refused (#412)
2026-10-11 trivial Restrict Editing: w:documentProtection (edit, formatting, password hash), w:locked styles and w:permStart/w:permEnd exceptions read and written (#412)
2026-10-12 trivial Word 365 cover page (#743): text-box internal margins and a:spAutoFit read and written; freeforms inside groups keep their custom geometry
2026-10-11 trivial DOCX diagrams (#611): shapes and connectors styled by the theme (wps:style) show their outline and fill; preset/system colours; VML lines and rectangles; lines run top-left to bottom-right as in DrawingML
2026-10-11 trivial WordArt text effects (w14: run properties), text warps (a:prstTxWarp) and connectors with glued ends read and written (#416)
2026-10-11 trivial Content controls read and written with their properties and nesting (#381)
2026-10-11 trivial Charts made in WordCraft written as chart parts and read back as editable (#409)
2026-10-11 trivial Hyphenation zone, words in capitals and consecutive-hyphen limit read and written (#407)
2026-10-11 trivial Alt text, titles and the decorative mark for every drawing, table captions and descriptions round-trip (#386)
2026-10-11 trivial Document grid (w:docGrid) and paragraph w:snapToGrid read and written (#391)
2026-10-11 trivial Move tracking (w:moveFrom/w:moveTo and their ranges) read and written (#400)
2026-10-11 trivial DOCX text-box bodyPr vert/anchor and linked text boxes (wps:linkedTxbx) read and written (#369)
2026-10-10 trivial Right-to-left tables (w:bidiVisual) read and written (#362)
2026-10-10 trivial Drawing canvas (wpc:wpc) read and written (#344); group shapes row brought up to date (#267)
2026-10-11 trivial Spreadsheets (.xlsx/.xlsm/.ods) read as mail-merge recipient lists (#334)
2026-10-12 trivial Font table (word/fontTable.xml), its relationships and embedded fonts (word/fonts/*) written back unchanged (#770)
2026-10-12 minor Preserve opaque custom XML stores and related properties; bindings and control support remain separate
2026-10-11 trivial Native saves protect existing temporary-name entries and originals on pre-replacement failure; synthetic macOS evidence, explicit durability/platform limits; readiness unchanged
2026-10-11 minor Preserve imported TOC ranges independently of paragraph styles, with explicit evaluation limits
2026-10-11 trivial Import/export fixes (#433–#440): TXT opens through the encoding-sniffing reader (Windows-1252, unmarked UTF-16) and saves list labels; RTF \uN in document info, bookmark names and field instructions; ODT common paragraph styles' text formatting and table-cell background colours; HTML borderless tables export without cell borders and white-space:pre keeps edge spaces; LaTeX brace groups scope \centering/\raggedleft/\raggedright
2026-10-11 trivial .doc import fixes per [MS-DOC]: piece Prm0/Prm1 decoding (#458), section-break kinds (#459), explicit orientation (#460), negative sprmPIlfo list references (#461), zero-based istdBase style inheritance (#462), font-table entries with alternate names (#463)
2026-10-11 minor Native drawing-level ink and its picture fallback survive DOCX edits and repeated saves; rendering and editing InkML remain missing
2026-10-11 trivial Formatting revisions (w:rPrChange, w:pPrChange, table, row, cell, section and numbering changes) read and written (#41)
2026-10-11 trivial Omitted w:pPrDefault stays omitted across saves; explicit empty/default properties and later spacing edits remain writable. Synthetic preservation checks only; readiness estimates unchanged
2026-10-10 trivial OLE objects turned or flipped in WordCraft keep the turn on save (VML rotation/flip, DrawingML a:xfrm with the rotated effect extent); test counts refreshed
2026-10-11 trivial Section text direction read and written (#491)
2026-10-10 trivial Charts, SmartArt and OLE objects written back on save with their parts (#319); chart/SmartArt reading (#292) recorded
2026-10-10 trivial Footnote and endnote separators and continuation notices read and written (#352)
2026-10-11 trivial Enclosed characters (EQ \o\ac) read, drawn and written (#297)
2026-10-11 trivial Ruby (w:ruby) read and written (#288)
2026-10-10 trivial wrapText on square, tight and through wraps read and written (#354)
2026-10-10 trivial Wrap polygons for Tight and Through wrapping read and written (#354)
2026-10-10 trivial DrawingML rotation and flips read and written (#332)
2026-10-11 trivial Footnote and endnote options round-trip for the document and per section (#385)
2026-10-10 trivial Equation breaks and m:mathPr wrapping options round-trip (#326)
2026-10-10 trivial Custom table styles round-trip (#256 merged)
2026-10-10 major First version: Word's full format list, read/write status, DOCX element coverage from the source, fidelity and hours
2026-10-10 trivial Freeform shapes and ink as DrawingML custom geometry, read and written (#307)