@stll/folio-core 0.44.0 → 0.46.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/__fixtures__/paragraphs.js +2 -2
- package/dist/ai-edits/apply.js +59 -19
- package/dist/ai-edits/headless.js +2 -1
- package/dist/compare/compare.js +2 -5
- package/dist/compare/content-alignment.js +78 -53
- package/dist/compare/inline-atoms.js +34 -20
- package/dist/compare/scenario.js +2 -5
- package/dist/compare/types.d.ts +9 -1
- package/dist/compare/types.js +12 -1
- package/dist/compat/eigenpal.d.ts +2 -1
- package/dist/compat/eigenpal.js +2 -1
- package/dist/content-controls/checkboxDisplay.d.ts +11 -0
- package/dist/content-controls/checkboxDisplay.js +40 -0
- package/dist/content-controls/findContentControls.js +3 -1
- package/dist/content-controls/mutateContentControls.js +21 -4
- package/dist/controller/contentControlWidgetController.d.ts +1 -0
- package/dist/controller/contentControlWidgetController.js +3 -0
- package/dist/controller/hiddenEditorApi.js +3 -1
- package/dist/controller/hiddenEditorManager.d.ts +1 -1
- package/dist/controller/hiddenEditorManager.js +6 -3
- package/dist/display-list/build/buildDisplayList.js +20 -1
- package/dist/display-list/build/imagePrimitives.d.ts +1 -1
- package/dist/display-list/build/imagePrimitives.js +3 -1
- package/dist/display-list/build/paragraphPrimitives.js +21 -2
- package/dist/display-list/dom/renderDisplayListToDom.js +18 -10
- package/dist/display-list/types.d.ts +17 -0
- package/dist/document-operations.js +14 -3
- package/dist/docx/attributeRemainder.d.ts +43 -0
- package/dist/docx/attributeRemainder.js +65 -0
- package/dist/docx/blockContentParser.d.ts +1 -1
- package/dist/docx/blockContentParser.js +87 -63
- package/dist/docx/blockPlainText.d.ts +3 -4
- package/dist/docx/blockPlainText.js +1 -0
- package/dist/docx/bookmarkPlacement.js +2 -0
- package/dist/docx/borderParser.js +5 -5
- package/dist/docx/commentAnchorIndex.d.ts +30 -0
- package/dist/docx/commentAnchorIndex.js +50 -0
- package/dist/docx/commentParser.d.ts +1 -1
- package/dist/docx/commentParser.js +78 -50
- package/dist/docx/commentRangeIntegrity.d.ts +16 -1
- package/dist/docx/commentRangeIntegrity.js +42 -1
- package/dist/docx/commentRangeJoin.d.ts +9 -0
- package/dist/docx/commentRangeJoin.js +33 -0
- package/dist/docx/commentReferenceCompletion.d.ts +9 -0
- package/dist/docx/commentReferenceCompletion.js +47 -0
- package/dist/docx/commentReferenceNormalization.js +1 -0
- package/dist/docx/commentReplyMarkers.js +11 -19
- package/dist/docx/commentThreadKey.d.ts +18 -0
- package/dist/docx/commentThreadKey.js +22 -0
- package/dist/docx/compatibility.js +1 -0
- package/dist/docx/containerChildren.d.ts +111 -0
- package/dist/docx/containerChildren.gen.d.ts +28 -0
- package/dist/docx/containerChildren.gen.js +246 -0
- package/dist/docx/containerChildren.js +103 -0
- package/dist/docx/diagramPreview.js +87 -27
- package/dist/docx/documentParser.d.ts +1 -1
- package/dist/docx/documentParser.js +3 -3
- package/dist/docx/ensureParaIds.js +17 -7
- package/dist/docx/fieldParser.d.ts +1 -1
- package/dist/docx/fieldParser.js +4 -4
- package/dist/docx/fieldState.d.ts +26 -0
- package/dist/docx/fieldState.js +53 -0
- package/dist/docx/footnoteParser.d.ts +1 -1
- package/dist/docx/graphicFrameLocks.d.ts +16 -4
- package/dist/docx/graphicFrameLocks.js +19 -6
- package/dist/docx/groupDrawingParser.js +3 -3
- package/dist/docx/headerFooterParser.js +1 -1
- package/dist/docx/headerFooterReferenceNormalization.js +1 -0
- package/dist/docx/hyperlinkParser.d.ts +27 -8
- package/dist/docx/hyperlinkParser.js +78 -20
- package/dist/docx/imageParser.d.ts +9 -1
- package/dist/docx/imageParser.js +91 -20
- package/dist/docx/imageRawXml.d.ts +14 -1
- package/dist/docx/imageRawXml.js +30 -6
- package/dist/docx/inlineWrapperContent.d.ts +85 -0
- package/dist/docx/inlineWrapperContent.js +84 -0
- package/dist/docx/mathToMathml.js +12 -14
- package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
- package/dist/docx/nonVisualDrawingProps.js +46 -0
- package/dist/docx/normalizeBaseDirection.js +10 -1
- package/dist/docx/paraIdAttribute.d.ts +21 -0
- package/dist/docx/paraIdAttribute.js +64 -0
- package/dist/docx/paragraphParser.d.ts +1 -1
- package/dist/docx/paragraphParser.js +277 -168
- package/dist/docx/paragraphPropertySource.js +5 -1
- package/dist/docx/paragraphTextBoxEnrichment.d.ts +1 -1
- package/dist/docx/paragraphTextBoxEnrichment.js +9 -52
- package/dist/docx/paragraphTraversal.js +7 -4
- package/dist/docx/parseWarningMessage.js +2 -1
- package/dist/docx/parser.js +2 -2
- package/dist/docx/preservedRunContent.d.ts +32 -0
- package/dist/docx/preservedRunContent.js +86 -0
- package/dist/docx/previewBudget.d.ts +64 -0
- package/dist/docx/previewBudget.js +88 -0
- package/dist/docx/renderedPageBreakNormalization.js +2 -4
- package/dist/docx/revisionIdNormalization.js +17 -5
- package/dist/docx/rezip.js +91 -36
- package/dist/docx/runParser.d.ts +1 -1
- package/dist/docx/runParser.js +16 -12
- package/dist/docx/sdtPropertiesPatch.js +24 -18
- package/dist/docx/sectionParser.js +8 -1
- package/dist/docx/sectionReferenceHistory.js +2 -2
- package/dist/docx/selectiveSave.js +6 -6
- package/dist/docx/selectiveXmlPatch.d.ts +46 -2
- package/dist/docx/selectiveXmlPatch.js +86 -39
- package/dist/docx/serializer/blockSdtSerializer.js +38 -26
- package/dist/docx/serializer/borderSerializer.d.ts +1 -1
- package/dist/docx/serializer/borderSerializer.js +15 -14
- package/dist/docx/serializer/commentSerializer.d.ts +41 -16
- package/dist/docx/serializer/commentSerializer.js +87 -92
- package/dist/docx/serializer/documentSerializer.js +8 -11
- package/dist/docx/serializer/fontTableSerializer.js +6 -6
- package/dist/docx/serializer/headerFooterSerializer.js +12 -14
- package/dist/docx/serializer/markupRangeAttributes.js +2 -2
- package/dist/docx/serializer/noteSerializer.js +8 -8
- package/dist/docx/serializer/numberingSerializer.js +7 -6
- package/dist/docx/serializer/paragraphSerializer.js +93 -72
- package/dist/docx/serializer/partNamespaces.js +2 -2
- package/dist/docx/serializer/runSerializer.js +73 -44
- package/dist/docx/serializer/sectionPropertiesSerializer.js +19 -14
- package/dist/docx/serializer/settingsSerializer.js +4 -3
- package/dist/docx/serializer/stylesSerializer.js +6 -6
- package/dist/docx/serializer/tableSerializer.js +28 -17
- package/dist/docx/serializer/textFormattingSerializer.js +29 -28
- package/dist/docx/serializer/themeSerializer.js +6 -6
- package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
- package/dist/docx/serializer/xmlUtils.d.ts +1 -2
- package/dist/docx/serializer/xmlUtils.js +1 -13
- package/dist/docx/server/boundedArchive.d.ts +12 -0
- package/dist/docx/server/boundedArchive.js +20 -1
- package/dist/docx/server/createBilingualDocument.js +3 -1
- package/dist/docx/server/materializeYjsDocx.d.ts +1 -1
- package/dist/docx/server/materializeYjsDocx.js +9 -1
- package/dist/docx/server/migrateYjsAttrSchema.d.ts +55 -0
- package/dist/docx/server/migrateYjsAttrSchema.js +95 -0
- package/dist/docx/server/validateDocxConformance.js +22 -1
- package/dist/docx/shapeParser.js +12 -10
- package/dist/docx/tableParser.d.ts +1 -1
- package/dist/docx/tableParser.js +206 -85
- package/dist/docx/textBoxParser.d.ts +25 -2
- package/dist/docx/textBoxParser.js +59 -4
- package/dist/docx/unzip.d.ts +23 -0
- package/dist/docx/unzip.js +37 -26
- package/dist/docx/verbatimCapture.js +1 -1
- package/dist/docx/vmlImageParser.d.ts +17 -1
- package/dist/docx/vmlImageParser.js +20 -3
- package/dist/docx/vmlPreview.d.ts +1 -3
- package/dist/docx/vmlPreview.js +2 -30
- package/dist/docx/xmlEncoding.d.ts +5 -0
- package/dist/docx/xmlEncoding.js +12 -0
- package/dist/docx/xmlParser.d.ts +26 -2
- package/dist/docx/xmlParser.js +70 -27
- package/dist/docx/xmlResourceLimits.d.ts +89 -9
- package/dist/docx/xmlResourceLimits.js +105 -24
- package/dist/headless-layout.js +10 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +5 -2
- package/dist/internal/paragraphFormattingSerialization.js +3 -2
- package/dist/layout-bridge/convert/toFlowBlocks.js +102 -12
- package/dist/layout-engine/measure/tableCellFloating.d.ts +2 -0
- package/dist/layout-engine/measure/tableCellFloating.js +2 -0
- package/dist/layout-engine/types.d.ts +23 -1
- package/dist/layout-painter/renderImage.d.ts +5 -1
- package/dist/layout-painter/renderImage.js +14 -6
- package/dist/layout-painter/renderPage.d.ts +2 -0
- package/dist/layout-painter/renderPage.js +4 -0
- package/dist/layout-painter/renderParagraph.d.ts +13 -1
- package/dist/layout-painter/renderParagraph.js +26 -6
- package/dist/managers/autoSaveCodec.d.ts +9 -1
- package/dist/managers/autoSaveCodec.js +14 -12
- package/dist/markdown/images.js +1 -4
- package/dist/markdown/renderBlock.js +1 -0
- package/dist/markdown/renderRuns.d.ts +1 -1
- package/dist/markdown/renderRuns.js +28 -5
- package/dist/markdown/renderTable.js +22 -5
- package/dist/markdown/trailers.js +4 -1
- package/dist/pdf/images.js +142 -6
- package/dist/prosemirror/attrs/index.d.ts +14 -3
- package/dist/prosemirror/attrs/index.js +224 -2
- package/dist/prosemirror/authoredTransformAttrs.d.ts +28 -0
- package/dist/prosemirror/authoredTransformAttrs.js +64 -0
- package/dist/prosemirror/commands/contentControls.js +10 -2
- package/dist/prosemirror/commands/image.d.ts +9 -2
- package/dist/prosemirror/commands/image.js +43 -28
- package/dist/prosemirror/commands/pageBreak.js +1 -1
- package/dist/prosemirror/commentReferenceAttrs.d.ts +8 -0
- package/dist/prosemirror/commentReferenceAttrs.js +33 -0
- package/dist/prosemirror/commentReferenceIntegrity.d.ts +47 -0
- package/dist/prosemirror/commentReferenceIntegrity.js +43 -0
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
- package/dist/prosemirror/conversion/fromProseDoc.js +338 -99
- package/dist/prosemirror/conversion/index.d.ts +2 -2
- package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -9
- package/dist/prosemirror/conversion/toProseDoc.js +551 -327
- package/dist/prosemirror/extensions/StarterKit.js +8 -58
- package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -1
- package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +45 -27
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -1
- package/dist/prosemirror/extensions/features/ImagePasteExtension.js +5 -3
- package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -0
- package/dist/prosemirror/extensions/markRegistry.d.ts +41 -0
- package/dist/prosemirror/extensions/markRegistry.js +75 -0
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.d.ts +18 -0
- package/dist/prosemirror/extensions/marks/InlineWrapperExtension.js +63 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
- package/dist/prosemirror/extensions/marks/markUtils.js +47 -4
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.d.ts +11 -0
- package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +87 -0
- package/dist/prosemirror/extensions/nodes/FieldExtension.js +9 -7
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +20 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.d.ts +32 -0
- package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +67 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.d.ts +16 -0
- package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +60 -0
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +10 -2
- package/dist/prosemirror/extensions/nodes/TableExtension.js +3 -2
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +13 -5
- package/dist/prosemirror/inlineWrapperStack.d.ts +39 -0
- package/dist/prosemirror/inlineWrapperStack.js +75 -0
- package/dist/prosemirror/pageBreakRunProjection.d.ts +17 -7
- package/dist/prosemirror/pageBreakRunProjection.js +19 -9
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +6 -3
- package/dist/prosemirror/paragraphFormattingProvenance.js +12 -3
- package/dist/prosemirror/replacedAnnotations.d.ts +59 -0
- package/dist/prosemirror/replacedAnnotations.js +165 -0
- package/dist/prosemirror/runFormattingInlineCarriers.d.ts +3 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +5 -1
- package/dist/prosemirror/schema/index.d.ts +3 -3
- package/dist/prosemirror/schema/marks.d.ts +25 -1
- package/dist/prosemirror/schema/nodes.d.ts +139 -3
- package/dist/prosemirror/schema/nodes.js +16 -1
- package/dist/prosemirror/trackedRunInlineAtoms.d.ts +2 -0
- package/dist/prosemirror/trackedRunInlineAtoms.js +2 -0
- package/dist/prosemirror/validation.js +16 -2
- package/dist/prosemirror/yjsDocumentMetadata.d.ts +73 -0
- package/dist/prosemirror/yjsDocumentMetadata.js +171 -0
- package/dist/prosemirror/zeroWidthAnchors.js +2 -0
- package/dist/render-dom/commentAnchorAttributes.d.ts +37 -0
- package/dist/render-dom/commentAnchorAttributes.js +54 -0
- package/dist/server.d.ts +3 -1
- package/dist/server.js +3 -1
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/base64.d.ts +36 -0
- package/dist/utils/base64.js +40 -0
- package/dist/utils/clipboard.d.ts +9 -1
- package/dist/utils/clipboard.js +29 -2
- package/dist/utils/findReplace.js +1 -1
- package/dist/utils/imageLuminance.d.ts +15 -0
- package/dist/utils/imageLuminance.js +32 -0
- package/dist/utils/mergeDocumentContent.js +7 -17
- package/dist/utils/replaceText.js +1 -0
- package/dist/utils/units.d.ts +10 -1
- package/dist/utils/units.js +12 -1
- package/dist/utils/urlSecurity.d.ts +8 -2
- package/dist/utils/urlSecurity.js +21 -3
- package/package.json +2 -2
- package/dist/docx/blockRangeMarkers.d.ts +0 -36
- package/dist/docx/blockRangeMarkers.js +0 -59
- package/dist/prosemirror/yjsParagraphSourceContract.d.ts +0 -9
- package/dist/prosemirror/yjsParagraphSourceContract.js +0 -26
|
@@ -262,10 +262,11 @@ const invalidTableCellParagraphSourcePayload = (classification, path) => {
|
|
|
262
262
|
const tableCellBlockTraversalByType = {
|
|
263
263
|
blockSdt: "blockSdt",
|
|
264
264
|
paragraph: "paragraph",
|
|
265
|
+
preservedBlock: "leaf",
|
|
265
266
|
table: "table"
|
|
266
267
|
};
|
|
267
268
|
const tableCellParagraphContentTraversalByType = {
|
|
268
|
-
|
|
269
|
+
inlineWrapper: "content",
|
|
269
270
|
bookmarkEnd: "leaf",
|
|
270
271
|
bookmarkStart: "leaf",
|
|
271
272
|
commentRangeEnd: "leaf",
|
|
@@ -283,6 +284,7 @@ const tableCellParagraphContentTraversalByType = {
|
|
|
283
284
|
moveTo: "content",
|
|
284
285
|
moveToRangeEnd: "leaf",
|
|
285
286
|
moveToRangeStart: "leaf",
|
|
287
|
+
preservedInline: "leaf",
|
|
286
288
|
run: "run",
|
|
287
289
|
simpleField: "content"
|
|
288
290
|
};
|
|
@@ -294,6 +296,7 @@ const tableCellRunContentTraversalByType = {
|
|
|
294
296
|
footnoteRef: "leaf",
|
|
295
297
|
instrText: "leaf",
|
|
296
298
|
noBreakHyphen: "leaf",
|
|
299
|
+
preservedXml: "leaf",
|
|
297
300
|
renderedPageBreak: "leaf",
|
|
298
301
|
shape: "shape",
|
|
299
302
|
softHyphen: "leaf",
|
|
@@ -453,6 +456,7 @@ function visitDecodedTableCellBlock(value, path, context) {
|
|
|
453
456
|
for (const [index, child] of content.entries()) visitDecodedTableCellBlock(child, `${path}.content[${index}]`, context);
|
|
454
457
|
return;
|
|
455
458
|
}
|
|
459
|
+
case "leaf": return;
|
|
456
460
|
default: return traversal;
|
|
457
461
|
}
|
|
458
462
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { NumberingMap } from "./numberingParser.js";
|
|
3
|
-
import { StyleMap } from "./styleParser.js";
|
|
4
3
|
import { XmlElement } from "./xmlParser.js";
|
|
4
|
+
import { StyleMap } from "./styleParser.js";
|
|
5
5
|
import { TableParserFn } from "./textBoxParser.js";
|
|
6
6
|
//#region src/docx/paragraphTextBoxEnrichment.d.ts
|
|
7
7
|
declare const enrichParagraphTextBoxes: (paragraph: document_d_exports.Paragraph, paraXml: XmlElement, styles: StyleMap | null, theme: document_d_exports.Theme | null, numbering: NumberingMap | null, rels: document_d_exports.RelationshipMap | null, media: Map<string, document_d_exports.MediaFile> | null, parseTable: TableParserFn) => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { pixelsToEmu } from "../utils/units.js";
|
|
2
2
|
import { parseParagraph } from "./paragraphParser.js";
|
|
3
|
-
import { getTextBoxContentElement,
|
|
3
|
+
import { getTextBoxContentElement, parseTextBox, parseTextBoxContent, scanRunForTextBoxDrawings } from "./textBoxParser.js";
|
|
4
|
+
import { isVmlPictParsedByRunParser } from "./vmlImageParser.js";
|
|
4
5
|
import { findDeep, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
|
|
5
6
|
//#region src/docx/paragraphTextBoxEnrichment.ts
|
|
6
7
|
const VML_HORIZONTAL_RELATIVES = /* @__PURE__ */ new Set([
|
|
@@ -182,7 +183,10 @@ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rel
|
|
|
182
183
|
if (parsedIndex < content.length && parsedContent?.type !== "run") parsedIndex += 1;
|
|
183
184
|
continue;
|
|
184
185
|
}
|
|
185
|
-
const { textBoxDrawings, vmlTextBoxes, hasNonTextBoxContent } = scanRunForTextBoxDrawings(
|
|
186
|
+
const { textBoxDrawings, vmlTextBoxes, hasNonTextBoxContent } = scanRunForTextBoxDrawings({
|
|
187
|
+
xmlRun: xmlChild,
|
|
188
|
+
claimedByRunParser: (pictElement) => isVmlPictParsedByRunParser(pictElement, rels, media)
|
|
189
|
+
});
|
|
186
190
|
const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
|
|
187
191
|
const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
|
|
188
192
|
const targetRunMatchesXml = targetRun !== void 0 && (hasNonTextBoxContent || parsedRun?.content.length === 0);
|
|
@@ -198,6 +202,9 @@ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rel
|
|
|
198
202
|
type: "shape",
|
|
199
203
|
shapeType: "textBox",
|
|
200
204
|
size: textBox.size,
|
|
205
|
+
...textBox.name !== void 0 ? { name: textBox.name } : {},
|
|
206
|
+
...textBox.alt !== void 0 ? { alt: textBox.alt } : {},
|
|
207
|
+
...textBox.title !== void 0 ? { title: textBox.title } : {},
|
|
201
208
|
...textBox.position !== void 0 ? { position: textBox.position } : {},
|
|
202
209
|
...textBox.wrap !== void 0 ? { wrap: textBox.wrap } : {},
|
|
203
210
|
...textBox.fill !== void 0 ? { fill: textBox.fill } : {},
|
|
@@ -251,56 +258,6 @@ const enrichTextBoxRuns = ({ content, xmlChildren, styles, theme, numbering, rel
|
|
|
251
258
|
}
|
|
252
259
|
}
|
|
253
260
|
};
|
|
254
|
-
const scanRunForTextBoxDrawings = (xmlRun) => {
|
|
255
|
-
const textBoxDrawings = [];
|
|
256
|
-
const vmlTextBoxes = [];
|
|
257
|
-
let hasNonTextBoxContent = false;
|
|
258
|
-
const visitDrawing = (drawingEl) => {
|
|
259
|
-
if (isTextBoxDrawing(drawingEl)) {
|
|
260
|
-
textBoxDrawings.push(drawingEl);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
hasNonTextBoxContent = true;
|
|
264
|
-
};
|
|
265
|
-
for (const el of getChildElements(xmlRun)) {
|
|
266
|
-
const name = getLocalName(el.name ?? "");
|
|
267
|
-
if (name === "rPr") continue;
|
|
268
|
-
if (name === "drawing") {
|
|
269
|
-
visitDrawing(el);
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
if (name === "pict") {
|
|
273
|
-
if (findDeep(el, "v", "textbox")) if (findDeep(el, "v", "imagedata")) hasNonTextBoxContent = true;
|
|
274
|
-
else vmlTextBoxes.push(el);
|
|
275
|
-
else hasNonTextBoxContent = true;
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (name === "AlternateContent") {
|
|
279
|
-
const branches = getChildElements(el);
|
|
280
|
-
const choice = branches.find((branch) => getLocalName(branch.name ?? "") === "Choice");
|
|
281
|
-
const fallback = branches.find((branch) => getLocalName(branch.name ?? "") === "Fallback");
|
|
282
|
-
const tryBranch = (branch) => {
|
|
283
|
-
if (!branch) return false;
|
|
284
|
-
let found = false;
|
|
285
|
-
for (const innerEl of getChildElements(branch)) if (getLocalName(innerEl.name ?? "") === "drawing") {
|
|
286
|
-
visitDrawing(innerEl);
|
|
287
|
-
found = true;
|
|
288
|
-
}
|
|
289
|
-
return found;
|
|
290
|
-
};
|
|
291
|
-
let foundInBranch = tryBranch(choice);
|
|
292
|
-
if (!foundInBranch) foundInBranch = tryBranch(fallback);
|
|
293
|
-
if (!foundInBranch) hasNonTextBoxContent = true;
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
hasNonTextBoxContent = true;
|
|
297
|
-
}
|
|
298
|
-
return {
|
|
299
|
-
textBoxDrawings,
|
|
300
|
-
vmlTextBoxes,
|
|
301
|
-
hasNonTextBoxContent
|
|
302
|
-
};
|
|
303
|
-
};
|
|
304
261
|
const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media, parseTable) => {
|
|
305
262
|
const shapeEl = findDeep(pictEl, "v", "shape");
|
|
306
263
|
const textBoxEl = shapeEl ? findDeep(shapeEl, "v", "textbox") : null;
|
|
@@ -16,7 +16,7 @@ const visitParagraphRuns = (paragraph, visit) => {
|
|
|
16
16
|
case "moveFrom":
|
|
17
17
|
case "moveTo":
|
|
18
18
|
case "inlineSdt":
|
|
19
|
-
case "
|
|
19
|
+
case "inlineWrapper":
|
|
20
20
|
for (const child of content.content) visitParagraphContent(child);
|
|
21
21
|
return;
|
|
22
22
|
case "complexField":
|
|
@@ -32,7 +32,8 @@ const visitParagraphRuns = (paragraph, visit) => {
|
|
|
32
32
|
case "moveFromRangeEnd":
|
|
33
33
|
case "moveToRangeStart":
|
|
34
34
|
case "moveToRangeEnd":
|
|
35
|
-
case "mathEquation":
|
|
35
|
+
case "mathEquation":
|
|
36
|
+
case "preservedInline": return;
|
|
36
37
|
default: return content;
|
|
37
38
|
}
|
|
38
39
|
};
|
|
@@ -69,7 +70,7 @@ const visitInlineContentSlots = (paragraph, visit) => {
|
|
|
69
70
|
case "deletion":
|
|
70
71
|
case "moveFrom":
|
|
71
72
|
case "moveTo":
|
|
72
|
-
case "
|
|
73
|
+
case "inlineWrapper":
|
|
73
74
|
visitContent(item.content);
|
|
74
75
|
break;
|
|
75
76
|
case "run":
|
|
@@ -83,7 +84,8 @@ const visitInlineContentSlots = (paragraph, visit) => {
|
|
|
83
84
|
case "moveFromRangeEnd":
|
|
84
85
|
case "moveToRangeStart":
|
|
85
86
|
case "moveToRangeEnd":
|
|
86
|
-
case "mathEquation":
|
|
87
|
+
case "mathEquation":
|
|
88
|
+
case "preservedInline": break;
|
|
87
89
|
default: panic(`Unsupported paragraph content: ${JSON.stringify(item)}`);
|
|
88
90
|
}
|
|
89
91
|
}
|
|
@@ -145,6 +147,7 @@ const visitDocxParagraphs = ({ documentBody, headers, footers, footnotes, endnot
|
|
|
145
147
|
visitTable(block);
|
|
146
148
|
return;
|
|
147
149
|
}
|
|
150
|
+
if (block.type === "preservedBlock") return;
|
|
148
151
|
visitBlocks(block.content);
|
|
149
152
|
};
|
|
150
153
|
const visitBlocks = (blocks) => {
|
|
@@ -36,7 +36,8 @@ const PARSE_WARNING_MESSAGES = {
|
|
|
36
36
|
[PARSE_WARNING_CODES.unrecognisedOnOffValue]: (warning) => `Ignored on/off value${quoted(warning.value)}${where(warning)}; ST_OnOff is 1, 0, true, false, on or off.`,
|
|
37
37
|
[PARSE_WARNING_CODES.borderWithoutValue]: (warning) => `Read a border with no w:val${where(warning)} as having no border style.`,
|
|
38
38
|
[PARSE_WARNING_CODES.styleSetDuplicateStyleId]: (warning) => `Dropped a style repeating the id${quoted(warning.value)} another style in the set already defines.`,
|
|
39
|
-
[PARSE_WARNING_CODES.styleSetInitialStyleMissing]: (warning) => `The style set names initial paragraph style${quoted(warning.value)}, which it does not contain; used the set's default instead${where(warning)}
|
|
39
|
+
[PARSE_WARNING_CODES.styleSetInitialStyleMissing]: (warning) => `The style set names initial paragraph style${quoted(warning.value)}, which it does not contain; used the set's default instead${where(warning)}.`,
|
|
40
|
+
[PARSE_WARNING_CODES.pageBreakProjectionApproximated]: (warning) => `${warning.detail ?? "An explicit page break is laid out approximately"}${where(warning)}.`
|
|
40
41
|
};
|
|
41
42
|
const formatParseWarning = (warning) => PARSE_WARNING_MESSAGES[warning.code](warning);
|
|
42
43
|
const formatParseWarnings = (warnings) => warnings.map(formatParseWarning);
|
package/dist/docx/parser.js
CHANGED
|
@@ -23,6 +23,7 @@ import { UNNUMBERED_PARAGRAPH_WARNING, UNNUMBERED_STYLE_WARNING, normalizeNumber
|
|
|
23
23
|
import { assignDocumentParagraphPropertySourceContract } from "./paragraphPropertySource.js";
|
|
24
24
|
import { createParseWarningCollector } from "./parseContext.js";
|
|
25
25
|
import { formatParseWarnings } from "./parseWarningMessage.js";
|
|
26
|
+
import { enforcePackagePreviewBudget } from "./previewBudget.js";
|
|
26
27
|
import { RELATIONSHIP_TYPES, parseRelationships, resolveRelativePath } from "./relsParser.js";
|
|
27
28
|
import { normalizeRenderedPageBreakHints } from "./renderedPageBreakNormalization.js";
|
|
28
29
|
import { parseSettings } from "./settingsParser.js";
|
|
@@ -30,7 +31,6 @@ import { parseStylesPackage } from "./styleParser.js";
|
|
|
30
31
|
import { applyThemeFontLang, parseTheme } from "./themeParser.js";
|
|
31
32
|
import { UNBALANCED_MOVE_RANGE_WARNING, normalizeTrackedMoveRanges } from "./trackedMoveRangeNormalization.js";
|
|
32
33
|
import { getMediaMimeType, mediaToDataUrl, unzipDocx } from "./unzip.js";
|
|
33
|
-
import { enforcePackageVmlPreviewBudget } from "./vmlPreview.js";
|
|
34
34
|
import { FOLIO_XML_RESOURCE_LIMITS } from "./xmlResourceLimits.js";
|
|
35
35
|
import { TaggedError } from "better-result";
|
|
36
36
|
import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
|
|
@@ -281,7 +281,7 @@ async function parseDocx(input, options = {}) {
|
|
|
281
281
|
...requiredFonts.length > 0 ? { requiredFonts } : {}
|
|
282
282
|
};
|
|
283
283
|
assignDocumentParagraphPropertySourceContract(document, await paragraphPropertySourceDigest);
|
|
284
|
-
|
|
284
|
+
enforcePackagePreviewBudget(document.package);
|
|
285
285
|
const validation = validateFolioDocumentModel(document);
|
|
286
286
|
const parsedCompleteModel = parseHeadersFooters && parseNotes;
|
|
287
287
|
if (!validation.valid && parsedCompleteModel) throw new DocxModelValidationError("Parsed DOCX produced an invalid document model", validation.issues);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/preservedRunContent.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The visible text a preserved run child contributes, or `""` when it shows
|
|
6
|
+
* nothing. Unknown markup contributes nothing on purpose: guessing at the text
|
|
7
|
+
* of an element folio has never seen would put invented words in a document.
|
|
8
|
+
*/
|
|
9
|
+
declare const preservedRunChildText: (element: XmlElement) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Capture one unmodelled run child.
|
|
12
|
+
*
|
|
13
|
+
* `captureVerbatimXml` materialises exactly the namespace bindings the
|
|
14
|
+
* fragment's own prefixes need and leaves the canonical ones to the rebuilt
|
|
15
|
+
* root, so ordinary `w:` markup comes back byte for byte while a foreign
|
|
16
|
+
* prefix still arrives bound. Copying the whole root scope onto the fragment
|
|
17
|
+
* instead would rewrite every capture with declarations it does not use.
|
|
18
|
+
*/
|
|
19
|
+
declare const preserveRunChild: (element: XmlElement) => document_d_exports.PreservedXmlContent;
|
|
20
|
+
/**
|
|
21
|
+
* One capture from the shared dispatcher's sink, as a member of the
|
|
22
|
+
* container's own inline union.
|
|
23
|
+
*
|
|
24
|
+
* The sink holds markup the schema does not declare for the container at all,
|
|
25
|
+
* so nothing is known about it beyond its bytes: `text` is empty because a
|
|
26
|
+
* name folio has never seen shows nothing folio can read.
|
|
27
|
+
*/
|
|
28
|
+
declare const preservedInlineCapture: (xml: string) => document_d_exports.PreservedInline;
|
|
29
|
+
/** Capture one unmodelled inline child of a paragraph or an inline wrapper. */
|
|
30
|
+
declare const preserveInlineChild: (element: XmlElement) => document_d_exports.PreservedInline;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { preserveInlineChild, preserveRunChild, preservedInlineCapture, preservedRunChildText };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
2
|
+
import { findChildrenByLocalName, getChildElements, getLocalName, getTextContent } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/preservedRunContent.ts
|
|
4
|
+
/**
|
|
5
|
+
* Where a preserved run child hides text a reader sees, by local name: the
|
|
6
|
+
* child elements whose `w:t` descendants are on the line rather than above,
|
|
7
|
+
* beside, or nowhere.
|
|
8
|
+
*
|
|
9
|
+
* `w:ruby` is the whole list today. Its `w:rt` is the annotation printed above
|
|
10
|
+
* the base and is not the sentence's text; its `w:rubyBase` is.
|
|
11
|
+
*/
|
|
12
|
+
const VISIBLE_TEXT_CHILDREN = /* @__PURE__ */ new Map([["ruby", ["rubyBase"]]]);
|
|
13
|
+
/** Cap on the text one preserved child contributes, mirroring `w:t` handling. */
|
|
14
|
+
const MAX_PRESERVED_TEXT_LENGTH = 1e5;
|
|
15
|
+
const collectTextContent = (element, into) => {
|
|
16
|
+
for (const child of getChildElements(element)) {
|
|
17
|
+
if (getLocalName(child.name) === "t") {
|
|
18
|
+
into.push(getTextContent(child));
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
collectTextContent(child, into);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The visible text a preserved run child contributes, or `""` when it shows
|
|
26
|
+
* nothing. Unknown markup contributes nothing on purpose: guessing at the text
|
|
27
|
+
* of an element folio has never seen would put invented words in a document.
|
|
28
|
+
*/
|
|
29
|
+
const preservedRunChildText = (element) => {
|
|
30
|
+
const sources = VISIBLE_TEXT_CHILDREN.get(getLocalName(element.name));
|
|
31
|
+
if (sources === void 0) return "";
|
|
32
|
+
const parts = [];
|
|
33
|
+
for (const localName of sources) for (const source of findChildrenByLocalName(element, localName)) collectTextContent(source, parts);
|
|
34
|
+
return parts.join("").slice(0, MAX_PRESERVED_TEXT_LENGTH);
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Capture one unmodelled run child.
|
|
38
|
+
*
|
|
39
|
+
* `captureVerbatimXml` materialises exactly the namespace bindings the
|
|
40
|
+
* fragment's own prefixes need and leaves the canonical ones to the rebuilt
|
|
41
|
+
* root, so ordinary `w:` markup comes back byte for byte while a foreign
|
|
42
|
+
* prefix still arrives bound. Copying the whole root scope onto the fragment
|
|
43
|
+
* instead would rewrite every capture with declarations it does not use.
|
|
44
|
+
*/
|
|
45
|
+
const preserveRunChild = (element) => ({
|
|
46
|
+
type: "preservedXml",
|
|
47
|
+
xml: captureVerbatimXml(element),
|
|
48
|
+
text: preservedRunChildText(element)
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Where an unmodelled *inline* child hides text a reader sees, by local name.
|
|
52
|
+
*
|
|
53
|
+
* `w:customXml` and `w:smartTag` are transparent wrappers (ECMA-376 §17.5.1,
|
|
54
|
+
* §17.5.1.9): their content is ordinary inline content, so their `w:t`
|
|
55
|
+
* descendants are on the line. Every other inline child folio captures —
|
|
56
|
+
* `w:permStart`, `w:proofErr` and the custom-XML revision ranges — is an
|
|
57
|
+
* empty marker, and an element folio has never seen contributes nothing on
|
|
58
|
+
* purpose, because guessing at its text would put invented words in a
|
|
59
|
+
* document.
|
|
60
|
+
*/
|
|
61
|
+
const VISIBLE_TEXT_INLINE_CHILDREN = /* @__PURE__ */ new Set(["customXml", "smartTag"]);
|
|
62
|
+
/**
|
|
63
|
+
* One capture from the shared dispatcher's sink, as a member of the
|
|
64
|
+
* container's own inline union.
|
|
65
|
+
*
|
|
66
|
+
* The sink holds markup the schema does not declare for the container at all,
|
|
67
|
+
* so nothing is known about it beyond its bytes: `text` is empty because a
|
|
68
|
+
* name folio has never seen shows nothing folio can read.
|
|
69
|
+
*/
|
|
70
|
+
const preservedInlineCapture = (xml) => ({
|
|
71
|
+
type: "preservedInline",
|
|
72
|
+
xml,
|
|
73
|
+
text: ""
|
|
74
|
+
});
|
|
75
|
+
/** Capture one unmodelled inline child of a paragraph or an inline wrapper. */
|
|
76
|
+
const preserveInlineChild = (element) => {
|
|
77
|
+
const parts = [];
|
|
78
|
+
if (VISIBLE_TEXT_INLINE_CHILDREN.has(getLocalName(element.name))) collectTextContent(element, parts);
|
|
79
|
+
return {
|
|
80
|
+
type: "preservedInline",
|
|
81
|
+
xml: captureVerbatimXml(element),
|
|
82
|
+
text: parts.join("").slice(0, MAX_PRESERVED_TEXT_LENGTH)
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
export { preserveInlineChild, preserveRunChild, preservedInlineCapture, preservedRunChildText };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/docx/previewBudget.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Every synthetic preview a parse attaches to the model, and the budget each
|
|
4
|
+
* one answers to.
|
|
5
|
+
*
|
|
6
|
+
* A preview is not document content. It is a drawing folio makes up so a shape
|
|
7
|
+
* it cannot project still occupies the page, and the package round-trips from
|
|
8
|
+
* its preserved XML whether the preview exists or not. So a preview is the one
|
|
9
|
+
* thing in the model that may be dropped, and a package that would retain more
|
|
10
|
+
* of it than it is worth has it dropped rather than being refused.
|
|
11
|
+
*
|
|
12
|
+
* Producer and budget have to agree on what a preview looks like. They used to
|
|
13
|
+
* agree by coincidence: the VML producer wrote its filename as a literal and
|
|
14
|
+
* the budget recognized it as a constant in another file, so renaming one
|
|
15
|
+
* would have stopped the other charging for it without anything failing. The
|
|
16
|
+
* table below is that agreement written once, and a producer builds its image
|
|
17
|
+
* out of the entry the budget matches against.
|
|
18
|
+
*/
|
|
19
|
+
declare const VML_PREVIEW_DATA_URL_PREFIX = "data:image/svg+xml;charset=utf-8,";
|
|
20
|
+
declare const PREVIEW_KINDS: {
|
|
21
|
+
/** A VML shape folio renders rather than projects (`v:shape`, `v:rect`, ...). */
|
|
22
|
+
readonly vmlShape: {
|
|
23
|
+
readonly mimeType: "image/svg+xml";
|
|
24
|
+
readonly filename: "vml-shape-preview.svg";
|
|
25
|
+
readonly srcPrefix: "data:image/svg+xml;charset=utf-8,";
|
|
26
|
+
readonly maxPackageCharacters: number;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A SmartArt diagram: its extent filled with one flat rectangle per shape.
|
|
30
|
+
*
|
|
31
|
+
* A raster rather than a vector because the display list decodes only base64
|
|
32
|
+
* PNG and JPEG, so a vector preview would be missing from every display-list
|
|
33
|
+
* backend (PDF among them) while still showing in the DOM. That is what
|
|
34
|
+
* makes this preview expensive: one of them is 7.3 MB of data URL whatever
|
|
35
|
+
* the package weighs, because its cost follows the extent the author chose
|
|
36
|
+
* rather than anything the drawing contains.
|
|
37
|
+
*
|
|
38
|
+
* Across the public corpus, the fifty packages that produce one retain a
|
|
39
|
+
* median of 7.3 MB and a maximum of 51.3 MB (ten previews, from a package
|
|
40
|
+
* under a megabyte). The cap is set above that maximum: it refuses no
|
|
41
|
+
* legitimate file in the corpus while bounding what had no bound at all, and
|
|
42
|
+
* it is a ceiling rather than a fix. The fix is for the preview to be a
|
|
43
|
+
* descriptor the renderer rasterizes, which needs the display-list contract
|
|
44
|
+
* to carry one.
|
|
45
|
+
*/
|
|
46
|
+
readonly smartArt: {
|
|
47
|
+
readonly mimeType: "image/png";
|
|
48
|
+
readonly filename: "smartart-preview.png";
|
|
49
|
+
readonly srcPrefix: "data:image/png;base64,";
|
|
50
|
+
readonly maxPackageCharacters: number;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
type PreviewKindName = keyof typeof PREVIEW_KINDS;
|
|
54
|
+
/** Per-kind allowances for one package, defaulting to the table's caps. */
|
|
55
|
+
type PreviewBudgetOverrides = Partial<Record<PreviewKindName, number>>;
|
|
56
|
+
/**
|
|
57
|
+
* Charge every generated preview in the model against its kind's allowance and
|
|
58
|
+
* drop the `src` of those past it. Dropping leaves the image in place with its
|
|
59
|
+
* size and wrap, so the page still reserves the space the drawing occupies,
|
|
60
|
+
* and never touches the preserved XML the package saves from.
|
|
61
|
+
*/
|
|
62
|
+
declare const enforcePackagePreviewBudget: (root: unknown, overrides?: PreviewBudgetOverrides) => void;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { PREVIEW_KINDS, PreviewBudgetOverrides, VML_PREVIEW_DATA_URL_PREFIX, enforcePackagePreviewBudget };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
//#region src/docx/previewBudget.ts
|
|
2
|
+
const VML_PREVIEW_DATA_URL_PREFIX = "data:image/svg+xml;charset=utf-8,";
|
|
3
|
+
const MEBIBYTE = 1024 * 1024;
|
|
4
|
+
const PREVIEW_KINDS = {
|
|
5
|
+
/** A VML shape folio renders rather than projects (`v:shape`, `v:rect`, ...). */
|
|
6
|
+
vmlShape: {
|
|
7
|
+
mimeType: "image/svg+xml",
|
|
8
|
+
filename: "vml-shape-preview.svg",
|
|
9
|
+
srcPrefix: VML_PREVIEW_DATA_URL_PREFIX,
|
|
10
|
+
maxPackageCharacters: 8 * MEBIBYTE
|
|
11
|
+
},
|
|
12
|
+
/**
|
|
13
|
+
* A SmartArt diagram: its extent filled with one flat rectangle per shape.
|
|
14
|
+
*
|
|
15
|
+
* A raster rather than a vector because the display list decodes only base64
|
|
16
|
+
* PNG and JPEG, so a vector preview would be missing from every display-list
|
|
17
|
+
* backend (PDF among them) while still showing in the DOM. That is what
|
|
18
|
+
* makes this preview expensive: one of them is 7.3 MB of data URL whatever
|
|
19
|
+
* the package weighs, because its cost follows the extent the author chose
|
|
20
|
+
* rather than anything the drawing contains.
|
|
21
|
+
*
|
|
22
|
+
* Across the public corpus, the fifty packages that produce one retain a
|
|
23
|
+
* median of 7.3 MB and a maximum of 51.3 MB (ten previews, from a package
|
|
24
|
+
* under a megabyte). The cap is set above that maximum: it refuses no
|
|
25
|
+
* legitimate file in the corpus while bounding what had no bound at all, and
|
|
26
|
+
* it is a ceiling rather than a fix. The fix is for the preview to be a
|
|
27
|
+
* descriptor the renderer rasterizes, which needs the display-list contract
|
|
28
|
+
* to carry one.
|
|
29
|
+
*/
|
|
30
|
+
smartArt: {
|
|
31
|
+
mimeType: "image/png",
|
|
32
|
+
filename: "smartart-preview.png",
|
|
33
|
+
srcPrefix: "data:image/png;base64,",
|
|
34
|
+
maxPackageCharacters: 64 * MEBIBYTE
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const KIND_NAMES = Object.keys(PREVIEW_KINDS);
|
|
38
|
+
/**
|
|
39
|
+
* The kind a model image was generated as, or `undefined` for one the package
|
|
40
|
+
* actually carries. A generated preview has no relationship behind it, so
|
|
41
|
+
* `rId` is empty; the filename and data-URL prefix name which producer made it.
|
|
42
|
+
*/
|
|
43
|
+
const previewKindOf = (value) => {
|
|
44
|
+
if (!("type" in value) || value.type !== "image" || !("rId" in value) || value.rId !== "" || !("src" in value) || typeof value.src !== "string" || !("mimeType" in value) || !("filename" in value)) return;
|
|
45
|
+
const { src, mimeType, filename } = value;
|
|
46
|
+
return KIND_NAMES.find((name) => {
|
|
47
|
+
const kind = PREVIEW_KINDS[name];
|
|
48
|
+
return mimeType === kind.mimeType && filename === kind.filename && src.startsWith(kind.srcPrefix);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Charge every generated preview in the model against its kind's allowance and
|
|
53
|
+
* drop the `src` of those past it. Dropping leaves the image in place with its
|
|
54
|
+
* size and wrap, so the page still reserves the space the drawing occupies,
|
|
55
|
+
* and never touches the preserved XML the package saves from.
|
|
56
|
+
*/
|
|
57
|
+
const enforcePackagePreviewBudget = (root, overrides = {}) => {
|
|
58
|
+
const remaining = new Map(KIND_NAMES.map((name) => [name, Math.max(0, overrides[name] ?? PREVIEW_KINDS[name].maxPackageCharacters)]));
|
|
59
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
60
|
+
const visit = (value) => {
|
|
61
|
+
if (value === null || typeof value !== "object" || visited.has(value)) return;
|
|
62
|
+
visited.add(value);
|
|
63
|
+
if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) return;
|
|
64
|
+
if (value instanceof Map) {
|
|
65
|
+
for (const child of value.values()) visit(child);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
for (const child of value) visit(child);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const kind = previewKindOf(value);
|
|
73
|
+
if (kind !== void 0) {
|
|
74
|
+
const image = value;
|
|
75
|
+
const length = image.src.length;
|
|
76
|
+
const left = remaining.get(kind);
|
|
77
|
+
if (length <= left) remaining.set(kind, left - length);
|
|
78
|
+
else {
|
|
79
|
+
remaining.set(kind, 0);
|
|
80
|
+
delete image.src;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const child of Object.values(value)) visit(child);
|
|
84
|
+
};
|
|
85
|
+
visit(root);
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { PREVIEW_KINDS, VML_PREVIEW_DATA_URL_PREFIX, enforcePackagePreviewBudget };
|
|
@@ -37,9 +37,7 @@ const scanHyperlink = (hyperlink, scan) => {
|
|
|
37
37
|
};
|
|
38
38
|
const scanInlineContent = (content, scan) => {
|
|
39
39
|
for (const child of content) {
|
|
40
|
-
|
|
41
|
-
if (child.type === "run") result = scanRun(child, scan);
|
|
42
|
-
else if (child.type === "hyperlink") result = scanHyperlink(child, scan);
|
|
40
|
+
const result = scanParagraphContent(child, scan);
|
|
43
41
|
if (result !== void 0) return result;
|
|
44
42
|
}
|
|
45
43
|
};
|
|
@@ -48,7 +46,7 @@ const scanParagraphContent = (content, scan) => {
|
|
|
48
46
|
if (content.type === "hyperlink") return scanHyperlink(content, scan);
|
|
49
47
|
if (content.type === "simpleField") return scanInlineContent(content.content, scan);
|
|
50
48
|
if (content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo") return scanInlineContent(content.content, scan);
|
|
51
|
-
if (content.type === "inlineSdt") {
|
|
49
|
+
if (content.type === "inlineSdt" || content.type === "inlineWrapper") {
|
|
52
50
|
for (const child of content.content) {
|
|
53
51
|
const result = scanParagraphContent(child, scan);
|
|
54
52
|
if (result !== void 0) return result;
|
|
@@ -117,7 +117,10 @@ const normalizeRevisionIdsInXmlParts = (parts) => {
|
|
|
117
117
|
const occurrencesByPath = /* @__PURE__ */ new Map();
|
|
118
118
|
const reserved = /* @__PURE__ */ new Set();
|
|
119
119
|
for (const [path, xml] of candidates) {
|
|
120
|
-
assertXmlResourceLimits(
|
|
120
|
+
assertXmlResourceLimits({
|
|
121
|
+
xml,
|
|
122
|
+
partPath: path
|
|
123
|
+
});
|
|
121
124
|
const ids = [];
|
|
122
125
|
if (rewriteStreamingXmlDecimalAttributes(xml, (element) => {
|
|
123
126
|
const identified = identifiedElement(element);
|
|
@@ -127,7 +130,9 @@ const normalizeRevisionIdsInXmlParts = (parts) => {
|
|
|
127
130
|
return null;
|
|
128
131
|
}).status === "unsupported") throw new XmlResourceLimitError({
|
|
129
132
|
message: `Revision-id normalization could not safely scan ${path}`,
|
|
130
|
-
limit: "syntax"
|
|
133
|
+
limit: "syntax",
|
|
134
|
+
observed: 0,
|
|
135
|
+
allowed: 0
|
|
131
136
|
});
|
|
132
137
|
occurrencesByPath.set(path, ids);
|
|
133
138
|
}
|
|
@@ -137,14 +142,19 @@ const normalizeRevisionIdsInXmlParts = (parts) => {
|
|
|
137
142
|
else firstSeen.add(id);
|
|
138
143
|
if (repeatedPaths.size > 0) for (const [path, xml] of parts) {
|
|
139
144
|
if (occurrencesByPath.has(path) || !ANNOTATION_ELEMENT_CANDIDATE.test(xml)) continue;
|
|
140
|
-
assertXmlResourceLimits(
|
|
145
|
+
assertXmlResourceLimits({
|
|
146
|
+
xml,
|
|
147
|
+
partPath: path
|
|
148
|
+
});
|
|
141
149
|
if (rewriteStreamingXmlDecimalAttributes(xml, (element) => {
|
|
142
150
|
const identified = identifiedElement(element);
|
|
143
151
|
if (identified !== null) reserved.add(identified.id);
|
|
144
152
|
return null;
|
|
145
153
|
}).status === "unsupported") throw new XmlResourceLimitError({
|
|
146
154
|
message: `Revision-id normalization could not safely scan ${path}`,
|
|
147
|
-
limit: "syntax"
|
|
155
|
+
limit: "syntax",
|
|
156
|
+
observed: 0,
|
|
157
|
+
allowed: 0
|
|
148
158
|
});
|
|
149
159
|
}
|
|
150
160
|
let nextId = 0;
|
|
@@ -185,7 +195,9 @@ const normalizeRevisionIdsInXmlParts = (parts) => {
|
|
|
185
195
|
});
|
|
186
196
|
if (rewritten.status === "unsupported") throw new XmlResourceLimitError({
|
|
187
197
|
message: `Revision-id normalization could not safely rewrite ${path}`,
|
|
188
|
-
limit: "syntax"
|
|
198
|
+
limit: "syntax",
|
|
199
|
+
observed: 0,
|
|
200
|
+
allowed: 0
|
|
189
201
|
});
|
|
190
202
|
normalized.set(path, rewritten.value);
|
|
191
203
|
}
|