@usejunior/docx-core 0.10.0 → 0.11.1
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/LICENSE +202 -21
- package/NOTICE +2 -0
- package/README.md +2 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/atomizer.d.ts +13 -7
- package/dist/atomizer.d.ts.map +1 -1
- package/dist/atomizer.js +59 -24
- package/dist/atomizer.js.map +1 -1
- package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts +99 -0
- package/dist/baselines/atomizer/auxiliaryIdCollision.d.ts.map +1 -0
- package/dist/baselines/atomizer/auxiliaryIdCollision.js +415 -0
- package/dist/baselines/atomizer/auxiliaryIdCollision.js.map +1 -0
- package/dist/baselines/atomizer/documentReconstructor.d.ts.map +1 -1
- package/dist/baselines/atomizer/documentReconstructor.js +120 -27
- package/dist/baselines/atomizer/documentReconstructor.js.map +1 -1
- package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts +9 -0
- package/dist/baselines/atomizer/inPlaceModifier-wrappers.d.ts.map +1 -1
- package/dist/baselines/atomizer/inPlaceModifier-wrappers.js +52 -4
- package/dist/baselines/atomizer/inPlaceModifier-wrappers.js.map +1 -1
- package/dist/baselines/atomizer/pipeline.d.ts +12 -53
- package/dist/baselines/atomizer/pipeline.d.ts.map +1 -1
- package/dist/baselines/atomizer/pipeline.js +126 -231
- package/dist/baselines/atomizer/pipeline.js.map +1 -1
- package/dist/baselines/atomizer/trackChangesAcceptorAst.d.ts.map +1 -1
- package/dist/baselines/atomizer/trackChangesAcceptorAst.js +153 -23
- package/dist/baselines/atomizer/trackChangesAcceptorAst.js.map +1 -1
- package/dist/baselines/wmlcomparer/DotnetCli.d.ts.map +1 -1
- package/dist/baselines/wmlcomparer/DotnetCli.js +7 -0
- package/dist/baselines/wmlcomparer/DotnetCli.js.map +1 -1
- package/dist/cli/compare-two.d.ts.map +1 -1
- package/dist/cli/compare-two.js +3 -1
- package/dist/cli/compare-two.js.map +1 -1
- package/dist/cli/conformance-adapter.d.ts +3 -0
- package/dist/cli/conformance-adapter.d.ts.map +1 -0
- package/dist/cli/conformance-adapter.js +93 -0
- package/dist/cli/conformance-adapter.js.map +1 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +5 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/compare-types.d.ts +46 -0
- package/dist/compare-types.d.ts.map +1 -1
- package/dist/generation/compile.d.ts +22 -0
- package/dist/generation/compile.d.ts.map +1 -0
- package/dist/generation/compile.js +58 -0
- package/dist/generation/compile.js.map +1 -0
- package/dist/generation/context.d.ts +42 -0
- package/dist/generation/context.d.ts.map +1 -0
- package/dist/generation/context.js +65 -0
- package/dist/generation/context.js.map +1 -0
- package/dist/generation/emit/comments-part.d.ts +36 -0
- package/dist/generation/emit/comments-part.d.ts.map +1 -0
- package/dist/generation/emit/comments-part.js +116 -0
- package/dist/generation/emit/comments-part.js.map +1 -0
- package/dist/generation/emit/document-part.d.ts +24 -0
- package/dist/generation/emit/document-part.d.ts.map +1 -0
- package/dist/generation/emit/document-part.js +60 -0
- package/dist/generation/emit/document-part.js.map +1 -0
- package/dist/generation/emit/emit-context.d.ts +28 -0
- package/dist/generation/emit/emit-context.d.ts.map +1 -0
- package/dist/generation/emit/emit-context.js +19 -0
- package/dist/generation/emit/emit-context.js.map +1 -0
- package/dist/generation/emit/font-table-part.d.ts +16 -0
- package/dist/generation/emit/font-table-part.d.ts.map +1 -0
- package/dist/generation/emit/font-table-part.js +74 -0
- package/dist/generation/emit/font-table-part.js.map +1 -0
- package/dist/generation/emit/header-footer-part.d.ts +23 -0
- package/dist/generation/emit/header-footer-part.d.ts.map +1 -0
- package/dist/generation/emit/header-footer-part.js +57 -0
- package/dist/generation/emit/header-footer-part.js.map +1 -0
- package/dist/generation/emit/numbering-part.d.ts +29 -0
- package/dist/generation/emit/numbering-part.d.ts.map +1 -0
- package/dist/generation/emit/numbering-part.js +102 -0
- package/dist/generation/emit/numbering-part.js.map +1 -0
- package/dist/generation/emit/package-parts.d.ts +24 -0
- package/dist/generation/emit/package-parts.d.ts.map +1 -0
- package/dist/generation/emit/package-parts.js +121 -0
- package/dist/generation/emit/package-parts.js.map +1 -0
- package/dist/generation/emit/paragraph.d.ts +24 -0
- package/dist/generation/emit/paragraph.d.ts.map +1 -0
- package/dist/generation/emit/paragraph.js +63 -0
- package/dist/generation/emit/paragraph.js.map +1 -0
- package/dist/generation/emit/properties.d.ts +36 -0
- package/dist/generation/emit/properties.d.ts.map +1 -0
- package/dist/generation/emit/properties.js +154 -0
- package/dist/generation/emit/properties.js.map +1 -0
- package/dist/generation/emit/run.d.ts +16 -0
- package/dist/generation/emit/run.d.ts.map +1 -0
- package/dist/generation/emit/run.js +71 -0
- package/dist/generation/emit/run.js.map +1 -0
- package/dist/generation/emit/section.d.ts +29 -0
- package/dist/generation/emit/section.d.ts.map +1 -0
- package/dist/generation/emit/section.js +117 -0
- package/dist/generation/emit/section.js.map +1 -0
- package/dist/generation/emit/settings-part.d.ts +13 -0
- package/dist/generation/emit/settings-part.d.ts.map +1 -0
- package/dist/generation/emit/settings-part.js +68 -0
- package/dist/generation/emit/settings-part.js.map +1 -0
- package/dist/generation/emit/styles-part.d.ts +16 -0
- package/dist/generation/emit/styles-part.d.ts.map +1 -0
- package/dist/generation/emit/styles-part.js +82 -0
- package/dist/generation/emit/styles-part.js.map +1 -0
- package/dist/generation/emit/table.d.ts +26 -0
- package/dist/generation/emit/table.d.ts.map +1 -0
- package/dist/generation/emit/table.js +209 -0
- package/dist/generation/emit/table.js.map +1 -0
- package/dist/generation/emit/theme-part.d.ts +21 -0
- package/dist/generation/emit/theme-part.d.ts.map +1 -0
- package/dist/generation/emit/theme-part.js +151 -0
- package/dist/generation/emit/theme-part.js.map +1 -0
- package/dist/generation/emit/web-settings-part.d.ts +12 -0
- package/dist/generation/emit/web-settings-part.d.ts.map +1 -0
- package/dist/generation/emit/web-settings-part.js +19 -0
- package/dist/generation/emit/web-settings-part.js.map +1 -0
- package/dist/generation/errors.d.ts +22 -0
- package/dist/generation/errors.d.ts.map +1 -0
- package/dist/generation/errors.js +29 -0
- package/dist/generation/errors.js.map +1 -0
- package/dist/generation/index.d.ts +13 -0
- package/dist/generation/index.d.ts.map +1 -0
- package/dist/generation/index.js +12 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/generation/ordering.d.ts +46 -0
- package/dist/generation/ordering.d.ts.map +1 -0
- package/dist/generation/ordering.js +119 -0
- package/dist/generation/ordering.js.map +1 -0
- package/dist/generation/recipes.d.ts +70 -0
- package/dist/generation/recipes.d.ts.map +1 -0
- package/dist/generation/recipes.js +149 -0
- package/dist/generation/recipes.js.map +1 -0
- package/dist/generation/structural-checks.d.ts +24 -0
- package/dist/generation/structural-checks.d.ts.map +1 -0
- package/dist/generation/structural-checks.js +318 -0
- package/dist/generation/structural-checks.js.map +1 -0
- package/dist/generation/theme-colors.d.ts +4 -0
- package/dist/generation/theme-colors.d.ts.map +1 -0
- package/dist/generation/theme-colors.js +18 -0
- package/dist/generation/theme-colors.js.map +1 -0
- package/dist/generation/types.d.ts +249 -0
- package/dist/generation/types.d.ts.map +1 -0
- package/dist/generation/types.js +54 -0
- package/dist/generation/types.js.map +1 -0
- package/dist/generation/validate-spec.d.ts +27 -0
- package/dist/generation/validate-spec.d.ts.map +1 -0
- package/dist/generation/validate-spec.js +359 -0
- package/dist/generation/validate-spec.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/integration/generation-probes.d.ts +15 -0
- package/dist/integration/generation-probes.d.ts.map +1 -0
- package/dist/integration/generation-probes.js +84 -0
- package/dist/integration/generation-probes.js.map +1 -0
- package/dist/integration/libreoffice-oracle.d.ts +8 -0
- package/dist/integration/libreoffice-oracle.d.ts.map +1 -1
- package/dist/integration/libreoffice-oracle.js +14 -6
- package/dist/integration/libreoffice-oracle.js.map +1 -1
- package/dist/integration/synthetic-docx-fixture.d.ts +72 -0
- package/dist/integration/synthetic-docx-fixture.d.ts.map +1 -1
- package/dist/integration/synthetic-docx-fixture.js +131 -4
- package/dist/integration/synthetic-docx-fixture.js.map +1 -1
- package/dist/primitives/accept_changes.d.ts +2 -1
- package/dist/primitives/accept_changes.d.ts.map +1 -1
- package/dist/primitives/accept_changes.js +153 -12
- package/dist/primitives/accept_changes.js.map +1 -1
- package/dist/primitives/document.d.ts +38 -0
- package/dist/primitives/document.d.ts.map +1 -1
- package/dist/primitives/document.js +75 -9
- package/dist/primitives/document.js.map +1 -1
- package/dist/primitives/document_view-comments.d.ts.map +1 -1
- package/dist/primitives/document_view-comments.js +4 -3
- package/dist/primitives/document_view-comments.js.map +1 -1
- package/dist/primitives/document_view-types.d.ts +15 -0
- package/dist/primitives/document_view-types.d.ts.map +1 -1
- package/dist/primitives/document_view.d.ts.map +1 -1
- package/dist/primitives/document_view.js +21 -13
- package/dist/primitives/document_view.js.map +1 -1
- package/dist/primitives/formatting_tags.d.ts +1 -0
- package/dist/primitives/formatting_tags.d.ts.map +1 -1
- package/dist/primitives/formatting_tags.js +16 -10
- package/dist/primitives/formatting_tags.js.map +1 -1
- package/dist/primitives/index.d.ts +4 -0
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +4 -0
- package/dist/primitives/index.js.map +1 -1
- package/dist/primitives/layout.d.ts.map +1 -1
- package/dist/primitives/layout.js +13 -0
- package/dist/primitives/layout.js.map +1 -1
- package/dist/primitives/minimal_save.d.ts +38 -0
- package/dist/primitives/minimal_save.d.ts.map +1 -0
- package/dist/primitives/minimal_save.js +323 -0
- package/dist/primitives/minimal_save.js.map +1 -0
- package/dist/primitives/namespaces.d.ts +46 -0
- package/dist/primitives/namespaces.d.ts.map +1 -1
- package/dist/primitives/namespaces.js +49 -0
- package/dist/primitives/namespaces.js.map +1 -1
- package/dist/primitives/reject_changes.d.ts +4 -2
- package/dist/primitives/reject_changes.d.ts.map +1 -1
- package/dist/primitives/reject_changes.js +177 -24
- package/dist/primitives/reject_changes.js.map +1 -1
- package/dist/primitives/revision-parts.d.ts +7 -0
- package/dist/primitives/revision-parts.d.ts.map +1 -0
- package/dist/primitives/revision-parts.js +27 -0
- package/dist/primitives/revision-parts.js.map +1 -0
- package/dist/primitives/revision-vocabulary.d.ts +7 -0
- package/dist/primitives/revision-vocabulary.d.ts.map +1 -0
- package/dist/primitives/revision-vocabulary.js +39 -0
- package/dist/primitives/revision-vocabulary.js.map +1 -0
- package/dist/primitives/schema-corpus-capture.d.ts +19 -0
- package/dist/primitives/schema-corpus-capture.d.ts.map +1 -0
- package/dist/primitives/schema-corpus-capture.js +29 -0
- package/dist/primitives/schema-corpus-capture.js.map +1 -0
- package/dist/primitives/sectPrAudit.d.ts +19 -0
- package/dist/primitives/sectPrAudit.d.ts.map +1 -0
- package/dist/primitives/sectPrAudit.js +165 -0
- package/dist/primitives/sectPrAudit.js.map +1 -0
- package/dist/primitives/semantic_tags.d.ts.map +1 -1
- package/dist/primitives/semantic_tags.js +2 -1
- package/dist/primitives/semantic_tags.js.map +1 -1
- package/dist/primitives/serialize_html.d.ts +1 -0
- package/dist/primitives/serialize_html.d.ts.map +1 -1
- package/dist/primitives/serialize_html.js +4 -2
- package/dist/primitives/serialize_html.js.map +1 -1
- package/dist/primitives/styles.d.ts +15 -0
- package/dist/primitives/styles.d.ts.map +1 -1
- package/dist/primitives/styles.js +11 -0
- package/dist/primitives/styles.js.map +1 -1
- package/dist/primitives/track-changes-emitter.d.ts +9 -0
- package/dist/primitives/track-changes-emitter.d.ts.map +1 -1
- package/dist/primitives/track-changes-emitter.js +54 -4
- package/dist/primitives/track-changes-emitter.js.map +1 -1
- package/dist/primitives/validate_ai_revisions.d.ts +35 -0
- package/dist/primitives/validate_ai_revisions.d.ts.map +1 -0
- package/dist/primitives/validate_ai_revisions.js +323 -0
- package/dist/primitives/validate_ai_revisions.js.map +1 -0
- package/dist/primitives/xml.d.ts +5 -0
- package/dist/primitives/xml.d.ts.map +1 -1
- package/dist/primitives/xml.js +5 -0
- package/dist/primitives/xml.js.map +1 -1
- package/dist/primitives/zip.d.ts +1 -0
- package/dist/primitives/zip.d.ts.map +1 -1
- package/dist/primitives/zip.js +21 -3
- package/dist/primitives/zip.js.map +1 -1
- package/dist/shared/field-structure.d.ts +14 -0
- package/dist/shared/field-structure.d.ts.map +1 -0
- package/dist/shared/field-structure.js +166 -0
- package/dist/shared/field-structure.js.map +1 -0
- package/package.json +7 -4
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* - Unwrapping w:ins elements (promoting children)
|
|
7
7
|
* - Removing w:moveFrom (source), unwrapping w:moveTo (destination)
|
|
8
8
|
* - Removing all *PrChange property change records
|
|
9
|
-
* - Stripping paragraph-level revision markers
|
|
9
|
+
* - Stripping paragraph-level revision markers, merging a paragraph whose
|
|
10
|
+
* mark was a tracked deletion into the following paragraph
|
|
10
11
|
* - Cleaning up move range markers and rsidDel attributes
|
|
11
12
|
*
|
|
12
13
|
* Operates on the W3C DOM (`@xmldom/xmldom`) — the same API used
|
|
@@ -89,6 +90,144 @@ const PR_CHANGE_LOCALS = [
|
|
|
89
90
|
'rPrChange', 'pPrChange', 'sectPrChange',
|
|
90
91
|
'tblPrChange', 'trPrChange', 'tcPrChange',
|
|
91
92
|
];
|
|
93
|
+
// Marker-ish elements that may sit between two paragraphs at block level
|
|
94
|
+
// without ending the search for a merge target: the full EG_RangeMarkupElements
|
|
95
|
+
// schema group (wml.xsd), plus permStart/permEnd range markers and proofErr
|
|
96
|
+
// proofing anchors.
|
|
97
|
+
const RANGE_MARKUP_BLOCK_SIBLING_LOCALS = new Set([
|
|
98
|
+
'bookmarkStart', 'bookmarkEnd',
|
|
99
|
+
'commentRangeStart', 'commentRangeEnd',
|
|
100
|
+
'moveFromRangeStart', 'moveFromRangeEnd',
|
|
101
|
+
'moveToRangeStart', 'moveToRangeEnd',
|
|
102
|
+
'customXmlInsRangeStart', 'customXmlInsRangeEnd',
|
|
103
|
+
'customXmlDelRangeStart', 'customXmlDelRangeEnd',
|
|
104
|
+
'customXmlMoveFromRangeStart', 'customXmlMoveFromRangeEnd',
|
|
105
|
+
'customXmlMoveToRangeStart', 'customXmlMoveToRangeEnd',
|
|
106
|
+
'permStart', 'permEnd',
|
|
107
|
+
'proofErr',
|
|
108
|
+
]);
|
|
109
|
+
/**
|
|
110
|
+
* Find the next sibling paragraph a paragraph-mark revision can merge into,
|
|
111
|
+
* skipping block-level range/annotation markers. Returns null when the next
|
|
112
|
+
* block is not a paragraph (table, sdt, sectPr, end of parent).
|
|
113
|
+
*/
|
|
114
|
+
function findFollowingSiblingParagraph(p) {
|
|
115
|
+
let sibling = p.nextSibling;
|
|
116
|
+
while (sibling) {
|
|
117
|
+
if (sibling.nodeType === 1) {
|
|
118
|
+
if (isW(sibling, 'p'))
|
|
119
|
+
return sibling;
|
|
120
|
+
const el = sibling;
|
|
121
|
+
if (el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? '')) {
|
|
122
|
+
sibling = sibling.nextSibling;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
sibling = sibling.nextSibling;
|
|
128
|
+
}
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
/** True iff the paragraph still holds content beyond w:pPr and bare annotation markers. */
|
|
132
|
+
function paragraphHasContent(p) {
|
|
133
|
+
for (let i = 0; i < p.childNodes.length; i++) {
|
|
134
|
+
const child = p.childNodes[i];
|
|
135
|
+
if (child.nodeType !== 1)
|
|
136
|
+
continue;
|
|
137
|
+
if (isW(child, 'pPr'))
|
|
138
|
+
continue;
|
|
139
|
+
const el = child;
|
|
140
|
+
if (el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? ''))
|
|
141
|
+
continue;
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* True iff removing an emptied mark-revised paragraph keeps its parent
|
|
148
|
+
* structurally valid for Word: the parent must retain at least one block
|
|
149
|
+
* element, must not end on a w:tbl (a trailing table needs a following
|
|
150
|
+
* paragraph), and two tables must not become adjacent (Word merges
|
|
151
|
+
* back-to-back tables). w:sectPr is ignored — a trailing body sectPr is not a
|
|
152
|
+
* block element.
|
|
153
|
+
*/
|
|
154
|
+
function canSafelyRemoveEmptyParagraph(p) {
|
|
155
|
+
const blockSibling = (start, dir) => {
|
|
156
|
+
let sibling = start;
|
|
157
|
+
while (sibling) {
|
|
158
|
+
if (sibling.nodeType === 1) {
|
|
159
|
+
const el = sibling;
|
|
160
|
+
if ((el.namespaceURI === W_NS && RANGE_MARKUP_BLOCK_SIBLING_LOCALS.has(el.localName ?? '')) ||
|
|
161
|
+
isW(el, 'sectPr')) {
|
|
162
|
+
sibling = sibling[dir];
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
return el;
|
|
166
|
+
}
|
|
167
|
+
sibling = sibling[dir];
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
};
|
|
171
|
+
const prev = blockSibling(p.previousSibling, 'previousSibling');
|
|
172
|
+
const next = blockSibling(p.nextSibling, 'nextSibling');
|
|
173
|
+
if (!prev && !next)
|
|
174
|
+
return false;
|
|
175
|
+
if (prev && isW(prev, 'tbl') && !next)
|
|
176
|
+
return false;
|
|
177
|
+
if (prev && next && isW(prev, 'tbl') && isW(next, 'tbl'))
|
|
178
|
+
return false;
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Resolve a paragraph whose paragraph MARK revision was applied (deleted mark
|
|
183
|
+
* accepted): the paragraph break disappears, so the paragraph's remaining
|
|
184
|
+
* content merges into the FOLLOWING paragraph. The surviving (following)
|
|
185
|
+
* paragraph keeps its own w:pPr — formatting follows the surviving paragraph
|
|
186
|
+
* mark — and the merged-away paragraph's w:pPr is dropped.
|
|
187
|
+
*
|
|
188
|
+
* The revision targets only the mark, never the paragraph's contents, so the
|
|
189
|
+
* contents must not be dropped wholesale. When no following sibling paragraph
|
|
190
|
+
* exists (last block, or the next block is a table), there is no break to
|
|
191
|
+
* remove into: content-bearing paragraphs are kept, and emptied ones are
|
|
192
|
+
* removed only where removal keeps the parent structurally valid
|
|
193
|
+
* (canSafelyRemoveEmptyParagraph).
|
|
194
|
+
*
|
|
195
|
+
* @conformance ECMA-376 edition 5, Part 1 § 17.13.5.15
|
|
196
|
+
* @see https://github.com/UseJunior/safe-docx/issues/431
|
|
197
|
+
*/
|
|
198
|
+
function resolveParagraphMarkRevision(p) {
|
|
199
|
+
const parent = p.parentNode;
|
|
200
|
+
if (!parent)
|
|
201
|
+
return;
|
|
202
|
+
const target = findFollowingSiblingParagraph(p);
|
|
203
|
+
if (!target) {
|
|
204
|
+
if (!paragraphHasContent(p) && canSafelyRemoveEmptyParagraph(p)) {
|
|
205
|
+
parent.removeChild(p);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// Insertion point: before the target's first non-pPr child (the merged
|
|
210
|
+
// content precedes the target's own content in document order).
|
|
211
|
+
let ref = null;
|
|
212
|
+
for (let i = 0; i < target.childNodes.length; i++) {
|
|
213
|
+
const c = target.childNodes[i];
|
|
214
|
+
if (c.nodeType === 1 && isW(c, 'pPr'))
|
|
215
|
+
continue;
|
|
216
|
+
ref = c;
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
const toMove = [];
|
|
220
|
+
for (let i = 0; i < p.childNodes.length; i++) {
|
|
221
|
+
const c = p.childNodes[i];
|
|
222
|
+
if (c.nodeType === 1 && isW(c, 'pPr'))
|
|
223
|
+
continue;
|
|
224
|
+
toMove.push(c);
|
|
225
|
+
}
|
|
226
|
+
for (const c of toMove) {
|
|
227
|
+
target.insertBefore(c, ref);
|
|
228
|
+
}
|
|
229
|
+
parent.removeChild(p);
|
|
230
|
+
}
|
|
92
231
|
// ── Public API ──────────────────────────────────────────────────────
|
|
93
232
|
/**
|
|
94
233
|
* Accept all tracked changes in the document body or story root, producing a
|
|
@@ -102,20 +241,22 @@ export function acceptChanges(doc) {
|
|
|
102
241
|
if (!root) {
|
|
103
242
|
return { insertionsAccepted: 0, deletionsAccepted: 0, movesResolved: 0, propertyChangesResolved: 0 };
|
|
104
243
|
}
|
|
105
|
-
// Phase A — Identify paragraphs
|
|
106
|
-
const
|
|
244
|
+
// Phase A — Identify paragraphs whose MARK is a tracked deletion
|
|
245
|
+
const markDeletedParagraphs = [];
|
|
107
246
|
const allParagraphs = collectByLocalName(root, 'p');
|
|
108
247
|
for (const p of allParagraphs) {
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
248
|
+
// A paragraph-mark deletion (w:p > w:pPr > w:rPr > w:del) means the
|
|
249
|
+
// paragraph BREAK was deleted — accepting it merges the paragraph into the
|
|
250
|
+
// following one (resolveParagraphMarkRevision); the contents are deleted
|
|
251
|
+
// only via their own run-level w:del wrappers.
|
|
252
|
+
// We deliberately do NOT touch a paragraph based on content ("all runs inside
|
|
112
253
|
// w:del/w:moveFrom"): a run-level deletion under an untracked mark means text was
|
|
113
254
|
// deleted from a pre-existing paragraph, which Word/LibreOffice keep (empty) on
|
|
114
255
|
// accept. safe-docx's deleted paragraphs always carry the mark now, so the
|
|
115
256
|
// mark-based rule suffices and is Word-faithful. (Mirrors acceptAllChanges and the
|
|
116
257
|
// reject-side rule.)
|
|
117
258
|
if (paragraphHasParaMarker(p, 'del')) {
|
|
118
|
-
|
|
259
|
+
markDeletedParagraphs.push(p);
|
|
119
260
|
}
|
|
120
261
|
}
|
|
121
262
|
// Phase B — Remove deletions and move sources
|
|
@@ -158,11 +299,11 @@ export function acceptChanges(doc) {
|
|
|
158
299
|
}
|
|
159
300
|
}
|
|
160
301
|
}
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
302
|
+
// Resolve paragraphs collected in Phase A: merge each into its following
|
|
303
|
+
// paragraph (document order, so consecutive mark-deleted paragraphs cascade
|
|
304
|
+
// forward into the first surviving one).
|
|
305
|
+
for (const p of markDeletedParagraphs) {
|
|
306
|
+
resolveParagraphMarkRevision(p);
|
|
166
307
|
}
|
|
167
308
|
// Strip w:rsidDel attributes on remaining elements
|
|
168
309
|
const allElements = root.getElementsByTagNameNS(W_NS, '*');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accept_changes.js","sourceRoot":"","sources":["../../src/primitives/accept_changes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"accept_changes.js","sourceRoot":"","sources":["../../src/primitives/accept_changes.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,10 +5,13 @@ import { type SerializeMarkdownOptions } from './serialize_markdown.js';
|
|
|
5
5
|
import { type SerializeHtmlOptions } from './serialize_html.js';
|
|
6
6
|
import { type SerializePlainTextOptions } from './serialize_plaintext.js';
|
|
7
7
|
import type { FormattingMode } from './formatting_tags.js';
|
|
8
|
+
import { type StylesModel } from './styles.js';
|
|
9
|
+
import { type NumberingModel } from './numbering.js';
|
|
8
10
|
import { type ParagraphSpacingMutation, type ParagraphSpacingMutationResult, type TableCellPaddingMutation, type TableCellPaddingMutationResult, type TableRowHeightMutation, type TableRowHeightMutationResult } from './layout.js';
|
|
9
11
|
import { type ExtractTablesOptions, type ExtractTablesResult } from './tables.js';
|
|
10
12
|
import { type MergeRunsOptions, type MergeRunsResult } from './merge_runs.js';
|
|
11
13
|
import { type ValidateDocumentResult } from './validate_document.js';
|
|
14
|
+
import { type AiRevisionValidationTouchedContext, type ValidateAiRevisionsResult } from './validate_ai_revisions.js';
|
|
12
15
|
import { type AcceptChangesResult } from './accept_changes.js';
|
|
13
16
|
import { type RejectChangesResult } from './reject_changes.js';
|
|
14
17
|
import { type AddCommentResult, type AddCommentReplyResult, type Comment } from './comments.js';
|
|
@@ -32,6 +35,12 @@ export declare class DocxDocument {
|
|
|
32
35
|
private relsMap;
|
|
33
36
|
private dirty;
|
|
34
37
|
private documentViewCache;
|
|
38
|
+
/**
|
|
39
|
+
* Raw document.xml text as loaded, before normalize()/edits mutate the DOM.
|
|
40
|
+
* Reference for minimal re-serialization in toBuffer(); null for instances
|
|
41
|
+
* not created via load().
|
|
42
|
+
*/
|
|
43
|
+
private originalDocumentXmlText;
|
|
35
44
|
private constructor();
|
|
36
45
|
static load(buffer: Buffer): Promise<DocxDocument>;
|
|
37
46
|
getParagraphs(): Element[];
|
|
@@ -51,6 +60,7 @@ export declare class DocxDocument {
|
|
|
51
60
|
* Non-destructive, read-only check.
|
|
52
61
|
*/
|
|
53
62
|
validate(): ValidateDocumentResult;
|
|
63
|
+
validateAiRevisions(aiAuthor: string, touched?: AiRevisionValidationTouchedContext): Promise<ValidateAiRevisionsResult>;
|
|
54
64
|
/**
|
|
55
65
|
* Accept all tracked changes in document.xml plus supported revisionable
|
|
56
66
|
* side-story parts, producing clean XML with no revision markup.
|
|
@@ -70,6 +80,19 @@ export declare class DocxDocument {
|
|
|
70
80
|
paragraphs: ParagraphRef[];
|
|
71
81
|
totalParagraphs: number;
|
|
72
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* Parsed `word/numbering.xml` model (abstract numberings + instances), or null when the
|
|
85
|
+
* document has no numbering part. The document view's `numbering` field only carries
|
|
86
|
+
* `num_id`/`ilvl`; semantic converters (DOCX → ODT) need `numFmt`/`lvlText`/`start` to
|
|
87
|
+
* synthesize target-format list styles, so the full model is exposed here.
|
|
88
|
+
*/
|
|
89
|
+
getNumberingModel(): NumberingModel | null;
|
|
90
|
+
/**
|
|
91
|
+
* Parsed named-style model of the loaded document (empty when the package has no
|
|
92
|
+
* `word/styles.xml`). Semantic converters (DOCX → ODT) resolve heading/body style chains
|
|
93
|
+
* through it to seed their own style templates from the source's definitions.
|
|
94
|
+
*/
|
|
95
|
+
getStylesModel(): StylesModel;
|
|
73
96
|
buildDocumentView(opts?: {
|
|
74
97
|
includeSemanticTags?: boolean;
|
|
75
98
|
showFormatting?: boolean;
|
|
@@ -217,11 +240,26 @@ export declare class DocxDocument {
|
|
|
217
240
|
* has no comments part.
|
|
218
241
|
*/
|
|
219
242
|
getCommentsXmlClone(): Promise<Document | null>;
|
|
243
|
+
/**
|
|
244
|
+
* Serialize the document to a .docx buffer.
|
|
245
|
+
*
|
|
246
|
+
* With `minimalReserialization` (requires `cleanBookmarks`), top-level body
|
|
247
|
+
* blocks that no edit touched are restored element-for-element from the
|
|
248
|
+
* original document.xml instead of carrying the open-time normalization
|
|
249
|
+
* (proofErr stripping, run merging) to disk — so output diffs reflect the
|
|
250
|
+
* actual edit blast radius. Edited/inserted blocks are emitted as-is.
|
|
251
|
+
* Falls back to full re-serialization (blocksRestored: 0) when no original
|
|
252
|
+
* text was captured or reconciliation fails.
|
|
253
|
+
*
|
|
254
|
+
* @see https://github.com/UseJunior/safe-docx/issues/408
|
|
255
|
+
*/
|
|
220
256
|
toBuffer(opts?: {
|
|
221
257
|
cleanBookmarks?: boolean;
|
|
258
|
+
minimalReserialization?: boolean;
|
|
222
259
|
}): Promise<{
|
|
223
260
|
buffer: Buffer;
|
|
224
261
|
bookmarksRemoved: number;
|
|
262
|
+
blocksRestored: number;
|
|
225
263
|
}>;
|
|
226
264
|
}
|
|
227
265
|
//# sourceMappingURL=document.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/primitives/document.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../../src/primitives/document.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DocxZip } from './zip.js';
|
|
2
2
|
import { parseXml, serializeXml } from './xml.js';
|
|
3
|
+
import { maybeCaptureEmittedDocumentXml } from './schema-corpus-capture.js';
|
|
3
4
|
import { OOXML, W } from './namespaces.js';
|
|
4
5
|
import { createWmlElement, isW, getDirectChildrenByName } from './dom-helpers.js';
|
|
5
6
|
import { findParagraphByBookmarkId, insertParagraphBookmarks, cleanupInternalBookmarks, getParagraphBookmarkId, insertSingleParagraphBookmark, } from './bookmarks.js';
|
|
@@ -9,23 +10,23 @@ import { buildNodesForDocumentView } from './document_view.js';
|
|
|
9
10
|
import { serializeToMarkdown } from './serialize_markdown.js';
|
|
10
11
|
import { serializeToHtml } from './serialize_html.js';
|
|
11
12
|
import { serializeToPlainText } from './serialize_plaintext.js';
|
|
13
|
+
import { parseStylesXml } from './styles.js';
|
|
14
|
+
import { parseNumberingXml } from './numbering.js';
|
|
12
15
|
import { findUniqueSubstringMatch } from './matching.js';
|
|
13
16
|
import { parseDocumentRels } from './relationships.js';
|
|
14
17
|
import { setParagraphSpacing, setTableCellPadding, setTableRowHeight, } from './layout.js';
|
|
15
18
|
import { extractTables, } from './tables.js';
|
|
16
19
|
import { mergeRuns } from './merge_runs.js';
|
|
20
|
+
import { restoreUntouchedBlocks } from './minimal_save.js';
|
|
17
21
|
import { simplifyRedlines } from './simplify_redlines.js';
|
|
18
22
|
import { preventDoubleElevation } from './prevent_double_elevation.js';
|
|
19
23
|
import { validateDocument } from './validate_document.js';
|
|
24
|
+
import { validateAiRevisions as validateAiRevisionsImpl, } from './validate_ai_revisions.js';
|
|
25
|
+
import { enumerateRevisionStoryPartPaths, REVISION_STORY_PART_PATHS, } from './revision-parts.js';
|
|
20
26
|
import { acceptChanges as acceptChangesImpl } from './accept_changes.js';
|
|
21
27
|
import { rejectChanges as rejectChangesImpl } from './reject_changes.js';
|
|
22
28
|
import { bootstrapCommentParts, addComment as addCommentImpl, addCommentReply as addCommentReplyImpl, getComments as getCommentsImpl, getComment as getCommentImpl, deleteComment as deleteCommentImpl, } from './comments.js';
|
|
23
29
|
import { bootstrapFootnoteParts, getFootnotes as getFootnotesImpl, getFootnote as getFootnoteImpl, addFootnote as addFootnoteImpl, updateFootnoteText as updateFootnoteTextImpl, deleteFootnote as deleteFootnoteImpl, } from './footnotes.js';
|
|
24
|
-
const REVISION_STORY_PART_PATHS = [
|
|
25
|
-
'word/footnotes.xml',
|
|
26
|
-
'word/endnotes.xml',
|
|
27
|
-
'word/comments.xml',
|
|
28
|
-
];
|
|
29
30
|
function emptyAcceptChangesResult() {
|
|
30
31
|
return { insertionsAccepted: 0, deletionsAccepted: 0, movesResolved: 0, propertyChangesResolved: 0 };
|
|
31
32
|
}
|
|
@@ -307,7 +308,13 @@ export class DocxDocument {
|
|
|
307
308
|
relsMap;
|
|
308
309
|
dirty;
|
|
309
310
|
documentViewCache;
|
|
310
|
-
|
|
311
|
+
/**
|
|
312
|
+
* Raw document.xml text as loaded, before normalize()/edits mutate the DOM.
|
|
313
|
+
* Reference for minimal re-serialization in toBuffer(); null for instances
|
|
314
|
+
* not created via load().
|
|
315
|
+
*/
|
|
316
|
+
originalDocumentXmlText;
|
|
317
|
+
constructor(zip, documentXml, stylesXml, numberingXml, footnotesXml, relsMap, originalDocumentXmlText = null) {
|
|
311
318
|
this.zip = zip;
|
|
312
319
|
this.documentXml = documentXml;
|
|
313
320
|
this.stylesXml = stylesXml;
|
|
@@ -316,6 +323,7 @@ export class DocxDocument {
|
|
|
316
323
|
this.relsMap = relsMap;
|
|
317
324
|
this.dirty = false;
|
|
318
325
|
this.documentViewCache = null;
|
|
326
|
+
this.originalDocumentXmlText = originalDocumentXmlText;
|
|
319
327
|
}
|
|
320
328
|
static async load(buffer) {
|
|
321
329
|
const zip = await DocxZip.load(buffer);
|
|
@@ -332,7 +340,7 @@ export class DocxDocument {
|
|
|
332
340
|
// Load document relationships for hyperlink resolution.
|
|
333
341
|
const relsText = await zip.readTextOrNull('word/_rels/document.xml.rels');
|
|
334
342
|
const relsMap = relsText ? parseDocumentRels(parseXml(relsText)) : new Map();
|
|
335
|
-
return new DocxDocument(zip, doc, stylesXml, numberingXml, footnotesXml, relsMap);
|
|
343
|
+
return new DocxDocument(zip, doc, stylesXml, numberingXml, footnotesXml, relsMap, xml);
|
|
336
344
|
}
|
|
337
345
|
getParagraphs() {
|
|
338
346
|
const body = this.documentXml.getElementsByTagNameNS(OOXML.W_NS, W.body).item(0);
|
|
@@ -389,6 +397,21 @@ export class DocxDocument {
|
|
|
389
397
|
validate() {
|
|
390
398
|
return validateDocument(this.documentXml);
|
|
391
399
|
}
|
|
400
|
+
async validateAiRevisions(aiAuthor, touched) {
|
|
401
|
+
const stories = [{ part: 'word/document.xml', doc: this.documentXml }];
|
|
402
|
+
for (const partPath of enumerateRevisionStoryPartPaths(this.zip)) {
|
|
403
|
+
const xml = await this.zip.readTextOrNull(partPath);
|
|
404
|
+
if (!xml)
|
|
405
|
+
continue;
|
|
406
|
+
stories.push({ part: partPath, doc: parseXml(xml) });
|
|
407
|
+
}
|
|
408
|
+
return validateAiRevisionsImpl({
|
|
409
|
+
aiAuthor,
|
|
410
|
+
stories,
|
|
411
|
+
packageZip: this.zip,
|
|
412
|
+
touched,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
392
415
|
/**
|
|
393
416
|
* Accept all tracked changes in document.xml plus supported revisionable
|
|
394
417
|
* side-story parts, producing clean XML with no revision markup.
|
|
@@ -500,6 +523,23 @@ export class DocxDocument {
|
|
|
500
523
|
const endIdx = typeof limit === 'number' ? Math.min(total, startIdx + limit) : total;
|
|
501
524
|
return { paragraphs: all.slice(startIdx, endIdx), totalParagraphs: total };
|
|
502
525
|
}
|
|
526
|
+
/**
|
|
527
|
+
* Parsed `word/numbering.xml` model (abstract numberings + instances), or null when the
|
|
528
|
+
* document has no numbering part. The document view's `numbering` field only carries
|
|
529
|
+
* `num_id`/`ilvl`; semantic converters (DOCX → ODT) need `numFmt`/`lvlText`/`start` to
|
|
530
|
+
* synthesize target-format list styles, so the full model is exposed here.
|
|
531
|
+
*/
|
|
532
|
+
getNumberingModel() {
|
|
533
|
+
return this.numberingXml ? parseNumberingXml(this.numberingXml) : null;
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Parsed named-style model of the loaded document (empty when the package has no
|
|
537
|
+
* `word/styles.xml`). Semantic converters (DOCX → ODT) resolve heading/body style chains
|
|
538
|
+
* through it to seed their own style templates from the source's definitions.
|
|
539
|
+
*/
|
|
540
|
+
getStylesModel() {
|
|
541
|
+
return parseStylesXml(this.stylesXml);
|
|
542
|
+
}
|
|
503
543
|
buildDocumentView(opts) {
|
|
504
544
|
const includeSemanticTags = opts?.includeSemanticTags ?? true;
|
|
505
545
|
const showFormatting = opts?.showFormatting ?? false;
|
|
@@ -991,23 +1031,49 @@ export class DocxDocument {
|
|
|
991
1031
|
return null;
|
|
992
1032
|
return parseXml(commentsText);
|
|
993
1033
|
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Serialize the document to a .docx buffer.
|
|
1036
|
+
*
|
|
1037
|
+
* With `minimalReserialization` (requires `cleanBookmarks`), top-level body
|
|
1038
|
+
* blocks that no edit touched are restored element-for-element from the
|
|
1039
|
+
* original document.xml instead of carrying the open-time normalization
|
|
1040
|
+
* (proofErr stripping, run merging) to disk — so output diffs reflect the
|
|
1041
|
+
* actual edit blast radius. Edited/inserted blocks are emitted as-is.
|
|
1042
|
+
* Falls back to full re-serialization (blocksRestored: 0) when no original
|
|
1043
|
+
* text was captured or reconciliation fails.
|
|
1044
|
+
*
|
|
1045
|
+
* @see https://github.com/UseJunior/safe-docx/issues/408
|
|
1046
|
+
*/
|
|
994
1047
|
async toBuffer(opts) {
|
|
995
1048
|
// Always write the latest document.xml when saving.
|
|
996
1049
|
// Important: when cleanBookmarks=true (download), we must NOT mutate session state.
|
|
997
1050
|
const xmlWithBookmarks = serializeXml(this.documentXml);
|
|
1051
|
+
maybeCaptureEmittedDocumentXml(xmlWithBookmarks);
|
|
998
1052
|
this.zip.writeText('word/document.xml', xmlWithBookmarks);
|
|
999
1053
|
if (opts?.cleanBookmarks) {
|
|
1000
1054
|
const cloned = parseXml(xmlWithBookmarks);
|
|
1001
1055
|
const bookmarksRemoved = cleanupInternalBookmarks(cloned);
|
|
1056
|
+
let blocksRestored = 0;
|
|
1057
|
+
if (opts.minimalReserialization && this.originalDocumentXmlText !== null) {
|
|
1058
|
+
try {
|
|
1059
|
+
blocksRestored = restoreUntouchedBlocks(cloned, this.originalDocumentXmlText);
|
|
1060
|
+
}
|
|
1061
|
+
catch {
|
|
1062
|
+
// Reconciliation is best-effort; the fully re-serialized DOM is
|
|
1063
|
+
// always a correct (if non-minimal) save.
|
|
1064
|
+
blocksRestored = 0;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1002
1067
|
const cleanedXml = serializeXml(cloned);
|
|
1003
1068
|
// Temporarily swap document.xml in the zip for output, then restore.
|
|
1069
|
+
maybeCaptureEmittedDocumentXml(cleanedXml);
|
|
1004
1070
|
this.zip.writeText('word/document.xml', cleanedXml);
|
|
1005
1071
|
const buffer = await this.zip.toBuffer();
|
|
1006
1072
|
this.zip.writeText('word/document.xml', xmlWithBookmarks);
|
|
1007
|
-
return { buffer, bookmarksRemoved };
|
|
1073
|
+
return { buffer, bookmarksRemoved, blocksRestored };
|
|
1008
1074
|
}
|
|
1009
1075
|
const buffer = await this.zip.toBuffer();
|
|
1010
|
-
return { buffer, bookmarksRemoved: 0 };
|
|
1076
|
+
return { buffer, bookmarksRemoved: 0, blocksRestored: 0 };
|
|
1011
1077
|
}
|
|
1012
1078
|
}
|
|
1013
1079
|
//# sourceMappingURL=document.js.map
|