@stll/folio-core 0.55.0 → 0.57.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 +214 -52
- package/dist/ai-edits/batch-claims.d.ts +3 -1
- package/dist/ai-edits/batch-claims.js +25 -1
- package/dist/ai-edits/headless.js +2 -2
- package/dist/ai-edits/table-row-column-mutations.js +17 -3
- package/dist/ai-edits/types.d.ts +7 -1
- package/dist/ai-suggestions/apply.js +20 -1
- package/dist/compare/compare.js +1 -0
- package/dist/compare/inline-atoms.js +40 -16
- package/dist/compare/inline-provenance.js +12 -5
- package/dist/compare/reproducible-package.d.ts +0 -17
- package/dist/compare/reproducible-package.js +12 -18
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/controller/canonicalClipboard.d.ts +23 -0
- package/dist/controller/canonicalClipboard.js +482 -0
- package/dist/controller/canonicalClipboardResources.d.ts +21 -0
- package/dist/controller/canonicalClipboardResources.js +382 -0
- package/dist/controller/canonicalComments.d.ts +41 -0
- package/dist/controller/canonicalComments.js +152 -0
- package/dist/controller/canonicalComposition.d.ts +24 -3
- package/dist/controller/canonicalComposition.js +208 -48
- package/dist/controller/canonicalInlineProjection.d.ts +118 -0
- package/dist/controller/canonicalInlineProjection.js +476 -0
- package/dist/controller/canonicalInput.d.ts +13 -4
- package/dist/controller/canonicalInput.js +62 -14
- package/dist/controller/canonicalInputTimer.d.ts +16 -0
- package/dist/controller/canonicalInputTimer.js +34 -0
- package/dist/controller/canonicalPublicOperations.d.ts +48 -0
- package/dist/controller/canonicalPublicOperations.js +648 -0
- package/dist/controller/canonicalSelection.d.ts +18 -0
- package/dist/controller/canonicalSelection.js +32 -0
- package/dist/controller/canonicalSession.d.ts +27 -6
- package/dist/controller/canonicalSession.js +298 -116
- package/dist/controller/canonicalStoryEditor.d.ts +7 -3
- package/dist/controller/canonicalStoryEditor.js +27 -2
- package/dist/controller/canonicalStructure.js +57 -4
- package/dist/controller/canonicalTocSelection.d.ts +11 -0
- package/dist/controller/canonicalTocSelection.js +43 -0
- package/dist/controller/folioEditor.d.ts +2 -9
- package/dist/controller/folioEditor.js +18 -4
- package/dist/controller/headerFooterEditorManager.d.ts +2 -1
- package/dist/controller/headerFooterEditorManager.js +26 -11
- package/dist/controller/hiddenEditorApi.d.ts +24 -3
- package/dist/controller/hiddenEditorApi.js +8 -0
- package/dist/controller/hiddenEditorManager.d.ts +5 -1
- package/dist/controller/hiddenEditorManager.js +378 -43
- package/dist/controller/noteEditorManager.d.ts +2 -1
- package/dist/controller/noteEditorManager.js +29 -13
- package/dist/document-operations.d.ts +8 -1
- package/dist/document-operations.js +6 -4
- package/dist/docx/blockPlainText.d.ts +1 -1
- package/dist/docx/blockPlainText.js +11 -3
- package/dist/docx/builtInStyles.js +13 -6
- package/dist/docx/canonicalResourceSave.d.ts +16 -0
- package/dist/docx/canonicalResourceSave.js +27 -0
- package/dist/docx/canonicalSave.d.ts +29 -0
- package/dist/docx/canonicalSave.js +101 -0
- package/dist/docx/canonicalStoryRepack.d.ts +1 -1
- package/dist/docx/canonicalStoryRepack.js +38 -5
- package/dist/docx/containerChildren.gen.d.ts +3 -1
- package/dist/docx/containerChildren.gen.js +33 -1
- package/dist/docx/documentParser.d.ts +1 -13
- package/dist/docx/documentParser.js +1 -47
- package/dist/docx/ensureParaIds.js +10 -4
- package/dist/docx/fieldParser.js +14 -2
- package/dist/docx/footnoteParser.d.ts +1 -11
- package/dist/docx/footnoteParser.js +1 -16
- package/dist/docx/headerFooterParser.d.ts +1 -9
- package/dist/docx/headerFooterParser.js +1 -12
- package/dist/docx/headerFooterVerbatim.d.ts +26 -1
- package/dist/docx/headerFooterVerbatim.js +81 -3
- package/dist/docx/hyperlinkParser.d.ts +1 -1
- package/dist/docx/hyperlinkParser.js +20 -1
- package/dist/docx/imageParser.d.ts +13 -1
- package/dist/docx/imageParser.js +20 -11
- package/dist/docx/inlineWrapperContent.d.ts +4 -4
- package/dist/docx/inlineWrapperContent.js +4 -4
- package/dist/docx/linkedSdtPreservation.d.ts +10 -0
- package/dist/docx/linkedSdtPreservation.js +37 -0
- package/dist/docx/metadataPrivacy.js +6 -1
- package/dist/docx/packageParts.js +9 -3
- package/dist/docx/paragraphParser.js +88 -67
- package/dist/docx/paragraphPropertySource.d.ts +22 -1
- package/dist/docx/paragraphPropertySource.js +109 -2
- package/dist/docx/parser.js +2 -1
- package/dist/docx/preservedRunContent.js +2 -1
- package/dist/docx/relsParser.js +26 -2
- package/dist/docx/removeHeaderFooterParts.js +17 -6
- package/dist/docx/rezip.d.ts +49 -5
- package/dist/docx/rezip.js +754 -235
- package/dist/docx/saveDiagnostics.d.ts +11 -0
- package/dist/docx/selectiveSave.d.ts +2 -1
- package/dist/docx/selectiveSave.js +42 -11
- package/dist/docx/selectiveXmlPatch.js +7 -5
- package/dist/docx/serializer/commentSerializer.d.ts +4 -1
- package/dist/docx/serializer/commentSerializer.js +7 -3
- package/dist/docx/serializer/documentSerializer.d.ts +9 -2
- package/dist/docx/serializer/documentSerializer.js +29 -10
- package/dist/docx/serializer/paragraphSerializer.js +207 -94
- package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
- package/dist/docx/server/materializeYjsDocx.js +14 -6
- package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
- package/dist/docx/storyBlockReplay.d.ts +21 -1
- package/dist/docx/storyBlockReplay.js +113 -9
- package/dist/docx/storyPlainText.d.ts +20 -0
- package/dist/docx/storyPlainText.js +23 -0
- package/dist/docx/structuralXmlPatch.js +10 -22
- package/dist/docx/styleParser.d.ts +5 -1
- package/dist/docx/styleParser.js +1 -1
- package/dist/docx/tableParser.d.ts +1 -8
- package/dist/docx/tableParser.js +1 -28
- package/dist/docx/textBoxParser.d.ts +1 -5
- package/dist/docx/textBoxParser.js +1 -20
- package/dist/docx/unzip.js +6 -1
- package/dist/i18n/messages/ar.gen.js +4 -0
- package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
- package/dist/i18n/messages/catalogs.gen.js +68 -0
- package/dist/i18n/messages/cs.gen.js +4 -0
- package/dist/i18n/messages/de.gen.js +4 -0
- package/dist/i18n/messages/en.gen.js +4 -0
- package/dist/i18n/messages/es.gen.js +4 -0
- package/dist/i18n/messages/et.gen.js +4 -0
- package/dist/i18n/messages/fr.gen.js +4 -0
- package/dist/i18n/messages/he.gen.js +4 -0
- package/dist/i18n/messages/hi.gen.js +4 -0
- package/dist/i18n/messages/hu.gen.js +4 -0
- package/dist/i18n/messages/lt.gen.js +4 -0
- package/dist/i18n/messages/lv.gen.js +4 -0
- package/dist/i18n/messages/messages.gen.d.ts +4 -0
- package/dist/i18n/messages/pl.gen.js +4 -0
- package/dist/i18n/messages/pt-BR.gen.js +4 -0
- package/dist/i18n/messages/sk.gen.js +4 -0
- package/dist/i18n/messages/tr.gen.js +4 -0
- package/dist/i18n/messages/zh-CN.gen.js +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/acceptedBlockProjection.d.ts +12 -0
- package/dist/internal/acceptedBlockProjection.js +45 -0
- package/dist/internal/revisionResolutionInline.js +25 -3
- package/dist/managers/DocumentLoaderManager.js +2 -1
- package/dist/markdown/escape.d.ts +3 -1
- package/dist/markdown/escape.js +9 -2
- package/dist/markdown/renderBlock.js +5 -120
- package/dist/markdown/renderParagraph.js +4 -2
- package/dist/markdown/renderRuns.d.ts +7 -1
- package/dist/markdown/renderRuns.js +33 -24
- package/dist/panel-layout.d.ts +11 -9
- package/dist/panel-layout.js +13 -9
- package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
- package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
- package/dist/prosemirror/attrs/index.js +5 -0
- package/dist/prosemirror/canonicalCommands.d.ts +28 -4
- package/dist/prosemirror/canonicalCommands.js +11 -4
- package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
- package/dist/prosemirror/canonicalSelectionRange.js +15 -0
- package/dist/prosemirror/clipboardIntent.d.ts +7 -0
- package/dist/prosemirror/clipboardIntent.js +9 -0
- package/dist/prosemirror/commands/comments.js +60 -35
- package/dist/prosemirror/commands/pageBreak.js +2 -2
- package/dist/prosemirror/commands/pastePlainText.js +2 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
- package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
- package/dist/prosemirror/commentOps.js +15 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
- package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
- package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -1
- package/dist/prosemirror/conversion/toProseDoc.js +124 -22
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +61 -35
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +65 -29
- package/dist/prosemirror/extensions/marks/markUtils.js +11 -8
- package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
- package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
- package/dist/prosemirror/fieldRepresentation.js +18 -0
- package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
- package/dist/prosemirror/hyperlinkRemoval.js +28 -9
- package/dist/prosemirror/insertOperations.js +2 -1
- package/dist/prosemirror/listNumbering.js +11 -5
- package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
- package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
- package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
- package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
- package/dist/prosemirror/noteReferenceReview.js +14 -1
- package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
- package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
- package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
- package/dist/prosemirror/plugins/documentStyles.js +17 -10
- package/dist/prosemirror/plugins/suggestionMode.js +48 -48
- package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
- package/dist/prosemirror/preservedXmlReview.js +35 -0
- package/dist/prosemirror/runFormattingFromMarks.js +2 -2
- package/dist/prosemirror/runFormattingReconciliation.js +5 -4
- package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
- package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
- package/dist/prosemirror/runStyleFormatting.js +3 -1
- package/dist/prosemirror/schema/marks.d.ts +1 -0
- package/dist/prosemirror/schema/nodes.d.ts +2 -0
- package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
- package/dist/prosemirror/textInput.d.ts +5 -1
- package/dist/prosemirror/textInput.js +3 -3
- package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
- package/dist/prosemirror/trackedRevisionPath.js +39 -1
- package/dist/prosemirror/validation.js +3 -5
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
- package/dist/types/canonicalCapabilities.d.ts +201 -0
- package/dist/types/canonicalCapabilities.js +198 -0
- package/dist/types/canonicalComments.d.ts +51 -0
- package/dist/types/canonicalComments.js +0 -0
- package/dist/types/canonicalSave.d.ts +11 -0
- package/dist/types/canonicalSave.js +0 -0
- package/dist/types/canonicalSections.d.ts +12 -0
- package/dist/types/canonicalSections.js +0 -0
- package/dist/types/docxSerialization.d.ts +14 -0
- package/dist/types/docxSerialization.js +7 -0
- package/dist/utils/headingCollector.js +45 -4
- package/dist/utils/outlineDepth.d.ts +9 -0
- package/dist/utils/outlineDepth.js +9 -0
- package/package.json +4 -4
|
@@ -239,58 +239,12 @@ function getNestedTables(table) {
|
|
|
239
239
|
return tables;
|
|
240
240
|
}
|
|
241
241
|
/**
|
|
242
|
-
* Get plain text from entire document body
|
|
243
|
-
*/
|
|
244
|
-
function getDocumentText(body) {
|
|
245
|
-
const lines = [];
|
|
246
|
-
for (const block of body.content) if (block.type === "paragraph") lines.push(getParagraphText(block));
|
|
247
|
-
else if (block.type === "table") lines.push(getTableText(block));
|
|
248
|
-
else if (block.type === "blockSdt" || block.type === "blockCustomXml") lines.push(getTextFromBlocks(block.content));
|
|
249
|
-
return lines.join("\n");
|
|
250
|
-
}
|
|
251
|
-
const getTextFromBlocks = (blocks) => blocks.flatMap((block) => {
|
|
252
|
-
if (block.type === "paragraph") return [getParagraphText(block)];
|
|
253
|
-
if (block.type === "table") return [getTableText(block)];
|
|
254
|
-
return block.type === "blockSdt" || block.type === "blockCustomXml" ? [getTextFromBlocks(block.content)] : [];
|
|
255
|
-
}).join("\n");
|
|
256
|
-
/**
|
|
257
|
-
* Get plain text from a table
|
|
258
|
-
*/
|
|
259
|
-
function getTableText(table) {
|
|
260
|
-
const lines = [];
|
|
261
|
-
for (const row of table.rows) {
|
|
262
|
-
const rowTexts = [];
|
|
263
|
-
for (const cell of row.cells) {
|
|
264
|
-
const cellTexts = [];
|
|
265
|
-
for (const content of cell.content) if (content.type === "paragraph") cellTexts.push(getParagraphText(content));
|
|
266
|
-
else if (content.type === "table") cellTexts.push(getTableText(content));
|
|
267
|
-
else if (content.type === "blockSdt" || content.type === "blockCustomXml") cellTexts.push(getTextFromBlocks(content.content));
|
|
268
|
-
rowTexts.push(cellTexts.join("\n"));
|
|
269
|
-
}
|
|
270
|
-
lines.push(rowTexts.join(" "));
|
|
271
|
-
}
|
|
272
|
-
return lines.join("\n");
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
242
|
* Count total paragraphs in document
|
|
276
243
|
*/
|
|
277
244
|
function getParagraphCount(body) {
|
|
278
245
|
return getAllParagraphs(body).length;
|
|
279
246
|
}
|
|
280
247
|
/**
|
|
281
|
-
* Count total words in document (approximate)
|
|
282
|
-
*/
|
|
283
|
-
function getWordCount(body) {
|
|
284
|
-
const words = getDocumentText(body).trim().split(/\s+/u);
|
|
285
|
-
return words.length > 0 && words[0] !== "" ? words.length : 0;
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Count total characters in document
|
|
289
|
-
*/
|
|
290
|
-
function getCharacterCount(body) {
|
|
291
|
-
return getDocumentText(body).length;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
248
|
* Get section count
|
|
295
249
|
*/
|
|
296
250
|
function getSectionCount(body) {
|
|
@@ -303,4 +257,4 @@ function hasTemplateVariables(body) {
|
|
|
303
257
|
return extractAllTemplateVariables(body.content).length > 0;
|
|
304
258
|
}
|
|
305
259
|
//#endregion
|
|
306
|
-
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables,
|
|
260
|
+
export { extractAllTemplateVariables, extractTemplateVariables, getAllParagraphs, getAllTables, getParagraphCount, getSectionCount, hasTemplateVariables, parseDocumentBody, parseDocumentBodyTree };
|
|
@@ -6,6 +6,7 @@ import { scanStreamingXmlElements } from "./streamingXmlParser.js";
|
|
|
6
6
|
import { resolveNamespaceUri } from "./xmlNamespaceContext.js";
|
|
7
7
|
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, WORDPROCESSINGML_NAMESPACE_URIS, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseXmlDocument, resolveAttributeNamespaceUri } from "./xmlParser.js";
|
|
8
8
|
import { TaggedError } from "better-result";
|
|
9
|
+
import { writeZipPart } from "@stll/docx-core/zip";
|
|
9
10
|
import JSZip from "jszip";
|
|
10
11
|
//#region src/docx/ensureParaIds.ts
|
|
11
12
|
/**
|
|
@@ -386,10 +387,15 @@ const ensureParaIdsInternal = async (docx, options) => {
|
|
|
386
387
|
for (const [partPath, content] of updates) {
|
|
387
388
|
const sourceEntry = zip.file(partPath);
|
|
388
389
|
if (sourceEntry === null) throw createEnsureParaIdsError(`Package part disappeared during normalization: ${partPath}`);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
390
|
+
writeZipPart({
|
|
391
|
+
zip,
|
|
392
|
+
path: partPath,
|
|
393
|
+
data: content,
|
|
394
|
+
options: {
|
|
395
|
+
compression: "DEFLATE",
|
|
396
|
+
compressionOptions: { level: 6 },
|
|
397
|
+
date: sourceEntry.date
|
|
398
|
+
}
|
|
393
399
|
});
|
|
394
400
|
}
|
|
395
401
|
return {
|
package/dist/docx/fieldParser.js
CHANGED
|
@@ -231,8 +231,20 @@ function finalizeComplexField(ctx) {
|
|
|
231
231
|
* @returns The display text
|
|
232
232
|
*/
|
|
233
233
|
function getFieldDisplayValue(field) {
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
const displayText = (content) => content.map((child) => {
|
|
235
|
+
switch (child.type) {
|
|
236
|
+
case "run": return getRunText(child);
|
|
237
|
+
case "hyperlink": return displayText(child.children);
|
|
238
|
+
case "inlineWrapper":
|
|
239
|
+
case "insertion":
|
|
240
|
+
case "deletion":
|
|
241
|
+
case "moveFrom":
|
|
242
|
+
case "moveTo": return displayText(child.content);
|
|
243
|
+
case "preservedInline": return child.text;
|
|
244
|
+
default: return "";
|
|
245
|
+
}
|
|
246
|
+
}).join("");
|
|
247
|
+
return displayText(field.type === "simpleField" ? field.content : field.fieldResult);
|
|
236
248
|
}
|
|
237
249
|
/**
|
|
238
250
|
* Helper to get text from a run (simplified)
|
|
@@ -67,16 +67,6 @@ declare function parseFootnotes(footnotesXml: string | null, styles?: StyleMap |
|
|
|
67
67
|
* @returns EndnoteMap with all endnotes
|
|
68
68
|
*/
|
|
69
69
|
declare function parseEndnotes(endnotesXml: string | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null, context?: ParseContext, previews?: PreviewLedger): EndnoteMap;
|
|
70
|
-
/**
|
|
71
|
-
* Get plain text content of a footnote.
|
|
72
|
-
*
|
|
73
|
-
* Uses the accepted tracked-change view and recurses through every note block.
|
|
74
|
-
*/
|
|
75
|
-
declare function getFootnoteText(footnote: document_d_exports.Footnote): string;
|
|
76
|
-
/**
|
|
77
|
-
* Get plain text content of an endnote.
|
|
78
|
-
*/
|
|
79
|
-
declare function getEndnoteText(endnote: document_d_exports.Endnote): string;
|
|
80
70
|
/**
|
|
81
71
|
* Check if a footnote is a separator (not regular content)
|
|
82
72
|
*/
|
|
@@ -102,4 +92,4 @@ declare function mergeFootnoteMaps(...maps: FootnoteMap[]): FootnoteMap;
|
|
|
102
92
|
*/
|
|
103
93
|
declare function mergeEndnoteMaps(...maps: EndnoteMap[]): EndnoteMap;
|
|
104
94
|
//#endregion
|
|
105
|
-
export { EndnoteMap, FootnoteMap, createEmptyEndnoteMap, createEmptyFootnoteMap,
|
|
95
|
+
export { EndnoteMap, FootnoteMap, createEmptyEndnoteMap, createEmptyFootnoteMap, isSeparatorEndnote, isSeparatorFootnote, mergeEndnoteMaps, mergeFootnoteMaps, parseEndnoteProperties, parseEndnotes, parseFootnoteProperties, parseFootnotes };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { blockPlainText } from "./blockPlainText.js";
|
|
2
1
|
import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
|
|
3
2
|
import { parseParagraph } from "./paragraphParser.js";
|
|
4
3
|
import { standalonePreviewLedger } from "./previewBudget.js";
|
|
@@ -196,20 +195,6 @@ function createEndnoteMap(byId, endnotes) {
|
|
|
196
195
|
};
|
|
197
196
|
}
|
|
198
197
|
/**
|
|
199
|
-
* Get plain text content of a footnote.
|
|
200
|
-
*
|
|
201
|
-
* Uses the accepted tracked-change view and recurses through every note block.
|
|
202
|
-
*/
|
|
203
|
-
function getFootnoteText(footnote) {
|
|
204
|
-
return blockPlainText(footnote.content);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Get plain text content of an endnote.
|
|
208
|
-
*/
|
|
209
|
-
function getEndnoteText(endnote) {
|
|
210
|
-
return blockPlainText(endnote.content);
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
198
|
* Check if a footnote is a separator (not regular content)
|
|
214
199
|
*/
|
|
215
200
|
function isSeparatorFootnote(footnote) {
|
|
@@ -258,4 +243,4 @@ function mergeEndnoteMaps(...maps) {
|
|
|
258
243
|
return createEndnoteMap(byId, endnotes);
|
|
259
244
|
}
|
|
260
245
|
//#endregion
|
|
261
|
-
export { createEmptyEndnoteMap, createEmptyFootnoteMap,
|
|
246
|
+
export { createEmptyEndnoteMap, createEmptyFootnoteMap, isSeparatorEndnote, isSeparatorFootnote, mergeEndnoteMaps, mergeFootnoteMaps, parseEndnoteProperties, parseEndnotes, parseFootnoteProperties, parseFootnotes };
|
|
@@ -81,14 +81,6 @@ declare function createEmptyHeaderFooterMap(): HeaderFooterMap;
|
|
|
81
81
|
* @returns HeaderFooterMap with all parsed headers/footers
|
|
82
82
|
*/
|
|
83
83
|
declare function buildHeaderFooterMap(references: (document_d_exports.HeaderReference | document_d_exports.FooterReference)[], xmlContents: Map<string, string>, isHeader: boolean, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, numbering?: NumberingMap | null, rels?: document_d_exports.RelationshipMap | null, media?: Map<string, document_d_exports.MediaFile> | null): HeaderFooterMap;
|
|
84
|
-
/**
|
|
85
|
-
* Get plain text content of a header/footer.
|
|
86
|
-
*
|
|
87
|
-
* Shares one walk with the note stories: this used to read only text runs, so a
|
|
88
|
-
* header's fields, hyperlinks, tabs and breaks were silently absent from its
|
|
89
|
-
* text while the same paragraph in a footnote read in full.
|
|
90
|
-
*/
|
|
91
|
-
declare function getHeaderFooterText(hf: document_d_exports.HeaderFooter): string;
|
|
92
84
|
/**
|
|
93
85
|
* Check if header/footer is empty (no content)
|
|
94
86
|
*/
|
|
@@ -129,4 +121,4 @@ declare function hasImages(hf: document_d_exports.HeaderFooter): boolean;
|
|
|
129
121
|
*/
|
|
130
122
|
declare function hasTables(hf: document_d_exports.HeaderFooter): boolean;
|
|
131
123
|
//#endregion
|
|
132
|
-
export { HeaderFooterMap, buildHeaderFooterMap, createEmptyHeaderFooterMap, getFooterForPage,
|
|
124
|
+
export { HeaderFooterMap, buildHeaderFooterMap, createEmptyHeaderFooterMap, getFooterForPage, getHeaderForPage, hasImages, hasPageNumberField, hasTables, headerFooterMapToTypeMap, isEmptyHeaderFooter, parseFooter, parseFooterReference, parseFooterReferences, parseHeader, parseHeaderFooter, parseHeaderReference, parseHeaderReferences };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { parseBlockContent } from "./blockContentParser.js";
|
|
2
|
-
import { blockPlainText } from "./blockPlainText.js";
|
|
3
2
|
import { parseFooterReference, parseFooterReferences, parseHeaderReference, parseHeaderReferences } from "./headerFooterRefParser.js";
|
|
4
3
|
import { assignHeaderFooterVerbatimXml } from "./headerFooterVerbatim.js";
|
|
5
4
|
import { cloneParagraphWithPropertySource } from "./paragraphPropertySource.js";
|
|
@@ -150,16 +149,6 @@ function buildHeaderFooterMap(references, xmlContents, isHeader, styles = null,
|
|
|
150
149
|
return createHeaderFooterMap(byId);
|
|
151
150
|
}
|
|
152
151
|
/**
|
|
153
|
-
* Get plain text content of a header/footer.
|
|
154
|
-
*
|
|
155
|
-
* Shares one walk with the note stories: this used to read only text runs, so a
|
|
156
|
-
* header's fields, hyperlinks, tabs and breaks were silently absent from its
|
|
157
|
-
* text while the same paragraph in a footnote read in full.
|
|
158
|
-
*/
|
|
159
|
-
function getHeaderFooterText(hf) {
|
|
160
|
-
return blockPlainText(hf.content);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
152
|
* Check if header/footer is empty (no content)
|
|
164
153
|
*/
|
|
165
154
|
function isEmptyHeaderFooter(hf) {
|
|
@@ -254,4 +243,4 @@ function hasTables(hf) {
|
|
|
254
243
|
return false;
|
|
255
244
|
}
|
|
256
245
|
//#endregion
|
|
257
|
-
export { buildHeaderFooterMap, createEmptyHeaderFooterMap, getFooterForPage,
|
|
246
|
+
export { buildHeaderFooterMap, createEmptyHeaderFooterMap, getFooterForPage, getHeaderForPage, hasImages, hasPageNumberField, hasTables, headerFooterMapToTypeMap, isEmptyHeaderFooter, parseFooter, parseFooterReference, parseFooterReferences, parseHeader, parseHeaderFooter, parseHeaderReference, parseHeaderReferences };
|
|
@@ -9,6 +9,13 @@ type HeaderFooterSourceBaseline = {
|
|
|
9
9
|
content: readonly document_d_exports.BlockContent[];
|
|
10
10
|
};
|
|
11
11
|
declare const captureHeaderFooterPackageBaselines: (document: document_d_exports.Document) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Transfer body, header and footer capture handles across a trusted
|
|
14
|
+
* document graph clone. `structuredClone` drops symbol-keyed properties, so a
|
|
15
|
+
* clone would otherwise read an edited part as uncaptured ("missing") rather
|
|
16
|
+
* than as a mismatch against its source.
|
|
17
|
+
*/
|
|
18
|
+
declare const copyHeaderFooterBaselineHandles: (target: document_d_exports.Document, source: document_d_exports.Document) => void;
|
|
12
19
|
/** Transfer the parsed package registry only across a trusted document graph clone. */
|
|
13
20
|
declare const copyHeaderFooterPackageBaselines: (target: document_d_exports.Document, source: document_d_exports.Document) => void;
|
|
14
21
|
declare const getHeaderFooterSourceBaseline: (hf: document_d_exports.HeaderFooter, originalBuffer?: ArrayBuffer) => HeaderFooterSourceBaseline;
|
|
@@ -18,5 +25,23 @@ declare const canReplayHeaderFooterVerbatim: (hf: document_d_exports.HeaderFoote
|
|
|
18
25
|
declare const assignHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter, xml: string) => void;
|
|
19
26
|
declare const refreshHeaderFooterVerbatimFingerprint: (hf: document_d_exports.HeaderFooter) => void;
|
|
20
27
|
declare const clearHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter) => void;
|
|
28
|
+
/** Capture the body in the same trusted package registry as secondary stories. */
|
|
29
|
+
declare const captureDocumentSourceBaseline: (document: document_d_exports.Document, xml: string) => void;
|
|
30
|
+
declare const getDocumentSourceBaseline: (document: document_d_exports.Document) => {
|
|
31
|
+
type: "missing";
|
|
32
|
+
} | {
|
|
33
|
+
type: "mismatch";
|
|
34
|
+
} | {
|
|
35
|
+
type: "captured";
|
|
36
|
+
body: document_d_exports.Document["package"]["document"];
|
|
37
|
+
xml: string;
|
|
38
|
+
fingerprint: string;
|
|
39
|
+
resourceStyles: document_d_exports.Document["package"]["styles"];
|
|
40
|
+
resourceRelationships: document_d_exports.Document["package"]["relationships"];
|
|
41
|
+
resourceMedia: ReadonlyMap<string, {
|
|
42
|
+
data: ArrayBuffer;
|
|
43
|
+
mimeType: string;
|
|
44
|
+
}>;
|
|
45
|
+
};
|
|
21
46
|
//#endregion
|
|
22
|
-
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterBlocks, canReplayHeaderFooterVerbatim, captureHeaderFooterPackageBaselines, clearHeaderFooterVerbatimXml, copyHeaderFooterPackageBaselines, getHeaderFooterSourceBaseline, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
47
|
+
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterBlocks, canReplayHeaderFooterVerbatim, captureDocumentSourceBaseline, captureHeaderFooterPackageBaselines, clearHeaderFooterVerbatimXml, copyHeaderFooterBaselineHandles, copyHeaderFooterPackageBaselines, getDocumentSourceBaseline, getHeaderFooterSourceBaseline, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
@@ -15,7 +15,7 @@ const readFingerprint = (hf) => {
|
|
|
15
15
|
});
|
|
16
16
|
return value;
|
|
17
17
|
};
|
|
18
|
-
const BASELINE_HANDLE = Symbol("
|
|
18
|
+
const BASELINE_HANDLE = Symbol("package-source-baseline");
|
|
19
19
|
const contentBaselines = /* @__PURE__ */ new WeakMap();
|
|
20
20
|
const captureContentBaseline = (hf) => {
|
|
21
21
|
const fingerprint = hf.verbatimFingerprint;
|
|
@@ -23,6 +23,7 @@ const captureContentBaseline = (hf) => {
|
|
|
23
23
|
const handle = {};
|
|
24
24
|
const content = structuredClone(hf.content);
|
|
25
25
|
contentBaselines.set(handle, {
|
|
26
|
+
type: "headerFooter",
|
|
26
27
|
fingerprint,
|
|
27
28
|
xml: hf.verbatimXml,
|
|
28
29
|
contentFingerprint: canonicalJson(content),
|
|
@@ -46,6 +47,33 @@ const captureHeaderFooterPackageBaselines = (document) => {
|
|
|
46
47
|
}
|
|
47
48
|
packageBaselines.set(document.originalBuffer, handles);
|
|
48
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Transfer body, header and footer capture handles across a trusted
|
|
52
|
+
* document graph clone. `structuredClone` drops symbol-keyed properties, so a
|
|
53
|
+
* clone would otherwise read an edited part as uncaptured ("missing") rather
|
|
54
|
+
* than as a mismatch against its source.
|
|
55
|
+
*/
|
|
56
|
+
const copyHeaderFooterBaselineHandles = (target, source) => {
|
|
57
|
+
const sourceBody = source.package.document;
|
|
58
|
+
if (BASELINE_HANDLE in sourceBody) Object.defineProperty(target.package.document, BASELINE_HANDLE, {
|
|
59
|
+
value: sourceBody[BASELINE_HANDLE],
|
|
60
|
+
enumerable: true,
|
|
61
|
+
configurable: true
|
|
62
|
+
});
|
|
63
|
+
for (const kind of ["headers", "footers"]) {
|
|
64
|
+
const targets = target.package[kind];
|
|
65
|
+
for (const [rId, sourcePart] of source.package[kind] ?? []) {
|
|
66
|
+
if (!(BASELINE_HANDLE in sourcePart)) continue;
|
|
67
|
+
const targetPart = targets?.get(rId);
|
|
68
|
+
if (!targetPart) continue;
|
|
69
|
+
Object.defineProperty(targetPart, BASELINE_HANDLE, {
|
|
70
|
+
value: sourcePart[BASELINE_HANDLE],
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
49
77
|
/** Transfer the parsed package registry only across a trusted document graph clone. */
|
|
50
78
|
const copyHeaderFooterPackageBaselines = (target, source) => {
|
|
51
79
|
if (!target.originalBuffer || !source.originalBuffer) return;
|
|
@@ -59,7 +87,7 @@ const getHeaderFooterSourceBaseline = (hf, originalBuffer) => {
|
|
|
59
87
|
if (handle === void 0 && !(BASELINE_HANDLE in hf)) return { type: "missing" };
|
|
60
88
|
if (typeof handle !== "object" || handle === null) return { type: "mismatch" };
|
|
61
89
|
const baseline = contentBaselines.get(handle);
|
|
62
|
-
if (!baseline || baseline.fingerprint !== hf.verbatimFingerprint || baseline.xml !== hf.verbatimXml || baseline.contentFingerprint !== canonicalJson(baseline.content)) return { type: "mismatch" };
|
|
90
|
+
if (!baseline || baseline.type !== "headerFooter" || baseline.fingerprint !== hf.verbatimFingerprint || baseline.xml !== hf.verbatimXml || baseline.contentFingerprint !== canonicalJson(baseline.content)) return { type: "mismatch" };
|
|
63
91
|
return {
|
|
64
92
|
type: "captured",
|
|
65
93
|
content: baseline.content
|
|
@@ -119,5 +147,55 @@ const clearHeaderFooterVerbatimXml = (hf) => {
|
|
|
119
147
|
delete ext.verbatimFingerprint;
|
|
120
148
|
Reflect.deleteProperty(hf, BASELINE_HANDLE);
|
|
121
149
|
};
|
|
150
|
+
/** Capture the body in the same trusted package registry as secondary stories. */
|
|
151
|
+
const captureDocumentSourceBaseline = (document, xml) => {
|
|
152
|
+
const body = structuredClone(document.package.document);
|
|
153
|
+
const handle = {};
|
|
154
|
+
contentBaselines.set(handle, {
|
|
155
|
+
type: "body",
|
|
156
|
+
fingerprint: { type: "pending" },
|
|
157
|
+
xml,
|
|
158
|
+
body,
|
|
159
|
+
resourceStyles: structuredClone(document.package.styles),
|
|
160
|
+
resourceRelationships: structuredClone(document.package.relationships),
|
|
161
|
+
resourceMedia: new Map([...document.package.media ?? []].map(([path, media]) => [path, {
|
|
162
|
+
data: media.data,
|
|
163
|
+
mimeType: media.mimeType
|
|
164
|
+
}]))
|
|
165
|
+
});
|
|
166
|
+
Object.defineProperty(document.package.document, BASELINE_HANDLE, {
|
|
167
|
+
value: handle,
|
|
168
|
+
enumerable: true,
|
|
169
|
+
configurable: true
|
|
170
|
+
});
|
|
171
|
+
if (document.originalBuffer) {
|
|
172
|
+
const registry = packageBaselines.get(document.originalBuffer) ?? /* @__PURE__ */ new Map();
|
|
173
|
+
registry.set("word/document.xml", /* @__PURE__ */ new Map([["body", handle]]));
|
|
174
|
+
packageBaselines.set(document.originalBuffer, registry);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const getDocumentSourceBaseline = (document) => {
|
|
178
|
+
const body = document.package.document;
|
|
179
|
+
const handle = BASELINE_HANDLE in body ? body[BASELINE_HANDLE] : document.originalBuffer && packageBaselines.get(document.originalBuffer)?.get("word/document.xml")?.get("body");
|
|
180
|
+
if (handle === void 0) return { type: "missing" };
|
|
181
|
+
if (typeof handle !== "object" || handle === null) return { type: "mismatch" };
|
|
182
|
+
const baseline = contentBaselines.get(handle);
|
|
183
|
+
if (!baseline || baseline.type !== "body") return { type: "mismatch" };
|
|
184
|
+
const fingerprint = JSON.stringify(baseline.body);
|
|
185
|
+
if (baseline.fingerprint.type === "pending") baseline.fingerprint = {
|
|
186
|
+
type: "captured",
|
|
187
|
+
value: fingerprint
|
|
188
|
+
};
|
|
189
|
+
if (baseline.fingerprint.value !== fingerprint) return { type: "mismatch" };
|
|
190
|
+
return {
|
|
191
|
+
type: "captured",
|
|
192
|
+
body: baseline.body,
|
|
193
|
+
xml: baseline.xml,
|
|
194
|
+
fingerprint,
|
|
195
|
+
resourceStyles: baseline.resourceStyles,
|
|
196
|
+
resourceRelationships: baseline.resourceRelationships,
|
|
197
|
+
resourceMedia: baseline.resourceMedia
|
|
198
|
+
};
|
|
199
|
+
};
|
|
122
200
|
//#endregion
|
|
123
|
-
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterBlocks, canReplayHeaderFooterVerbatim, captureHeaderFooterPackageBaselines, clearHeaderFooterVerbatimXml, copyHeaderFooterPackageBaselines, getHeaderFooterSourceBaseline, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
201
|
+
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterBlocks, canReplayHeaderFooterVerbatim, captureDocumentSourceBaseline, captureHeaderFooterPackageBaselines, clearHeaderFooterVerbatimXml, copyHeaderFooterBaselineHandles, copyHeaderFooterPackageBaselines, getDocumentSourceBaseline, getHeaderFooterSourceBaseline, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
@@ -86,7 +86,7 @@ declare const HYPERLINK_CHILD_HANDLERS: {
|
|
|
86
86
|
readonly permEnd: "capture";
|
|
87
87
|
readonly permStart: "capture";
|
|
88
88
|
readonly proofErr: "capture";
|
|
89
|
-
readonly sdt:
|
|
89
|
+
readonly sdt: (child: XmlElement, { push }: HyperlinkChildContext) => void;
|
|
90
90
|
readonly subDoc: "capture";
|
|
91
91
|
};
|
|
92
92
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
2
2
|
import { CAPTURE, dispatchChildrenWithContext, ownedElsewhere, withPreservedChildren } from "./containerChildren.js";
|
|
3
3
|
import { inlineWrapperOf } from "./inlineWrapperParser.js";
|
|
4
|
+
import { preserveLinkedSdt } from "./linkedSdtPreservation.js";
|
|
4
5
|
import { preserveInlineChild, preservedInlineCapture } from "./preservedRunContent.js";
|
|
5
6
|
import { standalonePreviewLedger } from "./previewBudget.js";
|
|
6
7
|
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
|
|
@@ -9,6 +10,22 @@ import { runHoldsPayload } from "./runPayload.js";
|
|
|
9
10
|
import { getAttribute, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
10
11
|
//#region src/docx/hyperlinkParser.ts
|
|
11
12
|
/**
|
|
13
|
+
* Hyperlink Parser - Parse hyperlinks (w:hyperlink) with URL resolution
|
|
14
|
+
*
|
|
15
|
+
* OOXML Reference:
|
|
16
|
+
* - Hyperlink element: w:hyperlink
|
|
17
|
+
* - Attributes:
|
|
18
|
+
* - r:id - Relationship ID for external link (resolves via .rels)
|
|
19
|
+
* - w:anchor - Internal bookmark name
|
|
20
|
+
* - w:tooltip - Tooltip/title text
|
|
21
|
+
* - w:tgtFrame - Target frame (_blank, _self, etc.)
|
|
22
|
+
* - w:history - Whether to add to history
|
|
23
|
+
* - w:docLocation - Location within a document
|
|
24
|
+
*
|
|
25
|
+
* External links use r:id to reference a relationship in document.xml.rels
|
|
26
|
+
* Internal links use w:anchor to reference a bookmark in the same document
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
12
29
|
* Parse bookmark start (w:bookmarkStart)
|
|
13
30
|
*
|
|
14
31
|
* Used for internal hyperlink targets within the document.
|
|
@@ -169,7 +186,9 @@ const HYPERLINK_CHILD_HANDLERS = {
|
|
|
169
186
|
permEnd: CAPTURE,
|
|
170
187
|
permStart: CAPTURE,
|
|
171
188
|
proofErr: CAPTURE,
|
|
172
|
-
sdt:
|
|
189
|
+
sdt: (child, { push }) => {
|
|
190
|
+
push(preserveLinkedSdt(child));
|
|
191
|
+
},
|
|
173
192
|
subDoc: CAPTURE
|
|
174
193
|
};
|
|
175
194
|
const LINKED_SMART_TAG_PROPERTIES_OWNER = ownedElsewhere({
|
|
@@ -22,6 +22,18 @@ declare function resolveImageData(rId: string | undefined, rels: document_d_expo
|
|
|
22
22
|
mimeType?: string;
|
|
23
23
|
filename?: string;
|
|
24
24
|
};
|
|
25
|
+
type ImageDerivedFactsOptions = {
|
|
26
|
+
id: string | undefined;
|
|
27
|
+
pictureNames: NonNullable<document_d_exports.Image["pictureNames"]>;
|
|
28
|
+
imageData: ReturnType<typeof resolveImageData>;
|
|
29
|
+
};
|
|
30
|
+
/** Facts the parser obtains from exported drawing markup and image relationships. */
|
|
31
|
+
declare const imageDerivedFactsOf: ({ id, pictureNames, imageData }: ImageDerivedFactsOptions) => {
|
|
32
|
+
filename?: string;
|
|
33
|
+
mimeType?: string;
|
|
34
|
+
pictureNames?: import("@stll/docx-core/model").NonVisualDrawingNames;
|
|
35
|
+
id?: string;
|
|
36
|
+
};
|
|
25
37
|
/**
|
|
26
38
|
* Parse a w:drawing element
|
|
27
39
|
*
|
|
@@ -97,4 +109,4 @@ declare function getWrapDistancesPx(image: document_d_exports.Image): {
|
|
|
97
109
|
*/
|
|
98
110
|
declare function needsTextWrapping(image: document_d_exports.Image): boolean;
|
|
99
111
|
//#endregion
|
|
100
|
-
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
112
|
+
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, imageDerivedFactsOf, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
package/dist/docx/imageParser.js
CHANGED
|
@@ -10,7 +10,7 @@ import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js
|
|
|
10
10
|
import { isTextBoxDrawing } from "./textBoxParser.js";
|
|
11
11
|
import { percentageSpelling } from "./transitionalSpelling.js";
|
|
12
12
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
13
|
-
import { findByFullName, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
|
|
13
|
+
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, findAttributeByNamespaceUri, findByFullName, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
|
|
14
14
|
import { relationshipIdOf } from "@stll/docx-core/model";
|
|
15
15
|
//#region src/docx/imageParser.ts
|
|
16
16
|
/**
|
|
@@ -129,7 +129,7 @@ const parseDocPropsExtensions = (docPr) => {
|
|
|
129
129
|
const parseDocPrLink = (docPr, localName) => {
|
|
130
130
|
const element = findChildByNamespaceUri(docPr, DRAWINGML_NAMESPACE_URIS, localName);
|
|
131
131
|
if (!element) return;
|
|
132
|
-
const rId =
|
|
132
|
+
const rId = findAttributeByNamespaceUri(element, OFFICE_RELATIONSHIP_NAMESPACE_URIS, "id")?.value;
|
|
133
133
|
return {
|
|
134
134
|
xml: captureVerbatimXml(element),
|
|
135
135
|
...rId == null ? {} : { rId }
|
|
@@ -382,6 +382,13 @@ function resolveImageData(rId, rels, media) {
|
|
|
382
382
|
...filename !== void 0 ? { filename } : {}
|
|
383
383
|
};
|
|
384
384
|
}
|
|
385
|
+
/** Facts the parser obtains from exported drawing markup and image relationships. */
|
|
386
|
+
const imageDerivedFactsOf = ({ id, pictureNames, imageData }) => ({
|
|
387
|
+
...id ? { id } : {},
|
|
388
|
+
...Object.keys(pictureNames).length > 0 ? { pictureNames } : {},
|
|
389
|
+
...imageData.mimeType ? { mimeType: imageData.mimeType } : {},
|
|
390
|
+
...imageData.filename ? { filename: imageData.filename } : {}
|
|
391
|
+
});
|
|
385
392
|
/**
|
|
386
393
|
* Parse a wp:inline element (inline image)
|
|
387
394
|
*
|
|
@@ -411,18 +418,19 @@ function parseInline(inlineEl, rels, media) {
|
|
|
411
418
|
size,
|
|
412
419
|
wrap
|
|
413
420
|
};
|
|
414
|
-
|
|
421
|
+
Object.assign(image, imageDerivedFactsOf({
|
|
422
|
+
id: props.id,
|
|
423
|
+
pictureNames,
|
|
424
|
+
imageData
|
|
425
|
+
}));
|
|
415
426
|
if (props.name !== void 0) image.docPrName = props.name;
|
|
416
427
|
if (props.alt !== void 0) image.alt = props.alt;
|
|
417
428
|
if (props.title !== void 0) image.title = props.title;
|
|
418
|
-
if (Object.keys(pictureNames).length > 0) image.pictureNames = pictureNames;
|
|
419
429
|
if (props.decorative !== void 0) image.decorative = props.decorative;
|
|
420
430
|
if (props.hidden !== void 0) image.hidden = props.hidden;
|
|
421
431
|
if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
|
|
422
432
|
const safeSrc = sanitizeImageSrc(imageData.src);
|
|
423
433
|
if (safeSrc) image.src = safeSrc;
|
|
424
|
-
if (imageData.mimeType) image.mimeType = imageData.mimeType;
|
|
425
|
-
if (imageData.filename) image.filename = imageData.filename;
|
|
426
434
|
if (padding) image.padding = padding;
|
|
427
435
|
if (transform) image.transform = transform;
|
|
428
436
|
if (crop) image.crop = crop;
|
|
@@ -492,18 +500,19 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
492
500
|
size,
|
|
493
501
|
wrap
|
|
494
502
|
};
|
|
495
|
-
|
|
503
|
+
Object.assign(image, imageDerivedFactsOf({
|
|
504
|
+
id: props.id,
|
|
505
|
+
pictureNames,
|
|
506
|
+
imageData
|
|
507
|
+
}));
|
|
496
508
|
if (props.name !== void 0) image.docPrName = props.name;
|
|
497
509
|
if (props.alt !== void 0) image.alt = props.alt;
|
|
498
510
|
if (props.title !== void 0) image.title = props.title;
|
|
499
|
-
if (Object.keys(pictureNames).length > 0) image.pictureNames = pictureNames;
|
|
500
511
|
if (props.decorative !== void 0) image.decorative = props.decorative;
|
|
501
512
|
if (props.hidden !== void 0) image.hidden = props.hidden;
|
|
502
513
|
if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
|
|
503
514
|
const safeSrc = sanitizeImageSrc(imageData.src);
|
|
504
515
|
if (safeSrc) image.src = safeSrc;
|
|
505
|
-
if (imageData.mimeType) image.mimeType = imageData.mimeType;
|
|
506
|
-
if (imageData.filename) image.filename = imageData.filename;
|
|
507
516
|
if (position) image.position = position;
|
|
508
517
|
if (padding) image.padding = padding;
|
|
509
518
|
if (transform) image.transform = transform;
|
|
@@ -628,4 +637,4 @@ function needsTextWrapping(image) {
|
|
|
628
637
|
].includes(image.wrap.type);
|
|
629
638
|
}
|
|
630
639
|
//#endregion
|
|
631
|
-
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
640
|
+
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, imageDerivedFactsOf, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
@@ -138,14 +138,14 @@ declare const SIMPLE_FIELD_CONTENT: {
|
|
|
138
138
|
readonly commentRangeStart: false;
|
|
139
139
|
readonly commentReference: false;
|
|
140
140
|
readonly complexField: false;
|
|
141
|
-
readonly deletion:
|
|
141
|
+
readonly deletion: true;
|
|
142
142
|
readonly inlineSdt: false;
|
|
143
|
-
readonly insertion:
|
|
143
|
+
readonly insertion: true;
|
|
144
144
|
readonly mathEquation: false;
|
|
145
|
-
readonly moveFrom:
|
|
145
|
+
readonly moveFrom: true;
|
|
146
146
|
readonly moveFromRangeEnd: false;
|
|
147
147
|
readonly moveFromRangeStart: false;
|
|
148
|
-
readonly moveTo:
|
|
148
|
+
readonly moveTo: true;
|
|
149
149
|
readonly moveToRangeEnd: false;
|
|
150
150
|
readonly moveToRangeStart: false;
|
|
151
151
|
readonly simpleField: false;
|
|
@@ -137,14 +137,14 @@ const SIMPLE_FIELD_CONTENT = {
|
|
|
137
137
|
commentRangeStart: false,
|
|
138
138
|
commentReference: false,
|
|
139
139
|
complexField: false,
|
|
140
|
-
deletion:
|
|
140
|
+
deletion: true,
|
|
141
141
|
inlineSdt: false,
|
|
142
|
-
insertion:
|
|
142
|
+
insertion: true,
|
|
143
143
|
mathEquation: false,
|
|
144
|
-
moveFrom:
|
|
144
|
+
moveFrom: true,
|
|
145
145
|
moveFromRangeEnd: false,
|
|
146
146
|
moveFromRangeStart: false,
|
|
147
|
-
moveTo:
|
|
147
|
+
moveTo: true,
|
|
148
148
|
moveToRangeEnd: false,
|
|
149
149
|
moveToRangeStart: false,
|
|
150
150
|
simpleField: false
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { XmlElement } from "./xmlParser.js";
|
|
2
|
+
//#region src/docx/linkedSdtPreservation.d.ts
|
|
3
|
+
declare const UnrepresentableLinkedSdtRevisionError_base: import("better-result").TaggedErrorClass<"UnrepresentableLinkedSdtRevisionError">;
|
|
4
|
+
declare class UnrepresentableLinkedSdtRevisionError extends UnrepresentableLinkedSdtRevisionError_base<{
|
|
5
|
+
message: string;
|
|
6
|
+
}> {}
|
|
7
|
+
/** Capture only the unsupported hyperlink child, never its enclosing revision. */
|
|
8
|
+
declare const preserveLinkedSdt: (root: XmlElement) => import("@stll/docx-core/model").PreservedInline;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { UnrepresentableLinkedSdtRevisionError, preserveLinkedSdt };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { preserveInlineChild } from "./preservedRunContent.js";
|
|
2
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, getChildElements, getLocalName } from "./xmlParser.js";
|
|
3
|
+
import { TaggedError } from "better-result";
|
|
4
|
+
//#region src/docx/linkedSdtPreservation.ts
|
|
5
|
+
var UnrepresentableLinkedSdtRevisionError = class extends TaggedError("UnrepresentableLinkedSdtRevisionError") {};
|
|
6
|
+
/** Capture only the unsupported hyperlink child, never its enclosing revision. */
|
|
7
|
+
const preserveLinkedSdt = (root) => {
|
|
8
|
+
const pending = getChildElements(root);
|
|
9
|
+
while (pending.length > 0) {
|
|
10
|
+
const node = pending.pop();
|
|
11
|
+
if (!node) continue;
|
|
12
|
+
const wordprocessing = WORDPROCESSINGML_NAMESPACE_URIS.has(node.namespaceUri ?? "");
|
|
13
|
+
const name = getLocalName(node.name);
|
|
14
|
+
if (wordprocessing && [
|
|
15
|
+
"ins",
|
|
16
|
+
"del",
|
|
17
|
+
"moveFrom",
|
|
18
|
+
"moveTo",
|
|
19
|
+
"rPrChange",
|
|
20
|
+
"pPrChange",
|
|
21
|
+
"sectPrChange",
|
|
22
|
+
"tblPrChange",
|
|
23
|
+
"tblGridChange",
|
|
24
|
+
"trPrChange",
|
|
25
|
+
"tblPrExChange",
|
|
26
|
+
"tcPrChange",
|
|
27
|
+
"cellIns",
|
|
28
|
+
"cellDel",
|
|
29
|
+
"cellMerge",
|
|
30
|
+
"numberingChange"
|
|
31
|
+
].includes(name)) throw new UnrepresentableLinkedSdtRevisionError({ message: "A content control under a hyperlink cannot preserve nested revisions as opaque XML." });
|
|
32
|
+
pending.push(...getChildElements(node));
|
|
33
|
+
}
|
|
34
|
+
return preserveInlineChild(root);
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
export { UnrepresentableLinkedSdtRevisionError, preserveLinkedSdt };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { countCentralDirectoryRecords, createInflationBudget, inflateEntryWithinLimits } from "./archiveInflation.js";
|
|
2
2
|
import { elementToXml, getLocalName, parseXmlDocument } from "./xmlParser.js";
|
|
3
3
|
import { TaggedError } from "better-result";
|
|
4
|
+
import { writeZipPart } from "@stll/docx-core/zip";
|
|
4
5
|
import JSZip from "jszip";
|
|
5
6
|
//#region src/docx/metadataPrivacy.ts
|
|
6
7
|
const FOLIO_DOCUMENT_METADATA_PROPERTIES = Object.freeze([
|
|
@@ -152,7 +153,11 @@ const rewriteDocxMetadataPrivacy = async (buffer, { transforms }) => {
|
|
|
152
153
|
removedMetadataProperties: []
|
|
153
154
|
}
|
|
154
155
|
};
|
|
155
|
-
|
|
156
|
+
writeZipPart({
|
|
157
|
+
zip,
|
|
158
|
+
path: coreProperties.name,
|
|
159
|
+
data: rewritten.xml
|
|
160
|
+
});
|
|
156
161
|
return {
|
|
157
162
|
buffer: await zip.generateAsync({
|
|
158
163
|
type: "arraybuffer",
|