@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
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { applyFolioAIEditOperations, previewFolioAIEditOperationsWithResult } from "./ai-edits/apply.js";
|
|
2
2
|
import { describeModelError, findIntroducedModelErrors } from "./ai-edits/result-validation.js";
|
|
3
3
|
import { LIST_KINDS } from "./docx/listNumberingInstances.js";
|
|
4
|
-
import { isNumberingReference } from "./docx/numberingReference.js";
|
|
5
4
|
import { completeNumberingForDoc } from "./prosemirror/listInstanceReferences.js";
|
|
6
5
|
import { outlineLevelFromAttrValue } from "./prosemirror/outlineLevelAttr.js";
|
|
7
6
|
import { getStatedDocumentNumbering } from "./prosemirror/plugins/documentNumbering.js";
|
|
8
7
|
import { LINE_SPACING_RULE_VALUES, PARAGRAPH_ALIGNMENT_VALUES } from "./types/documentEnumValues.js";
|
|
9
8
|
import { TaggedError } from "better-result";
|
|
10
9
|
import { sanitizeXmlCharacters } from "@stll/docx-core";
|
|
10
|
+
import { isNumberingReference, paragraphNumberingReference } from "@stll/docx-core/model";
|
|
11
11
|
//#region src/document-operations.ts
|
|
12
12
|
const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION = 1;
|
|
13
13
|
/** Direct paragraph-alignment values accepted by the operation contract. */
|
|
@@ -210,16 +210,6 @@ const readNonNegativeInteger = (value, key, path) => {
|
|
|
210
210
|
if (typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0) return candidate;
|
|
211
211
|
return invalidBatch(`${path}.${key}`, "expected a non-negative safe integer");
|
|
212
212
|
};
|
|
213
|
-
/**
|
|
214
|
-
* A non-negative integer that may also be cleared. `undefined` is "say
|
|
215
|
-
* nothing"; `null` is "there is none", which is a different instruction and
|
|
216
|
-
* the one absence alone cannot give.
|
|
217
|
-
*/
|
|
218
|
-
const readClearableNonNegativeInteger = (value, key, path) => {
|
|
219
|
-
const candidate = value[key];
|
|
220
|
-
if (candidate === void 0) return;
|
|
221
|
-
return candidate === null ? null : readNonNegativeInteger(value, key, path);
|
|
222
|
-
};
|
|
223
213
|
const readClearableParagraphAlignment = ({ value, key, path }) => {
|
|
224
214
|
const candidate = value[key];
|
|
225
215
|
if (candidate === void 0 || candidate === null) return candidate;
|
|
@@ -302,43 +292,64 @@ const readClearableParagraphIndentation = ({ value, key, path }) => {
|
|
|
302
292
|
const MAX_NEW_LIST_LEVEL = 8;
|
|
303
293
|
const LIST_KIND_SET = new Set(LIST_KINDS);
|
|
304
294
|
const isListKind = (value) => LIST_KIND_SET.has(value);
|
|
305
|
-
/** `{
|
|
295
|
+
/** `{ kind: "newList", format, level? }`: a list the operation starts. */
|
|
306
296
|
const readNewListReference = (candidate, numberingPath) => {
|
|
307
297
|
assertAllowedKeys(candidate, numberingPath, [
|
|
308
|
-
"start",
|
|
309
298
|
"kind",
|
|
299
|
+
"format",
|
|
310
300
|
"level"
|
|
311
301
|
]);
|
|
312
|
-
const
|
|
313
|
-
if (typeof
|
|
302
|
+
const format = candidate["format"];
|
|
303
|
+
if (typeof format !== "string" || !isListKind(format)) return invalidBatch(`${numberingPath}.format`, `expected one of ${LIST_KINDS.join(", ")}`);
|
|
314
304
|
if (candidate["level"] === void 0) return {
|
|
315
|
-
|
|
316
|
-
|
|
305
|
+
kind: "newList",
|
|
306
|
+
format
|
|
317
307
|
};
|
|
318
308
|
const level = readNonNegativeInteger(candidate, "level", numberingPath);
|
|
319
309
|
if (level > MAX_NEW_LIST_LEVEL) return invalidBatch(`${numberingPath}.level`, `expected at most ${MAX_NEW_LIST_LEVEL}`);
|
|
320
310
|
return {
|
|
321
|
-
|
|
322
|
-
|
|
311
|
+
kind: "newList",
|
|
312
|
+
format,
|
|
323
313
|
level
|
|
324
314
|
};
|
|
325
315
|
};
|
|
326
316
|
const readClearableNumbering = ({ value, key, path }) => {
|
|
327
317
|
const candidate = value[key];
|
|
328
|
-
if (candidate === void 0
|
|
318
|
+
if (candidate === void 0) return void 0;
|
|
329
319
|
const numberingPath = `${path}.${key}`;
|
|
330
|
-
if (!isPlainObject(candidate)) return invalidBatch(numberingPath, "expected
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
320
|
+
if (!isPlainObject(candidate)) return invalidBatch(numberingPath, "expected a numbering object");
|
|
321
|
+
const kind = candidate["kind"];
|
|
322
|
+
if (kind === "none" || kind === "inherit") {
|
|
323
|
+
assertAllowedKeys(candidate, numberingPath, ["kind"]);
|
|
324
|
+
return { kind };
|
|
334
325
|
}
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
326
|
+
if (kind === "levelOnly") {
|
|
327
|
+
assertAllowedKeys(candidate, numberingPath, ["kind", "ilvl"]);
|
|
328
|
+
const ilvl = readNonNegativeInteger(candidate, "ilvl", numberingPath);
|
|
329
|
+
if (ilvl > MAX_NEW_LIST_LEVEL) return invalidBatch(`${numberingPath}.ilvl`, `expected at most ${MAX_NEW_LIST_LEVEL}`);
|
|
330
|
+
return {
|
|
331
|
+
kind,
|
|
332
|
+
ilvl
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
if (kind === "reference") {
|
|
336
|
+
assertAllowedKeys(candidate, numberingPath, [
|
|
337
|
+
"kind",
|
|
338
|
+
"numId",
|
|
339
|
+
"ilvl"
|
|
340
|
+
]);
|
|
341
|
+
const numId = readNonNegativeInteger(candidate, "numId", numberingPath);
|
|
342
|
+
if (!isNumberingReference(numId)) return invalidBatch(`${numberingPath}.numId`, "expected a positive integer");
|
|
343
|
+
if (candidate["ilvl"] === void 0) return paragraphNumberingReference({ numId });
|
|
344
|
+
const ilvl = readNonNegativeInteger(candidate, "ilvl", numberingPath);
|
|
345
|
+
if (ilvl > MAX_NEW_LIST_LEVEL) return invalidBatch(`${numberingPath}.ilvl`, `expected at most ${MAX_NEW_LIST_LEVEL}`);
|
|
346
|
+
return paragraphNumberingReference({
|
|
347
|
+
numId,
|
|
348
|
+
ilvl
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
if (kind === "newList") return readNewListReference(candidate, numberingPath);
|
|
352
|
+
return invalidBatch(`${numberingPath}.kind`, "expected \"none\", \"inherit\", \"levelOnly\", \"reference\", or \"newList\"");
|
|
342
353
|
};
|
|
343
354
|
/**
|
|
344
355
|
* A rectangular grid of cell texts. Rectangular because a table whose rows
|
|
@@ -376,7 +387,6 @@ const readParagraphProperties = ({ value, key, path }) => {
|
|
|
376
387
|
assertAllowedKeys(candidate, propertiesPath, [
|
|
377
388
|
"styleId",
|
|
378
389
|
"outlineLevel",
|
|
379
|
-
"listLevel",
|
|
380
390
|
"numbering",
|
|
381
391
|
"alignment",
|
|
382
392
|
"spacing",
|
|
@@ -384,7 +394,6 @@ const readParagraphProperties = ({ value, key, path }) => {
|
|
|
384
394
|
]);
|
|
385
395
|
const styleId = candidate["styleId"] === null ? null : readOptionalString(candidate, "styleId", propertiesPath);
|
|
386
396
|
const outlineLevel = readClearableOutlineLevel(candidate, propertiesPath);
|
|
387
|
-
const listLevel = readClearableNonNegativeInteger(candidate, "listLevel", propertiesPath);
|
|
388
397
|
const numbering = readClearableNumbering({
|
|
389
398
|
value: candidate,
|
|
390
399
|
key: "numbering",
|
|
@@ -405,11 +414,10 @@ const readParagraphProperties = ({ value, key, path }) => {
|
|
|
405
414
|
key: "indentation",
|
|
406
415
|
path: propertiesPath
|
|
407
416
|
});
|
|
408
|
-
if (styleId === void 0 && outlineLevel === void 0 &&
|
|
417
|
+
if (styleId === void 0 && outlineLevel === void 0 && numbering === void 0 && alignment === void 0 && spacing === void 0 && indentation === void 0) return invalidBatch(propertiesPath, "expected at least one property to set");
|
|
409
418
|
return {
|
|
410
419
|
...styleId !== void 0 && { styleId },
|
|
411
420
|
...outlineLevel !== void 0 && { outlineLevel },
|
|
412
|
-
...listLevel !== void 0 && { listLevel },
|
|
413
421
|
...numbering !== void 0 && { numbering },
|
|
414
422
|
...alignment !== void 0 && { alignment },
|
|
415
423
|
...spacing !== void 0 && { spacing },
|
|
@@ -555,7 +563,6 @@ const OPERATION_KEY_DECISIONS = {
|
|
|
555
563
|
indentation: true,
|
|
556
564
|
lineBreakMode: true,
|
|
557
565
|
formattingScope: true,
|
|
558
|
-
listLevel: true,
|
|
559
566
|
numbering: true,
|
|
560
567
|
moveId: true,
|
|
561
568
|
pageBreakBefore: true,
|
|
@@ -573,7 +580,6 @@ const OPERATION_KEY_DECISIONS = {
|
|
|
573
580
|
indentation: true,
|
|
574
581
|
lineBreakMode: true,
|
|
575
582
|
formattingScope: true,
|
|
576
|
-
listLevel: true,
|
|
577
583
|
numbering: true,
|
|
578
584
|
moveId: true,
|
|
579
585
|
pageBreakBefore: true,
|
|
@@ -833,7 +839,6 @@ const parseDocumentOperation = (value, index) => {
|
|
|
833
839
|
const styleId = value["styleId"] === null ? null : readOptionalString(value, "styleId", path);
|
|
834
840
|
const outlineLevel = readClearableOutlineLevel(value, path);
|
|
835
841
|
const moveId = readOptionalString(value, "moveId", path);
|
|
836
|
-
const listLevel = readClearableNonNegativeInteger(value, "listLevel", path);
|
|
837
842
|
const numbering = readClearableNumbering({
|
|
838
843
|
value,
|
|
839
844
|
key: "numbering",
|
|
@@ -874,7 +879,6 @@ const parseDocumentOperation = (value, index) => {
|
|
|
874
879
|
...indentation !== void 0 && { indentation },
|
|
875
880
|
...lineBreakMode !== void 0 && { lineBreakMode },
|
|
876
881
|
...formattingScope !== void 0 && { formattingScope },
|
|
877
|
-
...listLevel !== void 0 && { listLevel },
|
|
878
882
|
...numbering !== void 0 && { numbering },
|
|
879
883
|
...moveId !== void 0 && { moveId },
|
|
880
884
|
...pageBreakBefore !== void 0 && { pageBreakBefore },
|
|
@@ -1250,7 +1254,7 @@ const inOperationOrder = (operations, skipped) => {
|
|
|
1250
1254
|
const indexById = new Map(operations.map(({ id }, index) => [id, index]));
|
|
1251
1255
|
return [...skipped].sort((left, right) => (indexById.get(left.id) ?? -1) - (indexById.get(right.id) ?? -1));
|
|
1252
1256
|
};
|
|
1253
|
-
const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates, replacementBackground,
|
|
1257
|
+
const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates, replacementBackground, undefinedReferences }) => {
|
|
1254
1258
|
const parsedBatch = parseFolioDocumentOperationBatch(batch);
|
|
1255
1259
|
const isAtomic = parsedBatch.atomic === true;
|
|
1256
1260
|
const beforeDoc = view.state.doc;
|
|
@@ -1265,7 +1269,7 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", a
|
|
|
1265
1269
|
...wordDiff !== void 0 && { wordDiff },
|
|
1266
1270
|
...tableTemplates !== void 0 && { tableTemplates },
|
|
1267
1271
|
...replacementBackground !== void 0 && { replacementBackground },
|
|
1268
|
-
|
|
1272
|
+
undefinedReferences
|
|
1269
1273
|
};
|
|
1270
1274
|
if (preview) return {
|
|
1271
1275
|
...previewFolioAIEditOperationsWithResult({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { XmlElement } from "./xmlParser.js";
|
|
2
1
|
import { ModelledAttributes } from "./propertyElementAttributes.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
3
|
import { PreservedAttribute } from "@stll/docx-core/model";
|
|
4
4
|
//#region src/docx/attributeRemainder.d.ts
|
|
5
5
|
declare const InvalidPreservedAttributeError_base: import("better-result").TaggedErrorClass<"InvalidPreservedAttributeError">;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/docx/bookmarkIdNormalization.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Give repeated bookmark ranges independent identities before editor pairing.
|
|
4
|
+
* The first range keeps its id. Ends close starts in encounter order, including
|
|
5
|
+
* overlapping ambiguous ranges. Only colliding ids are repaired: those require
|
|
6
|
+
* unique XML ids for a valid save. Every other source byte stays verbatim.
|
|
7
|
+
*/
|
|
8
|
+
declare const normalizeBookmarkIdsInXmlParts: (parts: ReadonlyMap<string, string>) => ReadonlyMap<string, string>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { normalizeBookmarkIdsInXmlParts };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { scanSelectedStreamingXmlElements } from "./selectedXmlIdentityScan.js";
|
|
2
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, findAttributeByNamespaceUri, getLocalName, getNamespaceUri } from "./xmlParser.js";
|
|
3
|
+
import { panic } from "better-result";
|
|
4
|
+
//#region src/docx/bookmarkIdNormalization.ts
|
|
5
|
+
const bookmarkIdentity = (element) => {
|
|
6
|
+
if (!WORDPROCESSINGML_NAMESPACE_URIS.has(getNamespaceUri(element) ?? "")) return null;
|
|
7
|
+
const name = getLocalName(element.name);
|
|
8
|
+
if (name !== "bookmarkStart" && name !== "bookmarkEnd") return null;
|
|
9
|
+
const attribute = findAttributeByNamespaceUri(element, WORDPROCESSINGML_NAMESPACE_URIS, "id");
|
|
10
|
+
if (!attribute) return null;
|
|
11
|
+
const id = Number(attribute.value);
|
|
12
|
+
if (!Number.isSafeInteger(id) || id < 0) return null;
|
|
13
|
+
return {
|
|
14
|
+
name,
|
|
15
|
+
attribute: attribute.name,
|
|
16
|
+
id
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Give repeated bookmark ranges independent identities before editor pairing.
|
|
21
|
+
* The first range keeps its id. Ends close starts in encounter order, including
|
|
22
|
+
* overlapping ambiguous ranges. Only colliding ids are repaired: those require
|
|
23
|
+
* unique XML ids for a valid save. Every other source byte stays verbatim.
|
|
24
|
+
*/
|
|
25
|
+
const normalizeBookmarkIdsInXmlParts = (parts) => {
|
|
26
|
+
const candidates = [...parts].filter(([, xml]) => /bookmark(?:Start|End)/u.test(xml));
|
|
27
|
+
const reserved = /* @__PURE__ */ new Set();
|
|
28
|
+
const repeated = /* @__PURE__ */ new Set();
|
|
29
|
+
const markersByPart = /* @__PURE__ */ new Map();
|
|
30
|
+
for (const [path, xml] of candidates) {
|
|
31
|
+
const starts = /* @__PURE__ */ new Set();
|
|
32
|
+
const markers = [];
|
|
33
|
+
if (scanSelectedStreamingXmlElements(xml, ({ element, attributeValueSpans }) => {
|
|
34
|
+
const marker = bookmarkIdentity(element);
|
|
35
|
+
if (!marker) return;
|
|
36
|
+
const span = attributeValueSpans.get(marker.attribute);
|
|
37
|
+
if (!span) panic("Missing bookmark identity source span");
|
|
38
|
+
markers.push({
|
|
39
|
+
marker,
|
|
40
|
+
...span
|
|
41
|
+
});
|
|
42
|
+
reserved.add(marker.id);
|
|
43
|
+
if (marker.name === "bookmarkStart") {
|
|
44
|
+
if (starts.has(marker.id)) repeated.add(path);
|
|
45
|
+
starts.add(marker.id);
|
|
46
|
+
}
|
|
47
|
+
}).status === "unsupported") {
|
|
48
|
+
repeated.delete(path);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
markersByPart.set(path, markers);
|
|
52
|
+
}
|
|
53
|
+
if (repeated.size === 0) return parts;
|
|
54
|
+
let next = 0;
|
|
55
|
+
const allocate = () => {
|
|
56
|
+
while (reserved.has(next)) next += 1;
|
|
57
|
+
const id = next++;
|
|
58
|
+
reserved.add(id);
|
|
59
|
+
return id;
|
|
60
|
+
};
|
|
61
|
+
const normalized = new Map(parts);
|
|
62
|
+
for (const [path, xml] of candidates) {
|
|
63
|
+
if (!repeated.has(path)) continue;
|
|
64
|
+
const seen = /* @__PURE__ */ new Set();
|
|
65
|
+
const open = /* @__PURE__ */ new Map();
|
|
66
|
+
const chunks = [];
|
|
67
|
+
let cursor = 0;
|
|
68
|
+
for (const { marker, start, end } of markersByPart.get(path) ?? []) {
|
|
69
|
+
let id = marker.id;
|
|
70
|
+
if (marker.name === "bookmarkStart") {
|
|
71
|
+
if (seen.has(id)) id = allocate();
|
|
72
|
+
seen.add(marker.id);
|
|
73
|
+
let queue = open.get(marker.id);
|
|
74
|
+
if (!queue) {
|
|
75
|
+
queue = {
|
|
76
|
+
ids: [],
|
|
77
|
+
cursor: 0
|
|
78
|
+
};
|
|
79
|
+
open.set(marker.id, queue);
|
|
80
|
+
}
|
|
81
|
+
queue.ids.push(id);
|
|
82
|
+
} else {
|
|
83
|
+
const queue = open.get(marker.id);
|
|
84
|
+
const paired = queue?.ids.at(queue.cursor);
|
|
85
|
+
if (paired !== void 0 && queue) {
|
|
86
|
+
id = paired;
|
|
87
|
+
queue.cursor += 1;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (id === marker.id) continue;
|
|
91
|
+
chunks.push(xml.slice(cursor, start), String(id));
|
|
92
|
+
cursor = end;
|
|
93
|
+
}
|
|
94
|
+
chunks.push(xml.slice(cursor));
|
|
95
|
+
normalized.set(path, chunks.join(""));
|
|
96
|
+
}
|
|
97
|
+
return normalized;
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
100
|
+
export { normalizeBookmarkIdsInXmlParts };
|
|
@@ -31,8 +31,10 @@ function createBookmarkMap() {
|
|
|
31
31
|
* @param bookmark - The bookmark start to add
|
|
32
32
|
*/
|
|
33
33
|
function addBookmark(map, bookmark) {
|
|
34
|
-
map.byId.set(bookmark.id, bookmark);
|
|
35
|
-
if (bookmark.name)
|
|
34
|
+
if (!map.byId.has(bookmark.id)) map.byId.set(bookmark.id, bookmark);
|
|
35
|
+
if (bookmark.name) {
|
|
36
|
+
if (!map.byName.has(bookmark.name)) map.byName.set(bookmark.name, bookmark);
|
|
37
|
+
}
|
|
36
38
|
map.bookmarks.push(bookmark);
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { ParseContext } from "./parseContext.js";
|
|
2
|
+
//#region src/docx/importedIdCollisions.d.ts
|
|
3
|
+
/** Definition sites only: paired markers and references never claim an identity. */
|
|
4
|
+
declare const IMPORTED_ID_COLLISION_REGISTRY: {
|
|
5
|
+
readonly bookmark: {
|
|
6
|
+
readonly kind: "bookmark";
|
|
7
|
+
readonly scope: "part";
|
|
8
|
+
readonly sites: readonly [{
|
|
9
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
10
|
+
readonly elements: Set<string>;
|
|
11
|
+
}];
|
|
12
|
+
readonly attribute: "id";
|
|
13
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
14
|
+
readonly encoding: "decimal";
|
|
15
|
+
};
|
|
16
|
+
readonly comment: {
|
|
17
|
+
readonly kind: "comment";
|
|
18
|
+
readonly scope: "part";
|
|
19
|
+
readonly sites: readonly [{
|
|
20
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
21
|
+
readonly elements: Set<string>;
|
|
22
|
+
}];
|
|
23
|
+
readonly attribute: "id";
|
|
24
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
25
|
+
readonly encoding: "decimal";
|
|
26
|
+
};
|
|
27
|
+
readonly footnote: {
|
|
28
|
+
readonly kind: "footnote";
|
|
29
|
+
readonly scope: "part";
|
|
30
|
+
readonly sites: readonly [{
|
|
31
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
32
|
+
readonly elements: Set<string>;
|
|
33
|
+
}];
|
|
34
|
+
readonly attribute: "id";
|
|
35
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
36
|
+
readonly encoding: "decimal";
|
|
37
|
+
};
|
|
38
|
+
readonly endnote: {
|
|
39
|
+
readonly kind: "endnote";
|
|
40
|
+
readonly scope: "part";
|
|
41
|
+
readonly sites: readonly [{
|
|
42
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
43
|
+
readonly elements: Set<string>;
|
|
44
|
+
}];
|
|
45
|
+
readonly attribute: "id";
|
|
46
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
47
|
+
readonly encoding: "decimal";
|
|
48
|
+
};
|
|
49
|
+
readonly revision: {
|
|
50
|
+
readonly kind: "revision";
|
|
51
|
+
readonly scope: "package";
|
|
52
|
+
readonly sites: readonly [{
|
|
53
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
54
|
+
readonly elements: Set<string>;
|
|
55
|
+
}];
|
|
56
|
+
readonly attribute: "id";
|
|
57
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
58
|
+
readonly encoding: "decimal";
|
|
59
|
+
};
|
|
60
|
+
readonly paraId: {
|
|
61
|
+
readonly kind: "paraId";
|
|
62
|
+
readonly scope: "part";
|
|
63
|
+
readonly sites: readonly [{
|
|
64
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
65
|
+
readonly elements: Set<string>;
|
|
66
|
+
}, {
|
|
67
|
+
readonly namespace: "http://schemas.microsoft.com/office/word/2012/wordml";
|
|
68
|
+
readonly elements: Set<string>;
|
|
69
|
+
}, {
|
|
70
|
+
readonly namespace: string;
|
|
71
|
+
readonly elements: Set<string>;
|
|
72
|
+
}];
|
|
73
|
+
readonly attribute: "paraId";
|
|
74
|
+
readonly attributeNamespace: "http://schemas.microsoft.com/office/word/2010/wordml";
|
|
75
|
+
readonly encoding: "hex";
|
|
76
|
+
};
|
|
77
|
+
readonly textId: {
|
|
78
|
+
readonly kind: "textId";
|
|
79
|
+
readonly scope: "part";
|
|
80
|
+
readonly sites: readonly [{
|
|
81
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
82
|
+
readonly elements: Set<string>;
|
|
83
|
+
}];
|
|
84
|
+
readonly attribute: "textId";
|
|
85
|
+
readonly attributeNamespace: "http://schemas.microsoft.com/office/word/2010/wordml";
|
|
86
|
+
readonly encoding: "hex";
|
|
87
|
+
};
|
|
88
|
+
readonly numId: {
|
|
89
|
+
readonly kind: "numId";
|
|
90
|
+
readonly scope: "part";
|
|
91
|
+
readonly sites: readonly [{
|
|
92
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
93
|
+
readonly elements: Set<string>;
|
|
94
|
+
}];
|
|
95
|
+
readonly attribute: "numId";
|
|
96
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
97
|
+
readonly encoding: "decimal";
|
|
98
|
+
};
|
|
99
|
+
readonly abstractNumId: {
|
|
100
|
+
readonly kind: "abstractNumId";
|
|
101
|
+
readonly scope: "part";
|
|
102
|
+
readonly sites: readonly [{
|
|
103
|
+
readonly namespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
104
|
+
readonly elements: Set<string>;
|
|
105
|
+
}];
|
|
106
|
+
readonly attribute: "abstractNumId";
|
|
107
|
+
readonly attributeNamespace: "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
108
|
+
readonly encoding: "decimal";
|
|
109
|
+
};
|
|
110
|
+
readonly drawing: {
|
|
111
|
+
readonly kind: "drawing";
|
|
112
|
+
readonly scope: "package";
|
|
113
|
+
readonly sites: readonly [{
|
|
114
|
+
readonly namespace: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing";
|
|
115
|
+
readonly elements: Set<string>;
|
|
116
|
+
}];
|
|
117
|
+
readonly attribute: "id";
|
|
118
|
+
readonly attributeNamespace: null;
|
|
119
|
+
readonly encoding: "decimal";
|
|
120
|
+
};
|
|
121
|
+
readonly relationship: {
|
|
122
|
+
readonly kind: "relationship";
|
|
123
|
+
readonly scope: "part";
|
|
124
|
+
readonly sites: readonly [{
|
|
125
|
+
readonly namespace: "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
126
|
+
readonly elements: Set<string>;
|
|
127
|
+
}];
|
|
128
|
+
readonly attribute: "Id";
|
|
129
|
+
readonly attributeNamespace: null;
|
|
130
|
+
readonly encoding: "string";
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
/** Reports repeated source definitions without changing the package or choosing a winner. */
|
|
134
|
+
declare const diagnoseImportedIdCollisions: (parts: ReadonlyMap<string, string>, context: ParseContext) => void;
|
|
135
|
+
//#endregion
|
|
136
|
+
export { IMPORTED_ID_COLLISION_REGISTRY, diagnoseImportedIdCollisions };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { paraIdAttribute, textIdAttribute } from "./paraIdAttribute.js";
|
|
2
|
+
import { REVISION_ELEMENT_NAMES } from "./revisionIdNormalization.js";
|
|
3
|
+
import { scanSelectedStreamingXmlElements } from "./selectedXmlIdentityScan.js";
|
|
4
|
+
import { OOXML_NAMESPACES } from "./serializer/partNamespaces.js";
|
|
5
|
+
import { toTransitionalNamespaceUri } from "./transitionalSpelling.js";
|
|
6
|
+
import { resolveNamespaceUri } from "./xmlNamespaceContext.js";
|
|
7
|
+
import { NAMESPACES, getLocalName, getNamespaceUri } from "./xmlParser.js";
|
|
8
|
+
import { panic } from "better-result";
|
|
9
|
+
import { IMPORTED_ID_COLLISION_KINDS, PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
10
|
+
//#region src/docx/importedIdCollisions.ts
|
|
11
|
+
const WORD_2010_NAMESPACE = "http://schemas.microsoft.com/office/word/2010/wordml";
|
|
12
|
+
const PACKAGE_RELATIONSHIP_NAMESPACE = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
13
|
+
const paragraphIdentityForKind = (kind, element) => {
|
|
14
|
+
switch (kind) {
|
|
15
|
+
case IMPORTED_ID_COLLISION_KINDS.paraId: return paraIdAttribute(element);
|
|
16
|
+
case IMPORTED_ID_COLLISION_KINDS.textId: return textIdAttribute(element);
|
|
17
|
+
default: return;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/** Definition sites only: paired markers and references never claim an identity. */
|
|
21
|
+
const IMPORTED_ID_COLLISION_REGISTRY = {
|
|
22
|
+
bookmark: {
|
|
23
|
+
kind: IMPORTED_ID_COLLISION_KINDS.bookmark,
|
|
24
|
+
scope: "part",
|
|
25
|
+
sites: [{
|
|
26
|
+
namespace: NAMESPACES.w,
|
|
27
|
+
elements: /* @__PURE__ */ new Set(["bookmarkStart"])
|
|
28
|
+
}],
|
|
29
|
+
attribute: "id",
|
|
30
|
+
attributeNamespace: NAMESPACES.w,
|
|
31
|
+
encoding: "decimal"
|
|
32
|
+
},
|
|
33
|
+
comment: {
|
|
34
|
+
kind: IMPORTED_ID_COLLISION_KINDS.comment,
|
|
35
|
+
scope: "part",
|
|
36
|
+
sites: [{
|
|
37
|
+
namespace: NAMESPACES.w,
|
|
38
|
+
elements: /* @__PURE__ */ new Set(["comment"])
|
|
39
|
+
}],
|
|
40
|
+
attribute: "id",
|
|
41
|
+
attributeNamespace: NAMESPACES.w,
|
|
42
|
+
encoding: "decimal"
|
|
43
|
+
},
|
|
44
|
+
footnote: {
|
|
45
|
+
kind: IMPORTED_ID_COLLISION_KINDS.footnote,
|
|
46
|
+
scope: "part",
|
|
47
|
+
sites: [{
|
|
48
|
+
namespace: NAMESPACES.w,
|
|
49
|
+
elements: /* @__PURE__ */ new Set(["footnote"])
|
|
50
|
+
}],
|
|
51
|
+
attribute: "id",
|
|
52
|
+
attributeNamespace: NAMESPACES.w,
|
|
53
|
+
encoding: "decimal"
|
|
54
|
+
},
|
|
55
|
+
endnote: {
|
|
56
|
+
kind: IMPORTED_ID_COLLISION_KINDS.endnote,
|
|
57
|
+
scope: "part",
|
|
58
|
+
sites: [{
|
|
59
|
+
namespace: NAMESPACES.w,
|
|
60
|
+
elements: /* @__PURE__ */ new Set(["endnote"])
|
|
61
|
+
}],
|
|
62
|
+
attribute: "id",
|
|
63
|
+
attributeNamespace: NAMESPACES.w,
|
|
64
|
+
encoding: "decimal"
|
|
65
|
+
},
|
|
66
|
+
revision: {
|
|
67
|
+
kind: IMPORTED_ID_COLLISION_KINDS.revision,
|
|
68
|
+
scope: "package",
|
|
69
|
+
sites: [{
|
|
70
|
+
namespace: NAMESPACES.w,
|
|
71
|
+
elements: REVISION_ELEMENT_NAMES
|
|
72
|
+
}],
|
|
73
|
+
attribute: "id",
|
|
74
|
+
attributeNamespace: NAMESPACES.w,
|
|
75
|
+
encoding: "decimal"
|
|
76
|
+
},
|
|
77
|
+
paraId: {
|
|
78
|
+
kind: IMPORTED_ID_COLLISION_KINDS.paraId,
|
|
79
|
+
scope: "part",
|
|
80
|
+
sites: [
|
|
81
|
+
{
|
|
82
|
+
namespace: NAMESPACES.w,
|
|
83
|
+
elements: /* @__PURE__ */ new Set(["p"])
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
namespace: NAMESPACES.w15,
|
|
87
|
+
elements: /* @__PURE__ */ new Set(["commentEx"])
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
namespace: OOXML_NAMESPACES.w16cex.uri,
|
|
91
|
+
elements: /* @__PURE__ */ new Set(["comment"])
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
attribute: "paraId",
|
|
95
|
+
attributeNamespace: WORD_2010_NAMESPACE,
|
|
96
|
+
encoding: "hex"
|
|
97
|
+
},
|
|
98
|
+
textId: {
|
|
99
|
+
kind: IMPORTED_ID_COLLISION_KINDS.textId,
|
|
100
|
+
scope: "part",
|
|
101
|
+
sites: [{
|
|
102
|
+
namespace: NAMESPACES.w,
|
|
103
|
+
elements: /* @__PURE__ */ new Set(["p"])
|
|
104
|
+
}],
|
|
105
|
+
attribute: "textId",
|
|
106
|
+
attributeNamespace: WORD_2010_NAMESPACE,
|
|
107
|
+
encoding: "hex"
|
|
108
|
+
},
|
|
109
|
+
numId: {
|
|
110
|
+
kind: IMPORTED_ID_COLLISION_KINDS.numId,
|
|
111
|
+
scope: "part",
|
|
112
|
+
sites: [{
|
|
113
|
+
namespace: NAMESPACES.w,
|
|
114
|
+
elements: /* @__PURE__ */ new Set(["num"])
|
|
115
|
+
}],
|
|
116
|
+
attribute: "numId",
|
|
117
|
+
attributeNamespace: NAMESPACES.w,
|
|
118
|
+
encoding: "decimal"
|
|
119
|
+
},
|
|
120
|
+
abstractNumId: {
|
|
121
|
+
kind: IMPORTED_ID_COLLISION_KINDS.abstractNumId,
|
|
122
|
+
scope: "part",
|
|
123
|
+
sites: [{
|
|
124
|
+
namespace: NAMESPACES.w,
|
|
125
|
+
elements: /* @__PURE__ */ new Set(["abstractNum"])
|
|
126
|
+
}],
|
|
127
|
+
attribute: "abstractNumId",
|
|
128
|
+
attributeNamespace: NAMESPACES.w,
|
|
129
|
+
encoding: "decimal"
|
|
130
|
+
},
|
|
131
|
+
drawing: {
|
|
132
|
+
kind: IMPORTED_ID_COLLISION_KINDS.drawing,
|
|
133
|
+
scope: "package",
|
|
134
|
+
sites: [{
|
|
135
|
+
namespace: NAMESPACES.wp,
|
|
136
|
+
elements: /* @__PURE__ */ new Set(["docPr"])
|
|
137
|
+
}],
|
|
138
|
+
attribute: "id",
|
|
139
|
+
attributeNamespace: null,
|
|
140
|
+
encoding: "decimal"
|
|
141
|
+
},
|
|
142
|
+
relationship: {
|
|
143
|
+
kind: IMPORTED_ID_COLLISION_KINDS.relationship,
|
|
144
|
+
scope: "part",
|
|
145
|
+
sites: [{
|
|
146
|
+
namespace: PACKAGE_RELATIONSHIP_NAMESPACE,
|
|
147
|
+
elements: /* @__PURE__ */ new Set(["Relationship"])
|
|
148
|
+
}],
|
|
149
|
+
attribute: "Id",
|
|
150
|
+
attributeNamespace: null,
|
|
151
|
+
encoding: "string"
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const normalizedIdentity = (value, encoding) => {
|
|
155
|
+
if (encoding === "string") return value;
|
|
156
|
+
if (encoding === "hex") return /^[0-9a-f]{8}$/iu.test(value) ? value.toUpperCase() : void 0;
|
|
157
|
+
const spelling = value.trim();
|
|
158
|
+
if (!/^[+-]?\d+$/u.test(spelling)) return void 0;
|
|
159
|
+
const digits = spelling.replace(/^[+-]?0*/u, "");
|
|
160
|
+
return digits === "" ? "0" : `${spelling.startsWith("-") ? "-" : ""}${digits}`;
|
|
161
|
+
};
|
|
162
|
+
/** Reports repeated source definitions without changing the package or choosing a winner. */
|
|
163
|
+
const diagnoseImportedIdCollisions = (parts, context) => {
|
|
164
|
+
const rules = Object.values(IMPORTED_ID_COLLISION_REGISTRY);
|
|
165
|
+
const packageSeen = /* @__PURE__ */ new Map();
|
|
166
|
+
for (const [part, xml] of parts) {
|
|
167
|
+
const partSeen = /* @__PURE__ */ new Map();
|
|
168
|
+
const scoped = context.scoped({ part });
|
|
169
|
+
scanSelectedStreamingXmlElements(xml, ({ element, attributeValueSpans }) => {
|
|
170
|
+
if (element.name === void 0) return;
|
|
171
|
+
const namespace = toTransitionalNamespaceUri(getNamespaceUri(element) ?? "");
|
|
172
|
+
const localName = getLocalName(element.name);
|
|
173
|
+
for (const rule of rules) {
|
|
174
|
+
const kind = rule.kind;
|
|
175
|
+
if (!rule.sites.some((site) => namespace === site.namespace && site.elements.has(localName))) continue;
|
|
176
|
+
const paragraphIdentity = paragraphIdentityForKind(kind, element);
|
|
177
|
+
const seen = rule.scope === "package" ? packageSeen : partSeen;
|
|
178
|
+
for (const [name, rawValue] of Object.entries(element.attributes ?? {})) {
|
|
179
|
+
if (getLocalName(name) !== rule.attribute || rawValue === void 0) continue;
|
|
180
|
+
const colon = name.indexOf(":");
|
|
181
|
+
const attributeNamespace = colon < 0 ? null : toTransitionalNamespaceUri(resolveNamespaceUri(element.namespaceScope, name.slice(0, colon)) ?? "");
|
|
182
|
+
if (rule.encoding === "hex") {
|
|
183
|
+
if (String(rawValue) !== paragraphIdentity) continue;
|
|
184
|
+
} else if (attributeNamespace !== rule.attributeNamespace) continue;
|
|
185
|
+
const value = String(rawValue);
|
|
186
|
+
const identity = normalizedIdentity(value, rule.encoding);
|
|
187
|
+
if (identity === void 0) continue;
|
|
188
|
+
const key = `${kind}:${identity}`;
|
|
189
|
+
const span = attributeValueSpans.get(name);
|
|
190
|
+
if (span === void 0) panic("Missing imported identity source span");
|
|
191
|
+
const offset = span.start;
|
|
192
|
+
const first = seen.get(key);
|
|
193
|
+
if (first === void 0) {
|
|
194
|
+
seen.set(key, {
|
|
195
|
+
part,
|
|
196
|
+
offset
|
|
197
|
+
});
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
scoped.warn({
|
|
201
|
+
code: PARSE_WARNING_CODES.duplicateImportedId,
|
|
202
|
+
identityKind: kind,
|
|
203
|
+
element: element.name,
|
|
204
|
+
at: `offset ${offset}`,
|
|
205
|
+
value,
|
|
206
|
+
detail: `${kind} identity repeats the definition at offset ${first.offset} in ${first.part}.`
|
|
207
|
+
});
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
//#endregion
|
|
215
|
+
export { IMPORTED_ID_COLLISION_REGISTRY, diagnoseImportedIdCollisions };
|