@stll/folio-core 0.37.5 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-edits/apply.js +275 -88
- package/dist/ai-edits/clean-text.js +12 -1
- package/dist/ai-edits/headless.d.ts +110 -0
- package/dist/ai-edits/headless.js +569 -40
- package/dist/ai-edits/snapshot.d.ts +24 -1
- package/dist/ai-edits/snapshot.js +206 -9
- package/dist/ai-edits/table-geometry.d.ts +7 -7
- package/dist/ai-edits/table-geometry.js +43 -27
- package/dist/ai-edits/table-template.d.ts +2 -1
- package/dist/ai-edits/table-template.js +9 -3
- package/dist/ai-edits/types.d.ts +37 -15
- package/dist/compare/__fixtures__/body-sequence.d.ts +4 -0
- package/dist/compare/__fixtures__/body-sequence.js +5 -3
- package/dist/compare/compare.d.ts +26 -2
- package/dist/compare/compare.js +444 -16
- package/dist/compare/content-alignment.js +3 -2
- package/dist/compare/content-types.d.ts +34 -2
- package/dist/compare/content.d.ts +13 -10
- package/dist/compare/content.js +69 -23
- package/dist/compare/formatting.d.ts +4 -22
- package/dist/compare/formatting.js +8 -112
- package/dist/compare/inline-atom-resources.d.ts +6 -0
- package/dist/compare/inline-atom-resources.js +26 -0
- package/dist/compare/inline-atoms.d.ts +35 -0
- package/dist/compare/inline-atoms.js +383 -0
- package/dist/compare/inline-provenance.d.ts +36 -0
- package/dist/compare/inline-provenance.js +334 -0
- package/dist/compare/plan.d.ts +4 -1
- package/dist/compare/plan.js +32 -4
- package/dist/compare/scenario.d.ts +4 -6
- package/dist/compare/section-boundary-properties.d.ts +63 -0
- package/dist/compare/section-boundary-properties.js +235 -0
- package/dist/compare/style-resources.d.ts +30 -0
- package/dist/compare/style-resources.js +404 -0
- package/dist/compare/types.d.ts +50 -11
- package/dist/compare/types.js +3 -1
- package/dist/compare/verification.d.ts +3 -5
- package/dist/compare/verification.js +8 -39
- package/dist/compat/eigenpal.d.ts +4 -4
- package/dist/compat/eigenpal.js +3 -3
- package/dist/controller/layoutPipeline.js +4 -0
- package/dist/display-list/build/buildContext.d.ts +3 -1
- package/dist/display-list/build/buildDisplayList.d.ts +4 -1
- package/dist/display-list/build/buildDisplayList.js +38 -4
- package/dist/display-list/build/commentAnnotations.d.ts +10 -0
- package/dist/display-list/build/commentAnnotations.js +17 -0
- package/dist/display-list/build/paragraphPrimitives.js +39 -1
- package/dist/display-list/primitives.d.ts +1 -1
- package/dist/display-list/types.d.ts +16 -1
- package/dist/document-operations.d.ts +5 -3
- package/dist/document-operations.js +112 -5
- package/dist/docx/blockContentParser.js +14 -2
- package/dist/docx/diagramPreview.d.ts +7 -0
- package/dist/docx/diagramPreview.js +191 -0
- package/dist/docx/drawingIdNormalization.js +43 -2
- package/dist/docx/drawingRelationships.d.ts +10 -0
- package/dist/docx/drawingRelationships.js +28 -0
- package/dist/docx/fieldParser.js +1 -1
- package/dist/docx/hyperlinkParser.js +3 -5
- package/dist/docx/imageRawXml.d.ts +8 -0
- package/dist/docx/imageRawXml.js +13 -0
- package/dist/docx/newImage.d.ts +2 -2
- package/dist/docx/newImage.js +3 -3
- package/dist/docx/numberingParser.js +30 -27
- package/dist/docx/paragraphParser.js +11 -4
- package/dist/docx/paragraphTextBoxEnrichment.js +2 -1
- package/dist/docx/parser.js +13 -0
- package/dist/docx/removeHeaderFooterParts.d.ts +14 -0
- package/dist/docx/removeHeaderFooterParts.js +87 -0
- package/dist/docx/rezip.d.ts +3 -1
- package/dist/docx/rezip.js +143 -41
- package/dist/docx/runParser.js +24 -5
- package/dist/docx/sectionParser.js +3 -0
- package/dist/docx/sectionReferenceHistory.d.ts +17 -0
- package/dist/docx/sectionReferenceHistory.js +59 -0
- package/dist/docx/selectiveSave.js +11 -31
- package/dist/docx/selectiveXmlPatch.d.ts +8 -1
- package/dist/docx/selectiveXmlPatch.js +62 -2
- package/dist/docx/serializer/paragraphSerializer.js +2 -0
- package/dist/docx/serializer/partNamespaces.d.ts +1 -1
- package/dist/docx/serializer/partNamespaces.js +4 -0
- package/dist/docx/serializer/runSerializer.js +5 -2
- package/dist/docx/serializer/sectionPropertiesSerializer.js +5 -2
- package/dist/docx/serializer/textFormattingSerializer.d.ts +1 -1
- package/dist/docx/serializer/textFormattingSerializer.js +3 -1
- package/dist/docx/tableParser.js +21 -11
- package/dist/docx/textBoxParser.js +25 -5
- package/dist/docx/xmlParser.d.ts +10 -1
- package/dist/docx/xmlParser.js +23 -1
- package/dist/export-pdf.js +2 -0
- package/dist/headless-layout.js +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/internal/compare/inline-presentation.d.ts +20 -0
- package/dist/internal/compare/inline-presentation.js +222 -0
- package/dist/internal/paragraphFormattingSerialization.d.ts +3 -1
- package/dist/internal/paragraphFormattingSerialization.js +8 -1
- package/dist/internal/sectionReferenceResolution.d.ts +21 -0
- package/dist/internal/sectionReferenceResolution.js +72 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +1 -0
- package/dist/layout-engine/index.js +5 -5
- package/dist/layout-engine/sectionVerticalAlignment.d.ts +7 -0
- package/dist/layout-engine/sectionVerticalAlignment.js +52 -0
- package/dist/layout-engine/types.d.ts +3 -1
- package/dist/markdown/renderRuns.js +1 -0
- package/dist/markdown/renderTable.js +1 -0
- package/dist/pdf/writePdf.js +37 -2
- package/dist/prosemirror/attrs/index.js +55 -1
- package/dist/prosemirror/commands/comments.d.ts +11 -1
- package/dist/prosemirror/commands/comments.js +68 -6
- package/dist/prosemirror/commands/propertyChangeScope.d.ts +9 -3
- package/dist/prosemirror/commands/propertyChangeScope.js +4 -10
- package/dist/prosemirror/conversion/fromProseDoc.js +17 -8
- package/dist/prosemirror/conversion/toProseDoc.js +18 -57
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +3 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -1
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +39 -1
- package/dist/prosemirror/imageCommit.js +7 -9
- package/dist/prosemirror/paragraphIndentation.d.ts +21 -0
- package/dist/prosemirror/paragraphIndentation.js +72 -0
- package/dist/prosemirror/plugins/documentNumbering.d.ts +3 -1
- package/dist/prosemirror/plugins/documentNumbering.js +7 -1
- package/dist/prosemirror/plugins/documentStyles.d.ts +3 -1
- package/dist/prosemirror/plugins/documentStyles.js +7 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +3 -1
- package/dist/prosemirror/rebaseParagraphRunFormatting.js +2 -1
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +15 -2
- package/dist/prosemirror/runFormattingInlineCarriers.js +33 -3
- package/dist/prosemirror/runStyleFormatting.d.ts +15 -2
- package/dist/prosemirror/runStyleFormatting.js +76 -2
- package/dist/prosemirror/schema/marks.d.ts +3 -1
- package/dist/prosemirror/schema/marks.js +2 -0
- package/dist/prosemirror/schema/nodes.d.ts +5 -0
- package/dist/prosemirror/tableCellRevisionVisibility.d.ts +6 -0
- package/dist/prosemirror/tableCellRevisionVisibility.js +14 -0
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -1
- package/dist/prosemirror/trackedRunInlineAtoms.js +1 -1
- package/dist/redline.js +15 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/version-comparison.d.ts +2 -0
- package/dist/version-comparison.js +7 -2
- package/package.json +2 -2
|
@@ -357,6 +357,19 @@ type DisplayLinkTarget = {
|
|
|
357
357
|
readonly pageIndex: number;
|
|
358
358
|
readonly yPx: number;
|
|
359
359
|
};
|
|
360
|
+
/**
|
|
361
|
+
* One DOCX comment whose anchor reaches this page.
|
|
362
|
+
*
|
|
363
|
+
* A range may cross run and line boundaries, so every painted rectangle is
|
|
364
|
+
* retained. Raster backends use those rectangles for the highlight; PDF uses
|
|
365
|
+
* the final one as the location of its single text annotation.
|
|
366
|
+
*/
|
|
367
|
+
type DisplayCommentAnnotation = {
|
|
368
|
+
readonly commentId: number;
|
|
369
|
+
readonly rects: readonly DisplayRect[];
|
|
370
|
+
readonly contents: string;
|
|
371
|
+
readonly author: string;
|
|
372
|
+
};
|
|
360
373
|
/**
|
|
361
374
|
* What kind of thing a click landed in.
|
|
362
375
|
*
|
|
@@ -437,6 +450,8 @@ type DisplayPage = {
|
|
|
437
450
|
*/
|
|
438
451
|
readonly regions: readonly DisplayHitRegion[];
|
|
439
452
|
readonly links: readonly DisplayLink[];
|
|
453
|
+
/** Native review comments anchored on this page. */
|
|
454
|
+
readonly comments: readonly DisplayCommentAnnotation[];
|
|
440
455
|
};
|
|
441
456
|
/** One heading, for a document outline. `pageIndex` is 0-based. */
|
|
442
457
|
type DisplayOutlineEntry = {
|
|
@@ -473,4 +488,4 @@ type DisplayList = {
|
|
|
473
488
|
readonly unsupported: readonly DisplayUnsupported[];
|
|
474
489
|
};
|
|
475
490
|
//#endregion
|
|
476
|
-
export { DisplayClipGroup, DisplayColor, DisplayEmbeddedFont, DisplayFontFace, DisplayFontRef, DisplayGlyphRun, DisplayHitRegion, DisplayHitRegionKind, DisplayHitRegionModel, DisplayImagePrimitive, DisplayImageRef, DisplayImageSource, DisplayLine, DisplayLink, DisplayLinkTarget, DisplayList, DisplayMetadata, DisplayModelRange, DisplayOpacityGroup, DisplayOutlineEntry, DisplayPage, DisplayPrimitive, DisplayRect, DisplayRectPrimitive, DisplayRotateGroup, DisplayRunAdjustments, DisplayStoryRef, DisplayStroke, DisplayStrokePattern, DisplayUnsupported };
|
|
491
|
+
export { DisplayClipGroup, DisplayColor, DisplayCommentAnnotation, DisplayEmbeddedFont, DisplayFontFace, DisplayFontRef, DisplayGlyphRun, DisplayHitRegion, DisplayHitRegionKind, DisplayHitRegionModel, DisplayImagePrimitive, DisplayImageRef, DisplayImageSource, DisplayLine, DisplayLink, DisplayLinkTarget, DisplayList, DisplayMetadata, DisplayModelRange, DisplayOpacityGroup, DisplayOutlineEntry, DisplayPage, DisplayPrimitive, DisplayRect, DisplayRectPrimitive, DisplayRotateGroup, DisplayRunAdjustments, DisplayStoryRef, DisplayStroke, DisplayStrokePattern, DisplayUnsupported };
|
|
@@ -7,6 +7,8 @@ declare const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION: 1;
|
|
|
7
7
|
declare const FOLIO_PARAGRAPH_ALIGNMENT_VALUES: readonly ("left" | "center" | "right" | "both" | "distribute" | "mediumKashida" | "highKashida" | "lowKashida" | "thaiDistribute")[];
|
|
8
8
|
/** `w:spacing/@w:lineRule` values accepted by the operation contract. */
|
|
9
9
|
declare const FOLIO_LINE_SPACING_RULE_VALUES: readonly ("auto" | "exact" | "atLeast")[];
|
|
10
|
+
/** `w:br/@w:clear` values accepted on an authored hard page break. */
|
|
11
|
+
declare const FOLIO_PAGE_BREAK_CLEAR_VALUES: readonly ["none", "left", "right", "all"];
|
|
10
12
|
declare const FOLIO_DOCUMENT_OPERATION_TYPES: readonly ["replaceInBlock", "replaceRange", "commentOnRange", "formatRange", "insertAfterBlock", "insertBeforeBlock", "replaceBlock", "deleteBlock", "splitBlock", "mergeBlockWithNext", "setBlockParagraphProperties", "insertTable", "deleteTable", "commentOnBlock", "insertSignatureTable", "insertTableRow", "deleteTableRow", "insertTableColumn", "deleteTableColumn", "mergeTableCells", "splitTableCell"];
|
|
11
13
|
declare const FOLIO_DOCUMENT_OPERATION_MODES: readonly ["direct", "tracked-changes", "suggested"];
|
|
12
14
|
declare const FOLIO_DOCUMENT_OPERATION_STORIES: readonly ["main", "header", "footer", "footnote", "endnote"];
|
|
@@ -97,8 +99,8 @@ declare const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE: Readonly<{
|
|
|
97
99
|
readonly replaceRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "replace", "comment"];
|
|
98
100
|
readonly commentOnRange: readonly ["id", "type", "range", "severity", "area", "precondition", "comment"];
|
|
99
101
|
readonly formatRange: readonly ["id", "type", "range", "severity", "area", "precondition", "suggestionId", "formatting"];
|
|
100
|
-
readonly insertAfterBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
101
|
-
readonly insertBeforeBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "listLevel", "moveId", "pageBreakBefore", "styleId", "comment"];
|
|
102
|
+
readonly insertAfterBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "indentation", "lineBreakMode", "listLevel", "numbering", "moveId", "pageBreakBefore", "hardPageBreak", "styleId", "comment"];
|
|
103
|
+
readonly insertBeforeBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "inheritFormatting", "alignment", "spacing", "indentation", "lineBreakMode", "listLevel", "numbering", "moveId", "pageBreakBefore", "hardPageBreak", "styleId", "comment"];
|
|
102
104
|
readonly replaceBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "text", "preserveFormatting", "styleId", "comment"];
|
|
103
105
|
readonly deleteBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "moveId", "comment"];
|
|
104
106
|
readonly splitBlock: readonly ["id", "type", "blockId", "severity", "area", "precondition", "suggestionId", "offset", "separator", "firstParagraphProperties", "secondParagraphProperties"];
|
|
@@ -282,4 +284,4 @@ type ApplyFolioDocumentOperationsOptions = {
|
|
|
282
284
|
};
|
|
283
285
|
declare const applyFolioDocumentOperations: ({ view, snapshot, batch, story, author, createCommentId, createUndoHandle, revisionStamp, wordDiff, tableTemplates }: ApplyFolioDocumentOperationsOptions) => FolioDocumentOperationResult;
|
|
284
286
|
//#endregion
|
|
285
|
-
export { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationBatchPrecondition, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationQueuedOperation, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
287
|
+
export { ApplyFolioDocumentOperationsOptions, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, FolioDocumentOperation, FolioDocumentOperationAffectedTarget, FolioDocumentOperationBatch, FolioDocumentOperationBatchPrecondition, FolioDocumentOperationCapabilities, FolioDocumentOperationIssue, FolioDocumentOperationMode, FolioDocumentOperationPrecondition, FolioDocumentOperationQueuedOperation, FolioDocumentOperationReceipt, FolioDocumentOperationRecovery, FolioDocumentOperationResult, FolioDocumentOperationResultBase, FolioDocumentOperationStatus, FolioDocumentOperationStory, FolioDocumentOperationType, FolioDocumentOperationUndoFailureReason, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
@@ -7,6 +7,13 @@ const FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION = 1;
|
|
|
7
7
|
const FOLIO_PARAGRAPH_ALIGNMENT_VALUES = Object.freeze([...PARAGRAPH_ALIGNMENT_VALUES]);
|
|
8
8
|
/** `w:spacing/@w:lineRule` values accepted by the operation contract. */
|
|
9
9
|
const FOLIO_LINE_SPACING_RULE_VALUES = Object.freeze([...LINE_SPACING_RULE_VALUES]);
|
|
10
|
+
/** `w:br/@w:clear` values accepted on an authored hard page break. */
|
|
11
|
+
const FOLIO_PAGE_BREAK_CLEAR_VALUES = Object.freeze([
|
|
12
|
+
"none",
|
|
13
|
+
"left",
|
|
14
|
+
"right",
|
|
15
|
+
"all"
|
|
16
|
+
]);
|
|
10
17
|
const FOLIO_DOCUMENT_OPERATION_TYPES = Object.freeze([
|
|
11
18
|
"replaceInBlock",
|
|
12
19
|
"replaceRange",
|
|
@@ -242,6 +249,51 @@ const readClearableParagraphSpacing = ({ value, key, path }) => {
|
|
|
242
249
|
}
|
|
243
250
|
return spacing;
|
|
244
251
|
};
|
|
252
|
+
const PARAGRAPH_INDENTATION_KEYS = [
|
|
253
|
+
"indentLeft",
|
|
254
|
+
"indentRight",
|
|
255
|
+
"indentFirstLine",
|
|
256
|
+
"hangingIndent"
|
|
257
|
+
];
|
|
258
|
+
/** Read one complete direct `w:ind` cluster, preserving zero and false. */
|
|
259
|
+
const readClearableParagraphIndentation = ({ value, key, path }) => {
|
|
260
|
+
const candidate = value[key];
|
|
261
|
+
if (candidate === void 0 || candidate === null) return candidate;
|
|
262
|
+
const indentationPath = `${path}.${key}`;
|
|
263
|
+
if (!isPlainObject(candidate)) return invalidBatch(indentationPath, "expected an object or null when provided");
|
|
264
|
+
assertAllowedKeys(candidate, indentationPath, PARAGRAPH_INDENTATION_KEYS);
|
|
265
|
+
if (Object.keys(candidate).length === 0) return invalidBatch(indentationPath, "expected at least one indentation property");
|
|
266
|
+
const indentation = {};
|
|
267
|
+
for (const numberKey of [
|
|
268
|
+
"indentLeft",
|
|
269
|
+
"indentRight",
|
|
270
|
+
"indentFirstLine"
|
|
271
|
+
]) {
|
|
272
|
+
const number = candidate[numberKey];
|
|
273
|
+
if (number === void 0) continue;
|
|
274
|
+
if (typeof number !== "number" || !Number.isSafeInteger(number)) return invalidBatch(`${indentationPath}.${numberKey}`, "expected a safe integer when provided");
|
|
275
|
+
indentation[numberKey] = number;
|
|
276
|
+
}
|
|
277
|
+
const hangingIndent = candidate["hangingIndent"];
|
|
278
|
+
if (hangingIndent !== void 0) {
|
|
279
|
+
if (typeof hangingIndent !== "boolean") return invalidBatch(`${indentationPath}.hangingIndent`, "expected a boolean when provided");
|
|
280
|
+
indentation.hangingIndent = hangingIndent;
|
|
281
|
+
}
|
|
282
|
+
return indentation;
|
|
283
|
+
};
|
|
284
|
+
const readClearableNumbering = ({ value, key, path }) => {
|
|
285
|
+
const candidate = value[key];
|
|
286
|
+
if (candidate === void 0 || candidate === null) return candidate;
|
|
287
|
+
const numberingPath = `${path}.${key}`;
|
|
288
|
+
if (!isPlainObject(candidate)) return invalidBatch(numberingPath, "expected an object or null when provided");
|
|
289
|
+
assertAllowedKeys(candidate, numberingPath, ["numId", "level"]);
|
|
290
|
+
const numId = readNonNegativeInteger(candidate, "numId", numberingPath);
|
|
291
|
+
if (numId === 0) return invalidBatch(`${numberingPath}.numId`, "expected a positive integer");
|
|
292
|
+
return {
|
|
293
|
+
numId,
|
|
294
|
+
level: readNonNegativeInteger(candidate, "level", numberingPath)
|
|
295
|
+
};
|
|
296
|
+
};
|
|
245
297
|
/**
|
|
246
298
|
* A rectangular grid of cell texts. Rectangular because a table whose rows
|
|
247
299
|
* hold different cell counts is not a table any consumer can lay out, and the
|
|
@@ -269,11 +321,18 @@ const readParagraphProperties = ({ value, key, path }) => {
|
|
|
269
321
|
assertAllowedKeys(candidate, propertiesPath, [
|
|
270
322
|
"styleId",
|
|
271
323
|
"listLevel",
|
|
324
|
+
"numbering",
|
|
272
325
|
"alignment",
|
|
273
|
-
"spacing"
|
|
326
|
+
"spacing",
|
|
327
|
+
"indentation"
|
|
274
328
|
]);
|
|
275
329
|
const styleId = candidate["styleId"] === null ? null : readOptionalString(candidate, "styleId", propertiesPath);
|
|
276
330
|
const listLevel = readClearableNonNegativeInteger(candidate, "listLevel", propertiesPath);
|
|
331
|
+
const numbering = readClearableNumbering({
|
|
332
|
+
value: candidate,
|
|
333
|
+
key: "numbering",
|
|
334
|
+
path: propertiesPath
|
|
335
|
+
});
|
|
277
336
|
const alignment = readClearableParagraphAlignment({
|
|
278
337
|
value: candidate,
|
|
279
338
|
key: "alignment",
|
|
@@ -284,12 +343,19 @@ const readParagraphProperties = ({ value, key, path }) => {
|
|
|
284
343
|
key: "spacing",
|
|
285
344
|
path: propertiesPath
|
|
286
345
|
});
|
|
287
|
-
|
|
346
|
+
const indentation = readClearableParagraphIndentation({
|
|
347
|
+
value: candidate,
|
|
348
|
+
key: "indentation",
|
|
349
|
+
path: propertiesPath
|
|
350
|
+
});
|
|
351
|
+
if (styleId === void 0 && listLevel === void 0 && numbering === void 0 && alignment === void 0 && spacing === void 0 && indentation === void 0) return invalidBatch(propertiesPath, "expected at least one property to set");
|
|
288
352
|
return {
|
|
289
353
|
...styleId !== void 0 && { styleId },
|
|
290
354
|
...listLevel !== void 0 && { listLevel },
|
|
355
|
+
...numbering !== void 0 && { numbering },
|
|
291
356
|
...alignment !== void 0 && { alignment },
|
|
292
|
-
...spacing !== void 0 && { spacing }
|
|
357
|
+
...spacing !== void 0 && { spacing },
|
|
358
|
+
...indentation !== void 0 && { indentation }
|
|
293
359
|
};
|
|
294
360
|
};
|
|
295
361
|
const readTextRange = (value, path) => {
|
|
@@ -430,9 +496,13 @@ const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE = Object.freeze({
|
|
|
430
496
|
"inheritFormatting",
|
|
431
497
|
"alignment",
|
|
432
498
|
"spacing",
|
|
499
|
+
"indentation",
|
|
500
|
+
"lineBreakMode",
|
|
433
501
|
"listLevel",
|
|
502
|
+
"numbering",
|
|
434
503
|
"moveId",
|
|
435
504
|
"pageBreakBefore",
|
|
505
|
+
"hardPageBreak",
|
|
436
506
|
"styleId",
|
|
437
507
|
"comment"
|
|
438
508
|
],
|
|
@@ -442,9 +512,13 @@ const FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE = Object.freeze({
|
|
|
442
512
|
"inheritFormatting",
|
|
443
513
|
"alignment",
|
|
444
514
|
"spacing",
|
|
515
|
+
"indentation",
|
|
516
|
+
"lineBreakMode",
|
|
445
517
|
"listLevel",
|
|
518
|
+
"numbering",
|
|
446
519
|
"moveId",
|
|
447
520
|
"pageBreakBefore",
|
|
521
|
+
"hardPageBreak",
|
|
448
522
|
"styleId",
|
|
449
523
|
"comment"
|
|
450
524
|
],
|
|
@@ -529,6 +603,18 @@ const parseSignatureParties = (value, path) => {
|
|
|
529
603
|
return parsedParty;
|
|
530
604
|
});
|
|
531
605
|
};
|
|
606
|
+
const readOptionalHardPageBreak = (value, path) => {
|
|
607
|
+
const candidate = value["hardPageBreak"];
|
|
608
|
+
if (candidate === void 0) return;
|
|
609
|
+
if (!isPlainObject(candidate)) return invalidBatch(`${path}.hardPageBreak`, "expected an object when provided");
|
|
610
|
+
const hardPageBreakPath = `${path}.hardPageBreak`;
|
|
611
|
+
assertAllowedKeys(candidate, hardPageBreakPath, ["clear"]);
|
|
612
|
+
const clear = candidate["clear"];
|
|
613
|
+
if (clear === void 0) return {};
|
|
614
|
+
const validatedClear = FOLIO_PAGE_BREAK_CLEAR_VALUES.find((supported) => supported === clear);
|
|
615
|
+
if (validatedClear === void 0) return invalidBatch(`${hardPageBreakPath}.clear`, "expected a supported break clear value");
|
|
616
|
+
return { clear: validatedClear };
|
|
617
|
+
};
|
|
532
618
|
const parseDocumentOperation = (value, index) => {
|
|
533
619
|
const path = `$.operations[${index}]`;
|
|
534
620
|
if (!isPlainObject(value)) return invalidBatch(path, "expected an object");
|
|
@@ -650,9 +736,15 @@ const parseDocumentOperation = (value, index) => {
|
|
|
650
736
|
if (type === "insertAfterBlock" || type === "insertBeforeBlock") {
|
|
651
737
|
const inheritFormatting = readOptionalBoolean(value, "inheritFormatting", path);
|
|
652
738
|
const pageBreakBefore = readOptionalBoolean(value, "pageBreakBefore", path);
|
|
739
|
+
const hardPageBreak = readOptionalHardPageBreak(value, path);
|
|
653
740
|
const styleId = value["styleId"] === null ? null : readOptionalString(value, "styleId", path);
|
|
654
741
|
const moveId = readOptionalString(value, "moveId", path);
|
|
655
742
|
const listLevel = readClearableNonNegativeInteger(value, "listLevel", path);
|
|
743
|
+
const numbering = readClearableNumbering({
|
|
744
|
+
value,
|
|
745
|
+
key: "numbering",
|
|
746
|
+
path
|
|
747
|
+
});
|
|
656
748
|
const alignment = readClearableParagraphAlignment({
|
|
657
749
|
value,
|
|
658
750
|
key: "alignment",
|
|
@@ -663,18 +755,33 @@ const parseDocumentOperation = (value, index) => {
|
|
|
663
755
|
key: "spacing",
|
|
664
756
|
path
|
|
665
757
|
});
|
|
758
|
+
const indentation = readClearableParagraphIndentation({
|
|
759
|
+
value,
|
|
760
|
+
key: "indentation",
|
|
761
|
+
path
|
|
762
|
+
});
|
|
763
|
+
const lineBreakMode = value["lineBreakMode"];
|
|
764
|
+
if (lineBreakMode !== void 0 && lineBreakMode !== "paragraph" && lineBreakMode !== "inline") return invalidBatch(`${path}.lineBreakMode`, "expected \"paragraph\" or \"inline\" when provided");
|
|
765
|
+
const text = readString(value, "text", path);
|
|
766
|
+
if (hardPageBreak !== void 0 && text.length > 0) return invalidBatch(`${path}.text`, "expected empty text with hardPageBreak");
|
|
767
|
+
if (hardPageBreak !== void 0 && pageBreakBefore !== void 0) return invalidBatch(`${path}.pageBreakBefore`, "cannot combine hardPageBreak with pageBreakBefore");
|
|
768
|
+
if (hardPageBreak !== void 0 && lineBreakMode !== void 0) return invalidBatch(`${path}.lineBreakMode`, "cannot combine hardPageBreak with lineBreakMode");
|
|
666
769
|
return {
|
|
667
770
|
...operationMeta,
|
|
668
771
|
id,
|
|
669
772
|
type,
|
|
670
773
|
blockId,
|
|
671
|
-
text
|
|
774
|
+
text,
|
|
672
775
|
...inheritFormatting !== void 0 && { inheritFormatting },
|
|
673
776
|
...alignment !== void 0 && { alignment },
|
|
674
777
|
...spacing !== void 0 && { spacing },
|
|
778
|
+
...indentation !== void 0 && { indentation },
|
|
779
|
+
...lineBreakMode !== void 0 && { lineBreakMode },
|
|
675
780
|
...listLevel !== void 0 && { listLevel },
|
|
781
|
+
...numbering !== void 0 && { numbering },
|
|
676
782
|
...moveId !== void 0 && { moveId },
|
|
677
783
|
...pageBreakBefore !== void 0 && { pageBreakBefore },
|
|
784
|
+
...hardPageBreak !== void 0 && { hardPageBreak },
|
|
678
785
|
...styleId !== void 0 && { styleId },
|
|
679
786
|
...comment !== void 0 && { comment }
|
|
680
787
|
};
|
|
@@ -1103,4 +1210,4 @@ const applyFolioDocumentOperations = ({ view, snapshot, batch, story = "main", a
|
|
|
1103
1210
|
};
|
|
1104
1211
|
};
|
|
1105
1212
|
//#endregion
|
|
1106
|
-
export { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
1213
|
+
export { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_BATCH_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_KEYS_BY_TYPE, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_LINE_SPACING_RULE_VALUES, FOLIO_PAGE_BREAK_CLEAR_VALUES, FOLIO_PARAGRAPH_ALIGNMENT_VALUES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch };
|
|
@@ -7,7 +7,7 @@ import { enrichParagraphTextBoxes } from "./paragraphTextBoxEnrichment.js";
|
|
|
7
7
|
import { parseSdtProperties } from "./sdtProperties.js";
|
|
8
8
|
import { parseTable } from "./tableParser.js";
|
|
9
9
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
10
|
-
import { findChild, getChildElements, getLocalName, mergeXmlnsDeclarations } from "./xmlParser.js";
|
|
10
|
+
import { findChild, getChildElements, getLocalName, mergeXmlnsDeclarations, selectAlternateContentBranch } from "./xmlParser.js";
|
|
11
11
|
//#region src/docx/blockContentParser.ts
|
|
12
12
|
const computeListMarker = (paragraph, { numbering, listCounters, abstractCounters, restartedNumIds, previousList }) => {
|
|
13
13
|
const listRendering = paragraph.listRendering;
|
|
@@ -80,6 +80,13 @@ const computeListMarker = (paragraph, { numbering, listCounters, abstractCounter
|
|
|
80
80
|
}
|
|
81
81
|
listRendering.marker = computedMarker;
|
|
82
82
|
};
|
|
83
|
+
const withContainerXmlns = (state, element) => ({
|
|
84
|
+
...state,
|
|
85
|
+
options: {
|
|
86
|
+
...state.options,
|
|
87
|
+
rootXmlns: mergeXmlnsDeclarations(state.options?.rootXmlns ?? {}, element)
|
|
88
|
+
}
|
|
89
|
+
});
|
|
83
90
|
const parseBlockContent = (parent, styles, theme, numbering, rels, media, options) => parseBlockContentWithState(parent, styles, theme, numbering, rels, media, {
|
|
84
91
|
listCounters: /* @__PURE__ */ new Map(),
|
|
85
92
|
abstractCounters: /* @__PURE__ */ new Map(),
|
|
@@ -132,12 +139,17 @@ const parseBlockContentWithState = (parent, styles, theme, numbering, rels, medi
|
|
|
132
139
|
const blockSdt = {
|
|
133
140
|
type: "blockSdt",
|
|
134
141
|
properties,
|
|
135
|
-
content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, state) : []
|
|
142
|
+
content: sdtContent ? parseBlockContentWithState(sdtContent, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), sdtContent)) : []
|
|
136
143
|
};
|
|
137
144
|
if (prependBookmarkMarkersToFirstParagraphInBlocks(blockSdt.content, pendingBookmarkMarkers)) pendingBookmarkMarkers.length = 0;
|
|
138
145
|
content.push(blockSdt);
|
|
139
146
|
continue;
|
|
140
147
|
}
|
|
148
|
+
if (localName === "AlternateContent") {
|
|
149
|
+
const selectedBranch = selectAlternateContentBranch(child);
|
|
150
|
+
if (selectedBranch) content.push(...parseBlockContentWithState(selectedBranch, styles, theme, numbering, rels, media, withContainerXmlns(withContainerXmlns(state, child), selectedBranch)));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
141
153
|
if (localName === "bookmarkStart" || localName === "bookmarkEnd") {
|
|
142
154
|
const marker = parseBookmarkMarker(child, localName);
|
|
143
155
|
if (!appendBookmarkMarkerToLastParagraphInBlocks(content, marker)) pendingBookmarkMarkers.push(marker);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/diagramPreview.d.ts
|
|
4
|
+
/** Create a deliberately simple, bounded preview; it is never an editable diagram projection. */
|
|
5
|
+
declare const parseDiagramPreview: (drawing: XmlElement, rels: document_d_exports.RelationshipMap | undefined, media: Map<string, document_d_exports.MediaFile> | undefined) => document_d_exports.Image | null;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { parseDiagramPreview };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { resolveRelativePath } from "./relsParser.js";
|
|
2
|
+
import { findChildByNamespaceUri, getAttribute, getLocalName, parseNumericAttribute, parseXmlDocument } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/diagramPreview.ts
|
|
4
|
+
const MAX_PREVIEW_SHAPES = 128;
|
|
5
|
+
const MAX_PREVIEW_PIXELS = 144e4;
|
|
6
|
+
const MAX_PREVIEW_PAINT_PIXELS = MAX_PREVIEW_PIXELS * 4;
|
|
7
|
+
const DRAWINGML_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/main", "http://purl.oclc.org/ooxml/drawingml/main"]);
|
|
8
|
+
const DIAGRAM_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/diagram", "http://purl.oclc.org/ooxml/drawingml/diagram"]);
|
|
9
|
+
const DIAGRAM_DRAWING_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.microsoft.com/office/drawing/2008/diagram"]);
|
|
10
|
+
const WORD_DRAWING_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", "http://purl.oclc.org/ooxml/drawingml/wordprocessingDrawing"]);
|
|
11
|
+
const crc32 = (bytes) => {
|
|
12
|
+
let crc = 4294967295;
|
|
13
|
+
for (const byte of bytes) {
|
|
14
|
+
crc ^= byte;
|
|
15
|
+
for (let bit = 0; bit < 8; bit += 1) crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
|
|
16
|
+
}
|
|
17
|
+
return (crc ^ 4294967295) >>> 0;
|
|
18
|
+
};
|
|
19
|
+
const adler32 = (bytes) => {
|
|
20
|
+
let a = 1;
|
|
21
|
+
let b = 0;
|
|
22
|
+
for (const byte of bytes) {
|
|
23
|
+
a = (a + byte) % 65521;
|
|
24
|
+
b = (b + a) % 65521;
|
|
25
|
+
}
|
|
26
|
+
return b << 16 | a;
|
|
27
|
+
};
|
|
28
|
+
const pngChunk = (type, data) => {
|
|
29
|
+
const name = new TextEncoder().encode(type);
|
|
30
|
+
const output = new Uint8Array(12 + data.length);
|
|
31
|
+
const view = new DataView(output.buffer);
|
|
32
|
+
view.setUint32(0, data.length);
|
|
33
|
+
output.set(name, 4);
|
|
34
|
+
output.set(data, 8);
|
|
35
|
+
view.setUint32(8 + data.length, crc32(output.subarray(4, 8 + data.length)));
|
|
36
|
+
return output;
|
|
37
|
+
};
|
|
38
|
+
const previewPng = (width, height, shapes) => {
|
|
39
|
+
const scale = Math.min(1, Math.sqrt(MAX_PREVIEW_PIXELS / (width * height)));
|
|
40
|
+
const w = Math.max(1, Math.round(width * scale));
|
|
41
|
+
const h = Math.max(1, Math.round(height * scale));
|
|
42
|
+
const pixels = new Uint8Array((w * 4 + 1) * h);
|
|
43
|
+
for (let y = 0; y < h; y += 1) {
|
|
44
|
+
const row = y * (w * 4 + 1);
|
|
45
|
+
pixels[row] = 0;
|
|
46
|
+
for (let x = 0; x < w; x += 1) {
|
|
47
|
+
const index = row + 1 + x * 4;
|
|
48
|
+
pixels[index] = 238;
|
|
49
|
+
pixels[index + 1] = 242;
|
|
50
|
+
pixels[index + 2] = 247;
|
|
51
|
+
pixels[index + 3] = 255;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
let paintedPixels = 0;
|
|
55
|
+
for (const shape of shapes) {
|
|
56
|
+
const sx = Math.max(0, Math.round(shape.x / width * w));
|
|
57
|
+
const sy = Math.max(0, Math.round(shape.y / height * h));
|
|
58
|
+
const ex = Math.min(w, Math.round((shape.x + shape.width) / width * w));
|
|
59
|
+
const ey = Math.min(h, Math.round((shape.y + shape.height) / height * h));
|
|
60
|
+
const red = Number.parseInt(shape.color.slice(0, 2), 16) || 232;
|
|
61
|
+
const green = Number.parseInt(shape.color.slice(2, 4), 16) || 238;
|
|
62
|
+
const blue = Number.parseInt(shape.color.slice(4, 6), 16) || 247;
|
|
63
|
+
const shapePixels = Math.max(0, ex - sx) * Math.max(0, ey - sy);
|
|
64
|
+
if (paintedPixels + shapePixels > MAX_PREVIEW_PAINT_PIXELS) break;
|
|
65
|
+
paintedPixels += shapePixels;
|
|
66
|
+
for (let y = sy; y < ey; y += 1) {
|
|
67
|
+
const row = y * (w * 4 + 1);
|
|
68
|
+
for (let x = sx; x < ex; x += 1) {
|
|
69
|
+
const index = row + 1 + x * 4;
|
|
70
|
+
pixels[index] = red;
|
|
71
|
+
pixels[index + 1] = green;
|
|
72
|
+
pixels[index + 2] = blue;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const compressed = new Uint8Array(2 + pixels.length + Math.ceil(pixels.length / 65535) * 5 + 4);
|
|
77
|
+
compressed[0] = 120;
|
|
78
|
+
compressed[1] = 1;
|
|
79
|
+
let cursor = 2;
|
|
80
|
+
for (let offset = 0; offset < pixels.length;) {
|
|
81
|
+
const length = Math.min(65535, pixels.length - offset);
|
|
82
|
+
compressed[cursor++] = offset + length === pixels.length ? 1 : 0;
|
|
83
|
+
compressed[cursor++] = length & 255;
|
|
84
|
+
compressed[cursor++] = length >>> 8;
|
|
85
|
+
compressed[cursor++] = ~length & 255;
|
|
86
|
+
compressed[cursor++] = ~length >>> 8 & 255;
|
|
87
|
+
compressed.set(pixels.subarray(offset, offset + length), cursor);
|
|
88
|
+
cursor += length;
|
|
89
|
+
offset += length;
|
|
90
|
+
}
|
|
91
|
+
const output = new Uint8Array(cursor + 4);
|
|
92
|
+
output.set(compressed.subarray(0, cursor));
|
|
93
|
+
new DataView(output.buffer).setUint32(cursor, adler32(pixels));
|
|
94
|
+
const signature = new Uint8Array([
|
|
95
|
+
137,
|
|
96
|
+
80,
|
|
97
|
+
78,
|
|
98
|
+
71,
|
|
99
|
+
13,
|
|
100
|
+
10,
|
|
101
|
+
26,
|
|
102
|
+
10
|
|
103
|
+
]);
|
|
104
|
+
const header = /* @__PURE__ */ new Uint8Array(13);
|
|
105
|
+
new DataView(header.buffer).setUint32(0, w);
|
|
106
|
+
new DataView(header.buffer).setUint32(4, h);
|
|
107
|
+
header[8] = 8;
|
|
108
|
+
header[9] = 6;
|
|
109
|
+
const chunks = [
|
|
110
|
+
signature,
|
|
111
|
+
pngChunk("IHDR", header),
|
|
112
|
+
pngChunk("IDAT", output),
|
|
113
|
+
pngChunk("IEND", /* @__PURE__ */ new Uint8Array())
|
|
114
|
+
];
|
|
115
|
+
const png = new Uint8Array(chunks.reduce((total, chunk) => total + chunk.length, 0));
|
|
116
|
+
let position = 0;
|
|
117
|
+
for (const chunk of chunks) {
|
|
118
|
+
png.set(chunk, position);
|
|
119
|
+
position += chunk.length;
|
|
120
|
+
}
|
|
121
|
+
return png;
|
|
122
|
+
};
|
|
123
|
+
const extent = (drawing) => {
|
|
124
|
+
const value = findChildByNamespaceUri(findChildByNamespaceUri(drawing, WORD_DRAWING_NAMESPACE_URIS, "inline") ?? findChildByNamespaceUri(drawing, WORD_DRAWING_NAMESPACE_URIS, "anchor"), WORD_DRAWING_NAMESPACE_URIS, "extent");
|
|
125
|
+
return {
|
|
126
|
+
width: parseNumericAttribute(value, null, "cx") ?? 0,
|
|
127
|
+
height: parseNumericAttribute(value, null, "cy") ?? 0
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
const cachedDiagramShapes = (rels, media) => {
|
|
131
|
+
const matches = [...rels.values()].filter((relationship) => relationship.type === "http://schemas.microsoft.com/office/2007/relationships/diagramDrawing");
|
|
132
|
+
if (matches.length !== 1 || !matches[0]?.target) return [];
|
|
133
|
+
const path = resolveRelativePath("word/document.xml", matches[0].target);
|
|
134
|
+
const file = media.get(path);
|
|
135
|
+
if (!file?.data) return [];
|
|
136
|
+
const root = parseXmlDocument(new TextDecoder().decode(file.data));
|
|
137
|
+
if (!root) return [];
|
|
138
|
+
const shapes = [];
|
|
139
|
+
for (const shape of descendantsByNamespace(root, DIAGRAM_DRAWING_NAMESPACE_URIS, "sp").slice(0, MAX_PREVIEW_SHAPES)) {
|
|
140
|
+
const properties = findChildByNamespaceUri(shape, DIAGRAM_DRAWING_NAMESPACE_URIS, "spPr");
|
|
141
|
+
const transform = findChildByNamespaceUri(properties, DRAWINGML_NAMESPACE_URIS, "xfrm");
|
|
142
|
+
const offset = findChildByNamespaceUri(transform, DRAWINGML_NAMESPACE_URIS, "off");
|
|
143
|
+
const size = findChildByNamespaceUri(transform, DRAWINGML_NAMESPACE_URIS, "ext");
|
|
144
|
+
const width = parseNumericAttribute(size, null, "cx") ?? 0;
|
|
145
|
+
const height = parseNumericAttribute(size, null, "cy") ?? 0;
|
|
146
|
+
if (width <= 0 || height <= 0) continue;
|
|
147
|
+
const color = findChildByNamespaceUri(findChildByNamespaceUri(properties, DRAWINGML_NAMESPACE_URIS, "solidFill"), DRAWINGML_NAMESPACE_URIS, "srgbClr");
|
|
148
|
+
shapes.push({
|
|
149
|
+
x: parseNumericAttribute(offset, null, "x") ?? 0,
|
|
150
|
+
y: parseNumericAttribute(offset, null, "y") ?? 0,
|
|
151
|
+
width,
|
|
152
|
+
height,
|
|
153
|
+
color: getAttribute(color, null, "val") ?? "E8EEF7"
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return shapes;
|
|
157
|
+
};
|
|
158
|
+
const descendantsByNamespace = (root, namespaceUris, localName) => {
|
|
159
|
+
const result = [];
|
|
160
|
+
const visit = (element) => {
|
|
161
|
+
if (element.namespaceUri && namespaceUris.has(element.namespaceUri) && getLocalName(element.name ?? "") === localName) result.push(element);
|
|
162
|
+
for (const child of element.elements ?? []) if (child.type === "element") visit(child);
|
|
163
|
+
};
|
|
164
|
+
visit(root);
|
|
165
|
+
return result;
|
|
166
|
+
};
|
|
167
|
+
/** Create a deliberately simple, bounded preview; it is never an editable diagram projection. */
|
|
168
|
+
const parseDiagramPreview = (drawing, rels, media) => {
|
|
169
|
+
if (!rels || !media) return null;
|
|
170
|
+
const graphicData = descendantsByNamespace(drawing, DRAWINGML_NAMESPACE_URIS, "graphicData").at(0);
|
|
171
|
+
if (!graphicData || !DIAGRAM_NAMESPACE_URIS.has(getAttribute(graphicData, null, "uri") ?? "")) return null;
|
|
172
|
+
const { width, height } = extent(drawing);
|
|
173
|
+
if (width <= 0 || height <= 0) return null;
|
|
174
|
+
const png = previewPng(width, height, cachedDiagramShapes(rels, media));
|
|
175
|
+
let binary = "";
|
|
176
|
+
for (let offset = 0; offset < png.length; offset += 32768) binary += String.fromCodePoint(...png.subarray(offset, offset + 32768));
|
|
177
|
+
return {
|
|
178
|
+
type: "image",
|
|
179
|
+
rId: "",
|
|
180
|
+
src: `data:image/png;base64,${btoa(binary)}`,
|
|
181
|
+
mimeType: "image/png",
|
|
182
|
+
filename: "smartart-preview.png",
|
|
183
|
+
size: {
|
|
184
|
+
width,
|
|
185
|
+
height
|
|
186
|
+
},
|
|
187
|
+
wrap: { type: "inline" }
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
//#endregion
|
|
191
|
+
export { parseDiagramPreview };
|
|
@@ -1,6 +1,27 @@
|
|
|
1
|
+
import { isNewDataUrlDrawing } from "./newImage.js";
|
|
1
2
|
import { visitDocxParagraphs, visitParagraphRuns } from "./paragraphTraversal.js";
|
|
3
|
+
import { toTransitionalNamespaceUri } from "./transitionalSpelling.js";
|
|
4
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
5
|
+
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, getLocalName, getNamespaceUri, parseXml } from "./xmlParser.js";
|
|
6
|
+
import { panic } from "better-result";
|
|
2
7
|
//#region src/docx/drawingIdNormalization.ts
|
|
3
8
|
const GENERATED_DRAWING_ID_START = 1e5;
|
|
9
|
+
const isDetachedRawDrawing = (drawing) => drawing?.rawXml !== void 0 && isNewDataUrlDrawing(drawing);
|
|
10
|
+
const reassignRawDrawingId = ({ xml, id }) => {
|
|
11
|
+
const root = parseXml(xml, OOXML_NAMESPACE_SCOPE);
|
|
12
|
+
let foundDocPr = false;
|
|
13
|
+
const visit = (element) => {
|
|
14
|
+
if (toTransitionalNamespaceUri(getNamespaceUri(element) ?? "") === NAMESPACES.wp && getLocalName(element.name) === "docPr" || toTransitionalNamespaceUri(getNamespaceUri(element) ?? "") === NAMESPACES.pic && getLocalName(element.name) === "cNvPr") {
|
|
15
|
+
for (const name of Object.keys(element.attributes ?? {})) if (getLocalName(name) === "id" && element.attributes) {
|
|
16
|
+
element.attributes[name] = id;
|
|
17
|
+
if (toTransitionalNamespaceUri(getNamespaceUri(element) ?? "") === NAMESPACES.wp && getLocalName(element.name) === "docPr") foundDocPr = true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
for (const child of element.elements ?? []) visit(child);
|
|
21
|
+
};
|
|
22
|
+
visit(root);
|
|
23
|
+
return foundDocPr ? (root.elements ?? []).map(captureVerbatimXml).join("") : null;
|
|
24
|
+
};
|
|
4
25
|
const needsGeneratedId = ({ id }) => id === void 0 || id === "" || id === "0";
|
|
5
26
|
const normalizeDrawingIds = (surfaces) => {
|
|
6
27
|
const entries = [];
|
|
@@ -16,12 +37,13 @@ const normalizeDrawingIds = (surfaces) => {
|
|
|
16
37
|
}
|
|
17
38
|
if (content.type === "drawing") entries.push({
|
|
18
39
|
drawing: content.image,
|
|
19
|
-
generateWhenMissing: content.rawXml === void 0
|
|
40
|
+
generateWhenMissing: content.rawXml === void 0,
|
|
41
|
+
...content.rawXml !== void 0 ? { rawDrawing: content } : {}
|
|
20
42
|
});
|
|
21
43
|
}
|
|
22
44
|
});
|
|
23
45
|
});
|
|
24
|
-
const usedIds = new Set(entries.flatMap(({ drawing }) => needsGeneratedId(drawing) ? [] : [drawing.id]));
|
|
46
|
+
const usedIds = new Set(entries.flatMap(({ drawing, rawDrawing }) => needsGeneratedId(drawing) || isDetachedRawDrawing(rawDrawing) ? [] : [drawing.id]));
|
|
25
47
|
let nextId = GENERATED_DRAWING_ID_START;
|
|
26
48
|
for (const { drawing, generateWhenMissing } of entries) {
|
|
27
49
|
if (!generateWhenMissing || !needsGeneratedId(drawing)) continue;
|
|
@@ -30,6 +52,25 @@ const normalizeDrawingIds = (surfaces) => {
|
|
|
30
52
|
usedIds.add(drawing.id);
|
|
31
53
|
nextId += 1;
|
|
32
54
|
}
|
|
55
|
+
for (const { drawing, rawDrawing } of entries) {
|
|
56
|
+
if (!isDetachedRawDrawing(rawDrawing)) continue;
|
|
57
|
+
if (!needsGeneratedId(drawing) && !usedIds.has(drawing.id)) {
|
|
58
|
+
usedIds.add(drawing.id);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
while (usedIds.has(String(nextId))) nextId += 1;
|
|
62
|
+
const sourceXml = rawDrawing.rawXml;
|
|
63
|
+
if (sourceXml === void 0) panic("Detached raw drawing must retain its XML.");
|
|
64
|
+
const rawXml = reassignRawDrawingId({
|
|
65
|
+
xml: sourceXml,
|
|
66
|
+
id: String(nextId)
|
|
67
|
+
});
|
|
68
|
+
if (rawXml === null) panic("Detached raw drawing must contain wp:docPr.");
|
|
69
|
+
drawing.id = String(nextId);
|
|
70
|
+
rawDrawing.rawXml = rawXml;
|
|
71
|
+
usedIds.add(drawing.id);
|
|
72
|
+
nextId += 1;
|
|
73
|
+
}
|
|
33
74
|
};
|
|
34
75
|
//#endregion
|
|
35
76
|
export { normalizeDrawingIds };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/docx/drawingRelationships.d.ts
|
|
2
|
+
type RebindDrawingImageRelationshipOptions = {
|
|
3
|
+
xml: string;
|
|
4
|
+
previousId: string;
|
|
5
|
+
nextId: string;
|
|
6
|
+
};
|
|
7
|
+
/** Only a single embedded image can travel without importing other package resources. */
|
|
8
|
+
declare const rebindDrawingImageRelationship: ({ xml, previousId, nextId }: RebindDrawingImageRelationshipOptions) => string | null;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { rebindDrawingImageRelationship };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
2
|
+
import { OFFICE_RELATIONSHIP_NAMESPACE_URIS, OOXML_NAMESPACE_SCOPE, findAttributeByNamespaceUri, getLocalName, getNamespaceUri, parseXml } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/drawingRelationships.ts
|
|
4
|
+
/** Only a single embedded image can travel without importing other package resources. */
|
|
5
|
+
const rebindDrawingImageRelationship = ({ xml, previousId, nextId }) => {
|
|
6
|
+
const root = parseXml(xml, OOXML_NAMESPACE_SCOPE);
|
|
7
|
+
let embeddedCount = 0;
|
|
8
|
+
let unsupported = false;
|
|
9
|
+
const visit = (element) => {
|
|
10
|
+
for (const name of Object.keys(element.attributes ?? {})) {
|
|
11
|
+
const localName = getLocalName(name);
|
|
12
|
+
const attribute = findAttributeByNamespaceUri(element, OFFICE_RELATIONSHIP_NAMESPACE_URIS, localName);
|
|
13
|
+
if (!attribute || attribute.name !== name) continue;
|
|
14
|
+
if (!(localName === "embed" || localName === "id" && getLocalName(element.name) === "imagedata" && getNamespaceUri(element) === "urn:schemas-microsoft-com:vml") || attribute.value !== previousId) {
|
|
15
|
+
unsupported = true;
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
embeddedCount++;
|
|
19
|
+
if (element.attributes) element.attributes[name] = nextId;
|
|
20
|
+
}
|
|
21
|
+
for (const child of element.elements ?? []) visit(child);
|
|
22
|
+
};
|
|
23
|
+
visit(root);
|
|
24
|
+
if (unsupported || embeddedCount !== 1) return null;
|
|
25
|
+
return (root.elements ?? []).map(captureVerbatimXml).join("");
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
28
|
+
export { rebindDrawingImageRelationship };
|
package/dist/docx/fieldParser.js
CHANGED
|
@@ -209,7 +209,7 @@ function resetComplexFieldContext(ctx) {
|
|
|
209
209
|
function finalizeComplexField(ctx) {
|
|
210
210
|
return {
|
|
211
211
|
type: "complexField",
|
|
212
|
-
instruction: ctx.instruction
|
|
212
|
+
instruction: ctx.instruction,
|
|
213
213
|
fieldType: parseFieldType(ctx.instruction),
|
|
214
214
|
fieldCode: ctx.codeRuns,
|
|
215
215
|
fieldResult: ctx.resultRuns,
|