docx-editor

Comments and notes

Write, edit, resolve and read comment threads, and insert, edit and read footnotes and endnotes.

Everything on this page comes from @portone/docx-editor/commands.

Comment commands

CommandWhat it does
addComment(comment, at?)Adds a comment to a stretch of text: the one named, or the current selection.
canAddComment(state, at?)Whether that stretch, or the current selection, can receive one.
updateComment(id, text)Replaces a comment's text and keeps its formatting.
setCommentBody(id, body)Replaces a comment's body with a formatted one.
removeComment(id)Deletes a comment and its replies.
addCommentReply(id, reply)Adds a reply and reopens the thread when it was resolved.
updateCommentReply(commentId, replyId, text)Replaces a reply's text.
removeCommentReply(commentId, replyId)Deletes one reply.
setCommentResolved(id, resolved)Marks a thread resolved or open.
selectComment(id)Selects the commented text and scrolls it into view; for a detached comment, puts the caret at its reference.

NewComment is { text, author, authorId?, initials?, date? }, where date is an ISO 8601 instant defaulting to now, kept to the second. The saved file records it the way Word does: the instant, and on the comment the time it reads on the clock of the runtime that adds it, which is the author's clock only when the author runs the editor. Pass author (the display name), initials, and authorId from mode.author, so the comment is recorded as that person's.

Comment records

documentComments(state) returns every comment in document order as a DocumentComment:

FieldWhat it holds
idThe comment's id, which every other command takes.
author, authorId, initialsWho wrote it, as the document records them. Null where the document names none.
dateWhen it was written, as an ISO 8601 instant in UTC such as 2026-09-30T06:00:00.000Z. A value that is not a readable date is returned as written. Null where the document names none.
textThe body as plain text.
from, toThe stretch it marks.
referencePosWhere its reference stands in the document.
anchoredWhether it still marks a stretch of text. false once the commented text was deleted; from and to then equal the reference position.
resolvedWhether the thread is resolved.
repliesIts replies, each a DocumentCommentReply with id, author, authorId, initials, date, and text.

A comment added with date reads the same instant back. When a comment was written says which instant a comment from another file reads as. The records are read-only; copy one to change it. Features describes what the built-in panel does with detached and resolved comments.

Formatted bodies

setCommentBody takes a doc node of docxSchema, so a composer of your own can write a bold run, a paragraph style, or a second paragraph:

import { docxSchema } from "@portone/docx-editor";
import { setCommentBody } from "@portone/docx-editor/commands";

const body = docxSchema.nodes.doc.create(null, [
  docxSchema.nodes.paragraph.create(null, [
    docxSchema.text("Please check", [
      docxSchema.marks.run.create({ rPr: "<w:rPr><w:b/></w:rPr>" }),
    ]),
  ]),
  docxSchema.nodes.paragraph.create(null, docxSchema.text("the second line.")),
]);

setCommentBody(comment.id, body)(view.state, view.dispatch);

It answers false for a body that is not a doc node, one that is only whitespace, or an unknown id. updateComment and updateCommentReply answer false when the text is unchanged.

Commenting on a range

addComment and canAddComment take an optional { from, to }; the range must be a non-empty span inside one paragraph, or the command returns false. A composer that stays open while the document is edited should keep the range it opened over, map it through transaction.mapping on every change, and pass it on submit.

Who may edit a comment

canEditComment(state, commentId, replyId?) answers whether the current author may edit or delete a comment or reply:

  • A comment with a recorded identity belongs to that author; an edit by anyone else is refused.
  • A comment with no recorded identity belongs to everyone.
  • Re-anchoring a comment onto other text counts as editing it.
  • A comment's author never changes after it is written.
  • mode.editableComments: "all" opens every comment to the current author.
  • Replying, resolving, and reopening are open to everyone under comment and edit.
  • Deleting a root comment deletes its replies, whoever wrote them.

A server checks the same rules with onlyCommentsChangedBy.

Footnotes and endnotes

documentNotes(state) returns the footnotes and endnotes the document references, in first-reference order, each a read-only DocumentNote with kind ("footnote" or "endnote"), id, label (as drawn, in the document's number format), text, and referencePos. label is empty for a reference whose own mark follows it in the text, such as a dagger the document wrote itself.

Each kind of note has its own four commands:

CommandWhat it does
insertFootnotePuts a footnote reference at the end of the selection, calling a new, empty footnote, and opens that footnote for editing.
canInsertFootnote(state)Whether a footnote can go in at the end of the selection.
openFootnote(id)Puts the caret just after the footnote's reference and opens the footnote for editing, which is what clicking its number runs.
setFootnoteBody(id, body)Replaces a footnote's body with a doc node of docxSchema, as setCommentBody does for a comment.
insertEndnoteThe same for an endnote, which is drawn after the last paragraph rather than at the foot of a page.
canInsertEndnote(state)Whether an endnote can go in at the end of the selection.
openEndnote(id)Puts the caret just after the endnote's reference, opens the endnote, and scrolls to it at the end of the document.
setEndnoteBody(id, body)Replaces an endnote's body with a doc node of docxSchema.

A new note is written in the document's FootnoteText or EndnoteText paragraph style with its number in the FootnoteReference or EndnoteReference character style where the document defines them, and in superscript where it does not. The insert and body commands do not apply under the readOnly and comment modes or where the reference stands in locked content. A body command also answers false for an id no reference in the text names, for a separator entry, and for a body that says what the note already says. It writes the body as handed and adds no reference mark, so a body that does not open with the note's own w:footnoteRef or w:endnoteRef mark opens in Word without the note's number.

openFootnote and openEndnote apply under every mode, since opening a note is reading it, and answer false only for an id no reference in the text names or a separator entry; a note opened where the body is shut takes no typing.

There is no delete command: a transaction that deletes the last reference to a note deletes the note with it, so one undo brings both back, and one that copies a reference gives the copy a new id and a copy of the note.

On this page