DOCX

Comments and Revisions

Document comments, track changes, and structured document tags (content controls)

Comments

Add a comment with the comment child, placed inline next to the text it covers:

{
  "sections": [
    {
      "children": [
        {
          "paragraph": {
            "children": [
              "This text is ",
              {
                "comment": {
                  "author": "Author Name",
                  "initials": "AN",
                  "children": ["Please review this section."],
                  "wrap": [{ "text": "commented" }]
                }
              },
              "."
            ]
          }
        }
      ]
    }
  ]
}

children is the comment reply (stored in the comments part — any paragraph content); wrap is the anchored document text the comment range covers (inline runs/text).

PropertyTypeDescription
authorstringComment author (defaults to empty)
initialsstringAuthor initials
dateDate | stringCreation date (defaults to now)
children(string | ParagraphOptions)[]Comment reply content
wrap(string | RunOptions)[]Anchored text the range wraps

Explicit markers (advanced)

For ranges that span paragraphs or tables, or to continue ids from an existing document, author the markers explicitly. The commentRangeStart, commentRangeEnd, and commentReference must share one id, which must also match a comments entry:

import { generateDocument } from "@office-open/docx";

await generateDocument({
  comments: {
    children: [
      {
        id: 0,
        author: "Author Name",
        date: new Date(),
        children: ["Please review this section."],
      },
    ],
  },
  sections: [
    {
      children: [
        {
          paragraph: {
            children: [
              { commentRangeStart: { id: 0 } },
              "This text has a comment attached.",
              { commentRangeEnd: { id: 0 } },
              { commentReference: 0 },
            ],
          },
        },
      ],
    },
  ],
});

Track Revisions

Track insertions, deletions, and moves in documents:

{
  "sections": [
    {
      "children": [
        {
          "paragraph": {
            "children": [
              "Original text, ",
              {
                "insertion": {
                  "id": 0,
                  "author": "Author",
                  "date": "2024-01-15T10:30:00Z",
                  "text": "inserted text"
                }
              },
              ", and ",
              {
                "deletion": {
                  "id": 1,
                  "author": "Author",
                  "date": "2024-01-15T10:30:00Z",
                  "text": "deleted text"
                }
              },
              "."
            ]
          }
        }
      ]
    }
  ]
}

Move Revisions

Track moved content with the moveFrom (source) and moveTo (destination) children. The moveFrom and moveTo of one logical move must share a name so Word links them:

{
  "sections": [
    {
      "children": [
        {
          "paragraph": {
            "children": [
              "This paragraph had text moved ",
              {
                "moveFrom": {
                  "name": "my-move",
                  "author": "Author",
                  "date": "2024-01-15T10:30:00Z",
                  "wrap": [{ "text": "moved text" }]
                }
              },
              "."
            ]
          }
        },
        {
          "paragraph": {
            "children": [
              "And it appeared here: ",
              {
                "moveTo": {
                  "name": "my-move",
                  "author": "Author",
                  "date": "2024-01-15T10:30:00Z",
                  "wrap": [{ "text": "moved text" }]
                }
              },
              "."
            ]
          }
        }
      ]
    }
  ]
}

wrap is the moved content carried by the move run (inline runs/text). author and date apply to both the range start and the move run.

PropertyTypeDescription
namestringMove name — share it across the from/to pair
authorstringAuthor of the move
datestringISO 8601 timestamp of the move
wrap(string | RunOptions)[]Moved content carried by the move run
colFirstnumberFirst column of a table-cell scope
colLastnumberLast column of a table-cell scope
displacedByCustomXml"before" | "after"Displacement vs. a sibling customXml

Explicit markers (advanced)

Author the range markers and move runs separately when you need cross-paragraph ranges, explicit id continuation, or independent placement. moveFromRangeStart/moveFromRangeEnd mark the source, moveToRangeStart/moveToRangeEnd the destination; movedFrom/movedTo carry the moved text as tracked-change runs:

import { generateDocument } from "@office-open/docx";

await generateDocument({
  sections: [
    {
      children: [
        {
          paragraph: {
            children: [
              {
                moveFromRangeStart: {
                  id: 0,
                  name: "my-move",
                  author: "Author",
                  date: "2024-01-15T10:30:00Z",
                },
              },
              {
                movedFrom: {
                  id: 1,
                  author: "Author",
                  date: "2024-01-15T10:30:00Z",
                  children: ["moved text"],
                },
              },
              { moveFromRangeEnd: { id: 0 } },
            ],
          },
        },
        {
          paragraph: {
            children: [
              {
                moveToRangeStart: {
                  id: 2,
                  name: "my-move",
                  author: "Author",
                  date: "2024-01-15T10:30:00Z",
                },
              },
              {
                movedTo: {
                  id: 3,
                  author: "Author",
                  date: "2024-01-15T10:30:00Z",
                  children: ["moved text"],
                },
              },
              { moveToRangeEnd: { id: 2 } },
            ],
          },
        },
      ],
    },
  ],
});

Range starts accept id (required) plus name, author, date, and table-column scope (colFirst/colLast); range ends take just { id }.

Structured Document Tags (Content Controls)

Use SDT to create editable regions and form controls:

{
  "sections": [
    {
      "children": [
        {
          "sdt": {
            "properties": { "alias": "FullName", "tag": "full-name", "richText": true },
            "children": [{ "paragraph": { "children": ["John Doe"] } }]
          }
        },
        {
          "sdt": {
            "properties": {
              "alias": "Color",
              "tag": "combo-color",
              "comboBox": {
                "items": [
                  { "displayText": "Red", "value": "red" },
                  { "displayText": "Blue", "value": "blue" }
                ],
                "lastValue": "Red"
              }
            },
            "children": [{ "paragraph": { "children": ["Red"] } }]
          }
        }
      ]
    }
  ]
}

SDTs support various control types for forms, templates, and document automation.

Document Protection

Restrict editing on the document using settings:

{
  "features": {
    "updateFields": true,
    "documentProtection": {
      "edit": "readOnly",
      "password": "123"
    }
  },
  "sections": [
    {
      "children": [{ "paragraph": { "children": ["Protected document content."] } }]
    }
  ]
}

Protection types: "readOnly", "comments", "trackedChanges", "forms".

When password is provided, a SHA-512 hash with random salt and 100,000 iterations is computed automatically. You can also provide pre-computed hash values directly.

OptionTypeDescription
editstringProtection type
passwordstringPlaintext password (auto-hashed)
algorithmNamestringHash algorithm (e.g. "SHA-512")
hashValuestringBase64-encoded password hash
saltValuestringBase64-encoded salt
spinCountnumberNumber of hash iterations
formattingbooleanRestrict formatting
hashstringLegacy password hash (w:hash)
saltstringLegacy password salt (w:salt)
cryptoAlgorithmClassstringCryptographic algorithm class
cryptoAlgorithmSidnumberCryptographic algorithm SID
cryptoAlgorithmTypestringCryptographic algorithm type
cryptoProviderstringCryptographic provider
cryptoProviderTypestringCryptographic provider type
cryptoProviderTypeExtensionnumberProvider type extension
cryptoProviderTypeExtensionSourcestringProvider type extension source
algorithmExtensionIdnumberAlgorithm extension ID
algorithmExtensionSourcestringAlgorithm extension source
cryptoSpinCountnumberLegacy cryptographic spin count

Track Changes Options

When using insertion and deletion objects:

OptionTypeDescription
idnumberRevision ID
authorstringAuthor name for the revision
datestringISO 8601 timestamp

Both also accept all text run properties (text, bold, italic, color, etc.).

Copyright © 2026