Skip to content

Releases: portone-io/docx-editor

@portone/docx-editor@0.6.0

Choose a tag to compare

@github-actions github-actions released this 10 Sep 07:00
Immutable release. Only release title and notes can be modified.
c87a881

Minor Changes

  • #131 5dd468a Thanks @Deea222! - A comment now outlives the text it was written for, and a resolved one stops marking the page.

    Deleting commented text used to delete the comment and everything said under it. The thread now
    stays. Trim the highlighted text - type over part of it, backspace through its edge - and the
    comment follows what is left. Delete all of it and the comment comes back detached: no longer drawn
    beside the page, since there is nothing to draw it next to, and listed under All comments marked
    "Original content deleted". Cutting commented text leaves it behind the same way instead of dropping
    it. Word has no detached state, so such a comment reaches the saved file as an ordinary comment
    sitting where the deleted text was. Deleting a comment from its own Delete button still deletes it,
    and undo and redo still take a deletion back and make it again.

    Resolving a thread now takes its highlight off the text, and reopening puts it back. Clicking a
    resolved comment's card in All comments selects the text it was written about and scrolls it into
    view, which selectComment now does for every caller.

    documentComments reports a new anchored field on every comment, false for one that no longer
    marks a stretch of the document. Its existing fields are unchanged, so a panel of your own keeps
    working and can read the new field to decide what a click on a card should do.

@portone/docx-editor@0.5.1

Choose a tag to compare

@github-actions github-actions released this 09 Sep 06:54
Immutable release. Only release title and notes can be modified.
f6bb0d2

Patch Changes

  • #125 88ff33a Thanks @Deea222! - Pasting from Word, Google Docs or LibreOffice now keeps tables as tables and Word lists as lists.

    A table on the clipboard used to arrive as a single paragraph holding the text of every cell run
    together. It now arrives as a table: one paragraph for each block a cell held, the columns and rows
    a cell reached across kept, and the same width and lines a table inserted here has.

    Word writes list items as ordinary paragraphs that name the list they belong to and draw their own
    bullet or number, so pasting one used to give unnumbered paragraphs each beginning with a stray
    marker. The items of one Word list now join one list, at the level Word gives them, counted when
    the marker Word drew counts.

    A table's caption is kept as the paragraph above it, a table inside a list item is read as a table
    rather than as the item's own text, and a table too large for the editor to hold is read as one
    paragraph per row instead of as a single run-on one.

    A copy wrapped in a single element, which is how Google Docs writes one, no longer has its
    paragraphs pressed into one.

  • #123 3d6b0a5 Thanks @Deea222! - Copied HTML and text now follow one declared outbound shape per node and mark, so what leaves the editor is decided beside the schema rather than filtered out of the page's own drawing afterwards. A copy pasted into another application carries paragraphs, styles, runs, links, images at the size they were drawn, and tables as tables, and none of the document's internals. A comment marker, a bookmark, and the placeholder standing for content the editor could not model now leave nothing behind them, where before they left an element carrying the editor's own name for what stood there.

    Copied plain text reads as the page does. A table pasted into a spreadsheet keeps one row per row, with everything a cell holds on the one line that cell stands on, and a block the editor only kept no longer opens a blank line where it stood. A kept line break and a kept character, such as a no-break hyphen, travel with the text they stand in, and so does the text a placeholder draws: a field's cached result and the words of a tracked insertion read in a copy as they read on the page.

  • #124 936b2a0 Thanks @Deea222! - Hyperlinks that hold content controls, and nested controls, open as editable text.

    Only one of the arrangements used to be readable - a control holding a link. A link holding a
    control, or a control holding a control, brought the inner one in as a small box naming the element
    it stood for, and the text it held could not be typed in. Any depth and any order of the two is now
    ordinary text wearing a wrapper each, and goes back out nested as it came. A hyperlink inside a
    hyperlink is the one arrangement still kept whole, since a link marks the text it covers once.

    A link made on text inside a control is written inside that control, and a lock put on a stretch
    that sits wholly inside a link is written inside that link, instead of either wrapper being split
    around the other. Where a control holds a control, locking shuts the outer one and lifting a lock
    opens the inner one the selection stands in.

    Plugins reading the drawn page will find data-key and data-depth on a control and a link in
    place of data-sdt-key and data-link-key.

@portone/docx-editor@0.5.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 18:28
Immutable release. Only release title and notes can be modified.
1257a73

Minor Changes

  • #105 efe7dbf Thanks @Deea222! - Keep markup the editor cannot model where it stood, instead of standing the paragraph around it down.

    Opening a document used to walk a handful of element names and give up on the rest, and giving up
    travelled outward until a whole paragraph became an "Unsupported content" placeholder. A word
    processor writes a w:lastRenderedPageBreak on every page it lays out, so a real document opened
    with one locked paragraph per page.

    Every level of the document now has a preservation rule of its own. A run child stays inside its
    run, a paragraph child beside the runs, a block stays a block, and only a marker or a wrapper
    standing between the rows or the cells of a table - where there is no node to keep it in - still
    stands the table down. What is left shows as a small box naming the element it stands for, or as
    nothing where the file drew nothing, and the paragraph around it stays editable.

    • A field code and its drawn result, a tracked insertion or deletion, a symbol, a positional tab
      and a content control the editor could not take apart are visible where they stand.
    • Bookmarks, permission ranges, the markers of a moved passage and the pieces of a field cannot be
      removed by an edit; a tracked-change container, a simple field and a symbol can be selected and
      deleted whole.
    • documentFidelity and the notes of importDocx now report preserved-run-content, and no
      longer report paragraph-demoted for a document being opened.
    • New node rawRunContent, and rawInline gains the attrs element, display, text and
      guarded. A plugin reading the document model sees both.
    • A footnote body, a comment body and a header now read a w:cr and a w:noBreakHyphen the way
      the document body does.
  • #106 f2871cd Thanks @Deea222! - The comment composer keeps the text it was opened over while the document is edited elsewhere, and closes when that text is deleted or the mode turns read-only. The comment is written on that text rather than on whatever is selected when the writer submits.

    Opening the composer no longer scrolls the document back to its first page.

    addComment and canAddComment take an optional { from, to } range as their last argument, which a composer of your own can hold across edits the same way; the current selection is still used when none is given.

  • #116 4d9964d Thanks @Deea222! - Comment bodies keep their formatting when edited, and setCommentBody accepts a formatted body.

    Breaking: the commentReference node loses its text, commentXml and imported attrs and
    the noteReference node loses its text attr, together with the data-comment-text,
    data-comment-xml, data-comment-imported and data-note-text attributes that carried them into
    the DOM. A plugin that matched any of those reads what a comment or a note says through
    documentComments and documentNotes instead, which answer as they always did.

    Breaking: DocumentComment, DocumentCommentReply and DocumentNote declare every field
    readonly. They are the editor's own records, worked out once per edit and handed out rather than
    copied, so a caller that was writing into one copies it first.

    A side story - a comment's body, a footnote's - is now read the way the document body is: the same
    block readers, the same verbatim slices, one document of the editor's own schema per story. It
    stands on the document node under doc.attrs.stories, so an edit to it rides a transaction and
    lands in the history, and everything the edit did not touch is written back as the bytes it arrived
    as. Editing a comment used to flatten its body to plain text and rewrite it as one run, which lost
    its bold, its paragraph style and its second paragraph.

    setCommentBody(id, body) is a new command on ./commands. It takes a doc node of docxSchema,
    which is what a composer of your own builds a formatted body as; updateComment(id, text) stays
    what it was for a body that is only text.

    Dropping those attrs is what the story replaces them with: what a comment or a note says is no
    longer written on the node marking where it stands, so nothing has to keep the two in step, a copy
    of the node no longer carries the body along with it, and neither reaches the clipboard.

  • #108 d783e24 Thanks @Deea222! - Keep a table whose markers stand between its rows or its cells, and stand every block the editor
    cannot model as one kind of placeholder.

    Breaking: the docxRaw and bookmarkBlock node types no longer exist. Both were placeholders
    for a block nobody could read, differing only in where the block stood and whether anything of it
    was drawn, and rawBlock is now the one node for all of them. A plugin that matched either name
    matches rawBlock instead and reads display ("chip" for a placeholder box, "hidden" for a
    marker that draws nothing) and guarded to tell them apart. The class names
    docx-editor-bookmark-block, docx-editor-raw-xml and docx-editor-table are gone with them;
    every placeholder now draws as docx-editor-raw-block.

    • A bookmark spanning a table column stands under the row rather than inside a cell, and used to
      cost the whole table its structure. Such a table now opens as a table, and the marker goes back
      exactly where it stood. A marker following a cell that only continues a vertical merge is the
      remaining exception, since that cell is created fresh on export.
    • documentFidelity and the notes of importDocx no longer report table-demoted for a table
      whose only unread markup is a marker.
    • A placeholder can now be moved between the body and a table cell and still export.
    • table and tableRow gain a leadingXml attr, tableRow and tableCell a trailingXml attr:
      the markers each carries between its children.

    Table markers remain protected against deletion, duplication and reordering, including markers
    whose ranges cross into a cell paragraph. Export checks read those fragments in document order.

Patch Changes

  • #109 05e9431 Thanks @Deea222! - Cache comment and note lists between document edits. Public readers continue to return independent comment, reply, and note records, so changes to their results cannot alter the editor's cached data.

  • #118 7de8870 Thanks @Deea222! - Every section now previews the headers and footers it names. A document whose second section
    selects a header of its own used to draw the first section's on every page, because only the first
    section's references were ever resolved.

    A header and a footer body is read the way the document body is: the same block readers, the same
    verbatim slices, one story per part on the document node beside the comment and footnote stories.
    The plain-text walker each of them used to have is gone, so a w:cr, a no-break hyphen and a field
    read the same in a header as they do anywhere else, and a PAGE or NUMPAGES field is now found by
    pairing the field characters it is written between rather than by scanning the text they surround.

    A header story the editor rewrote is written back into its own part, around the two ends that part
    arrived with, and every part nobody rewrote is repacked as the bytes it came as. Editing a header is
    not offered in the editor yet; this is the model and the export path underneath it.

  • #115 9c5331d Thanks @Deea222! - Copying and pasting inside the same document now keeps what it was copied as: paragraph and character formatting, tabs, breaks, images, links, and whole tables, instead of the part an HTML reader could make out. Copying a grid of cells and pasting it over selected cells fills them in place. Comment markers, bookmarks, and note references are not copied, so cutting and pasting them back drops them. A pasted list whose numbering the document no longer defines is given a number that it does, keeping the bullets or numbers it was copied with; a list arriving from another document or application is renumbered by the reader that reads it. Content copied from another document, including a second editor on the same page, still comes in through that reader.

  • #119 9b4b3fc Thanks @Deea222! - Page boundaries and table widths now follow the paper of the section a block sits in. A document
    whose second section is landscape used to be paginated as though the whole of it were the first
    section's portrait paper, and a table put in that section was...

Read more

@portone/docx-editor@0.4.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 05:28
Immutable release. Only release title and notes can be modified.
63b52c0

Minor Changes

  • #102 4258530 Thanks @Deea222! - Draw the table styles and list numbering a document defines, and let a document that never held a list take one.

    A table style is now displayed part by part: the header row, the closing row, the first and last column, the corners and the banded rows take the shading, the lines and the text formatting the style dresses them with (w:tblStylePr), and w:tblLook decides which of those parts a table takes.
    The bands are as many rows or columns wide as the style says (w:tblStyleRowBandSize, w:tblStyleColBandSize), and the header row and the closing row are not banded with the rest.
    Text already in a cell follows its new position after a row edit, and the conditional-formatting markup a document arrived with goes back out untouched.

    A list that takes its numbers from a numbering style now draws them.
    Such a list holds no numbers of its own: it names a style (w:numStyleLink), the style names a list, and that list's definition is where the numbers are, which is how Word writes a list built from its gallery.
    Alongside decimal, bullets, upper and lower letters and lower Roman numerals, a list may now count in upper Roman numerals, decimal numbers with a leading zero, Ganada, Korean digits and the Chinese counting system; a format past those is still shown with decimal numbers.
    Each level is drawn the way it asks to be: where its counting starts over (w:lvlRestart), whether the numbers in its text are all spelled as decimals (w:isLgl), what stands between its number and the paragraph text (w:suff), and where the number sits in the room kept for it (w:lvlJc).
    A marker is also drawn in the character formatting its own level writes down (lvl/rPr), so bold, italic, color, size and typeface reach the number and never the text of the paragraph it stands in front of.
    All of this is read; the numbering part goes back out exactly as it arrived.

    A new list no longer needs the document to have arrived with a numbering part.
    The export writes word/numbering.xml, relates it from the main part and declares it in the content types, so a document that never held a list can take one; the list commands, which used to report that they did not apply in such a document, now do.
    If an existing numbering relationship points to a missing part, the new definition is written at that location so the document can find the list when it is reopened.

    A new or pasted list is exported with the definition it was started with, rather than a format inferred from its numbering IDs, and undo restores that registration along with the edit.
    A list whose definition is missing or unsupported is refused as unsupported-content, and a package with no [Content_Types].xml for the new numbering part to be declared in is refused as missing-content-types; exportProblems reports either ahead of the write.
    List and abstract definition IDs stay distinct in a document already using the largest safely representable integer, and a value that cannot be written faithfully is rejected rather than silently changed or discarded.

    An ECMA-376 Strict package is refused with the new unsupported-conformance code, and a document whose main part root does not bind w to Transitional WordprocessingML is refused as unsupported-content.
    Word saves neither by default, and both used to open far enough to fail later and obscurely: a Strict package as missing-part, and a document under another prefix as a malformed-xml about bookmarks on its first edit.
    A write needing a prefix already bound to a different namespace is refused instead of silently giving new markup the wrong meaning, and a new hyperlink relationship attribute is checked for a declaration that shadows the root binding.
    The comment and hyperlink writers now have the part's root declare the prefix they write under rather than declaring it on every element written, and editing an existing numbering or comment extension part that uses another prefix adds the writer's declaration at the root, so an untouched document still exports byte for byte and the exported XML stays readable.

    DocxImportErrorCode gains unsupported-conformance.
    DocxExportErrorCode loses missing-numbering-part, since nothing can reach it any more, and that is a compile error for a switch over the code written to be exhaustive; drop the branch.
    missing-content-types now also covers the numbering part a new list is defined in.
    On ./core, Numbering gains added, and the new NewList and NewListLevel types describe the definitions the editor registered.
    Level maps are read-only, and a registered definition carries a restart, legal numbering and a suffix, while marker run formatting and custom tab stops stay outside what can be registered.

Patch Changes

  • #101 1b6c723 Thanks @Deea222! - Stop drawing the page number on the corner of each page.

    The page guides laid a small grey number inside the top right corner of every page, over the paper the text sits on.
    It is gone, and the guides now draw the gaps between pages and the header and footer stories alone.
    A document that prints its own page number through a PAGE field in a header or footer is unaffected: that number is the document's, not the editor's.

    The docx-editor-page-badge class the number carried is no longer emitted, so a rule of your own written against it in the published stylesheet no longer matches anything.

@portone/docx-editor@0.3.0

Choose a tag to compare

@github-actions github-actions released this 07 Sep 21:28
Immutable release. Only release title and notes can be modified.
6958dc5

Minor Changes

  • #62 5c481e7 Thanks @Deea222! - onlyCommentsChangedBy answers comment-markup-rejected where it used to answer part-changed for a comment part entry this editor would not have written for this author, or an entry nothing refers to that changed. part still names the comment part the entry sits in.

    The verdicts themselves are unchanged: every file accepted before is accepted now, and every file refused before is refused now. What moves is the name a server logs, so "a part this file was not supposed to touch" and "markup forged into a comment" no longer read alike. A switch over verdict.reason needs the new case.

  • #77 a0b5cc6 Thanks @Deea222! - Ask whether a document can be exported before trying.

    exportProblems(doc, session) on the core entry, and canExport(state) with documentExportProblems(state) on the commands entry, report known reasons the writer would refuse the document, in the order it would raise them: each under the code and with the message the DocxExportError would carry, and with its position where the problem stands in the document. exportDocx throws the first entry of the same list, so problems reported by the query are also refused by the write.

    The editor's handle answers the same list as exportProblems() beside exportBytes(), and downloadDocx asks it first and returns { status: "blocked", problems } instead of throwing. A refusal the list does not foresee, such as a node a plugin stripped of an attribute the writer needs, is still thrown. DownloadDocxResult gaining a fourth member is a compile error for a switch over status written to be exhaustive; add a blocked branch that shows the problems.

    A document whose comments part arrived as an empty element used to refuse its first comment with malformed-xml, since the writer looked for a closing tag the element does not have; the part is now opened for the entry, the way an empty extended comments part already was.

  • #63 1a4ec92 Thanks @Deea222! - Read what a document holds that this editor cannot model. importDocx returns a notes array alongside the document and the session, the new exportDocxReport returns the same list beside the bytes it writes, and the new documentFidelity(state) on ./commands answers the question about the document standing in an editor. A FidelityNote says how much of the original survived, what kind of content it was, the part and body block it came from, where in the document it stands, and the original element name, so a host can list what a file lost instead of guessing at it. Destructuring importDocx is unaffected.

    A table now carries its w:tblGridChange instead of losing it whenever the table is rebuilt. The grid is still written from the column widths, and the revision markup closes it where CT_TblGrid takes it. onlyCommentsChangedBy therefore catches a submission that lost a w:tblGridChange, where it used to accept one: a returned file that dropped it now answers body-changed rather than ok.

  • #79 70d4801 Thanks @Deea222! - Applying a paragraph style keeps the spacing the document defaults lay down, and formatting a style or the document defaults switch on can be switched off: the off is written into the run (w:b w:val="0") and drawn as off, where it used to be dropped and the style's value drawn again.

    Every display value a paragraph or a run carries is now resolved in the ECMA-376 §17.7.2 order by one resolver, whichever path built the paragraph: opening the document, applying a style, a paragraph edit, a paste, or typing into a fresh paragraph. A character style a run points at (w:rStyle) takes its place in that order, a hanging indent's implicit tab stop follows the indent actually drawn, and a document's w:noTabHangInd setting switches that stop off.

    RunFormat grows to say so: bold, italic, strike and smallCaps are boolean (false is a toggle the run switches off outright), and underline may be "none". A reader checking === true or a truthy value is unaffected.

    Supported character defaults now appear in the text and toolbar, so a default bold setting turns off with one press. Clearing a direct font size immediately restores the inherited paragraph or character style in the formatting controls.

  • #82 f804ba1 Thanks @Deea222! - A paragraph marked keep with next (w:keepNext), by its own properties or by its style, stays on the same page as the start of the block after it in the page guides, as it does in Word. A run of such paragraphs moves together with the first piece of the block the keeps end at; a run no page can hold is laid out as if no keep were set. The document is not changed: the mark is read, never written.

    ParagraphFormat grows keepNext?: boolean to say so, beside pageBreakBefore.

    An explicit off (w:keepNext w:val="0") overrides an inherited keep, so a paragraph can opt out of the keep imposed by its style.

  • #80 a37b4fe Thanks @Deea222! - Run formatting is read, written and compared through one property table, so the value a control reads, the XML an edit writes and the check that leaves text already in that state alone can no longer drift apart. The XML written is byte for byte what it was.

    RunFormat gains caps, doubleStrike and characterSpacingPt, read off a run's w:caps, w:dstrike and w:spacing. They reach the format attr a plugin reads; the editor does not draw or edit them yet.

    An underline setter now distinguishes underline kinds; the public underline toggle still turns any existing kind off.

  • #72 578e73e Thanks @Deea222! - srcId now names the block within the session it was opened in. A preserved block used to carry a bare index into the blocks of whichever document it was exported against, so a block moved or pasted in from another document pointed at this document's block of the same number and went out as that block's XML instead of its own. The attribute is now a string naming the document, the story and the place in it, and a block whose document is not the one being exported is refused with lost-original rather than written as something else.

    A plugin that read node.attrs.srcId as a number needs to change: it is a string, and the only thing to do with it is hand it back as it was found. Nothing else about the attribute is public, and no exported type or function signature changed.

  • #60 1b5d0fd Thanks @Deea222! - Hand importDocx, exportDocx, onlyCommentsChangedBy, documentNumbering and parseNumbering an xmlParser to read a document on a runtime that has no DOMParser global, instead of installing one.

    A call given neither is refused with DocxImportError and the new import code no-xml-parser. It used to fail with a bare ReferenceError, which a server checking a file a counterparty returned could not tell apart from a document that arrived damaged. Reading a document no longer asks for a Node global at all, so DOMParser, however it is supplied, is the only thing the core entry needs from a DOM.

    Each entry point settles its parser as the call comes in, so a runtime holding none is turned down before the bytes are looked at: bytes that are not a docx opened without a parser now report no-xml-parser where they reported not-a-docx. A parser that answers markup it cannot read by throwing, rather than by handing back a document holding a parsererror, is read as malformed-xml instead of having its own exception reach the caller.

Patch Changes

  • #75 c79e417 Thanks @Deea222! - Document which schema attributes plugins may rely on and which raw OOXML attributes are internal.
    An internal classification now records the provenance of every node and mark attribute without changing import, editing, or export behavior.

  • #65 a9a7e6d Thanks @Deea222! - Content control properties are written in the order the schema lays down. Locking a control that declares what kind of control it is - a date picker, a drop-down, plain text - used to write w:lock after that declaration, where CT_SdtPr puts w:lock before it, so a validator reading the exported file could refuse a control this editor had rewritten. ...

Read more

@portone/docx-editor@0.2.1

Choose a tag to compare

@github-actions github-actions released this 07 Sep 02:10
Immutable release. Only release title and notes can be modified.
be9a01e

Patch Changes

  • #53 d264803 Thanks @Deea222! - Stop text copied out of the editor from carrying the document's private data.

    A copy was drawn the way the editor draws itself, so the HTML it left on the clipboard held the paragraph and run XML, the name and recorded identity of a comment's author, what the comment and its replies say, and the body of a footnote.
    All of it landed in whatever application it was pasted into, and in comment mode a reader who may not change the body could take the body out this way.
    A copy now carries only what a reader of it needs, and the paragraph style it names is the style's id rather than the whole w:pPr.
    A link goes out as a link, so it can be followed where it lands and comes back as one when it is pasted here again.

    The plain text beside it says what was copied: a tab is a tab, a line break is a line, a page break is a form feed, and a table's cells stand apart by a tab and its rows by a line, so a table pasted into a spreadsheet arrives as a table.
    A cell holding a line break is the exception, since the line inside it reads as the start of the next row.

  • #50 41d82c5 Thanks @Deea222! - Stop onlyCommentsChangedBy from excusing a part a submission relates as a comment part.

    The three comment parts are left out of the byte comparison, and which parts those were came from the submitted file's own relationships.
    A file could relate a second comments, extended comments or people part at any part it liked and have that part go uncompared, so a rewritten styles part, a settings part pointing at a template off the package, replaced image bytes or forged document properties were all reported as a change to nothing but comments.
    The parts left out are now the ones the reader opened, a comment part may be related once, one related for the first time has to be a part the submission brought with it, and a relationship part naming one id twice is turned down.

    A file that relates an extended comments part but carries no comments part now has that part read, so writing the first comment into it writes that part rather than a second one beside it.
    Two extended parts related at once was a file whose settled threads a reader would lose, since only the first of them is read.

    This affects 0.2.0. A server that accepted files on this verdict should upgrade and run the check again over what it accepted, where such a file now answers part-changed naming the part, or relationship-changed naming the relationship part.

  • #56 467f6f5 Thanks @Deea222! - Commands and canRunCommand now report false where a bookmark marker or a note reference would be removed, instead of reporting true and changing nothing.

    A refusal over one of those markers also ends an open IME composition, the way a refusal over a locked control already did.

  • #59 6d7b97f Thanks @Deea222! - Formatting XML is now written through shared primitives that consistently escape attribute values while preserving existing formatting behavior.

  • #58 d9edb75 Thanks @Deea222! - Pagination measures every block as a list of break candidates; no visible change

  • #55 7110baa Thanks @Deea222! - Turn down a raw OOXML fragment that does not hold its shape as it enters the document, rather than writing it into the exported file.

    Keep imported formatting when a document uses an inherited default namespace or an alternative WordprocessingML prefix. Reject nested namespace rebinding that could disconnect hyperlinks from their targets on export.

    The editor draws the original XML of a paragraph, a run, a table, an image or an annotation into the page as a data- attribute, so that it can read the live DOM back after an IME composition or a browser edit. A fragment written into one of those attributes from outside, by a consumer plugin or through view.pasteHTML, is now held to what that attribute goes back out as: a whole element under an expected name, an opening tag's attributes, or an opening tag the writer closes itself. One that does not hold it is turned down along with the rule reading it, so the content settles one level plainer - a paragraph keeps its text and loses its properties, a run loses its mark, a content control or a hyperlink loses its wrapper - instead of a data-ppr reading </w:p><w:p>... writing a second paragraph into the exported body, or one that never closed reaching export and failing the whole document with malformed-xml.

  • #54 8aea477 Thanks @Deea222! - An untouched table opened in the editor is written back byte for byte, its w:tblGridChange included.

    Export decided whether a block was untouched by comparing it with the one import produced, attrs and all.
    Opening a document works some of those attrs out again from the formatting around them - a table's shared cell borders among them - so a table nobody had touched compared unequal and was rebuilt, and the rebuild dropped the markup the writer does not model.

    Each attr now declares whether the writer writes from it, whether the editor works it out for the screen, or whether it identifies something in the open document, and the comparison ignores the ones worked out for the screen.
    Exporting through createEditorState is held to the same byte identity as exporting straight from importDocx.

  • #48 de84006 Thanks @Deea222! - Stop onlyCommentsChangedBy from refusing a comment written into a table cell.

    A commented table is rebuilt on the way out, so it came back worded the way this editor words it while the original carried the wording its producer chose, and the two were compared word for word.
    The story is now compared as this editor writes it back, so two blocks this editor would write alike are read alike: the attribute order inside a w:tcW or a w:tblW, a percentage width written as 100% or as 5000, runs a producer split that say the same text, and a table's w:tblGridChange.
    Formatting properties keep the line breaks, comments and text a producer wrote between them, so rewriting a run's bold, a paragraph's alignment or a cell of a rebuilt table no longer drops them.
    A rebuilt table keeps what stood inside its width and span properties too.

  • #52 991ba48 Thanks @Deea222! - Read the comment parts entry by entry in onlyCommentsChangedBy.

    The three parts a comment is written across are the ones a comment edit may rewrite, so the package comparison passes over their bytes.
    Nothing read them afterwards, which let a submission carry a field pointing at a remote image inside a comment body, a comment attributed to a third author that nothing refers to, or markup wrapped around a body, and still be answered as a file where only comments changed.
    Each entry now has to arrive as it was, or be one this editor writes for an author who could have written it, and an entry nothing refers to has to stay as it was.
    A file that fails is refused as part-changed naming the comment part.

    Settling or replying to a comment that arrived with the file no longer rewrites its entry as plain text.
    The entry keeps what it said, and its last paragraph gains the w14:paraId the thread state is written against.
    The extended comments part carries an entry only for a comment that has thread state.

@portone/docx-editor@0.2.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 11:40
Immutable release. Only release title and notes can be modified.
adf7160

Minor Changes

  • #45 3190a35 Thanks @Deea222! - Add a comment mode and record who wrote each comment.

    Breaking: mode is now required and the commentAuthor prop is removed.
    author: { id, name, initials? } moves into mode for its comment and edit kinds.
    contextMenus moves off mode onto DocxEditor itself, so mode: { kind: "edit", contextMenus: false } becomes contextMenus={false}.

    In comment mode the text can be selected and copied but not changed, while comments can be written, answered, resolved, and reopened.
    A comment records its author's identity in the document, so two authors sharing a display name stay distinct.
    Only a comment's author may edit or delete it, and anyone may reply, resolve, and reopen.
    mode.editableComments: "all" opens every comment to a moderator.
    The canEditComment and editingProtection queries report what the current mode allows.
    A server can check a file coming back with onlyCommentsChangedBy from @portone/docx-editor/core, which answers { ok: true } or { ok: false, reason } for whether the file differs in nothing but one author's comments.

@portone/docx-editor@0.1.1

Choose a tag to compare

@github-actions github-actions released this 28 Aug 11:01
Immutable release. Only release title and notes can be modified.
1370a74

Patch Changes

  • #36 ab518b9 - Read two Unicode spellings of one font name as the same font.

    A name a document writes down can be composed or decomposed (NFC or NFD) while the same name elsewhere in the document, or among the toolbar's presets, is written the other way.
    Those spellings used to compare unequal, so the font dropdown listed the same font twice and a selection that all carried one font could report as mixed and blank the dropdown.
    Names are now compared in composed form, and the spelling the document wrote is what stays stored, exported, and shown.

    A list marker cut to its length cap is also cut between characters now, instead of possibly splitting an emoji or a combining sequence in half and drawing a replacement glyph.

@portone/docx-editor@0.1.0

Choose a tag to compare

@Deea222 Deea222 released this 25 Aug 15:14
Immutable release. Only release title and notes can be modified.

The first release.

The documentation covers what the editor edits, what it preserves untouched, and its current limitations.

Install it from npm as @portone/docx-editor.