@stll/folio-core 0.58.5 → 0.60.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/README.md +10 -1
- package/dist/ai-edits/apply.d.ts +11 -12
- package/dist/ai-edits/apply.js +179 -168
- package/dist/ai-edits/headless.d.ts +15 -13
- package/dist/ai-edits/headless.js +40 -13
- package/dist/ai-edits/index.d.ts +3 -3
- package/dist/ai-edits/newListNumbering.d.ts +3 -9
- package/dist/ai-edits/newListNumbering.js +36 -41
- package/dist/ai-edits/referenceClassification.d.ts +22 -0
- package/dist/ai-edits/referenceClassification.js +21 -0
- package/dist/ai-edits/snapshot.js +39 -40
- package/dist/ai-edits/types.d.ts +24 -32
- package/dist/compare/column-alignment.d.ts +4 -4
- package/dist/compare/compare.d.ts +3 -7
- package/dist/compare/compare.js +25 -27
- package/dist/compare/content-alignment.d.ts +9 -9
- package/dist/compare/content-types.d.ts +23 -10
- package/dist/compare/content-types.js +14 -0
- package/dist/compare/content.d.ts +16 -17
- package/dist/compare/content.js +30 -7
- package/dist/compare/formatting.d.ts +3 -3
- package/dist/compare/import-style-closure.d.ts +22 -0
- package/dist/compare/import-style-closure.js +33 -0
- package/dist/compare/inserted-resource-snapshot.d.ts +15 -0
- package/dist/compare/inserted-resource-snapshot.js +63 -0
- package/dist/compare/plan.js +20 -13
- package/dist/compare/scenario.js +12 -2
- package/dist/compare/style-resources.d.ts +8 -2
- package/dist/compare/style-resources.js +63 -14
- package/dist/compare/verification.d.ts +15 -3
- package/dist/compare/verification.js +47 -8
- package/dist/compat/eigenpal.d.ts +5 -5
- package/dist/compat/eigenpal.js +2 -2
- package/dist/controller/canonicalListRendering.js +13 -22
- package/dist/controller/canonicalPublicOperations.js +1 -1
- package/dist/controller/canonicalSession.js +3 -2
- package/dist/controller/canonicalStructure.js +55 -28
- package/dist/controller/fontReadiness.js +1 -1
- package/dist/controller/layoutPipeline.js +7 -1
- package/dist/controller/layoutSession.d.ts +2 -0
- package/dist/display-list/build/fontTable.js +7 -5
- package/dist/display-list/build/furniture.d.ts +1 -0
- package/dist/display-list/build/furniture.js +1 -0
- package/dist/display-list/build/watermarkPrimitives.d.ts +2 -1
- package/dist/display-list/build/watermarkPrimitives.js +9 -3
- package/dist/display-list/editor/pageRenderer.js +1 -0
- package/dist/document-operations.d.ts +4 -9
- package/dist/document-operations.js +45 -41
- package/dist/docx/attributeRemainder.d.ts +1 -1
- package/dist/docx/bookmarkIdNormalization.d.ts +10 -0
- package/dist/docx/bookmarkIdNormalization.js +100 -0
- package/dist/docx/bookmarkParser.js +4 -2
- package/dist/docx/importedIdCollisions.d.ts +136 -0
- package/dist/docx/importedIdCollisions.js +215 -0
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/listMarkerComputation.js +9 -14
- package/dist/docx/listTemplate.d.ts +22 -0
- package/dist/docx/listTemplate.js +40 -0
- package/dist/docx/numberingParser.js +4 -4
- package/dist/docx/numberingReferenceNormalization.js +3 -3
- package/dist/docx/paragraphParser.js +3 -4
- package/dist/docx/paragraphPropertySource.js +1 -2
- package/dist/docx/parseContext.d.ts +2 -1
- package/dist/docx/parseContext.js +1 -0
- package/dist/docx/parseWarningMessage.js +1 -0
- package/dist/docx/parser.js +5 -1
- package/dist/docx/relsParser.js +1 -1
- package/dist/docx/rezip.js +4 -3
- package/dist/docx/selectedXmlIdentityScan.d.ts +10 -0
- package/dist/docx/selectedXmlIdentityScan.js +36 -0
- package/dist/docx/selectiveSave.js +5 -4
- package/dist/docx/selectiveXmlPatch.js +44 -52
- package/dist/docx/serializer/commentSerializer.d.ts +3 -1
- package/dist/docx/serializer/commentSerializer.js +11 -2
- package/dist/docx/serializer/runSerializer.js +2 -2
- package/dist/docx/serializer/trackedChangeAttributes.d.ts +1 -3
- package/dist/docx/serializer/trackedChangeAttributes.js +1 -11
- package/dist/docx/server/materializeYjsDocx.js +2 -2
- package/dist/docx/server/migrateYjsAttrSchema.js +5 -5
- package/dist/fonts/embeddedFontFingerprint.d.ts +5 -0
- package/dist/fonts/embeddedFontFingerprint.js +18 -0
- package/dist/fonts/embeddedFonts.d.ts +1 -1
- package/dist/fonts/embeddedFonts.js +1 -1
- package/dist/fonts/headlessMeasure.js +0 -0
- package/dist/generated/text_shaper.js +8 -4
- package/dist/generated/text_shaper_bg.wasm +0 -0
- package/dist/headless-layout.js +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/internal/paragraphFormattingSerialization.d.ts +1 -8
- package/dist/internal/paragraphFormattingSerialization.js +6 -20
- package/dist/layout-bridge/convert/flowConversionShared.d.ts +3 -1
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -1
- package/dist/layout-bridge/convert/footnoteLayout.js +3 -0
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +2 -0
- package/dist/layout-bridge/convert/listMarkers.d.ts +1 -2
- package/dist/layout-bridge/convert/listMarkers.js +3 -11
- package/dist/layout-bridge/convert/paragraphAttrs.d.ts +1 -1
- package/dist/layout-bridge/convert/paragraphAttrs.js +8 -4
- package/dist/layout-bridge/convert/paragraphConversion.js +8 -1
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -1
- package/dist/layout-bridge/convert/toFlowBlocks.js +27 -2
- package/dist/layout-engine/measure/cache.js +39 -7
- package/dist/layout-engine/measure/lineTypography.js +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +1 -0
- package/dist/layout-engine/measure/measureContainer.js +3 -4
- package/dist/layout-engine/measure/measureHelpers.d.ts +6 -9
- package/dist/layout-engine/measure/measureHelpers.js +21 -18
- package/dist/layout-engine/measure/measureParagraph.js +2 -0
- package/dist/layout-engine/measure/measureTypes.d.ts +2 -0
- package/dist/layout-engine/types.d.ts +4 -1
- package/dist/layout-painter/renderPage.d.ts +1 -0
- package/dist/layout-painter/renderPage.js +11 -3
- package/dist/layout-painter/renderParagraph.js +13 -3
- package/dist/layout-painter/renderWatermark.d.ts +1 -0
- package/dist/layout-painter/renderWatermark.js +7 -3
- package/dist/managers/editorShortcuts.d.ts +2 -1
- package/dist/managers/editorShortcuts.js +2 -1
- package/dist/markdown/renderParagraph.js +29 -3
- package/dist/prosemirror/canonicalSelectionRange.d.ts +4 -1
- package/dist/prosemirror/canonicalSelectionRange.js +9 -3
- package/dist/prosemirror/commands/comments.js +5 -32
- package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +7 -1
- package/dist/prosemirror/commands/paragraphBookmarkJoin.js +35 -1
- package/dist/prosemirror/commands/propertyChangeScope.js +6 -0
- package/dist/prosemirror/commands/resolveParagraphProperties.js +10 -5
- package/dist/prosemirror/conversion/fromProseDoc.js +23 -9
- package/dist/prosemirror/conversion/toProseDoc.js +31 -7
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +29 -14
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/AutoBidiDetectionExtension.js +39 -3
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ImageDragExtension.js +4 -3
- package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +4 -3
- package/dist/prosemirror/extensions/features/ListExtension.js +51 -21
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +9 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +6 -5
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +8 -2
- package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +11 -3
- package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +4 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +1 -1
- package/dist/prosemirror/listInstanceReferences.js +21 -15
- package/dist/prosemirror/listLabels.d.ts +4 -3
- package/dist/prosemirror/listLabels.js +18 -51
- package/dist/prosemirror/listMarker.d.ts +2 -19
- package/dist/prosemirror/listMarker.js +28 -57
- package/dist/prosemirror/listNumbering.js +16 -6
- package/dist/prosemirror/listRendering.d.ts +4 -3
- package/dist/prosemirror/listRendering.js +22 -3
- package/dist/prosemirror/listRenderingAttrs.d.ts +2 -1
- package/dist/prosemirror/listRenderingAttrs.js +6 -11
- package/dist/prosemirror/numberedRefFields.js +9 -5
- package/dist/prosemirror/numberingAttr.d.ts +19 -1
- package/dist/prosemirror/numberingAttr.js +16 -2
- package/dist/prosemirror/paragraphIndentation.js +5 -2
- package/dist/prosemirror/paragraphMarkJoin.js +17 -3
- package/dist/prosemirror/paragraphPropertyCarry.js +5 -6
- package/dist/prosemirror/pluginKeyOwner.d.ts +13 -0
- package/dist/prosemirror/pluginKeyOwner.js +35 -0
- package/dist/prosemirror/plugins/aiCitationDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiCitationDecorations.js +16 -3
- package/dist/prosemirror/plugins/aiSuggestionDecorations.d.ts +11 -4
- package/dist/prosemirror/plugins/aiSuggestionDecorations.js +18 -3
- package/dist/prosemirror/plugins/anonymizationDecorations.d.ts +11 -11
- package/dist/prosemirror/plugins/anonymizationDecorations.js +23 -13
- package/dist/prosemirror/plugins/autocompleteSuggestion.d.ts +8 -2
- package/dist/prosemirror/plugins/autocompleteSuggestion.js +27 -5
- package/dist/prosemirror/plugins/contentControlWidgets.d.ts +8 -2
- package/dist/prosemirror/plugins/contentControlWidgets.js +4 -3
- package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +6 -5
- package/dist/prosemirror/plugins/createDocScanPlugin.js +1 -1
- package/dist/prosemirror/plugins/documentNumbering.js +5 -3
- package/dist/prosemirror/plugins/documentStyleState.d.ts +8 -2
- package/dist/prosemirror/plugins/documentStyleState.js +2 -2
- package/dist/prosemirror/plugins/documentStyles.js +1 -1
- package/dist/prosemirror/plugins/selectionTracker.d.ts +8 -2
- package/dist/prosemirror/plugins/selectionTracker.js +4 -3
- package/dist/prosemirror/plugins/suggestionMode.d.ts +8 -2
- package/dist/prosemirror/plugins/suggestionMode.js +4 -3
- package/dist/prosemirror/plugins/templateDirectives.d.ts +8 -2
- package/dist/prosemirror/plugins/templateDirectives.js +19 -4
- package/dist/prosemirror/plugins/templatePreviewValues.d.ts +8 -2
- package/dist/prosemirror/plugins/templatePreviewValues.js +27 -5
- package/dist/prosemirror/plugins/templateSlashMenu.d.ts +8 -2
- package/dist/prosemirror/plugins/templateSlashMenu.js +23 -5
- package/dist/prosemirror/plugins/transactionInvariants.js +29 -5
- package/dist/prosemirror/schema/nodes.d.ts +2 -1
- package/dist/prosemirror/selectionState.js +5 -1
- package/dist/prosemirror/storyListNumbering.js +11 -12
- package/dist/prosemirror/styles/paragraphStyleCascade.js +2 -6
- package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +11 -4
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +28 -18
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
- package/dist/prosemirror/yjsDocumentMetadata.js +42 -10
- package/dist/redline.d.ts +17 -1
- package/dist/redline.js +118 -57
- package/dist/server.d.ts +3 -3
- package/dist/server.js +2 -2
- package/dist/utils/fontLoader.d.ts +2 -2
- package/dist/utils/fontLoader.js +2 -7
- package/dist/utils/fontResolver.d.ts +7 -3
- package/dist/utils/fontResolver.js +6 -8
- package/dist/version-comparison.d.ts +1 -2
- package/dist/version-comparison.js +1 -2
- package/package.json +26 -9
package/dist/docx/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCachedNumberingMap } from "./numberingParser.js";
|
|
2
|
-
import { NO_NUMBERING_NUM_ID, NO_PARAGRAPH_NUMBERING, ParagraphNumberingOverride, ParagraphNumberingSlots, ResolvedParagraphNumbering, isNumberingReference, mergeParagraphNumbering, paragraphNumberingFromSlots, paragraphNumberingLevel, paragraphNumberingReferenceId, paragraphNumberingSlots, readParagraphNumbering, resolveParagraphNumbering, sameEffectiveParagraphNumbering, sameStatedParagraphNumbering } from "./numberingReference.js";
|
|
3
2
|
import { DOCX_ENCRYPTION_ERROR_CODES, DocxEncryptionError, DocxEncryptionErrorCode, isDocxEncryptionError } from "./encryption/errors.js";
|
|
4
3
|
import { DecryptDocxOptions, DecryptDocxResult, decryptDocxIfNeeded, openDocxBuffer } from "./encryption/openEncryptedDocx.js";
|
|
4
|
+
import { NO_NUMBERING_NUM_ID, NO_PARAGRAPH_NUMBERING, ParagraphNumberingOverride, ParagraphNumberingSlots, ResolvedParagraphNumbering, isNumberingReference, mergeParagraphNumbering, paragraphNumberingFromSlots, paragraphNumberingLevel, paragraphNumberingReferenceId, paragraphNumberingSlots, readParagraphNumbering, resolveParagraphNumbering, sameEffectiveParagraphNumbering, sameStatedParagraphNumbering } from "./numberingReference.js";
|
|
5
5
|
import { FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, FolioDocumentMetadataProperty, FolioDocumentPrivacyArchiveError, FolioDocumentPrivacyOptions, FolioDocumentPrivacyReport, FolioDocumentPrivacyTransform, InvalidFolioDocumentPrivacyOptionsError, RewriteDocxMetadataPrivacyResult, isFolioDocumentPrivacyTransform, rewriteDocxMetadataPrivacy } from "./metadataPrivacy.js";
|
|
6
6
|
export { DOCX_ENCRYPTION_ERROR_CODES, type DecryptDocxOptions, type DecryptDocxResult, DocxEncryptionError, type DocxEncryptionErrorCode, FOLIO_DOCUMENT_METADATA_PROPERTIES, FOLIO_DOCUMENT_PRIVACY_TRANSFORMS, type FolioDocumentMetadataProperty, FolioDocumentPrivacyArchiveError, type FolioDocumentPrivacyOptions, type FolioDocumentPrivacyReport, type FolioDocumentPrivacyTransform, InvalidFolioDocumentPrivacyOptionsError, NO_NUMBERING_NUM_ID, NO_PARAGRAPH_NUMBERING, type ParagraphNumberingOverride, type ParagraphNumberingSlots, type ResolvedParagraphNumbering, type RewriteDocxMetadataPrivacyResult, decryptDocxIfNeeded, getCachedNumberingMap, isDocxEncryptionError, isFolioDocumentPrivacyTransform, isNumberingReference, mergeParagraphNumbering, openDocxBuffer, paragraphNumberingFromSlots, paragraphNumberingLevel, paragraphNumberingReferenceId, paragraphNumberingSlots, readParagraphNumbering, resolveParagraphNumbering, rewriteDocxMetadataPrivacy, sameEffectiveParagraphNumbering, sameStatedParagraphNumbering };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { bulletMarkerFontName, convertBulletToUnicode } from "./bulletMarkers.js";
|
|
2
|
+
import { resolveListTemplate } from "./listTemplate.js";
|
|
2
3
|
import { isNumberingReference } from "./numberingReference.js";
|
|
3
|
-
import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
|
|
4
4
|
//#region src/docx/listMarkerComputation.ts
|
|
5
5
|
const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
|
|
6
6
|
const listRendering = paragraph.listRendering;
|
|
@@ -22,7 +22,7 @@ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounter
|
|
|
22
22
|
let counters = listCounters.get(numId);
|
|
23
23
|
if (!counters) return;
|
|
24
24
|
const abstractNumId = numbering.getAbstractNumId(numId);
|
|
25
|
-
const styleNumbering = paragraph.formatting?.numPrFromStyle;
|
|
25
|
+
const styleNumbering = paragraph.formatting?.numPr?.kind !== "reference" && paragraph.formatting?.numPrFromStyle?.kind === "reference";
|
|
26
26
|
const resumesRestartedInstance = firstEncounter && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.numId !== null && previousList.numId !== numId && restartedNumIds.has(previousList.numId);
|
|
27
27
|
const resumesStyleInstance = firstEncounter && !styleNumbering && listRendering.startOverride === void 0 && abstractNumId !== null && previousList.abstractNumId === abstractNumId && previousList.fromStyle === true;
|
|
28
28
|
if (abstractNumId !== null && (styleNumbering || resumesRestartedInstance || resumesStyleInstance)) {
|
|
@@ -60,18 +60,13 @@ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounter
|
|
|
60
60
|
previousList.numId = null;
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const formatted = formatOoxmlCounter(value, useLegalNumbering ? "decimal" : levelInfo?.numFmt || "decimal");
|
|
71
|
-
computedMarker = computedMarker.replaceAll(placeholder, formatted);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
listRendering.marker = computedMarker;
|
|
63
|
+
const currentLevelInfo = numbering.getLevel(numId, level);
|
|
64
|
+
listRendering.marker = resolveListTemplate({
|
|
65
|
+
template: pattern,
|
|
66
|
+
counters,
|
|
67
|
+
levelFormats: listRendering.levelNumFmts ?? counters.map((_counter, ilvl) => numbering.getLevel(numId, ilvl)?.numFmt),
|
|
68
|
+
forceDecimal: currentLevelInfo?.isLgl === true || listRendering.isLegal === true
|
|
69
|
+
});
|
|
75
70
|
};
|
|
76
71
|
//#endregion
|
|
77
72
|
export { computeListMarker };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
//#region src/docx/listTemplate.d.ts
|
|
3
|
+
type ResolvedListComponent = {
|
|
4
|
+
level: number;
|
|
5
|
+
relativeStart: number;
|
|
6
|
+
start: number;
|
|
7
|
+
end: number;
|
|
8
|
+
};
|
|
9
|
+
type ResolvedListTemplate = {
|
|
10
|
+
value: string;
|
|
11
|
+
components: readonly ResolvedListComponent[];
|
|
12
|
+
};
|
|
13
|
+
type ResolveListTemplateOptions = {
|
|
14
|
+
template: string;
|
|
15
|
+
counters: readonly number[];
|
|
16
|
+
levelFormats?: readonly (document_d_exports.CounterFormat | undefined)[] | undefined;
|
|
17
|
+
forceDecimal?: boolean | undefined;
|
|
18
|
+
};
|
|
19
|
+
declare function resolveListTemplate(options: ResolveListTemplateOptions): string;
|
|
20
|
+
declare function resolveListTemplateWithComponents({ template, counters, levelFormats, forceDecimal }: ResolveListTemplateOptions): ResolvedListTemplate;
|
|
21
|
+
//#endregion
|
|
22
|
+
export { ResolvedListComponent, ResolvedListTemplate, resolveListTemplate, resolveListTemplateWithComponents };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { formatOoxmlCounter } from "./ooxmlCounterFormatter.js";
|
|
2
|
+
//#region src/docx/listTemplate.ts
|
|
3
|
+
function resolveListTemplate(options) {
|
|
4
|
+
return resolveListTemplateWithComponents(options).value;
|
|
5
|
+
}
|
|
6
|
+
function resolveListTemplateWithComponents({ template, counters, levelFormats, forceDecimal = false }) {
|
|
7
|
+
const components = [];
|
|
8
|
+
let value = "";
|
|
9
|
+
let sourceEnd = 0;
|
|
10
|
+
for (const match of template.matchAll(/%(?<digit>\d)(?<punct>[.):\]])?/gu)) {
|
|
11
|
+
const sourceStart = match.index;
|
|
12
|
+
const relativeStart = value.length;
|
|
13
|
+
value += template.slice(sourceEnd, sourceStart);
|
|
14
|
+
sourceEnd = sourceStart + match[0].length;
|
|
15
|
+
const index = Number.parseInt(match.groups?.["digit"] ?? "", 10) - 1;
|
|
16
|
+
const counter = counters[index];
|
|
17
|
+
if (index < 0 || counter === void 0 || !Number.isFinite(counter)) {
|
|
18
|
+
value += match.groups?.["punct"] ?? "";
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const formatted = formatOoxmlCounter(counter, forceDecimal ? "decimal" : levelFormats?.[index]);
|
|
22
|
+
if (!formatted) continue;
|
|
23
|
+
const start = value.length;
|
|
24
|
+
value += formatted;
|
|
25
|
+
components.push({
|
|
26
|
+
level: index,
|
|
27
|
+
relativeStart,
|
|
28
|
+
start,
|
|
29
|
+
end: value.length
|
|
30
|
+
});
|
|
31
|
+
value += match.groups?.["punct"] ?? "";
|
|
32
|
+
}
|
|
33
|
+
value += template.slice(sourceEnd);
|
|
34
|
+
return {
|
|
35
|
+
value,
|
|
36
|
+
components
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { resolveListTemplate, resolveListTemplateWithComponents };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DERIVED_PART_ROOT_ATTRIBUTES, attributeRemainder } from "./attributeRemainder.js";
|
|
2
2
|
import { CAPTURE, dispatchChildrenWithContext, sequencePositions } from "./containerChildren.js";
|
|
3
|
-
import { isNumberingReference } from "./numberingReference.js";
|
|
3
|
+
import { isNumberingReference as isNumberingReference$1 } from "./numberingReference.js";
|
|
4
4
|
import { formatOoxmlCounter, padDecimal } from "./ooxmlCounterFormatter.js";
|
|
5
5
|
import { parseParagraphProperties } from "./paragraphProperties.js";
|
|
6
6
|
import { LevelSuffixSchema, NumberFormatSchema, ParagraphAlignmentSchema, narrowEnum } from "./parserEnums.js";
|
|
@@ -398,9 +398,9 @@ function getCachedNumberingMap(definitions) {
|
|
|
398
398
|
*/
|
|
399
399
|
function createNumberingMap(definitions) {
|
|
400
400
|
const abstractMap = /* @__PURE__ */ new Map();
|
|
401
|
-
for (const abs of definitions.abstractNums) abstractMap.set(abs.abstractNumId, abs);
|
|
401
|
+
for (const abs of definitions.abstractNums) if (!abstractMap.has(abs.abstractNumId)) abstractMap.set(abs.abstractNumId, abs);
|
|
402
402
|
const numMap = /* @__PURE__ */ new Map();
|
|
403
|
-
for (const num of definitions.nums) numMap.set(num.numId, num);
|
|
403
|
+
for (const num of definitions.nums) if (!numMap.has(num.numId)) numMap.set(num.numId, num);
|
|
404
404
|
return {
|
|
405
405
|
definitions,
|
|
406
406
|
getLevel(numId, ilvl) {
|
|
@@ -459,7 +459,7 @@ function createNumberingMap(definitions) {
|
|
|
459
459
|
*/
|
|
460
460
|
function computeListRendering(numPr, numbering) {
|
|
461
461
|
const { numId, ilvl = 0 } = numPr;
|
|
462
|
-
if (!isNumberingReference(numId)) return null;
|
|
462
|
+
if (!isNumberingReference$1(numId)) return null;
|
|
463
463
|
const level = numbering.getLevel(numId, ilvl);
|
|
464
464
|
if (!level) return null;
|
|
465
465
|
const levelNumFmts = [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NO_PARAGRAPH_NUMBERING as NO_PARAGRAPH_NUMBERING$1, paragraphNumberingReferenceId
|
|
1
|
+
import { NO_PARAGRAPH_NUMBERING as NO_PARAGRAPH_NUMBERING$1, paragraphNumberingReferenceId } from "./numberingReference.js";
|
|
2
2
|
import { visitDocxParagraphs } from "./paragraphTraversal.js";
|
|
3
3
|
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
4
4
|
//#region src/docx/numberingReferenceNormalization.ts
|
|
@@ -40,7 +40,7 @@ const normalizeNumberingReferences = ({ documentBody, numbering, headers, footer
|
|
|
40
40
|
endnotes
|
|
41
41
|
}, (paragraph) => {
|
|
42
42
|
const formatting = paragraph.formatting;
|
|
43
|
-
const numId = paragraphNumberingReferenceId
|
|
43
|
+
const numId = paragraphNumberingReferenceId(formatting?.numPr);
|
|
44
44
|
if (!formatting || numId === void 0 || resolvesNumbering(numId, numbering)) return;
|
|
45
45
|
formatting.numPr = NO_PARAGRAPH_NUMBERING$1;
|
|
46
46
|
delete formatting.numPrFromStyle;
|
|
@@ -53,7 +53,7 @@ const normalizeStyleNumberingReferences = ({ styles, numbering }) => {
|
|
|
53
53
|
const unnumberedStyleIds = [];
|
|
54
54
|
for (const style of styles) {
|
|
55
55
|
const pPr = style.pPr;
|
|
56
|
-
const numId = paragraphNumberingReferenceId
|
|
56
|
+
const numId = paragraphNumberingReferenceId(pPr?.numPr);
|
|
57
57
|
if (!pPr || numId === void 0 || resolvesNumbering(numId, numbering)) continue;
|
|
58
58
|
pPr.numPr = NO_PARAGRAPH_NUMBERING$1;
|
|
59
59
|
unnumberedStyleIds.push(style.styleId);
|
|
@@ -12,7 +12,7 @@ import { inlineWrapperOf } from "./inlineWrapperParser.js";
|
|
|
12
12
|
import { preserveLinkedSdt } from "./linkedSdtPreservation.js";
|
|
13
13
|
import { parseMarkupRangeMarker, parseMoveBookmarkMarker } from "./markupRangeMarker.js";
|
|
14
14
|
import { counterFormatOf, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot } from "./numberingParser.js";
|
|
15
|
-
import { mergeParagraphNumbering as mergeParagraphNumbering$1, paragraphNumberingReferenceId
|
|
15
|
+
import { mergeParagraphNumbering as mergeParagraphNumbering$1, paragraphNumberingReferenceId, resolveParagraphNumbering as resolveParagraphNumbering$1 } from "./numberingReference.js";
|
|
16
16
|
import { paraIdAttribute, textIdAttribute } from "./paraIdAttribute.js";
|
|
17
17
|
import { paraIdInRange } from "./paraIdRangeNormalization.js";
|
|
18
18
|
import { EMPTY_MARK_PROPERTIES_ATTRIBUTE, restoreEmptyMarkProperties } from "./paragraphMarkPropertyPresence.js";
|
|
@@ -1253,7 +1253,6 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
|
|
|
1253
1253
|
let effectiveNumPr = directNumPr;
|
|
1254
1254
|
if (paragraphFormatting && numPrFromStyle) {
|
|
1255
1255
|
effectiveNumPr = mergeParagraphNumbering$1(styleNumPr, directNumPr);
|
|
1256
|
-
if (effectiveNumPr !== void 0) paragraphFormatting.numPr = effectiveNumPr;
|
|
1257
1256
|
paragraphFormatting.numPrFromStyle = styleNumPr;
|
|
1258
1257
|
}
|
|
1259
1258
|
const resolvedNumbering = resolveParagraphNumbering$1(effectiveNumPr);
|
|
@@ -1444,7 +1443,7 @@ function isEmptyParagraph(paragraph) {
|
|
|
1444
1443
|
* @returns true if paragraph has numbering properties
|
|
1445
1444
|
*/
|
|
1446
1445
|
function isListItem(paragraph) {
|
|
1447
|
-
return paragraphNumberingReferenceId$1(paragraph.formatting?.numPr) !== void 0;
|
|
1446
|
+
return paragraphNumberingReferenceId(mergeParagraphNumbering$1(paragraph.formatting?.numPrFromStyle, paragraph.formatting?.numPr)) !== void 0;
|
|
1448
1447
|
}
|
|
1449
1448
|
/**
|
|
1450
1449
|
* Get the list level of a paragraph (0-8)
|
|
@@ -1453,7 +1452,7 @@ function isListItem(paragraph) {
|
|
|
1453
1452
|
* @returns List level or undefined if not a list item
|
|
1454
1453
|
*/
|
|
1455
1454
|
function getListLevel(paragraph) {
|
|
1456
|
-
const resolved = resolveParagraphNumbering$1(paragraph.formatting?.numPr);
|
|
1455
|
+
const resolved = resolveParagraphNumbering$1(mergeParagraphNumbering$1(paragraph.formatting?.numPrFromStyle, paragraph.formatting?.numPr));
|
|
1457
1456
|
return resolved.kind === "reference" ? resolved.ilvl : void 0;
|
|
1458
1457
|
}
|
|
1459
1458
|
/**
|
|
@@ -5,7 +5,6 @@ import { parseParagraphProperties } from "./paragraphProperties.js";
|
|
|
5
5
|
import { visitDocxParagraphs } from "./paragraphTraversal.js";
|
|
6
6
|
import { parseXmlDocument } from "./xmlParser.js";
|
|
7
7
|
import { TaggedError, panic } from "better-result";
|
|
8
|
-
import { PluginKey } from "prosemirror-state";
|
|
9
8
|
//#region src/docx/paragraphPropertySource.ts
|
|
10
9
|
const paragraphPropertySourceEmissionFingerprint = Symbol("paragraphPropertySourceEmissionFingerprint");
|
|
11
10
|
const paragraphPropertySourceIndentationBaseline = Symbol("paragraphPropertySourceIndentationBaseline");
|
|
@@ -793,7 +792,7 @@ const createProseParagraphWithPropertySource = (nodeType, sourceParagraph, optio
|
|
|
793
792
|
linkProseParagraphPropertySource(paragraph, sourceParagraph);
|
|
794
793
|
return paragraph;
|
|
795
794
|
};
|
|
796
|
-
const paragraphPropertySourceTransfersKey =
|
|
795
|
+
const paragraphPropertySourceTransfersKey = "stll.folio.meta.paragraphPropertySourceTransfers";
|
|
797
796
|
/** Join adjacent paragraphs when revision semantics deliberately select the right owner. */
|
|
798
797
|
const joinProseParagraphsWithRightPropertySource = ({ attrs, pos, transaction }) => {
|
|
799
798
|
const $pos = transaction.doc.resolve(pos);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { ParseWarning, ParseWarningCode } from "@stll/docx-core/model";
|
|
1
|
+
import { ImportedIdCollisionKind, ParseWarning, ParseWarningCode } from "@stll/docx-core/model";
|
|
2
2
|
//#region src/docx/parseContext.d.ts
|
|
3
3
|
/** What a call site states; the collector supplies the rest. */
|
|
4
4
|
type ParseWarningReport = {
|
|
5
5
|
code: ParseWarningCode;
|
|
6
|
+
identityKind?: ImportedIdCollisionKind;
|
|
6
7
|
/** The element as written, prefix included. */
|
|
7
8
|
element?: string;
|
|
8
9
|
/** The best position this part can name, e.g. `style "Heading1"`. */
|
|
@@ -30,6 +30,7 @@ const createParseWarningCollector = (part = PACKAGE_PART) => {
|
|
|
30
30
|
retainedByCode.set(report.code, kept + 1);
|
|
31
31
|
retained.push({
|
|
32
32
|
code: report.code,
|
|
33
|
+
...report.identityKind === void 0 ? {} : { identityKind: report.identityKind },
|
|
33
34
|
location: {
|
|
34
35
|
...location,
|
|
35
36
|
...report.element === void 0 ? {} : { element: report.element },
|
|
@@ -22,6 +22,7 @@ const PARSE_WARNING_MESSAGES = {
|
|
|
22
22
|
[PARSE_WARNING_CODES.documentPartMissing]: () => "No document.xml found in DOCX",
|
|
23
23
|
[PARSE_WARNING_CODES.documentModelIssue]: (warning) => warning.detail ?? "The document model reported an issue.",
|
|
24
24
|
[PARSE_WARNING_CODES.duplicateCommentId]: (warning) => `Dropped ${plural(warning.count, "comment")} repeating a w:id another comment already defines.`,
|
|
25
|
+
[PARSE_WARNING_CODES.duplicateImportedId]: (warning) => `Repeated imported identity${quoted(warning.value)}${where(warning)}: ${warning.detail ?? "multiple definitions share an identity."}`,
|
|
25
26
|
[PARSE_WARNING_CODES.missingCommentId]: (warning) => `Dropped ${plural(warning.count, "comment")} with no readable w:id.`,
|
|
26
27
|
[PARSE_WARNING_CODES.duplicateNoteId]: (warning) => `Dropped ${plural(warning.count, "note")} repeating a w:id another note already defines.`,
|
|
27
28
|
[PARSE_WARNING_CODES.danglingCommentReference]: (warning) => `Removed ${plural(warning.count, "dangling comment reference marker")} whose comments.xml entries are missing.`,
|
package/dist/docx/parser.js
CHANGED
|
@@ -2,6 +2,7 @@ import { toArrayBuffer } from "../utils/docxInput.js";
|
|
|
2
2
|
import { loadFontsWithMapping } from "../utils/fontLoader.js";
|
|
3
3
|
import { MAX_PACKAGE_TIFF_PIXELS, convertTiffToPngDataUrl, isTiffMimeType } from "../utils/tiffConverter.js";
|
|
4
4
|
import { ALT_CHUNK_PLAIN_TEXT_LIMIT_BYTES, getAltChunkRelationshipId, isAltChunkMarkup } from "./altChunk.js";
|
|
5
|
+
import { normalizeBookmarkIdsInXmlParts } from "./bookmarkIdNormalization.js";
|
|
5
6
|
import { DUPLICATE_COMMENT_ID_WARNING, normalizeCommentIds } from "./commentIdNormalization.js";
|
|
6
7
|
import { parseComments } from "./commentParser.js";
|
|
7
8
|
import { DANGLING_COMMENT_REFERENCE_WARNING, UNBALANCED_COMMENT_RANGE_WARNING, normalizeCommentReferences } from "./commentReferenceNormalization.js";
|
|
@@ -16,6 +17,7 @@ import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
|
16
17
|
import { parseFooter, parseHeader } from "./headerFooterParser.js";
|
|
17
18
|
import { DANGLING_FOOTER_REFERENCE_WARNING, DANGLING_HEADER_REFERENCE_WARNING, assignHeaderFooterRoles, normalizeHeaderFooterReferences } from "./headerFooterReferenceNormalization.js";
|
|
18
19
|
import { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, captureDocumentSourceBaseline, captureHeaderFooterPackageBaselines, refreshHeaderFooterVerbatimFingerprint } from "./headerFooterVerbatim.js";
|
|
20
|
+
import { diagnoseImportedIdCollisions } from "./importedIdCollisions.js";
|
|
19
21
|
import { extractMetafileRaster, isMetafileMimeType } from "./metafileRaster.js";
|
|
20
22
|
import { renderEmfSvg } from "./metafileSvg.js";
|
|
21
23
|
import { DocxModelValidationError, formatDocumentModelIssues, validateFolioDocumentModel } from "./modelValidation.js";
|
|
@@ -34,7 +36,7 @@ import { parseSettings } from "./settingsParser.js";
|
|
|
34
36
|
import { parseStylesPackage } from "./styleParser.js";
|
|
35
37
|
import { applyThemeFontLang, parseTheme } from "./themeParser.js";
|
|
36
38
|
import { UNBALANCED_MOVE_RANGE_WARNING, normalizeTrackedMoveRanges } from "./trackedMoveRangeNormalization.js";
|
|
37
|
-
import { getEntryUncompressedSize, getMediaMimeType, mediaToDataUrl, unzipDocx } from "./unzip.js";
|
|
39
|
+
import { getEntryUncompressedSize, getMediaMimeType, mediaToDataUrl, replaceRawDocxXmlParts, unzipDocx } from "./unzip.js";
|
|
38
40
|
import { getAttribute, getChildElements, getLocalName, parseXml, parseXmlDocument } from "./xmlParser.js";
|
|
39
41
|
import { FOLIO_XML_RESOURCE_LIMITS } from "./xmlResourceLimits.js";
|
|
40
42
|
import { TaggedError, panic } from "better-result";
|
|
@@ -192,6 +194,8 @@ async function parseDocxWithPreviewBudget(input, options, previewBudget) {
|
|
|
192
194
|
password,
|
|
193
195
|
extractAllXml: false
|
|
194
196
|
}));
|
|
197
|
+
diagnoseImportedIdCollisions(raw.allXml, parseContext);
|
|
198
|
+
await replaceRawDocxXmlParts(raw, normalizeBookmarkIdsInXmlParts(raw.allXml));
|
|
195
199
|
const repairedDocumentTree = await normalizeRawDocxNumericIds(raw);
|
|
196
200
|
const paragraphPropertySourceDigest = sha256Hex(raw.originalBuffer);
|
|
197
201
|
if (raw.wasEncrypted) parseContext.warn({ code: PARSE_WARNING_CODES.packageDecrypted });
|
package/dist/docx/relsParser.js
CHANGED
|
@@ -86,7 +86,7 @@ function parseRelationships(relsXml) {
|
|
|
86
86
|
};
|
|
87
87
|
if (targetMode === "External") relationship.targetMode = "External";
|
|
88
88
|
else if (targetMode === "Internal") relationship.targetMode = "Internal";
|
|
89
|
-
map.set(id, relationship);
|
|
89
|
+
if (!map.has(id)) map.set(id, relationship);
|
|
90
90
|
}
|
|
91
91
|
return map;
|
|
92
92
|
}
|
package/dist/docx/rezip.js
CHANGED
|
@@ -16,7 +16,7 @@ import { assertValidFolioDocumentModel } from "./modelValidation.js";
|
|
|
16
16
|
import { isNewDataUrlDrawing } from "./newImage.js";
|
|
17
17
|
import { missingNoteReferenceStyles, noteReferenceNeeds } from "./noteReferenceStyles.js";
|
|
18
18
|
import { parseNumbering } from "./numberingParser.js";
|
|
19
|
-
import { paragraphNumberingReferenceId
|
|
19
|
+
import { paragraphNumberingReferenceId } from "./numberingReference.js";
|
|
20
20
|
import { isUnsafePackagePath, reconcilePackageReferences, removeUnsafeEntries } from "./packageParts.js";
|
|
21
21
|
import { normalizeParaIdRangeInXmlParts } from "./paraIdRangeNormalization.js";
|
|
22
22
|
import { cloneDocumentWithParagraphPropertySources, cloneParagraphWithPropertySource, copyDocumentParagraphPropertySourceContract } from "./paragraphPropertySource.js";
|
|
@@ -25,7 +25,7 @@ import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./r
|
|
|
25
25
|
import { removeResolvedHeaderFooterParts } from "./removeHeaderFooterParts.js";
|
|
26
26
|
import { normalizeRevisionIdsInXmlParts } from "./revisionIdNormalization.js";
|
|
27
27
|
import { buildPatchedNotePartXml, collectChangedNoteParaIds, collectParaIds, patchNumberingDefinitions, spliceXml } from "./selectiveXmlPatch.js";
|
|
28
|
-
import { hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
28
|
+
import { canReplayCommentsPart, hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
29
29
|
import { serializeDocument } from "./serializer/documentSerializer.js";
|
|
30
30
|
import { serializeFontTableXml } from "./serializer/fontTableSerializer.js";
|
|
31
31
|
import { serializeHeaderFooter } from "./serializer/headerFooterSerializer.js";
|
|
@@ -201,6 +201,7 @@ async function serializeCommentsToZip(doc, zip, compressionLevel) {
|
|
|
201
201
|
const comments = doc.package.document.comments ?? [];
|
|
202
202
|
const sourceCommentsFile = findZipEntryCaseInsensitive(zip, "word/comments.xml");
|
|
203
203
|
const sourceCommentsXml = sourceCommentsFile ? await sourceCommentsFile.async("text") : void 0;
|
|
204
|
+
if (sourceCommentsXml !== void 0 && canReplayCommentsPart(doc, sourceCommentsXml)) return;
|
|
204
205
|
if (comments.length === 0) {
|
|
205
206
|
const ownsCommentsPart = hasOwnedCommentsPart(doc);
|
|
206
207
|
if (sourceCommentsXml === void 0 ? !ownsCommentsPart : !hasCommentEntries(sourceCommentsXml)) return;
|
|
@@ -2462,7 +2463,7 @@ const overrideXml = (partName, contentType) => `<Override PartName="${partName}"
|
|
|
2462
2463
|
const assertStyleNumberingReferences = (doc) => {
|
|
2463
2464
|
const referenced = /* @__PURE__ */ new Set();
|
|
2464
2465
|
for (const style of doc.package.styles?.styles ?? []) {
|
|
2465
|
-
const numId = paragraphNumberingReferenceId
|
|
2466
|
+
const numId = paragraphNumberingReferenceId(style.pPr?.numPr);
|
|
2466
2467
|
if (numId !== void 0) referenced.add(numId);
|
|
2467
2468
|
}
|
|
2468
2469
|
if (referenced.size === 0) return;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { scanStreamingXmlElements } from "./streamingXmlParser.js";
|
|
2
|
+
//#region src/docx/selectedXmlIdentityScan.d.ts
|
|
3
|
+
/** Identity census follows the parser's first-Choice, otherwise-Fallback policy. */
|
|
4
|
+
declare const scanSelectedStreamingXmlElements: (xml: string, visitor: Parameters<typeof scanStreamingXmlElements>[1]) => {
|
|
5
|
+
status: "unsupported";
|
|
6
|
+
} | {
|
|
7
|
+
status: "scanned";
|
|
8
|
+
};
|
|
9
|
+
//#endregion
|
|
10
|
+
export { scanSelectedStreamingXmlElements };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { scanStreamingXmlElements } from "./streamingXmlParser.js";
|
|
2
|
+
import { NAMESPACES, getLocalName, getNamespaceUri, selectAlternateContentBranch } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/selectedXmlIdentityScan.ts
|
|
4
|
+
const isCompatibilityElement = (element, name) => getNamespaceUri(element) === NAMESPACES.mc && getLocalName(element.name) === name;
|
|
5
|
+
/** Identity census follows the parser's first-Choice, otherwise-Fallback policy. */
|
|
6
|
+
const scanSelectedStreamingXmlElements = (xml, visitor) => {
|
|
7
|
+
if (!xml.includes("AlternateContent")) return scanStreamingXmlElements(xml, visitor);
|
|
8
|
+
const alternatives = /* @__PURE__ */ new Map();
|
|
9
|
+
const positions = /* @__PURE__ */ new WeakMap();
|
|
10
|
+
const scanned = scanStreamingXmlElements(xml, ({ element, parent, nameEnd }) => {
|
|
11
|
+
positions.set(element, nameEnd);
|
|
12
|
+
if (isCompatibilityElement(element, "AlternateContent")) {
|
|
13
|
+
element.elements = [];
|
|
14
|
+
alternatives.set(nameEnd, element);
|
|
15
|
+
}
|
|
16
|
+
if (!parent || !isCompatibilityElement(parent, "AlternateContent")) return;
|
|
17
|
+
parent.elements?.push(element);
|
|
18
|
+
});
|
|
19
|
+
if (scanned.status === "unsupported") return scanned;
|
|
20
|
+
const selectedPositions = /* @__PURE__ */ new Map();
|
|
21
|
+
for (const [position, alternative] of alternatives) {
|
|
22
|
+
const selected = selectAlternateContentBranch(alternative);
|
|
23
|
+
selectedPositions.set(position, selected === void 0 ? void 0 : positions.get(selected));
|
|
24
|
+
}
|
|
25
|
+
const active = /* @__PURE__ */ new WeakMap();
|
|
26
|
+
return scanStreamingXmlElements(xml, (entry) => {
|
|
27
|
+
const { element, parent, nameEnd } = entry;
|
|
28
|
+
positions.set(element, nameEnd);
|
|
29
|
+
let included = parent === void 0 || active.get(parent) === true;
|
|
30
|
+
if (parent && isCompatibilityElement(parent, "AlternateContent")) included &&= nameEnd === selectedPositions.get(positions.get(parent) ?? -1);
|
|
31
|
+
active.set(element, included);
|
|
32
|
+
if (included) visitor(entry);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
//#endregion
|
|
36
|
+
export { scanSelectedStreamingXmlElements };
|
|
@@ -10,7 +10,7 @@ import { RELATIONSHIP_TYPES } from "./relsParser.js";
|
|
|
10
10
|
import { COMMENTS_CONTENT_TYPE, COMMENTS_EXTENDED_PART_LOWER, addCommentsExtendedOverride, addCommentsExtendedRelationship, applyUpdatesToZip, collectHeaderFooterUpdates, findMaxRId, hasModelDrivenPictureWatermark, hasUnmaterializedHeaderFooter, hasUnmaterializedHyperlinkBindings, hasUnmaterializedInlineResources, planAddedStyles, publishCanonicalImageResources, updateCoreProperties, withoutAttachedTemplate } from "./rezip.js";
|
|
11
11
|
import "./selectiveSaveFlags.js";
|
|
12
12
|
import { buildPatchedDocumentXml, buildPatchedNoteXml, collectAddedNumberingDefs, collectParaIds, patchNumberingDefinitions } from "./selectiveXmlPatch.js";
|
|
13
|
-
import { hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
13
|
+
import { canReplayCommentsPart, hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended } from "./serializer/commentSerializer.js";
|
|
14
14
|
import { serializeDocument } from "./serializer/documentSerializer.js";
|
|
15
15
|
import { serializeEndnotes, serializeFootnotes } from "./serializer/noteSerializer.js";
|
|
16
16
|
import { serializeNumberingXml } from "./serializer/numberingSerializer.js";
|
|
@@ -262,8 +262,9 @@ async function attemptSelectiveSave(doc, originalBuffer, options) {
|
|
|
262
262
|
}
|
|
263
263
|
const sourceCommentsFile = findZipEntryCaseInsensitive(zip, "word/comments.xml");
|
|
264
264
|
const commentsPartPath = sourceCommentsFile?.name ?? "word/comments.xml";
|
|
265
|
-
|
|
266
|
-
|
|
265
|
+
const sourceCommentsXml = sourceCommentsFile ? await sourceCommentsFile.async("text") : void 0;
|
|
266
|
+
const commentsUnchanged = sourceCommentsXml !== void 0 && canReplayCommentsPart(doc, sourceCommentsXml);
|
|
267
|
+
if (!commentsUnchanged && (hasComments || ownsCommentsPart || sourceCommentsFile)) {
|
|
267
268
|
const commentsXml = serializeComments(commentPlan, sourceCommentsXml === void 0 ? void 0 : readRootNamespaceBindings(sourceCommentsXml));
|
|
268
269
|
if (commentsXml !== sourceCommentsXml) updates.set(commentsPartPath, commentsXml);
|
|
269
270
|
}
|
|
@@ -283,7 +284,7 @@ async function attemptSelectiveSave(doc, originalBuffer, options) {
|
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
|
-
if (!await patchCommentsExtended(zip, commentPlan, updates)) return null;
|
|
287
|
+
if (!commentsUnchanged && !await patchCommentsExtended(zip, commentPlan, updates)) return null;
|
|
287
288
|
if (!await patchNumberingPart(zip, doc, updates)) return null;
|
|
288
289
|
const styles = await planAddedStyles(doc, zip);
|
|
289
290
|
switch (styles.type) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { patchBreaksCommentRangeBalance } from "./commentRangeIntegrity.js";
|
|
2
2
|
import { resolveParagraphIdentities } from "./paraIdAttribute.js";
|
|
3
3
|
import { readRootNamespaceBindings } from "./serializer/partNamespaces.js";
|
|
4
|
+
import { scanStreamingXmlElements } from "./streamingXmlParser.js";
|
|
4
5
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
5
6
|
import { PARAGRAPH_SCAN_NAMES, hasCanonicalWordprocessingPrefixes, matchCloseTag, matchOpenTag, resolveSelectiveScanPrefixes, splicesAsCanonical } from "./wordprocessingPrefixes.js";
|
|
6
7
|
import { resolveNamespaceUri } from "./xmlNamespaceContext.js";
|
|
@@ -650,36 +651,32 @@ function extractElementByIdAttr(xml, openLiteral, closeTag, idAttr, id) {
|
|
|
650
651
|
const qualifiedName = (prefix, localName) => prefix.length === 0 ? localName : `${prefix}:${localName}`;
|
|
651
652
|
const collectNoteElementSyntax = (xml, elementName) => {
|
|
652
653
|
const byId = /* @__PURE__ */ new Map();
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
if (
|
|
654
|
+
let root;
|
|
655
|
+
scanStreamingXmlElements(xml, ({ element, parent, nameEnd }) => {
|
|
656
|
+
if (parent === void 0) {
|
|
657
|
+
root = element;
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
if (parent !== root || getLocalName(element.name) !== elementName || !WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(element) ?? "")) return;
|
|
656
661
|
const idAttribute = findAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, "id");
|
|
657
|
-
if (!element.name || !idAttribute)
|
|
662
|
+
if (!element.name || !idAttribute) return;
|
|
663
|
+
const spelling = idAttribute.value.trim();
|
|
664
|
+
if (!/^[+-]?\d+$/u.test(spelling) || !Number.isSafeInteger(Number(spelling))) return;
|
|
665
|
+
const id = String(Number(spelling));
|
|
666
|
+
const offsets = scanElementRange(xml, nameEnd - element.name.length - 1, `<${element.name}`, `</${element.name}>`);
|
|
667
|
+
if (!offsets) return;
|
|
658
668
|
const syntax = {
|
|
659
|
-
|
|
660
|
-
idAttributeName: idAttribute.name,
|
|
669
|
+
offsets,
|
|
661
670
|
elementPrefix: getNamespacePrefix(element.name) ?? "",
|
|
662
671
|
attributePrefix: getNamespacePrefix(idAttribute.name) ?? ""
|
|
663
672
|
};
|
|
664
|
-
const entries = byId.get(
|
|
673
|
+
const entries = byId.get(id);
|
|
665
674
|
if (entries) entries.push(syntax);
|
|
666
|
-
else byId.set(
|
|
667
|
-
}
|
|
675
|
+
else byId.set(id, [syntax]);
|
|
676
|
+
});
|
|
668
677
|
return byId;
|
|
669
678
|
};
|
|
670
|
-
const
|
|
671
|
-
openLiteral: `<${syntax.elementName}`,
|
|
672
|
-
closeTag: `</${syntax.elementName}>`,
|
|
673
|
-
idAttr: syntax.idAttributeName
|
|
674
|
-
});
|
|
675
|
-
const extractNoteElement = (xml, syntax, id) => {
|
|
676
|
-
const { openLiteral, closeTag, idAttr } = syntaxLiteral(syntax);
|
|
677
|
-
return extractElementByIdAttr(xml, openLiteral, closeTag, idAttr, id);
|
|
678
|
-
};
|
|
679
|
-
const findNoteElement = (xml, syntax, id) => {
|
|
680
|
-
const { openLiteral, closeTag, idAttr } = syntaxLiteral(syntax);
|
|
681
|
-
return findElementByIdAttr(xml, openLiteral, closeTag, idAttr, id);
|
|
682
|
-
};
|
|
679
|
+
const extractNoteElement = (xml, syntax) => xml.slice(syntax.offsets.start, syntax.offsets.end);
|
|
683
680
|
const rewriteWordprocessingPrefixes = (xml, { source, target, sourceXmlnsDeclarations }) => {
|
|
684
681
|
let rewritten = "";
|
|
685
682
|
let quote = null;
|
|
@@ -824,7 +821,7 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
824
821
|
const replacementSyntaxEntries = replacementElements.get(id);
|
|
825
822
|
if (originalSyntaxEntries === void 0) {
|
|
826
823
|
const replacementSyntax = currentSyntaxEntries.length === 1 && replacementSyntaxEntries?.length === 1 ? replacementSyntaxEntries[0] : void 0;
|
|
827
|
-
const replacementNote = replacementSyntax ? extractNoteElement(replacementXml, replacementSyntax
|
|
824
|
+
const replacementNote = replacementSyntax ? extractNoteElement(replacementXml, replacementSyntax) : null;
|
|
828
825
|
if (!replacementSyntax || !replacementNote) return {
|
|
829
826
|
type: "refused",
|
|
830
827
|
reason: "unroutable-paragraph"
|
|
@@ -836,24 +833,20 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
836
833
|
});
|
|
837
834
|
continue;
|
|
838
835
|
}
|
|
839
|
-
if (currentSyntaxEntries.length !== 1 || originalSyntaxEntries?.length
|
|
836
|
+
if (currentSyntaxEntries.length !== 1 || !originalSyntaxEntries?.length || replacementSyntaxEntries?.length !== 1) return {
|
|
840
837
|
type: "refused",
|
|
841
838
|
reason: "unroutable-paragraph"
|
|
842
839
|
};
|
|
843
840
|
const currentSyntax = currentSyntaxEntries[0];
|
|
844
|
-
const originalSyntax = originalSyntaxEntries
|
|
841
|
+
const originalSyntax = originalSyntaxEntries.at(0);
|
|
845
842
|
const replacementSyntax = replacementSyntaxEntries[0];
|
|
846
843
|
if (!currentSyntax || !originalSyntax || !replacementSyntax) return {
|
|
847
844
|
type: "refused",
|
|
848
845
|
reason: "unroutable-paragraph"
|
|
849
846
|
};
|
|
850
|
-
const currentNote = extractNoteElement(serializedXml, currentSyntax
|
|
851
|
-
const originalOffsets =
|
|
852
|
-
const replacementNote = extractNoteElement(replacementXml, replacementSyntax
|
|
853
|
-
if (!currentNote || !originalOffsets || !replacementNote) return {
|
|
854
|
-
type: "refused",
|
|
855
|
-
reason: "unroutable-paragraph"
|
|
856
|
-
};
|
|
847
|
+
const currentNote = extractNoteElement(serializedXml, currentSyntax);
|
|
848
|
+
const originalOffsets = originalSyntax.offsets;
|
|
849
|
+
const replacementNote = extractNoteElement(replacementXml, replacementSyntax);
|
|
857
850
|
const originalNote = originalXml.slice(originalOffsets.start, originalOffsets.end);
|
|
858
851
|
const currentParagraphs = paragraphRanges(currentNote, currentSyntax.elementPrefix);
|
|
859
852
|
const originalParagraphs = paragraphRanges(originalNote, originalSyntax.elementPrefix);
|
|
@@ -861,7 +854,7 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
861
854
|
const noteChangedParaIds = [...collectParaIds(currentNote).keys()].filter((paraId) => unroutedChangedParaIds.has(paraId));
|
|
862
855
|
const baselineSyntaxEntries = baselineElements.get(id);
|
|
863
856
|
const baselineSyntax = baselineSyntaxEntries?.length === 1 ? baselineSyntaxEntries[0] : void 0;
|
|
864
|
-
const baselineNote = baselineSyntax ? extractNoteElement(baselineXml, baselineSyntax
|
|
857
|
+
const baselineNote = baselineSyntax ? extractNoteElement(baselineXml, baselineSyntax) : null;
|
|
865
858
|
const reshaped = baselineSyntax !== void 0 && baselineNote !== null && baselineNote !== currentNote && noteShapeChanged({
|
|
866
859
|
note: baselineNote,
|
|
867
860
|
prefix: baselineSyntax.elementPrefix
|
|
@@ -910,26 +903,29 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
910
903
|
for (const [id, baselineSyntaxEntries] of baselineElements) {
|
|
911
904
|
if (currentElements.has(id) || baselineSyntaxEntries.length !== 1) continue;
|
|
912
905
|
const originalSyntaxEntries = originalElements.get(id);
|
|
913
|
-
|
|
914
|
-
const originalOffsets = originalSyntax && findNoteElement(originalXml, originalSyntax, id);
|
|
915
|
-
if (!originalOffsets) return {
|
|
906
|
+
if (!originalSyntaxEntries?.length) return {
|
|
916
907
|
type: "refused",
|
|
917
908
|
reason: "unroutable-paragraph"
|
|
918
909
|
};
|
|
919
|
-
const
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
910
|
+
for (const { offsets } of originalSyntaxEntries) {
|
|
911
|
+
const removal = {
|
|
912
|
+
...offsets,
|
|
913
|
+
newXml: ""
|
|
914
|
+
};
|
|
915
|
+
paragraphSplices.push(removal);
|
|
916
|
+
noteSplices.push(removal);
|
|
917
|
+
}
|
|
926
918
|
}
|
|
927
919
|
if (unroutedChangedParaIds.size > 0) return {
|
|
928
920
|
type: "refused",
|
|
929
921
|
reason: "unroutable-paragraph"
|
|
930
922
|
};
|
|
931
923
|
if (addedNotes.length > 0) {
|
|
932
|
-
const appended = appendNotesSplice(
|
|
924
|
+
const appended = appendNotesSplice({
|
|
925
|
+
originalElements,
|
|
926
|
+
addedNotes,
|
|
927
|
+
sourceXmlnsDeclarations: replacementXmlnsDeclarations
|
|
928
|
+
});
|
|
933
929
|
if (!appended) return {
|
|
934
930
|
type: "refused",
|
|
935
931
|
reason: "unroutable-paragraph"
|
|
@@ -951,15 +947,11 @@ function buildPatchedNotePartXml({ originalXml, baselineXml, serializedXml, repl
|
|
|
951
947
|
xml: wholeNotes
|
|
952
948
|
};
|
|
953
949
|
}
|
|
954
|
-
|
|
955
|
-
* Insert new notes after the part's last note, spelled with that note's
|
|
956
|
-
* prefixes. Null when the part holds no note to follow.
|
|
957
|
-
*/
|
|
958
|
-
const appendNotesSplice = (originalXml, originalElements, addedNotes, { sourceXmlnsDeclarations }) => {
|
|
950
|
+
const appendNotesSplice = ({ originalElements, addedNotes, sourceXmlnsDeclarations }) => {
|
|
959
951
|
let last = null;
|
|
960
|
-
for (const
|
|
961
|
-
const offsets =
|
|
962
|
-
if (
|
|
952
|
+
for (const entries of originalElements.values()) for (const syntax of entries) {
|
|
953
|
+
const offsets = syntax.offsets;
|
|
954
|
+
if (!last || offsets.end > last.end) last = {
|
|
963
955
|
end: offsets.end,
|
|
964
956
|
syntax
|
|
965
957
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
2
|
import { Comment } from "../../types/content.js";
|
|
3
3
|
//#region src/docx/serializer/commentSerializer.d.ts
|
|
4
|
+
/** An unrelated body edit must retain unmodelled duplicate comment definitions. */
|
|
5
|
+
declare const canReplayCommentsPart: (document: document_d_exports.Document, sourceXml: string) => boolean;
|
|
4
6
|
/** An owned empty part survives deletion of its final thread. */
|
|
5
7
|
declare const hasOwnedCommentsPart: (document: document_d_exports.Document) => boolean;
|
|
6
8
|
/**
|
|
@@ -55,4 +57,4 @@ declare function serializeComments({ order, byId }: CommentPartPlan, sourceBindi
|
|
|
55
57
|
*/
|
|
56
58
|
declare function serializeCommentsExtended(plan: CommentPartPlan): string | null;
|
|
57
59
|
//#endregion
|
|
58
|
-
export { CommentPartPlan, hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended };
|
|
60
|
+
export { CommentPartPlan, canReplayCommentsPart, hasOwnedCommentsPart, planCommentParts, serializeComments, serializeCommentsExtended };
|