@portone/docx-editor 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +109 -0
- package/CONTRIBUTING.md +5 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +12 -29
- package/dist/core.d.ts +23 -8
- package/dist/core.js +9 -4
- package/dist/docx/cloning.d.ts +38 -0
- package/dist/docx/cloning.js +74 -0
- package/dist/docx/commentOnlyChange.d.ts +12 -7
- package/dist/docx/commentOnlyChange.js +9 -156
- package/dist/docx/comments/constants.d.ts +0 -1
- package/dist/docx/comments/constants.js +0 -2
- package/dist/docx/comments/grammar.d.ts +10 -4
- package/dist/docx/comments/grammar.js +12 -2
- package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +16 -92
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.js +8 -10
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +52 -111
- package/dist/docx/documentSettings.d.ts +7 -0
- package/dist/docx/documentSettings.js +10 -2
- package/dist/docx/exportDocx.d.ts +40 -5
- package/dist/docx/exportDocx.js +69 -71
- package/dist/docx/exportRefs.d.ts +5 -2
- package/dist/docx/exportRefs.js +3 -1
- package/dist/docx/fidelity.d.ts +43 -0
- package/dist/docx/fidelity.js +64 -0
- package/dist/docx/formatting/attrs.d.ts +27 -0
- package/dist/docx/formatting/attrs.js +31 -0
- package/dist/docx/formatting/context.d.ts +31 -0
- package/dist/docx/formatting/context.js +42 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -78
- package/dist/docx/formatting/resolve.d.ts +45 -0
- package/dist/docx/formatting/resolve.js +140 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.js +3 -3
- package/dist/docx/formatting/tabStops.js +7 -22
- package/dist/docx/formatting.d.ts +4 -1
- package/dist/docx/formatting.js +4 -1
- package/dist/docx/headersFooters.js +6 -13
- package/dist/docx/identities.d.ts +67 -0
- package/dist/docx/identities.js +174 -0
- package/dist/docx/importDocx.d.ts +12 -1
- package/dist/docx/importDocx.js +72 -79
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +1 -1
- package/dist/docx/importTable.js +17 -1
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +256 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +20 -0
- package/dist/docx/newLists.js +36 -0
- package/dist/docx/notes.js +3 -7
- package/dist/docx/numberingPlanner.d.ts +8 -0
- package/dist/docx/numberingPlanner.js +19 -0
- package/dist/docx/packageParts.d.ts +42 -0
- package/dist/docx/packageParts.js +135 -0
- package/dist/docx/pageGeometry.d.ts +2 -0
- package/dist/docx/pageGeometry.js +18 -9
- package/dist/docx/paraProps.d.ts +10 -22
- package/dist/docx/paraProps.js +47 -76
- package/dist/docx/partPlan.d.ts +36 -0
- package/dist/docx/partPlan.js +59 -0
- package/dist/docx/protectionPolicy.d.ts +127 -0
- package/dist/docx/protectionPolicy.js +169 -0
- package/dist/docx/relationships.d.ts +1 -1
- package/dist/docx/relationships.js +8 -13
- package/dist/docx/runProps.d.ts +9 -22
- package/dist/docx/runProps.js +15 -168
- package/dist/docx/scan.js +20 -52
- package/dist/docx/sdt.js +9 -34
- package/dist/docx/sdtProps.d.ts +8 -1
- package/dist/docx/sdtProps.js +10 -0
- package/dist/docx/serializeBlock.d.ts +2 -0
- package/dist/docx/serializeBlock.js +8 -5
- package/dist/docx/serializeTable.js +32 -15
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +43 -17
- package/dist/docx/tableFormatting/editing.js +108 -139
- package/dist/docx/tableFormatting/reading.d.ts +16 -6
- package/dist/docx/tableFormatting/reading.js +40 -20
- package/dist/docx/tableTemplate.js +18 -7
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/inlineFormatting.js +19 -30
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +19 -31
- package/dist/editor/commands/exportQueries.d.ts +15 -0
- package/dist/editor/commands/exportQueries.js +14 -0
- package/dist/editor/commands/fidelityQueries.d.ts +12 -0
- package/dist/editor/commands/fidelityQueries.js +8 -0
- package/dist/editor/commands/formatting/editing.d.ts +2 -2
- package/dist/editor/commands/formatting/editing.js +26 -108
- package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
- package/dist/editor/commands/formatting/propertyCommands.js +103 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/indentCommands.js +5 -4
- package/dist/editor/commands/index.d.ts +11 -0
- package/dist/editor/commands/index.js +5 -0
- package/dist/editor/commands/linkCommands.js +5 -6
- package/dist/editor/commands/listCommands.js +8 -10
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -46
- package/dist/editor/commands/paragraphCommands.js +28 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +58 -58
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +56 -0
- package/dist/editor/editorDocument.js +74 -0
- package/dist/editor/externalClipboard.js +16 -45
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +11 -18
- package/dist/editor/paragraphEdits.js +7 -16
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/imagePaste.js +4 -3
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
- package/dist/editor/plugins/numberingDecorations.js +7 -17
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +51 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +30 -8
- package/dist/model/format.js +35 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listTemplate.js +24 -7
- package/dist/numbering/parseNumbering.d.ts +14 -1
- package/dist/numbering/parseNumbering.js +35 -22
- package/dist/numbering/writeNumbering.d.ts +3 -4
- package/dist/numbering/writeNumbering.js +14 -25
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/element.d.ts +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +3 -2
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +169 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
- package/dist/ooxml/simpleTypes.d.ts +103 -0
- package/dist/ooxml/simpleTypes.js +182 -0
- package/dist/ooxml/tabStops.js +8 -27
- package/dist/ooxml/tagScan.d.ts +34 -0
- package/dist/ooxml/tagScan.js +108 -0
- package/dist/ooxml/units.d.ts +25 -13
- package/dist/ooxml/units.js +65 -31
- package/dist/ooxml/xml.d.ts +27 -6
- package/dist/ooxml/xml.js +37 -5
- package/dist/page/blockKinds.d.ts +61 -0
- package/dist/page/blockKinds.js +11 -0
- package/dist/page/kinds/index.d.ts +6 -0
- package/dist/page/kinds/index.js +10 -0
- package/dist/page/kinds/paragraphKind.d.ts +10 -0
- package/dist/page/kinds/paragraphKind.js +71 -0
- package/dist/page/kinds/tableKind.d.ts +10 -0
- package/dist/page/kinds/tableKind.js +178 -0
- package/dist/page/measureBlocks.d.ts +3 -14
- package/dist/page/measureBlocks.js +24 -45
- package/dist/page/pageDecorations.d.ts +27 -44
- package/dist/page/pageDecorations.js +70 -152
- package/dist/page/pageLayout.d.ts +2 -19
- package/dist/page/pageLayout.js +36 -6
- package/dist/page/usePageLayout.d.ts +2 -17
- package/dist/page/usePageLayout.js +3 -39
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +102 -67
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +3 -0
- package/dist/schema/docxSchema.js +26 -14
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.d.ts +37 -14
- package/dist/schema/guards.js +29 -3
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +11 -44
- package/dist/schema/locks.js +0 -9
- package/dist/schema/preservedGuards.d.ts +26 -6
- package/dist/schema/preservedGuards.js +31 -1
- package/dist/schema/protection.d.ts +7 -1
- package/dist/schema/protection.js +2 -1
- package/dist/schema/sourceEquality.d.ts +1 -9
- package/dist/schema/sourceEquality.js +1 -27
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +10 -18
- package/dist/table/commands.js +20 -18
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +3 -9
- package/dist/table/gridBorders.d.ts +14 -16
- package/dist/table/gridBorders.js +3 -41
- package/dist/table/merge.d.ts +2 -6
- package/dist/table/merge.js +5 -5
- package/package.json +7 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/comments/verifying.js +0 -206
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -67
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -18
- package/dist/page/tableMeasurements.js +0 -119
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,114 @@
|
|
|
1
1
|
# @portone/docx-editor
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#62](https://github.com/portone-io/docx-editor/pull/62) [`5c481e7`](https://github.com/portone-io/docx-editor/commit/5c481e7c6e9a27373dad90d866a70cd80919b294) Thanks [@Deea222](https://github.com/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.
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
- [#77](https://github.com/portone-io/docx-editor/pull/77) [`a0b5cc6`](https://github.com/portone-io/docx-editor/commit/a0b5cc643bbeb6cf3407a0d729e7cc74fec304d6) Thanks [@Deea222](https://github.com/Deea222)! - Ask whether a document can be exported before trying.
|
|
12
|
+
|
|
13
|
+
`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.
|
|
14
|
+
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
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.
|
|
18
|
+
|
|
19
|
+
- [#63](https://github.com/portone-io/docx-editor/pull/63) [`1a4ec92`](https://github.com/portone-io/docx-editor/commit/1a4ec92162477d468fdb14a95a47388befba45f9) Thanks [@Deea222](https://github.com/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.
|
|
20
|
+
|
|
21
|
+
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`.
|
|
22
|
+
|
|
23
|
+
- [#79](https://github.com/portone-io/docx-editor/pull/79) [`70d4801`](https://github.com/portone-io/docx-editor/commit/70d48015f52a126824f25bbd03a65b5509699de2) Thanks [@Deea222](https://github.com/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.
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
`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.
|
|
28
|
+
|
|
29
|
+
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.
|
|
30
|
+
|
|
31
|
+
- [#82](https://github.com/portone-io/docx-editor/pull/82) [`f804ba1`](https://github.com/portone-io/docx-editor/commit/f804ba1eb5e5e6ed5ebf811e1edf2fa1858dc601) Thanks [@Deea222](https://github.com/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.
|
|
32
|
+
|
|
33
|
+
`ParagraphFormat` grows `keepNext?: boolean` to say so, beside `pageBreakBefore`.
|
|
34
|
+
|
|
35
|
+
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.
|
|
36
|
+
|
|
37
|
+
- [#80](https://github.com/portone-io/docx-editor/pull/80) [`a37b4fe`](https://github.com/portone-io/docx-editor/commit/a37b4fea75bbf6e9c342c830d358ba21119dd17c) Thanks [@Deea222](https://github.com/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.
|
|
38
|
+
|
|
39
|
+
`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.
|
|
40
|
+
|
|
41
|
+
An underline setter now distinguishes underline kinds; the public underline toggle still turns any existing kind off.
|
|
42
|
+
|
|
43
|
+
- [#72](https://github.com/portone-io/docx-editor/pull/72) [`578e73e`](https://github.com/portone-io/docx-editor/commit/578e73ed9444f528231048621a13651511438e79) Thanks [@Deea222](https://github.com/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.
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
- [#60](https://github.com/portone-io/docx-editor/pull/60) [`1b5d0fd`](https://github.com/portone-io/docx-editor/commit/1b5d0fd96f13341de0fe34374c2a7dedec57525c) Thanks [@Deea222](https://github.com/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.
|
|
48
|
+
|
|
49
|
+
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.
|
|
50
|
+
|
|
51
|
+
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.
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- [#75](https://github.com/portone-io/docx-editor/pull/75) [`c79e417`](https://github.com/portone-io/docx-editor/commit/c79e417bc7c2ec9cc3be804a1010533780558954) Thanks [@Deea222](https://github.com/Deea222)! - Document which schema attributes plugins may rely on and which raw OOXML attributes are internal.
|
|
56
|
+
An internal classification now records the provenance of every node and mark attribute without changing import, editing, or export behavior.
|
|
57
|
+
|
|
58
|
+
- [#65](https://github.com/portone-io/docx-editor/pull/65) [`a9a7e6d`](https://github.com/portone-io/docx-editor/commit/a9a7e6d92277f7725d995415da43ae5f3488e079) Thanks [@Deea222](https://github.com/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. A control carrying `w:label` or `w:tabIndex` was written the same wrong way round.
|
|
59
|
+
|
|
60
|
+
Untouched documents retain their original XML.
|
|
61
|
+
|
|
62
|
+
- [#73](https://github.com/portone-io/docx-editor/pull/73) [`ddda545`](https://github.com/portone-io/docx-editor/commit/ddda545d43788007cf8c2c0507a33b1326d593ca) Thanks [@Deea222](https://github.com/Deea222)! - Enter no longer duplicates paragraph identifiers or a paragraph-level section break. The continuing paragraph keeps its identifiers, and the section break stays on the last paragraph of the split.
|
|
63
|
+
|
|
64
|
+
Deleting or joining away a section-ending paragraph is refused until section editing is supported. Replacing text within that paragraph remains available.
|
|
65
|
+
|
|
66
|
+
- [#81](https://github.com/portone-io/docx-editor/pull/81) [`94d4ed7`](https://github.com/portone-io/docx-editor/commit/94d4ed748b22f49054acfb0b9cf7abcd83f19f09) Thanks [@Deea222](https://github.com/Deea222)! - The lines of a table's cells and the style values of a paragraph are worked out again by one plugin, which also works every value out again when the document's formatting is replaced under it; no behavior change for a document opened today.
|
|
67
|
+
|
|
68
|
+
Changing the formatting context also refreshes existing run marks, so text does not keep its previous style after the paragraph display values change. These updates preserve the original run XML, including in locked content and protected documents.
|
|
69
|
+
|
|
70
|
+
- [#74](https://github.com/portone-io/docx-editor/pull/74) [`c22f1da`](https://github.com/portone-io/docx-editor/commit/c22f1da7e1aec0a4a5ffbd805eb7b761655ea84f) Thanks [@Deea222](https://github.com/Deea222)! - Commands now share guard helpers so their applicability checks and dispatched edits respect the same rules. Formatting at a caret inside locked content is refused; formatting queries continue to report the selected text's values under document protection.
|
|
71
|
+
|
|
72
|
+
- [#90](https://github.com/portone-io/docx-editor/pull/90) [`3b37fbd`](https://github.com/portone-io/docx-editor/commit/3b37fbd69eb90fd27011af4ecce2dfd47b61b64f) Thanks [@Deea222](https://github.com/Deea222)! - Importing `emuToPx`, `pxToEmu` or `toImageExtent` off `./core`, or the image file helpers off `./commands`, no longer carries the XML naming layer into a consumer's bundle. The picture module read the namespace table at the top of the file, which a bundler keeps as a side effect, so one multiplication cost 817 bytes minified where it costs 182. Nothing written into a document changes.
|
|
73
|
+
|
|
74
|
+
- [#70](https://github.com/portone-io/docx-editor/pull/70) [`9d7f659`](https://github.com/portone-io/docx-editor/commit/9d7f6598c2f010ee53753cbd3c7952e8b4bc7f1e) Thanks [@Deea222](https://github.com/Deea222)! - The editor reads document-level values such as styles, numbering and page geometry from one snapshot; no visible change.
|
|
75
|
+
|
|
76
|
+
- [#69](https://github.com/portone-io/docx-editor/pull/69) [`4f8c94a`](https://github.com/portone-io/docx-editor/commit/4f8c94abf38c4b77eecb632dc783f215d5decb41) Thanks [@Deea222](https://github.com/Deea222)! - A page measurement applies its pushes, break spaces and table continuations in one transaction instead of three. The pages look exactly as they did; what changes is that a single measurement now reaches the editor as a single state change, so anything watching transactions - an `onStateChange` handler, a plugin, a React state hook - sees one rather than three per remeasure.
|
|
77
|
+
|
|
78
|
+
A table's repeated header now also refreshes as soon as its source row is edited, without waiting for the next measurement.
|
|
79
|
+
|
|
80
|
+
Changing a continued row's formatting keeps its page gap until remeasurement. Page pushes also update when their measured contribution changes but the total top margin stays the same.
|
|
81
|
+
|
|
82
|
+
- [#83](https://github.com/portone-io/docx-editor/pull/83) [`14f3b87`](https://github.com/portone-io/docx-editor/commit/14f3b875004ae28c41a3fd0d58c7783fa9731d67) Thanks [@Deea222](https://github.com/Deea222)! - A relationships part whose root carries a namespace prefix, or that arrived as an empty element, is now spliced correctly when the export adds a relationship to it: the entry goes inside the root, spelled under the root's own prefix, where the export used to refuse the file with `malformed-xml` for want of a bare closing tag. A numbering part that arrived as an empty element takes a new list definition the same way instead of being refused.
|
|
83
|
+
|
|
84
|
+
When one export adds several parts, `[Content_Types].xml` now declares them in the order they were added, a media type's `Default` ahead of any `Override`; each writer used to put its own declaration first, so the declarations came out in the reverse order of adding. Every declaration is still placed right after the opening tag, and the rest of the part is left as it arrived.
|
|
85
|
+
|
|
86
|
+
Every XML part the export rewrites is now read back before the file is repacked, so a part that would not open is refused with `malformed-xml` naming the part rather than handed back.
|
|
87
|
+
|
|
88
|
+
New part names and content-type requests recognize names differing only in case, avoiding duplicate package entries and declarations.
|
|
89
|
+
|
|
90
|
+
- [#71](https://github.com/portone-io/docx-editor/pull/71) [`a0bcd87`](https://github.com/portone-io/docx-editor/commit/a0bcd8798a33ecf3aba267bc2cdfbbca2b98d632) Thanks [@Deea222](https://github.com/Deea222)! - Comment-only verification and export now share the definitions for comment package parts. Public types are unchanged.
|
|
91
|
+
|
|
92
|
+
Verification rejects new or altered content around comment entries, including outside the XML root, while accepting annotations preserved from the original and those removed by normal comment-part rewrites. Namespace rebindings under rewritten comment markup are also rejected.
|
|
93
|
+
|
|
94
|
+
- [#76](https://github.com/portone-io/docx-editor/pull/76) [`46c8ba7`](https://github.com/portone-io/docx-editor/commit/46c8ba73cedd06cd85141ea44f09119648315396) Thanks [@Deea222](https://github.com/Deea222)! - Table pagination moves into a block-kind module; no visible change. What the page engine knows about a table - where it may be parted between rows, the spacer and repeated header a continued page is drawn with, and which positions a page cut may stand at - used to be spread over the measurer, the decorations and the plugin state. It is now one module beside the paragraph's, and the engine asks whichever kind claims a block. Pages, page breaks and continued tables look exactly as they did.
|
|
95
|
+
|
|
96
|
+
- [#63](https://github.com/portone-io/docx-editor/pull/63) [`1a4ec92`](https://github.com/portone-io/docx-editor/commit/1a4ec92162477d468fdb14a95a47388befba45f9) Thanks [@Deea222](https://github.com/Deea222)! - Keep namespace bindings declared on a table grid when preserving its revision history, so editing the table can still produce a readable DOCX. Rebuilt tables also retain the required empty table-properties element when no properties are set.
|
|
97
|
+
|
|
98
|
+
- [#78](https://github.com/portone-io/docx-editor/pull/78) [`3bdf81d`](https://github.com/portone-io/docx-editor/commit/3bdf81dc3c6b0a92091e46fc8312907e60cfc67e) Thanks [@Deea222](https://github.com/Deea222)! - A paragraph copied inside the editor no longer exports a duplicate `w14:paraId`. The copy goes out as a paragraph of its own, without the original's identifiers, and the original still goes out as the bytes it arrived as.
|
|
99
|
+
|
|
100
|
+
A preserved block copied twice, a body-level bookmark marker or a section break among them, is refused with `unsupported-content` instead of written twice. `exportProblems` and `canExport` report that refusal ahead of the write, at the place the second copy stands.
|
|
101
|
+
|
|
102
|
+
- [#67](https://github.com/portone-io/docx-editor/pull/67) [`77a468f`](https://github.com/portone-io/docx-editor/commit/77a468f5c4159e619a20b446bd35d14b4833f44a) Thanks [@Deea222](https://github.com/Deea222)! - Universal measures such as `8.5in` are read correctly. A measurement in a document may be written as a length with a unit - `8.5in`, `2.54cm`, `12pt` - as well as a count, and every one of them used to be read as its leading digits alone. A US Letter document whose section says `w:pgSz w:w="8.5in"` was drawn as a page 8.5 twips wide, which is no page at all, so the editor fell back to A4 and showed the wrong paper; a tab stop at `1.5in` landed at 0.08pt and an automatic tab interval of `0.75in` collapsed every tab in that document to no width. Page size and margins, indents, spacing, font sizes, table and cell widths, cell margins, row heights and tab stops are now read as the lengths they name.
|
|
103
|
+
|
|
104
|
+
`on` and `off` spellings of boolean attributes are read as the schema admits. A style marked `w:default="on"` is now recognised as the default style for its kind, as `w:default="1"` already was, so a document that marks its defaults that way is shown with the formatting they lay down.
|
|
105
|
+
|
|
106
|
+
Integer measurements retain support for an explicit `+` sign. Table and cell widths with an explicit `%` follow Word's percentage interpretation even when their width type says otherwise. Rebuilt table widths and grid columns are written in whole units; untouched XML is preserved.
|
|
107
|
+
|
|
108
|
+
Overflowing universal-measure and percentage conversions are rejected during import.
|
|
109
|
+
|
|
110
|
+
- [#65](https://github.com/portone-io/docx-editor/pull/65) [`a9a7e6d`](https://github.com/portone-io/docx-editor/commit/a9a7e6d92277f7725d995415da43ae5f3488e079) Thanks [@Deea222](https://github.com/Deea222)! - An edit to a cell border, a cell shading, a row height, a paragraph indent, or a line spacing now reads and writes the WordprocessingML attribute alone. A producer's own attribute that shares the local name (`x:val` beside `w:val`, declared ignorable) used to be taken for the formatting value, or written over in its place; it is now left as the producer wrote it, and the value Word reads is the one read and written.
|
|
111
|
+
|
|
3
112
|
## 0.2.1
|
|
4
113
|
|
|
5
114
|
### Patch Changes
|
package/CONTRIBUTING.md
CHANGED
|
@@ -54,7 +54,11 @@ A command added to `./commands` or `./table` needs a writer probe in `src/docx/_
|
|
|
54
54
|
|
|
55
55
|
If you changed anything under `src/`, run `pnpm changeset` and commit the file it writes.
|
|
56
56
|
It becomes the CHANGELOG entry, so write it for someone reading release notes rather than the diff.
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
The public API is the exported names and types of the four entry points - `.`, `./core`, `./commands`, and `./table` - together with the parts of the document model that [What a plugin may rely on](https://docx-editor.portone.io/docs/custom-controls#what-a-plugin-may-rely-on) calls stable.
|
|
59
|
+
An attr that page calls internal is not part of it, and neither is anything under `src/` that no entry point reaches.
|
|
60
|
+
|
|
61
|
+
Choose `patch` unless the change adds to that surface, takes something out of it, or changes what a part of it means.
|
|
58
62
|
Those are `minor` while the package is below 1.0.
|
|
59
63
|
A declaration added, removed, or rewritten in `etc/*.api.md` after running `pnpm api:update` is what that looks like; a line that only gains or loses an `(undocumented)` marker is not.
|
|
60
64
|
Commit the regenerated report in the same commit as the changeset.
|
package/dist/DocxEditor.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { Plugin } from "prosemirror-state";
|
|
|
11
11
|
import type { EditorView } from "prosemirror-view";
|
|
12
12
|
import { type CSSProperties, type ReactNode } from "react";
|
|
13
13
|
import { type DocxSource } from "./docx/importDocx";
|
|
14
|
+
import { type ExportProblem } from "./docx/invariants";
|
|
14
15
|
import { type CommentAuthor } from "./editor/commands/commentCommands";
|
|
15
16
|
import { DocxImportError } from "./ooxml/errors";
|
|
16
17
|
import type { EditableComments } from "./schema/protection";
|
|
@@ -21,6 +22,11 @@ export interface DocxEditorHandle {
|
|
|
21
22
|
view: EditorView;
|
|
22
23
|
/** Turns the editor state currently on screen into docx bytes */
|
|
23
24
|
exportBytes: () => Uint8Array;
|
|
25
|
+
/**
|
|
26
|
+
* Every reason `exportBytes` would refuse the state currently on screen, each under the code
|
|
27
|
+
* the refusal would carry; empty when it would write. `downloadDocx` answers `blocked` with it
|
|
28
|
+
*/
|
|
29
|
+
exportProblems: () => readonly ExportProblem[];
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
32
|
* What the editor is for, which decides what it offers.
|
package/dist/DocxEditor.js
CHANGED
|
@@ -10,16 +10,16 @@ import {
|
|
|
10
10
|
} from "react";
|
|
11
11
|
import { exportDocx } from "./docx/exportDocx.js";
|
|
12
12
|
import { importDocx } from "./docx/importDocx.js";
|
|
13
|
+
import { exportProblems } from "./docx/invariants.js";
|
|
13
14
|
import {
|
|
14
15
|
documentComments
|
|
15
16
|
} from "./editor/commands/commentCommands.js";
|
|
16
17
|
import { activeLinkSpan } from "./editor/commands/linkCommands.js";
|
|
17
|
-
import {
|
|
18
|
+
import { createEditorView, editorStateForSession } from "./editor/createEditor.js";
|
|
18
19
|
import { setProtection } from "./editor/plugins/documentProtection.js";
|
|
19
20
|
import { isLinkPanelOpen } from "./editor/plugins/linkPanel.js";
|
|
20
21
|
import { tableMenuAnchor } from "./editor/plugins/tableContextMenu.js";
|
|
21
22
|
import { textMenuAnchor } from "./editor/plugins/textContextMenu.js";
|
|
22
|
-
import { parseNumbering } from "./numbering/parseNumbering.js";
|
|
23
23
|
import { DocxImportError } from "./ooxml/errors.js";
|
|
24
24
|
import { PageGuides } from "./page/PageGuides.js";
|
|
25
25
|
import { A4_PAGE_PIXELS, pagePixels } from "./page/pageLayout.js";
|
|
@@ -71,12 +71,7 @@ function affordancesOf(mode) {
|
|
|
71
71
|
function openDocument(bytes) {
|
|
72
72
|
try {
|
|
73
73
|
const { doc, session } = importDocx(bytes);
|
|
74
|
-
return {
|
|
75
|
-
status: "opened",
|
|
76
|
-
doc,
|
|
77
|
-
session,
|
|
78
|
-
numbering: parseNumbering(session.numberingXml)
|
|
79
|
-
};
|
|
74
|
+
return { status: "opened", doc, session };
|
|
80
75
|
} catch (error) {
|
|
81
76
|
if (error instanceof DocxImportError) return { status: "rejected", error };
|
|
82
77
|
throw error;
|
|
@@ -112,6 +107,9 @@ function useDocumentBytes(source) {
|
|
|
112
107
|
return read.bytes;
|
|
113
108
|
}
|
|
114
109
|
var IMPORT_REJECTION_REASON = {
|
|
110
|
+
// `DOMParser` is built into the browser rather than loaded with the page, so a browser that
|
|
111
|
+
// reaches this line has no XML reader at all and will not have gained one on a second try
|
|
112
|
+
"no-xml-parser": "This browser cannot read documents.",
|
|
115
113
|
"not-a-docx": "This file is not a docx document, or it is damaged.",
|
|
116
114
|
"too-large": "This document is too large to open.",
|
|
117
115
|
"missing-part": "This document is missing the part that holds its body.",
|
|
@@ -184,32 +182,13 @@ function DocxEditorSurface({
|
|
|
184
182
|
const kept = keptState.current;
|
|
185
183
|
const view = createEditorView({
|
|
186
184
|
mount,
|
|
187
|
-
state: kept?.of === opened ? kept.state :
|
|
188
|
-
numbering: opened.numbering,
|
|
189
|
-
styles: opened.session.styles,
|
|
190
|
-
defaults: opened.session.defaults,
|
|
191
|
-
paragraphDefaults: opened.session.paragraphDefaults,
|
|
192
|
-
canStartNewList: opened.session.numberingPartPath !== null,
|
|
185
|
+
state: kept?.of === opened ? kept.state : editorStateForSession(opened, {
|
|
193
186
|
consumerPlugins: mountedPlugins,
|
|
194
|
-
paragraphStyles: opened.session.paragraphStyles,
|
|
195
187
|
contextMenus: mountedContextMenus,
|
|
196
|
-
geometry: opened.session.geometry,
|
|
197
|
-
defaultTabStopPt: opened.session.defaultTabStopPt,
|
|
198
|
-
reservedCommentIds: opened.session.comments.byId.keys(),
|
|
199
|
-
reservedCommentParaIds: [
|
|
200
|
-
...opened.session.comments.ordered.flatMap(
|
|
201
|
-
(comment) => comment.paraId === null ? [] : [comment.paraId]
|
|
202
|
-
),
|
|
203
|
-
...opened.session.comments.extendedOrdered.map(
|
|
204
|
-
(extension) => extension.paraId
|
|
205
|
-
)
|
|
206
|
-
],
|
|
207
188
|
protection,
|
|
208
189
|
author,
|
|
209
190
|
editableComments
|
|
210
191
|
}),
|
|
211
|
-
defaults: opened.session.defaults,
|
|
212
|
-
geometry: opened.session.geometry,
|
|
213
192
|
fontFallbacks: mountedFontFallbacks,
|
|
214
193
|
onStateChange: (state) => {
|
|
215
194
|
keptState.current = { of: opened, state };
|
|
@@ -252,7 +231,11 @@ function DocxEditorSurface({
|
|
|
252
231
|
const view = viewRef.current;
|
|
253
232
|
if (!view || opened?.status !== "opened") return null;
|
|
254
233
|
const session = opened.session;
|
|
255
|
-
return {
|
|
234
|
+
return {
|
|
235
|
+
view,
|
|
236
|
+
exportBytes: () => exportDocx(view.state.doc, session),
|
|
237
|
+
exportProblems: () => exportProblems(view.state.doc, session)
|
|
238
|
+
};
|
|
256
239
|
}, [opened]);
|
|
257
240
|
const overlay = usePageLayout({
|
|
258
241
|
view: live?.view ?? null,
|
package/dist/core.d.ts
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Framework-free DOCX import and export API. The opaque session preserves package parts between
|
|
3
|
-
* calls
|
|
3
|
+
* calls.
|
|
4
|
+
*
|
|
5
|
+
* Reading a package needs an XML parser. A browser has one; anywhere else, hand one in as
|
|
6
|
+
* `xmlParser` or install a `DOMParser` global, or the call is refused with the import code
|
|
7
|
+
* `no-xml-parser`.
|
|
4
8
|
*/
|
|
5
9
|
import type { Node as PMNode } from "prosemirror-model";
|
|
6
|
-
import {
|
|
10
|
+
import type { FidelityNote } from "./docx/fidelity";
|
|
11
|
+
import { type DocxBytes, type ImportOptions } from "./docx/importDocx";
|
|
7
12
|
import type { DocxSession } from "./docx/session";
|
|
8
13
|
export type { CommentOnlyVerdict } from "./docx/commentOnlyChange";
|
|
9
14
|
export { onlyCommentsChangedBy } from "./docx/commentOnlyChange";
|
|
10
|
-
export {
|
|
15
|
+
export type { ExportOptions } from "./docx/exportDocx";
|
|
16
|
+
export { exportDocx, exportDocxReport } from "./docx/exportDocx";
|
|
17
|
+
export type { FidelityCode, FidelityNote, FidelitySeverity, } from "./docx/fidelity";
|
|
11
18
|
export type { ParagraphStyleOption } from "./docx/formatting";
|
|
12
|
-
export type { DocxBytes } from "./docx/importDocx";
|
|
19
|
+
export type { DocxBytes, ImportOptions } from "./docx/importDocx";
|
|
20
|
+
/**
|
|
21
|
+
* What the writer would refuse the document over, asked ahead of the write. The first entry is
|
|
22
|
+
* what `exportDocx` throws, so the two cannot disagree.
|
|
23
|
+
*/
|
|
24
|
+
export type { ExportProblem } from "./docx/invariants";
|
|
25
|
+
export { exportProblems } from "./docx/invariants";
|
|
13
26
|
export type { DocxSession } from "./docx/session";
|
|
14
27
|
export { documentNumbering, documentPartPath } from "./docx/session";
|
|
15
28
|
export type { CellFormat, CellVerticalAlign, DocumentDefaults, HighlightName, LineSpacing, NumberingRef, ParagraphAlign, ParagraphFormat, RowFormat, RowHeight, RunFormat, TableFormat, TableWidth, TableWidthType, UnderlineKind, VerticalAlign, } from "./model/format";
|
|
16
29
|
export { toCellFormat, toParagraphFormat, toRowFormat, toRunFormat, toTableFormat, toTableWidth, } from "./model/format";
|
|
17
|
-
export type { LevelIndent, NumberFormat, Numbering, NumberingLevel, NumberingList, } from "./numbering/parseNumbering";
|
|
30
|
+
export type { LevelIndent, NumberFormat, Numbering, NumberingLevel, NumberingList, NumberingOptions, } from "./numbering/parseNumbering";
|
|
18
31
|
export { parseNumbering } from "./numbering/parseNumbering";
|
|
19
32
|
export type { DocxExportErrorCode, DocxImportErrorCode, } from "./ooxml/errors";
|
|
20
33
|
export { DocxExportError, DocxImportError } from "./ooxml/errors";
|
|
@@ -24,15 +37,17 @@ export { DocxExportError, DocxImportError } from "./ooxml/errors";
|
|
|
24
37
|
*/
|
|
25
38
|
export type { ImageExtent } from "./ooxml/image";
|
|
26
39
|
export { emuToPx, pxToEmu, toImageExtent } from "./ooxml/image";
|
|
40
|
+
export type { XmlParser } from "./ooxml/xml";
|
|
27
41
|
export { docxSchema } from "./schema";
|
|
28
42
|
/**
|
|
29
|
-
* Opens docx bytes into the document to work on
|
|
30
|
-
* from.
|
|
43
|
+
* Opens docx bytes into the document to work on, the session that remembers the file they came
|
|
44
|
+
* from, and what the file holds that this editor could not model.
|
|
31
45
|
*
|
|
32
46
|
* The engine hands out the store it fills in; this is where it narrows to the opaque session, so
|
|
33
47
|
* that the original XML behind it stays the exporter's business.
|
|
34
48
|
*/
|
|
35
|
-
export declare function importDocx(input: DocxBytes): {
|
|
49
|
+
export declare function importDocx(input: DocxBytes, options?: ImportOptions): {
|
|
36
50
|
doc: PMNode;
|
|
37
51
|
session: DocxSession;
|
|
52
|
+
notes: FidelityNote[];
|
|
38
53
|
};
|
package/dist/core.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
// src/core.ts
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
importDocx as openDocx
|
|
4
|
+
} from "./docx/importDocx.js";
|
|
3
5
|
import { onlyCommentsChangedBy } from "./docx/commentOnlyChange.js";
|
|
4
|
-
import { exportDocx } from "./docx/exportDocx.js";
|
|
6
|
+
import { exportDocx, exportDocxReport } from "./docx/exportDocx.js";
|
|
7
|
+
import { exportProblems } from "./docx/invariants.js";
|
|
5
8
|
import { documentNumbering, documentPartPath } from "./docx/session.js";
|
|
6
9
|
import {
|
|
7
10
|
toCellFormat,
|
|
@@ -15,8 +18,8 @@ import { parseNumbering } from "./numbering/parseNumbering.js";
|
|
|
15
18
|
import { DocxExportError, DocxImportError } from "./ooxml/errors.js";
|
|
16
19
|
import { emuToPx, pxToEmu, toImageExtent } from "./ooxml/image.js";
|
|
17
20
|
import { docxSchema } from "./schema/index.js";
|
|
18
|
-
function importDocx(input) {
|
|
19
|
-
return openDocx(input);
|
|
21
|
+
function importDocx(input, options) {
|
|
22
|
+
return openDocx(input, options);
|
|
20
23
|
}
|
|
21
24
|
export {
|
|
22
25
|
DocxExportError,
|
|
@@ -26,6 +29,8 @@ export {
|
|
|
26
29
|
docxSchema,
|
|
27
30
|
emuToPx,
|
|
28
31
|
exportDocx,
|
|
32
|
+
exportDocxReport,
|
|
33
|
+
exportProblems,
|
|
29
34
|
importDocx,
|
|
30
35
|
onlyCommentsChangedBy,
|
|
31
36
|
parseNumbering,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a node an edit makes out of another node carries over from it.
|
|
3
|
+
*
|
|
4
|
+
* A paragraph built from another one - either half of the two Enter leaves behind, or a copy - used
|
|
5
|
+
* to arrive holding every attr of the original. Two paragraphs then claimed the same `w14:paraId`,
|
|
6
|
+
* and a paragraph-level `w:sectPr` went out twice, which
|
|
7
|
+
* gives the document a section break it never had.
|
|
8
|
+
*
|
|
9
|
+
* `CLONE_POLICIES` is the one place that answers what becomes of each attr, and it answers per
|
|
10
|
+
* side: the half a split leaves standing is not the half it makes, and a free-standing copy is
|
|
11
|
+
* neither. What the answer turns on is whether the attr names the node - an identifier, or the
|
|
12
|
+
* block it was opened from - or describes it. A name may be held by one node only; a description
|
|
13
|
+
* is free to be copied.
|
|
14
|
+
*/
|
|
15
|
+
import type { Attrs, Node as PMNode } from "prosemirror-model";
|
|
16
|
+
/** Which half of a split the clone becomes, or a free-standing copy */
|
|
17
|
+
export type CloneSide = "before" | "after" | "copy";
|
|
18
|
+
export interface ClonePolicy {
|
|
19
|
+
/** The attrs a node made from `source` carries when it stands on `side` */
|
|
20
|
+
attrs(source: PMNode, side: CloneSide): Attrs;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The opening tag's attributes without the paragraph identifiers.
|
|
24
|
+
*
|
|
25
|
+
* A paragraph carrying none goes back out spelled exactly as it arrived, and so does one whose
|
|
26
|
+
* attribute text cannot be made out, which is left alone rather than written again from a guess.
|
|
27
|
+
*/
|
|
28
|
+
export declare function withoutParagraphIds(value: unknown): unknown;
|
|
29
|
+
/** One policy per node type that an edit can make from another node */
|
|
30
|
+
export declare const CLONE_POLICIES: Readonly<Record<"paragraph" | "tableCell" | "tableRow", ClonePolicy>>;
|
|
31
|
+
/**
|
|
32
|
+
* The two halves Enter leaves behind. `before` keeps the text, `after` keeps the paragraph mark's
|
|
33
|
+
* section break
|
|
34
|
+
*/
|
|
35
|
+
export declare function splitParagraphAttrs(parent: PMNode): {
|
|
36
|
+
before: Attrs;
|
|
37
|
+
after: Attrs;
|
|
38
|
+
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/docx/cloning.ts
|
|
2
|
+
import { attrsText, withoutAttrs } from "../ooxml/element.js";
|
|
3
|
+
import { parseProps, renderProps, setChild } from "../ooxml/props.js";
|
|
4
|
+
import { parseAttrs } from "../ooxml/tagScan.js";
|
|
5
|
+
var carried = (value) => value;
|
|
6
|
+
var defaulted = () => void 0;
|
|
7
|
+
var PARAGRAPH_ID_ATTRS = ["paraId", "textId"];
|
|
8
|
+
function withoutParagraphIds(value) {
|
|
9
|
+
if (typeof value !== "string") return value;
|
|
10
|
+
const attrs = parseAttrs(value);
|
|
11
|
+
if (attrs === null) return value;
|
|
12
|
+
const kept = withoutAttrs(attrs, PARAGRAPH_ID_ATTRS, "w14");
|
|
13
|
+
if (kept.length === attrs.length) return value;
|
|
14
|
+
return kept.length === 0 ? null : attrsText(kept);
|
|
15
|
+
}
|
|
16
|
+
function withoutSectionBreak(value) {
|
|
17
|
+
if (typeof value !== "string") return value;
|
|
18
|
+
const props = parseProps(value);
|
|
19
|
+
if (props === null) return value;
|
|
20
|
+
const without = setChild(props, "sectPr", null);
|
|
21
|
+
if (without.children.length === props.children.length) return value;
|
|
22
|
+
return renderProps(without) || null;
|
|
23
|
+
}
|
|
24
|
+
var INHERITED_CELL_ATTRS = ["tcAttrs", "tcPr", "tcW", "format"];
|
|
25
|
+
var INHERITED_ROW_ATTRS = ["trAttrs", "trPr", "format"];
|
|
26
|
+
function inherits(names) {
|
|
27
|
+
return Object.fromEntries(names.map((name) => [name, carried]));
|
|
28
|
+
}
|
|
29
|
+
function policy(rules, rest) {
|
|
30
|
+
return {
|
|
31
|
+
attrs(source, side) {
|
|
32
|
+
const attrs = {};
|
|
33
|
+
for (const [name, value] of Object.entries(source.attrs)) {
|
|
34
|
+
const held = (rules[name] ?? rest)(value, side);
|
|
35
|
+
if (held !== void 0) attrs[name] = held;
|
|
36
|
+
}
|
|
37
|
+
return attrs;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
var CLONE_POLICIES = {
|
|
42
|
+
paragraph: policy(
|
|
43
|
+
{
|
|
44
|
+
// The half that carries on where the original stood keeps the original's name. The one the
|
|
45
|
+
// edit made is a new paragraph and goes out with none, so no two ever claim the same
|
|
46
|
+
// paragraph identity.
|
|
47
|
+
pAttrs: (value, side) => side === "before" ? value : withoutParagraphIds(value),
|
|
48
|
+
// A paragraph-level `w:sectPr` ends the section it stands in, so it belongs to whichever
|
|
49
|
+
// paragraph ends up last in that section: the second half of a split, and no half of a copy,
|
|
50
|
+
// which is lifted out of the section it was taken from.
|
|
51
|
+
pPr: (value, side) => side === "after" ? value : withoutSectionBreak(value),
|
|
52
|
+
// What names the block this paragraph was opened from. Only the half still standing where
|
|
53
|
+
// that block stood may go on claiming it; `docx/exportDocx` writes the original bytes back
|
|
54
|
+
// for whatever claims one.
|
|
55
|
+
srcId: (value, side) => side === "before" ? value : void 0
|
|
56
|
+
},
|
|
57
|
+
// `format` and `styleRun` among them: display values `editor/plugins/paragraphDisplay` derives
|
|
58
|
+
// again from the formatting context, which nothing compares and nothing writes out.
|
|
59
|
+
carried
|
|
60
|
+
),
|
|
61
|
+
tableCell: policy(inherits(INHERITED_CELL_ATTRS), defaulted),
|
|
62
|
+
tableRow: policy(inherits(INHERITED_ROW_ATTRS), defaulted)
|
|
63
|
+
};
|
|
64
|
+
function splitParagraphAttrs(parent) {
|
|
65
|
+
return {
|
|
66
|
+
before: CLONE_POLICIES.paragraph.attrs(parent, "before"),
|
|
67
|
+
after: CLONE_POLICIES.paragraph.attrs(parent, "after")
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
CLONE_POLICIES,
|
|
72
|
+
splitParagraphAttrs,
|
|
73
|
+
withoutParagraphIds
|
|
74
|
+
};
|
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
* free to rewrite anything the story does not carry - the paper the document is written on, its
|
|
8
8
|
* styles, its headers - and a document comparison would see none of it.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import type { XmlParser } from "../ooxml/xml";
|
|
11
|
+
import type { EditableComments } from "../schema/protection";
|
|
12
|
+
import type { DocxBytes } from "./importDocx";
|
|
12
13
|
/**
|
|
13
|
-
* Why a file is not the one it claims to be. `part-changed
|
|
14
|
-
* part they were reached over; the other three are about the
|
|
14
|
+
* Why a file is not the one it claims to be. `part-changed`, `relationship-changed` and
|
|
15
|
+
* `comment-markup-rejected` name the part they were reached over; the other three are about the
|
|
16
|
+
* document story itself.
|
|
15
17
|
*/
|
|
16
18
|
export type CommentOnlyVerdict = {
|
|
17
19
|
ok: true;
|
|
@@ -20,7 +22,7 @@ export type CommentOnlyVerdict = {
|
|
|
20
22
|
reason: "body-changed" | "comment-not-owned" | "comment-author-forged";
|
|
21
23
|
} | {
|
|
22
24
|
ok: false;
|
|
23
|
-
reason: "part-changed" | "relationship-changed";
|
|
25
|
+
reason: "part-changed" | "relationship-changed" | "comment-markup-rejected";
|
|
24
26
|
part: string;
|
|
25
27
|
};
|
|
26
28
|
/**
|
|
@@ -30,7 +32,7 @@ export type CommentOnlyVerdict = {
|
|
|
30
32
|
* Every part of the package has to arrive as it left, save for the three a comment is written
|
|
31
33
|
* across and the relationship and content type they are declared with; the document story itself
|
|
32
34
|
* has to read as it did, comments aside. Those three parts are read entry by entry instead
|
|
33
|
-
* (`./comments/
|
|
35
|
+
* (`./comments/policy`), since a comment edit is free to rewrite them and something has to say
|
|
34
36
|
* what it may have written there. A comment carrying no recorded identity is everyone's to
|
|
35
37
|
* edit here as it is in the editor (`schema/protection`), while a comment that appeared has to
|
|
36
38
|
* carry this identity: a file can claim any author, and the editor's own hand in writing it is
|
|
@@ -38,10 +40,13 @@ export type CommentOnlyVerdict = {
|
|
|
38
40
|
*
|
|
39
41
|
* `editableComments: "all"` judges the file of an editor opened for a moderator, where every
|
|
40
42
|
* comment was theirs to edit; an identity is nobody's to rewrite under either setting.
|
|
43
|
+
* `xmlParser` names the parser both files are read through, for a runtime that holds no
|
|
44
|
+
* `DOMParser` global of its own.
|
|
41
45
|
*
|
|
42
46
|
* Bytes that are not a readable docx are turned down the way opening one is, with a
|
|
43
47
|
* `DocxImportError`, rather than being answered as a file that changed.
|
|
44
48
|
*/
|
|
45
|
-
export declare function onlyCommentsChangedBy(original: DocxBytes, submitted: DocxBytes, authorId: string, { editableComments }?: {
|
|
49
|
+
export declare function onlyCommentsChangedBy(original: DocxBytes, submitted: DocxBytes, authorId: string, { editableComments, xmlParser, }?: {
|
|
46
50
|
editableComments?: EditableComments;
|
|
51
|
+
xmlParser?: XmlParser;
|
|
47
52
|
}): CommentOnlyVerdict;
|