Word snapshot format
A Word snapshot is UTF-8 text with LF line endings, saved as {name}.verified.docx.txt. It reads like the document:
one line per paragraph with its runs merged, and only what differs from its style listed.
# docx-snapshot v1
document
metadata title="Trail notes" created=yes modified=yes
settings lang=en-US compat=15 track-changes=no protection=none even-odd-headers=no
defaults font="Calibri" size=11
sections
s1 letter margins=72,72,72,72 header=36 footer=36 columns=1 break=nextPage headers=[default]
styles
ListParagraph paragraph "List Paragraph" font="Arial" size=12 indent-left=36
TableGrid table "Table Grid" font="Calibri" size=11
numbering
list 1 definition=1
level 0 format=decimal text="%1." start=1 indent=36 hanging=18
body
P style=ListParagraph list=1:0 label="1." "Bring a trail map"
span "trail" bold
Table style=TableGrid widths=[144,216]
Row header
Cell
P "Trail"
Cell
P "Length"
P "Visit example.com"
link "example.com" target="https://example.com" at=6
P
image inline size=120x40 alt=(missing) type=png hash=3f9c0a1b2d4e5f60 at=0
headers
s1 default
P "Page 3"
field "PAGE" result="3" at=5
footers
(none)
notes
(none)
Sections
Sections always appear in this order. Each can be left out with DocxSection.
| Section | Contents |
|---|---|
document |
A metadata line with the file's title, subject, author, keywords, description, category, company and attached template, each only when set, and whether created and modified dates are present (created=yes); a property "Name" value="..." line for each custom property, sorted by name; a settings line with the language, the default East Asian and complex-script languages and fonts, compatibility mode, whether changes are tracked, protection and even and odd headers, with other= for the rest, such as hyphenation, the default tab stop, mirrored margins, footnote numbering, compatibility options and equation settings; a defaults line with what the document defaults (w:docDefaults) give text and paragraphs before any style, such as the font, size and spacing, with other= for the rest; parts that couldn't be read |
sections |
One line per section (s1, s2, ...): page size, margins, header and footer distances, columns, section break, page numbering, title page, which headers and footers it has; a tracked change to its settings |
styles |
The styles the document uses, with their properties resolved through the styles they're based on. A style's languages, and its East Asian and complex-script fonts, print only when they aren't the ones on the settings line. An inserted Word document's styles are compared with that line too, so one in another language prints lang= on its styles |
numbering |
The lists the document uses, and each level's format, text, start and indents, with other= for what else it sets, such as the label's size, color or bold, its alignment, what follows it and a picture bullet's image. Lists, and the definitions they number from, are numbered from 1 in the order the snapshot first uses them, not by their ids in the file, which Word changes when it saves a file again |
body |
Paragraphs, tables, content controls and inserted documents, in reading order |
headers, footers |
Each section's headers and footers, by kind (default, first, even) |
notes |
Footnotes, endnotes and comments, with their content. Each kind is numbered from 1 in the order the snapshot first refers to them, with the ones nothing refers to last |
checks |
Only with Check(DocxCheckSet): what the checks find, one line per finding with its rule and path (ImageAltText body > P[3] > image), by rule in the order the rules are declared, then in snapshot order, or (none) |
Body lines
| Line | Means |
|---|---|
P ... "text" |
A paragraph: its style, list item and label, layout that differs from its style (such as align=, indent-left=, rtl-paragraph, borders= or shading=), then its text. When the text is in a complex script but the style isn't right to left, the style's complex-script bold, italic and size print here where they differ from the Latin ones (bold-complex=no), since the style line has no text to show whether they apply |
span "text" ... |
Part of the paragraph whose formatting differs from the paragraph's, such as bold, font=, hidden (text Word doesn't show or print), double-strike, rtl (right to left) or lang=fr-FR. A span that covers all of the paragraph's text leaves the text out (span bold). East Asian and complex-script text has its own language and font (lang-east-asian=, lang-complex=, font-east-asian=, font-complex=); complex-script means the whole run takes the complex-script formatting. On right-to-left or complex-script text, complex-script bold, italic and size print where they differ from the Latin ones (bold-complex=no, size-complex=14) |
Table ... |
A table: style, grid widths, width, cell margins, borders, and its alt text (caption=, description=) |
Row / Row header |
A table row; a header row repeats on each page. Its height (height=20, height=20-exact or height=auto) and split=no when it's kept on one page |
Cell ... |
A cell: span, merge, shading, width, margins, borders, vertical alignment (valign=), text direction (text-direction=) |
Control <kind> ... |
A content control, with its tag (name=) and title. Under a cell, around marks one around the cell |
Inserted <kind> |
An inserted document (w:altChunk); a DOCX is read in place, with its own defaults line (its languages, and its East Asian and complex-script fonts, only where they differ from the outer document's), styles, numbering, body and notes; other formats are kept by hash |
bookmark "Name" |
A bookmark between blocks, rows or cells; columns=0-2 for a table-column bookmark |
unsupported <element> hash=... |
Something PDiffy doesn't read yet, kept by hash so a change to it still shows |
ends-section s1 |
The paragraph that ends a section |
Lines inside a paragraph
Each ends with at=N, the position in the paragraph's text where it sits, counted in code points, so a character
outside the Basic Multilingual Plane, such as an emoji, counts as one.
| Line | Means |
|---|---|
link "text" target="..." |
A hyperlink and where it goes: a web address, or # and a bookmark's name |
field "CODE" result="..." |
A field, such as PAGE, and the result Word last computed. A field nested in another's code shows there in braces, as in field "= {PAGE} - 2", and gets its own line after it |
image, chart, shape, object, control, ... |
A picture, other graphic, embedded object or ActiveX control: inline or floating, size, alt text, type, and a hash of its data as the file stores it |
math "text" hash=... |
An equation |
symbol font=... code=... |
A character from a symbol font |
break page / break column |
A page or column break |
form <kind> ... |
A form control: name, title, value, choices (options=["Ohio","Texas"]) |
note footnote 1, comment 1 |
Where a note or comment is attached, numbered as in the notes section |
bookmark "Name" |
A bookmark |
insert, delete, move-to, move-from, format "text" |
A tracked change to text, with its author |
paragraph-insert, paragraph-format, ... |
A tracked change to the paragraph itself |
stray-text "text" |
Text in a place Word may drop or move it |
unsupported <element> hash=... |
Something PDiffy doesn't read yet |
Tables, rows and cells list their own tracked changes (table-format, row-insert, cell-delete and so on) under
their line. See DocxRevisionKind for every kind.
Rules
- When anything is ignored, the next lines list it:
# ignored sections: ...and# ignored fields: ....Checkadds# checks: ...with the rule set and how many rules it has, such as# checks: latest, 4 rules. - An empty section prints
(none)and an ignored one prints(ignored). - Lengths are in points. Colors print as
#rrggbb(color=#2f5496), andautois Word's automatic color. - A list that can hold any number of items prints in brackets (
widths=[144,216],tabs=[start:72],borders=[top:single:0.5]); a fixed set, such as a section's four margins, prints with commas alone. - Alignment and tab stops say
startandend(align=end,tabs=[start:72]). Older files sayleftandright, and Word reads both as the side a line starts or ends on, sostartis the right side in right-to-left text. - Text is quoted and normalized to Unicode NFC, so a letter typed with a separate accent prints as one letter.
"and\are escaped, a tab and a line break print as\tand\n, and characters a reader can't see or tell apart print as\uXXXX: control and format characters (such as the soft hyphen and zero-width and direction marks), private-use characters, line and paragraph separators, spaces other than U+0020 (such as a no-break space), U+FFFD to U+FFFF and variation selectors. other=is a hash of the formatting PDiffy doesn't read, such as character spacing or a table's indent, on a style, span, paragraph, table, row, cell, section, list level,settingsordefaultsline, so a change to it still shows. Only the line's own properties count, not what it inherits. A style's hash covers its table, row and cell properties and a table style's formatting for header rows, banding and so on (w:tblStylePr); a row's covers its table exceptions (w:tblPrEx). For a property PDiffy reads part of, such asw:spacing, the hash still covers the attributes PDiffy doesn't print, such as automatic spacing or an underline's color, apart from defaults Word writes everywhere: aclearshading pattern, anautoshading color, a border space of 0, a cell margin in twentieths of a point (dxa), a page size's paper code, an orientation that matches the page's size, a gap between columns when there's only one, and a font for other Latin characters (w:hAnsi) that's the same as the ASCII one. Noise Word writes into nearly every document is left out: proofing and web-view marks, a document grid with no type or thedefaulttype, conditional-format markers, a paragraph mark's own formatting and later Word versions' extensions (w14:and so on). The paragraph mark's formatting does count in a list item, where it formats the label, and in an empty paragraph, where it sets the line's height. Settings Word rewrites on every save or takes from the computer's region are left out too, such as editing-session IDs, the zoom, the proofing state and the list separator.- A color set from the theme (
w:themeColor,w:themeFill) is read as the theme's color after the settings' color mapping and its tint or shade are applied, whether it prints or counts inother=, so changing the theme's colors changes the snapshot. Word's own copy of the color, written next to it, is used only when the theme doesn't have the color. - Word's own theme leaves its East Asian and complex-script fonts empty and picks one by language, so a theme font
the theme leaves empty prints as its theme name, such as
font-east-asian="minorEastAsia". - Relationship IDs, editing-session IDs, the zip's layout and styles nothing uses are left out, so regenerating the same document gives the same snapshot.
Damaged files
A part that can't be read is treated as missing. It prints an unreadable line in the document section with a hash of
its bytes, such as unreadable word/styles.xml hash=3f9c0a1b2d4e5f60, so a change to it still fails the test. A part is
unreadable when it isn't well-formed XML, has a DTD, nests elements more than 256 deep (an inserted document's nesting
counts from where it's inserted) or is larger than 256 MB. An inserted document that can't be read is marked where it's
inserted instead: Inserted docx unreadable. A file whose body can't be read throws.