@stll/folio-core 0.37.5 → 0.39.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/dist/ai-edits/apply.js +275 -88
- package/dist/ai-edits/clean-text.js +12 -1
- package/dist/ai-edits/headless.d.ts +110 -0
- package/dist/ai-edits/headless.js +569 -40
- package/dist/ai-edits/snapshot.d.ts +24 -1
- package/dist/ai-edits/snapshot.js +206 -9
- package/dist/ai-edits/table-geometry.d.ts +7 -7
- package/dist/ai-edits/table-geometry.js +43 -27
- package/dist/ai-edits/table-template.d.ts +2 -1
- package/dist/ai-edits/table-template.js +9 -3
- package/dist/ai-edits/types.d.ts +37 -15
- package/dist/compare/__fixtures__/body-sequence.d.ts +4 -0
- package/dist/compare/__fixtures__/body-sequence.js +5 -3
- package/dist/compare/compare.d.ts +26 -2
- package/dist/compare/compare.js +444 -16
- package/dist/compare/content-alignment.js +3 -2
- package/dist/compare/content-types.d.ts +34 -2
- package/dist/compare/content.d.ts +13 -10
- package/dist/compare/content.js +69 -23
- package/dist/compare/formatting.d.ts +4 -22
- package/dist/compare/formatting.js +8 -112
- package/dist/compare/inline-atom-resources.d.ts +6 -0
- package/dist/compare/inline-atom-resources.js +26 -0
- package/dist/compare/inline-atoms.d.ts +35 -0
- package/dist/compare/inline-atoms.js +383 -0
- package/dist/compare/inline-provenance.d.ts +36 -0
- package/dist/compare/inline-provenance.js +334 -0
- package/dist/compare/plan.d.ts +4 -1
- package/dist/compare/plan.js +32 -4
- package/dist/compare/scenario.d.ts +4 -6
- package/dist/compare/section-boundary-properties.d.ts +63 -0
- package/dist/compare/section-boundary-properties.js +235 -0
- package/dist/compare/style-resources.d.ts +30 -0
- package/dist/compare/style-resources.js +404 -0
- package/dist/compare/types.d.ts +50 -11
- package/dist/compare/types.js +3 -1
- package/dist/compare/verification.d.ts +3 -5
- package/dist/compare/verification.js +8 -39
- package/dist/compat/eigenpal.d.ts +4 -4
- package/dist/compat/eigenpal.js +3 -3
- package/dist/controller/layoutPipeline.js +4 -0
- package/dist/display-list/build/buildContext.d.ts +3 -1
- package/dist/display-list/build/buildDisplayList.d.ts +4 -1
- package/dist/display-list/build/buildDisplayList.js +38 -4
- package/dist/display-list/build/commentAnnotations.d.ts +10 -0
- package/dist/display-list/build/commentAnnotations.js +17 -0
- package/dist/display-list/build/paragraphPrimitives.js +39 -1
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/display-list/types.d.ts +16 -1
- package/dist/document-operations.d.ts +5 -3
- package/dist/document-operations.js +112 -5
- package/dist/docx/blockContentParser.js +14 -2
- package/dist/docx/diagramPreview.d.ts +7 -0
- package/dist/docx/diagramPreview.js +191 -0
- package/dist/docx/drawingIdNormalization.js +43 -2
- package/dist/docx/drawingRelationships.d.ts +10 -0
- package/dist/docx/drawingRelationships.js +28 -0
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/hyperlinkParser.js +3 -5
- package/dist/docx/imageRawXml.d.ts +8 -0
- package/dist/docx/imageRawXml.js +13 -0
- package/dist/docx/newImage.d.ts +2 -2
- package/dist/docx/newImage.js +3 -3
- package/dist/docx/numberingParser.js +30 -27
- package/dist/docx/paragraphParser.js +11 -4
- package/dist/docx/paragraphTextBoxEnrichment.js +2 -1
- package/dist/docx/parser.js +13 -0
- package/dist/docx/removeHeaderFooterParts.d.ts +14 -0
- package/dist/docx/removeHeaderFooterParts.js +87 -0
- package/dist/docx/rezip.d.ts +3 -1
- package/dist/docx/rezip.js +143 -41
- package/dist/docx/runParser.js +24 -5
- package/dist/docx/sectionParser.js +3 -0
- package/dist/docx/sectionReferenceHistory.d.ts +17 -0
- package/dist/docx/sectionReferenceHistory.js +59 -0
- package/dist/docx/selectiveSave.js +11 -31
- package/dist/docx/selectiveXmlPatch.d.ts +8 -1
- package/dist/docx/selectiveXmlPatch.js +62 -2
- package/dist/docx/serializer/paragraphSerializer.js +2 -0
- package/dist/docx/serializer/partNamespaces.d.ts +1 -1
- package/dist/docx/serializer/partNamespaces.js +4 -0
- package/dist/docx/serializer/runSerializer.js +5 -2
- package/dist/docx/serializer/sectionPropertiesSerializer.js +5 -2
- package/dist/docx/serializer/textFormattingSerializer.d.ts +1 -1
- package/dist/docx/serializer/textFormattingSerializer.js +3 -1
- package/dist/docx/tableParser.js +21 -11
- package/dist/docx/textBoxParser.js +25 -5
- package/dist/docx/xmlParser.d.ts +10 -1
- package/dist/docx/xmlParser.js +23 -1
- package/dist/export-pdf.js +2 -0
- package/dist/headless-layout.js +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/internal/compare/inline-presentation.d.ts +20 -0
- package/dist/internal/compare/inline-presentation.js +222 -0
- package/dist/internal/paragraphFormattingSerialization.d.ts +3 -1
- package/dist/internal/paragraphFormattingSerialization.js +8 -1
- package/dist/internal/sectionReferenceResolution.d.ts +21 -0
- package/dist/internal/sectionReferenceResolution.js +72 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +1 -0
- package/dist/layout-engine/index.js +5 -5
- package/dist/layout-engine/sectionVerticalAlignment.d.ts +7 -0
- package/dist/layout-engine/sectionVerticalAlignment.js +52 -0
- package/dist/layout-engine/types.d.ts +3 -1
- package/dist/markdown/renderRuns.js +1 -0
- package/dist/markdown/renderTable.js +1 -0
- package/dist/pdf/writePdf.js +37 -2
- package/dist/prosemirror/attrs/index.js +55 -1
- package/dist/prosemirror/commands/comments.d.ts +11 -1
- package/dist/prosemirror/commands/comments.js +68 -6
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +9 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +4 -10
- package/dist/prosemirror/conversion/fromProseDoc.js +17 -8
- package/dist/prosemirror/conversion/toProseDoc.js +18 -57
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +3 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +39 -1
- package/dist/prosemirror/imageCommit.js +7 -9
- package/dist/prosemirror/paragraphIndentation.d.ts +21 -0
- package/dist/prosemirror/paragraphIndentation.js +72 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +3 -1
- package/dist/prosemirror/plugins/documentNumbering.js +7 -1
- package/dist/prosemirror/plugins/documentStyles.d.ts +3 -1
- package/dist/prosemirror/plugins/documentStyles.js +7 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +3 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +15 -2
- package/dist/prosemirror/runFormattingInlineCarriers.js +33 -3
- package/dist/prosemirror/runStyleFormatting.d.ts +15 -2
- package/dist/prosemirror/runStyleFormatting.js +76 -2
- package/dist/prosemirror/schema/marks.d.ts +3 -1
- package/dist/prosemirror/schema/marks.js +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +5 -0
- package/dist/prosemirror/tableCellRevisionVisibility.d.ts +6 -0
- package/dist/prosemirror/tableCellRevisionVisibility.js +14 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
- package/dist/redline.js +15 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/version-comparison.d.ts +2 -0
- package/dist/version-comparison.js +7 -2
- package/package.json +2 -2
|
@@ -52,8 +52,7 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
|
|
|
52
52
|
if (rels) {
|
|
53
53
|
const rel = rels.get(rId);
|
|
54
54
|
if (rel) {
|
|
55
|
-
|
|
56
|
-
if (safeHref) hyperlink.href = safeHref;
|
|
55
|
+
if (sanitizeExternalUrl(rel.target)) hyperlink.href = rel.target;
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -172,9 +171,8 @@ function resolveHyperlinkUrl(hyperlink, rels) {
|
|
|
172
171
|
if (hyperlink.rId) {
|
|
173
172
|
const rel = rels.get(hyperlink.rId);
|
|
174
173
|
if (rel) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
hyperlink.href = safeHref;
|
|
174
|
+
if (sanitizeExternalUrl(rel.target)) {
|
|
175
|
+
hyperlink.href = rel.target;
|
|
178
176
|
return hyperlink.href;
|
|
179
177
|
}
|
|
180
178
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/imageRawXml.d.ts
|
|
3
|
+
/** Fingerprints modeled image fields which make raw DrawingML stale when edited. */
|
|
4
|
+
declare const imageRawXmlFingerprint: (image: document_d_exports.Image) => string;
|
|
5
|
+
/** Editable raw drawing XML can replay only while its modeled projection is unchanged. */
|
|
6
|
+
declare const canReplayEditableImageRawXml: (drawing: document_d_exports.DrawingContent) => boolean;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { canReplayEditableImageRawXml, imageRawXmlFingerprint };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { canonicalJson } from "../utils/canonicalJson.js";
|
|
2
|
+
import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
|
|
3
|
+
//#region src/docx/imageRawXml.ts
|
|
4
|
+
const editableImageProjection = ({ id: _id, rId: _rId, src: _src, mimeType: _mimeType, filename: _filename, ...image }) => image;
|
|
5
|
+
/** Fingerprints modeled image fields which make raw DrawingML stale when edited. */
|
|
6
|
+
const imageRawXmlFingerprint = (image) => canonicalJson(editableImageProjection(image));
|
|
7
|
+
/** Editable raw drawing XML can replay only while its modeled projection is unchanged. */
|
|
8
|
+
const canReplayEditableImageRawXml = (drawing) => {
|
|
9
|
+
if (drawing.rawXmlMode === DRAWING_RAW_XML_MODES.PRESERVE_ONLY) return true;
|
|
10
|
+
return drawing.rawImageFingerprint === void 0 || drawing.rawImageFingerprint === imageRawXmlFingerprint(drawing.image);
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { canReplayEditableImageRawXml, imageRawXmlFingerprint };
|
package/dist/docx/newImage.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { DrawingContent, RunContent } from "../types/content.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* A drawing needs a new package image part only when it is model-driven.
|
|
5
5
|
*
|
|
6
|
-
* Raw OOXML drawings can carry
|
|
7
|
-
*
|
|
6
|
+
* Raw OOXML drawings can carry previews for browser rendering. Only an explicit
|
|
7
|
+
* synthetic relationship opts a detached raw picture into media registration.
|
|
8
8
|
*/
|
|
9
9
|
declare const isNewDataUrlDrawing: (content: RunContent) => content is DrawingContent;
|
|
10
10
|
//#endregion
|
package/dist/docx/newImage.js
CHANGED
|
@@ -3,9 +3,9 @@ const SYNTHETIC_IMAGE_RID_PREFIX = "rId_img_";
|
|
|
3
3
|
/**
|
|
4
4
|
* A drawing needs a new package image part only when it is model-driven.
|
|
5
5
|
*
|
|
6
|
-
* Raw OOXML drawings can carry
|
|
7
|
-
*
|
|
6
|
+
* Raw OOXML drawings can carry previews for browser rendering. Only an explicit
|
|
7
|
+
* synthetic relationship opts a detached raw picture into media registration.
|
|
8
8
|
*/
|
|
9
|
-
const isNewDataUrlDrawing = (content) => content.type === "drawing" && !content.rawXml && content.image.src?.startsWith("data:") === true && (!content.image.rId || content.image.rId.startsWith(SYNTHETIC_IMAGE_RID_PREFIX));
|
|
9
|
+
const isNewDataUrlDrawing = (content) => content.type === "drawing" && (!content.rawXml || content.image.rId?.startsWith(SYNTHETIC_IMAGE_RID_PREFIX) === true) && content.image.src?.startsWith("data:") === true && (!content.image.rId || content.image.rId.startsWith(SYNTHETIC_IMAGE_RID_PREFIX));
|
|
10
10
|
//#endregion
|
|
11
11
|
export { isNewDataUrlDrawing };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { formatOoxmlCounter, padDecimal } from "./ooxmlCounterFormatter.js";
|
|
2
2
|
import { LevelSuffixSchema, narrowEnum } from "./parserEnums.js";
|
|
3
3
|
import { parseRunProperties } from "./runParser.js";
|
|
4
|
-
import { findChild, findChildren, getAttribute, parseBooleanElement, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
4
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, findChild, findChildren, getAttribute, getLocalName, getNamespaceUri, parseBooleanElement, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
5
5
|
//#region src/docx/numberingParser.ts
|
|
6
6
|
const NUMBER_FORMAT_MAP = {
|
|
7
7
|
decimal: "decimal",
|
|
@@ -65,6 +65,7 @@ const NUMBER_FORMAT_MAP = {
|
|
|
65
65
|
thaiNumbers: "thaiNumbers",
|
|
66
66
|
thaiCounting: "thaiCounting"
|
|
67
67
|
};
|
|
68
|
+
const wordprocessingLocalName = (element) => WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(element) ?? "") ? getLocalName(element.name) : null;
|
|
68
69
|
/**
|
|
69
70
|
* Parse numbering.xml into NumberingDefinitions
|
|
70
71
|
*
|
|
@@ -110,20 +111,20 @@ function parseAbstractNumbering(element) {
|
|
|
110
111
|
const levelElements = [];
|
|
111
112
|
for (const child of element.elements ?? []) {
|
|
112
113
|
if (child.type !== "element") continue;
|
|
113
|
-
switch (child
|
|
114
|
-
case "
|
|
114
|
+
switch (wordprocessingLocalName(child)) {
|
|
115
|
+
case "multiLevelType":
|
|
115
116
|
multiLevelTypeEl ??= child;
|
|
116
117
|
break;
|
|
117
|
-
case "
|
|
118
|
+
case "name":
|
|
118
119
|
nameEl ??= child;
|
|
119
120
|
break;
|
|
120
|
-
case "
|
|
121
|
+
case "numStyleLink":
|
|
121
122
|
numStyleLinkEl ??= child;
|
|
122
123
|
break;
|
|
123
|
-
case "
|
|
124
|
+
case "styleLink":
|
|
124
125
|
styleLinkEl ??= child;
|
|
125
126
|
break;
|
|
126
|
-
case "
|
|
127
|
+
case "lvl":
|
|
127
128
|
levelElements.push(child);
|
|
128
129
|
break;
|
|
129
130
|
default: break;
|
|
@@ -164,11 +165,11 @@ function parseNumberingInstance(element) {
|
|
|
164
165
|
const overrideElements = [];
|
|
165
166
|
for (const child of element.elements ?? []) {
|
|
166
167
|
if (child.type !== "element") continue;
|
|
167
|
-
if (child
|
|
168
|
+
if (wordprocessingLocalName(child) === "abstractNumId") {
|
|
168
169
|
abstractNumIdEl ??= child;
|
|
169
170
|
continue;
|
|
170
171
|
}
|
|
171
|
-
if (child
|
|
172
|
+
if (wordprocessingLocalName(child) === "lvlOverride") overrideElements.push(child);
|
|
172
173
|
}
|
|
173
174
|
if (!abstractNumIdEl) return null;
|
|
174
175
|
const abstractNumIdStr = getAttribute(abstractNumIdEl, "w", "val");
|
|
@@ -191,11 +192,11 @@ function parseNumberingInstance(element) {
|
|
|
191
192
|
let lvlEl;
|
|
192
193
|
for (const child of overrideEl.elements ?? []) {
|
|
193
194
|
if (child.type !== "element") continue;
|
|
194
|
-
if (child
|
|
195
|
+
if (wordprocessingLocalName(child) === "startOverride") {
|
|
195
196
|
startOverrideEl ??= child;
|
|
196
197
|
continue;
|
|
197
198
|
}
|
|
198
|
-
if (child
|
|
199
|
+
if (wordprocessingLocalName(child) === "lvl") lvlEl ??= child;
|
|
199
200
|
}
|
|
200
201
|
if (startOverrideEl) {
|
|
201
202
|
const startVal = getAttribute(startOverrideEl, "w", "val");
|
|
@@ -239,38 +240,40 @@ function parseListLevel(element) {
|
|
|
239
240
|
let rPrEl;
|
|
240
241
|
for (const child of element.elements ?? []) {
|
|
241
242
|
if (child.type !== "element") continue;
|
|
242
|
-
|
|
243
|
-
|
|
243
|
+
const localName = wordprocessingLocalName(child);
|
|
244
|
+
if (localName === null) {
|
|
245
|
+
if (getLocalName(child.name) === "AlternateContent") alternateEl ??= child;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
switch (localName) {
|
|
249
|
+
case "start":
|
|
244
250
|
startEl ??= child;
|
|
245
251
|
break;
|
|
246
|
-
case "
|
|
252
|
+
case "numFmt":
|
|
247
253
|
numFmtEl ??= child;
|
|
248
254
|
break;
|
|
249
|
-
case "
|
|
250
|
-
alternateEl ??= child;
|
|
251
|
-
break;
|
|
252
|
-
case "w:lvlText":
|
|
255
|
+
case "lvlText":
|
|
253
256
|
lvlTextEl ??= child;
|
|
254
257
|
break;
|
|
255
|
-
case "
|
|
258
|
+
case "lvlJc":
|
|
256
259
|
lvlJcEl ??= child;
|
|
257
260
|
break;
|
|
258
|
-
case "
|
|
261
|
+
case "suff":
|
|
259
262
|
suffEl ??= child;
|
|
260
263
|
break;
|
|
261
|
-
case "
|
|
264
|
+
case "isLgl":
|
|
262
265
|
isLglEl ??= child;
|
|
263
266
|
break;
|
|
264
|
-
case "
|
|
267
|
+
case "lvlRestart":
|
|
265
268
|
lvlRestartEl ??= child;
|
|
266
269
|
break;
|
|
267
|
-
case "
|
|
270
|
+
case "legacy":
|
|
268
271
|
legacyEl ??= child;
|
|
269
272
|
break;
|
|
270
|
-
case "
|
|
273
|
+
case "pPr":
|
|
271
274
|
pPrEl ??= child;
|
|
272
275
|
break;
|
|
273
|
-
case "
|
|
276
|
+
case "rPr":
|
|
274
277
|
rPrEl ??= child;
|
|
275
278
|
break;
|
|
276
279
|
default: break;
|
|
@@ -361,11 +364,11 @@ function parseLevelParagraphProps(pPr) {
|
|
|
361
364
|
let tabsEl;
|
|
362
365
|
for (const child of pPr.elements ?? []) {
|
|
363
366
|
if (child.type !== "element") continue;
|
|
364
|
-
if (child
|
|
367
|
+
if (wordprocessingLocalName(child) === "ind") {
|
|
365
368
|
indEl ??= child;
|
|
366
369
|
continue;
|
|
367
370
|
}
|
|
368
|
-
if (child
|
|
371
|
+
if (wordprocessingLocalName(child) === "tabs") tabsEl ??= child;
|
|
369
372
|
}
|
|
370
373
|
if (indEl) {
|
|
371
374
|
const left = parseNumericAttribute(indEl, "w", "left");
|
|
@@ -13,10 +13,11 @@ import { parseSdtProperties } from "./sdtProperties.js";
|
|
|
13
13
|
import { parseSectionProperties } from "./sectionParser.js";
|
|
14
14
|
import { parsePropertyChangeInfo, parseTrackedChangeInfo } from "./trackedChangeInfo.js";
|
|
15
15
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
16
|
-
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findChild, findChildByNamespaceUri, findChildren, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, matchesName, mergeXmlnsDeclarations, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute } from "./xmlParser.js";
|
|
16
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findChild, findChildByNamespaceUri, findChildren, findChildrenByNamespaceUri, getAttribute, getAttributeByNamespaceUri, getChildElements, getLocalName, matchesName, mergeXmlnsDeclarations, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute, selectAlternateContentBranch } from "./xmlParser.js";
|
|
17
17
|
import { panic } from "better-result";
|
|
18
|
-
import { PARAGRAPH_MARK_CHANGE_KINDS } from "@stll/docx-core/model";
|
|
18
|
+
import { PARAGRAPH_MARK_CHANGE_KINDS, REVIEW_CARRIERS } from "@stll/docx-core/model";
|
|
19
19
|
//#region src/docx/paragraphParser.ts
|
|
20
|
+
const FOLIO_REVIEW_HISTORY_NAMESPACES = /* @__PURE__ */ new Set(["urn:stella:folio:review-history:1"]);
|
|
20
21
|
/**
|
|
21
22
|
* Extract plain text from a math element (recursive text content extraction)
|
|
22
23
|
*/
|
|
@@ -532,7 +533,7 @@ function parseParagraphMarkChange(pPr) {
|
|
|
532
533
|
}
|
|
533
534
|
}
|
|
534
535
|
function isTrackedChangeWrapperChild(content) {
|
|
535
|
-
return content.type === "run" || content.type === "hyperlink" || content.type === "bookmarkStart" || content.type === "bookmarkEnd" || content.type === "simpleField" || content.type === "complexField" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo";
|
|
536
|
+
return content.type === "run" || content.type === "hyperlink" || content.type === "bookmarkStart" || content.type === "bookmarkEnd" || content.type === "simpleField" || content.type === "complexField" || content.type === "mathEquation" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo";
|
|
536
537
|
}
|
|
537
538
|
function isInlineSdtContent(content) {
|
|
538
539
|
return content.type === "run" || content.type === "hyperlink" || content.type === "simpleField" || content.type === "complexField" || content.type === "inlineSdt" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo" || content.type === "mathEquation";
|
|
@@ -887,7 +888,7 @@ function parseParagraphContents(paraElement, styles, theme, _numbering, rels, me
|
|
|
887
888
|
}];
|
|
888
889
|
const complexField = {
|
|
889
890
|
type: "complexField",
|
|
890
|
-
instruction: complexFieldInstr
|
|
891
|
+
instruction: complexFieldInstr,
|
|
891
892
|
fieldType: parseFieldType(complexFieldInstr),
|
|
892
893
|
fieldCode: complexFieldCodeRuns,
|
|
893
894
|
fieldResult: resultRuns
|
|
@@ -911,6 +912,11 @@ function parseParagraphContents(paraElement, styles, theme, _numbering, rels, me
|
|
|
911
912
|
} else if (run.content.length > 0 || hasRunPayloadElement(runElement)) contents.push(run);
|
|
912
913
|
break;
|
|
913
914
|
}
|
|
915
|
+
case "AlternateContent": {
|
|
916
|
+
const selectedBranch = selectAlternateContentBranch(child);
|
|
917
|
+
if (selectedBranch) contents.push(...parseParagraphContents(selectedBranch, styles, theme, null, rels, media, trackedContext, mergeXmlnsDeclarations(inScopeXmlns, child)));
|
|
918
|
+
break;
|
|
919
|
+
}
|
|
914
920
|
case "hyperlink":
|
|
915
921
|
contents.push(...parseHyperlinkParagraphContents(child, rels, styles, theme, media, inScopeXmlns));
|
|
916
922
|
break;
|
|
@@ -1078,6 +1084,7 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
|
|
|
1078
1084
|
if (paraId && isValidHexId(paraId)) paragraph.paraId = paraIdInRange(paraId);
|
|
1079
1085
|
const textId = getAttribute(node, "w14", "textId") ?? getAttribute(node, "w", "textId");
|
|
1080
1086
|
if (textId && isValidHexId(textId)) paragraph.textId = paraIdInRange(textId);
|
|
1087
|
+
if (getAttributeByNamespaceUri(node, FOLIO_REVIEW_HISTORY_NAMESPACES, "reviewCarrier") === REVIEW_CARRIERS.TERMINAL_TABLE) paragraph.reviewCarrier = REVIEW_CARRIERS.TERMINAL_TABLE;
|
|
1081
1088
|
if (!options?.inHeaderFooter && paragraphStartsWithRenderedPageBreak(node)) paragraph.renderedPageBreakBefore = true;
|
|
1082
1089
|
const pPr = findChild(node, "w", "pPr");
|
|
1083
1090
|
if (pPr) {
|
|
@@ -207,7 +207,8 @@ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rel
|
|
|
207
207
|
...textBox.autoFit !== void 0 ? { autoFit: textBox.autoFit } : {},
|
|
208
208
|
...textBox.textWrap !== void 0 ? { textWrap: textBox.textWrap } : {},
|
|
209
209
|
...textBox.verticalAlign !== void 0 ? { anchor: textBox.verticalAlign } : {},
|
|
210
|
-
...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
|
|
210
|
+
...textBox.margins !== void 0 ? { margins: textBox.margins } : {},
|
|
211
|
+
...textBox.wordArt !== void 0 ? { wordArt: textBox.wordArt } : {}
|
|
211
212
|
}
|
|
212
213
|
};
|
|
213
214
|
if (textBox.id) shape.id = textBox.id;
|
package/dist/docx/parser.js
CHANGED
|
@@ -27,6 +27,7 @@ import { applyThemeFontLang, parseTheme } from "./themeParser.js";
|
|
|
27
27
|
import { normalizeTrackedMoveRanges } from "./trackedMoveRangeNormalization.js";
|
|
28
28
|
import { getMediaMimeType, mediaToDataUrl, unzipDocx } from "./unzip.js";
|
|
29
29
|
import { enforcePackageVmlPreviewBudget } from "./vmlPreview.js";
|
|
30
|
+
import { FOLIO_XML_RESOURCE_LIMITS } from "./xmlResourceLimits.js";
|
|
30
31
|
import { TaggedError } from "better-result";
|
|
31
32
|
//#region src/docx/parser.ts
|
|
32
33
|
/**
|
|
@@ -341,6 +342,18 @@ async function buildMediaMap(raw, rels) {
|
|
|
341
342
|
const normalizedPath = path.replace(/^word\//u, "");
|
|
342
343
|
if (normalizedPath !== path) media.set(normalizedPath, mediaFile);
|
|
343
344
|
}
|
|
345
|
+
for (const [path, xml] of raw.allXml.entries()) {
|
|
346
|
+
if (!/^word\/diagrams\/[^/]+\.xml$/iu.test(path) || new TextEncoder().encode(xml).byteLength > FOLIO_XML_RESOURCE_LIMITS.maxBytes) continue;
|
|
347
|
+
const data = new TextEncoder().encode(xml).buffer;
|
|
348
|
+
const file = {
|
|
349
|
+
path,
|
|
350
|
+
filename: path.split("/").pop() ?? path,
|
|
351
|
+
mimeType: "application/xml",
|
|
352
|
+
data
|
|
353
|
+
};
|
|
354
|
+
media.set(path, file);
|
|
355
|
+
media.set(path.replace(/^word\//u, ""), file);
|
|
356
|
+
}
|
|
344
357
|
return media;
|
|
345
358
|
}
|
|
346
359
|
async function applyMediaResolver(media, resolver) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { RemovedSectionReference } from "../internal/sectionEndpointResolution.js";
|
|
3
|
+
import JSZip from "jszip";
|
|
4
|
+
//#region src/docx/removeHeaderFooterParts.d.ts
|
|
5
|
+
type RemoveResolvedHeaderFooterPartsOptions = {
|
|
6
|
+
document: document_d_exports.Document;
|
|
7
|
+
zip: JSZip;
|
|
8
|
+
removedReferences: readonly RemovedSectionReference[];
|
|
9
|
+
compressionLevel: number;
|
|
10
|
+
};
|
|
11
|
+
/** Remove only parts whose last selection was explicitly resolved out of the document. */
|
|
12
|
+
declare const removeResolvedHeaderFooterParts: ({ document, zip, removedReferences, compressionLevel }: RemoveResolvedHeaderFooterPartsOptions) => Promise<void>;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { removeResolvedHeaderFooterParts };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { isUnsafePackagePath } from "./packageParts.js";
|
|
2
|
+
import { parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
3
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
4
|
+
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, cloneElement, getAttribute, getLocalName, getNamespaceUri, parseXmlDocument } from "./xmlParser.js";
|
|
5
|
+
import { panic } from "better-result";
|
|
6
|
+
import { OOXML_NS } from "@stll/docx-utils";
|
|
7
|
+
//#region src/docx/removeHeaderFooterParts.ts
|
|
8
|
+
const DOCUMENT_RELS_PATH = "word/_rels/document.xml.rels";
|
|
9
|
+
const officeRelationshipHasType = (type, kind) => [...OFFICE_RELATIONSHIP_NAMESPACE_URIS].some((namespace) => type === `${namespace}/${kind}`);
|
|
10
|
+
const withoutChildren = (xml, remove) => {
|
|
11
|
+
const root = parseXmlDocument(xml);
|
|
12
|
+
if (!root) return panic("Cannot update malformed package metadata");
|
|
13
|
+
return captureVerbatimXml(cloneElement(root, { elements: (root.elements ?? []).filter((child) => !remove(child)) }));
|
|
14
|
+
};
|
|
15
|
+
/** Remove only parts whose last selection was explicitly resolved out of the document. */
|
|
16
|
+
const removeResolvedHeaderFooterParts = async ({ document, zip, removedReferences, compressionLevel }) => {
|
|
17
|
+
if (removedReferences.length === 0) return;
|
|
18
|
+
const relsFile = zip.file(DOCUMENT_RELS_PATH);
|
|
19
|
+
if (!relsFile) return panic("A resolved header/footer part has no document relationships");
|
|
20
|
+
const relsXml = await relsFile.async("text");
|
|
21
|
+
const relationships = parseRelationships(relsXml);
|
|
22
|
+
const removedIds = /* @__PURE__ */ new Set();
|
|
23
|
+
const candidates = /* @__PURE__ */ new Set();
|
|
24
|
+
for (const { part, relationshipId } of removedReferences) {
|
|
25
|
+
if ((part === "header" ? document.package.headers : document.package.footers)?.has(relationshipId)) continue;
|
|
26
|
+
const relationship = relationships.get(relationshipId);
|
|
27
|
+
if (!relationship) continue;
|
|
28
|
+
if (!officeRelationshipHasType(relationship.type, part) || relationship.targetMode === "External") return panic("Resolved header/footer relationship has an unexpected part type");
|
|
29
|
+
const path = resolveRelativePath(DOCUMENT_RELS_PATH, relationship.target);
|
|
30
|
+
if (isUnsafePackagePath(path)) return panic("Resolved header/footer has an unsafe package path");
|
|
31
|
+
removedIds.add(relationshipId);
|
|
32
|
+
candidates.add(path);
|
|
33
|
+
}
|
|
34
|
+
if (removedIds.size === 0) return;
|
|
35
|
+
for (const relationship of relationships.values()) {
|
|
36
|
+
if (removedIds.has(relationship.id) || relationship.targetMode === "External") continue;
|
|
37
|
+
candidates.delete(resolveRelativePath(DOCUMENT_RELS_PATH, relationship.target));
|
|
38
|
+
}
|
|
39
|
+
for (const file of Object.values(zip.files)) {
|
|
40
|
+
if (file.dir || !file.name.endsWith(".rels") || file.name === DOCUMENT_RELS_PATH) continue;
|
|
41
|
+
const otherRelationships = parseRelationships(await file.async("text"));
|
|
42
|
+
for (const relationship of otherRelationships.values()) if (relationship.targetMode !== "External") candidates.delete(resolveRelativePath(file.name, relationship.target));
|
|
43
|
+
}
|
|
44
|
+
const retiredMedia = /* @__PURE__ */ new Set();
|
|
45
|
+
for (const path of candidates) {
|
|
46
|
+
const slash = path.lastIndexOf("/");
|
|
47
|
+
const relsPath = `${path.slice(0, slash + 1)}_rels/${path.slice(slash + 1)}.rels`;
|
|
48
|
+
const partRels = zip.file(relsPath);
|
|
49
|
+
if (!partRels) continue;
|
|
50
|
+
for (const relationship of parseRelationships(await partRels.async("text")).values()) {
|
|
51
|
+
if (!officeRelationshipHasType(relationship.type, "image") || relationship.targetMode === "External") continue;
|
|
52
|
+
const mediaPath = resolveRelativePath(relsPath, relationship.target);
|
|
53
|
+
if (!isUnsafePackagePath(mediaPath) && mediaPath.startsWith("word/media/")) retiredMedia.add(mediaPath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const compressionOptions = { level: compressionLevel };
|
|
57
|
+
zip.file(DOCUMENT_RELS_PATH, withoutChildren(relsXml, (child) => getNamespaceUri(child) === OOXML_NS.pr && getLocalName(child.name) === "Relationship" && removedIds.has(getAttribute(child, null, "Id") ?? "")), {
|
|
58
|
+
compression: "DEFLATE",
|
|
59
|
+
compressionOptions
|
|
60
|
+
});
|
|
61
|
+
if (document.package.relationships) {
|
|
62
|
+
document.package.relationships = new Map(document.package.relationships);
|
|
63
|
+
for (const id of removedIds) document.package.relationships.delete(id);
|
|
64
|
+
}
|
|
65
|
+
for (const path of candidates) {
|
|
66
|
+
zip.remove(path);
|
|
67
|
+
const slash = path.lastIndexOf("/");
|
|
68
|
+
zip.remove(`${path.slice(0, slash + 1)}_rels/${path.slice(slash + 1)}.rels`);
|
|
69
|
+
}
|
|
70
|
+
for (const file of Object.values(zip.files)) {
|
|
71
|
+
if (file.dir || !file.name.endsWith(".rels")) continue;
|
|
72
|
+
for (const relationship of parseRelationships(await file.async("text")).values()) if (relationship.targetMode !== "External") retiredMedia.delete(resolveRelativePath(file.name, relationship.target));
|
|
73
|
+
}
|
|
74
|
+
for (const path of retiredMedia) {
|
|
75
|
+
zip.remove(path);
|
|
76
|
+
candidates.add(path);
|
|
77
|
+
}
|
|
78
|
+
const contentTypes = zip.file("[Content_Types].xml");
|
|
79
|
+
if (!contentTypes) return panic("The package has no content types");
|
|
80
|
+
const contentTypesXml = await contentTypes.async("text");
|
|
81
|
+
zip.file("[Content_Types].xml", withoutChildren(contentTypesXml, (child) => getNamespaceUri(child) === OOXML_NS.ct && getLocalName(child.name) === "Override" && candidates.has((getAttribute(child, null, "PartName") ?? "").replace(/^\//u, ""))), {
|
|
82
|
+
compression: "DEFLATE",
|
|
83
|
+
compressionOptions
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
export { removeResolvedHeaderFooterParts };
|
package/dist/docx/rezip.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ declare function findMaxRId(relsXml: string): number;
|
|
|
15
15
|
* These are newly created hyperlinks that need relationship entries.
|
|
16
16
|
*/
|
|
17
17
|
declare function collectHyperlinksWithoutRId(blocks: BlockContent[]): Hyperlink[];
|
|
18
|
+
/** The selective save boundary must use the same resource census as full repack. */
|
|
19
|
+
declare const hasUnmaterializedInlineResources: (blocks: BlockContent[]) => boolean;
|
|
18
20
|
/**
|
|
19
21
|
* Options for repacking DOCX
|
|
20
22
|
*/
|
|
@@ -197,4 +199,4 @@ declare function createEmptyDocx(): Promise<ArrayBuffer>;
|
|
|
197
199
|
*/
|
|
198
200
|
declare function createDocx(doc: document_d_exports.Document): Promise<ArrayBuffer>;
|
|
199
201
|
//#endregion
|
|
200
|
-
export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxPackageFidelityError, RepackOptions, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
|
|
202
|
+
export { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_CONTENT_TYPE, COMMENTS_EXTENDED_PART, COMMENTS_EXTENDED_PART_LOWER, DocxPackageFidelityError, RepackOptions, addCommentsExtendedOverride, addCommentsExtendedRelationship, addMedia, addRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, collectHyperlinksWithoutRId, createDocx, createEmptyDocx, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedInlineResources, isDocxBuffer, notePartRelsPath, removeCommentsExtendedOverride, removeCommentsExtendedRelationship, repackDocx, repackDocxFromRaw, updateCoreProperties, updateDocumentXml, updateMultipleFiles, updateXmlFile, validateDocx, withoutAttachedTemplate };
|