@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
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { parseOnOffAttribute } from "./xmlParser.js";
|
|
2
|
+
//#region src/docx/fieldState.ts
|
|
3
|
+
/**
|
|
4
|
+
* `@w:fldLock` and `@w:dirty`, the two `ST_OnOff` attributes every field form
|
|
5
|
+
* carries.
|
|
6
|
+
*
|
|
7
|
+
* A simple field states them on `<w:fldSimple>`; a complex field states them on
|
|
8
|
+
* the `<w:fldChar w:fldCharType="begin"/>` that opens it, and folio hoists them
|
|
9
|
+
* from there onto the assembled `ComplexField`. Neither attribute has an XSD
|
|
10
|
+
* default, so a field states one of three things about each: nothing, an
|
|
11
|
+
* explicit off, an explicit on. `w:dirty="0"` on a field inside a `TOC` result
|
|
12
|
+
* is the case that matters: it says "do not recompute this", which is not what
|
|
13
|
+
* an absent attribute says.
|
|
14
|
+
*
|
|
15
|
+
* Three readers and three writers had drifted into the same `=== true` /
|
|
16
|
+
* truthiness collapse, so both directions live here instead.
|
|
17
|
+
*/
|
|
18
|
+
/** Read both attributes off a `w:fldSimple` or `w:fldChar`, keeping an explicit off. */
|
|
19
|
+
const parseFieldState = (element) => {
|
|
20
|
+
const state = {};
|
|
21
|
+
const fldLock = parseOnOffAttribute(element, "w", "fldLock");
|
|
22
|
+
if (fldLock !== void 0) state.fldLock = fldLock;
|
|
23
|
+
const dirty = parseOnOffAttribute(element, "w", "dirty");
|
|
24
|
+
if (dirty !== void 0) state.dirty = dirty;
|
|
25
|
+
return state;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The stated flags of a field, without the rest of it.
|
|
29
|
+
*
|
|
30
|
+
* The complex-field assembly carries the begin `w:fldChar`'s state across the
|
|
31
|
+
* runs between `begin` and `end`, and this is the one place that knows which
|
|
32
|
+
* fields that state is made of.
|
|
33
|
+
*/
|
|
34
|
+
const fieldStateOf = ({ fldLock, dirty }) => {
|
|
35
|
+
const state = {};
|
|
36
|
+
if (fldLock !== void 0) state.fldLock = fldLock;
|
|
37
|
+
if (dirty !== void 0) state.dirty = dirty;
|
|
38
|
+
return state;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The attributes to write for a field's stated flags, in schema order.
|
|
42
|
+
*
|
|
43
|
+
* `1`/`0` is what Word writes and what the table, section and border
|
|
44
|
+
* serializers write.
|
|
45
|
+
*/
|
|
46
|
+
const fieldStateAttributes = ({ fldLock, dirty }) => {
|
|
47
|
+
const attrs = [];
|
|
48
|
+
if (fldLock !== void 0) attrs.push(`w:fldLock="${fldLock ? "1" : "0"}"`);
|
|
49
|
+
if (dirty !== void 0) attrs.push(`w:dirty="${dirty ? "1" : "0"}"`);
|
|
50
|
+
return attrs;
|
|
51
|
+
};
|
|
52
|
+
//#endregion
|
|
53
|
+
export { fieldStateAttributes, fieldStateOf, parseFieldState };
|
|
@@ -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 { ParseContext } from "./parseContext.js";
|
|
4
|
+
import { StyleMap } from "./styleParser.js";
|
|
5
5
|
import { parseEndnoteProperties, parseFootnoteProperties } from "./notePropertiesParser.js";
|
|
6
6
|
//#region src/docx/footnoteParser.d.ts
|
|
7
7
|
/**
|
|
@@ -12,11 +12,23 @@ declare const GRAPHIC_FRAME_LOCK_KEYS: ("noGrp" | "noDrilldown" | "noSelect" | "
|
|
|
12
12
|
*/
|
|
13
13
|
declare const parseGraphicFrameLocks: (parent: XmlElement) => document_d_exports.ImageFrameLocks | undefined;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* The locks folio gives a picture it creates itself, at the insert that creates
|
|
16
|
+
* it: Word writes `noChangeAspect="1"` on a picture inserted through its own
|
|
17
|
+
* UI, and an inserted picture should behave the same in both.
|
|
16
18
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
+
* It lives here because it is a fact about this element, and it is applied at
|
|
20
|
+
* construction rather than at serialization, where "the author wrote no frame"
|
|
21
|
+
* and "folio made this picture" are the same `undefined`.
|
|
22
|
+
*/
|
|
23
|
+
declare const FOLIO_INSERTED_PICTURE_FRAME_LOCKS: document_d_exports.ImageFrameLocks;
|
|
24
|
+
/**
|
|
25
|
+
* Emit `wp:cNvGraphicFramePr` for regenerated DrawingML, or nothing.
|
|
26
|
+
*
|
|
27
|
+
* Absent locks are the author's silence, and silence is written back as
|
|
28
|
+
* silence: a frame the source never carried is not invented on the rebuild
|
|
29
|
+
* path, where it would appear on every edited document and on none of the
|
|
30
|
+
* replayed ones.
|
|
19
31
|
*/
|
|
20
32
|
declare const serializeGraphicFrameLocks: (locks: document_d_exports.ImageFrameLocks | undefined) => string;
|
|
21
33
|
//#endregion
|
|
22
|
-
export { GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
|
|
34
|
+
export { FOLIO_INSERTED_PICTURE_FRAME_LOCKS, GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
|
|
@@ -38,18 +38,31 @@ const parseGraphicFrameLocks = (parent) => {
|
|
|
38
38
|
return present ? locks : void 0;
|
|
39
39
|
};
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* The locks folio gives a picture it creates itself, at the insert that creates
|
|
42
|
+
* it: Word writes `noChangeAspect="1"` on a picture inserted through its own
|
|
43
|
+
* UI, and an inserted picture should behave the same in both.
|
|
42
44
|
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
+
* It lives here because it is a fact about this element, and it is applied at
|
|
46
|
+
* construction rather than at serialization, where "the author wrote no frame"
|
|
47
|
+
* and "folio made this picture" are the same `undefined`.
|
|
48
|
+
*/
|
|
49
|
+
const FOLIO_INSERTED_PICTURE_FRAME_LOCKS = { noChangeAspect: true };
|
|
50
|
+
/**
|
|
51
|
+
* Emit `wp:cNvGraphicFramePr` for regenerated DrawingML, or nothing.
|
|
52
|
+
*
|
|
53
|
+
* Absent locks are the author's silence, and silence is written back as
|
|
54
|
+
* silence: a frame the source never carried is not invented on the rebuild
|
|
55
|
+
* path, where it would appear on every edited document and on none of the
|
|
56
|
+
* replayed ones.
|
|
45
57
|
*/
|
|
46
58
|
const serializeGraphicFrameLocks = (locks) => {
|
|
47
|
-
|
|
59
|
+
if (!locks) return "";
|
|
60
|
+
const attrs = GRAPHIC_FRAME_LOCK_KEYS.flatMap((key) => {
|
|
48
61
|
const value = locks[key];
|
|
49
62
|
return value === void 0 ? [] : [`${GRAPHIC_FRAME_LOCK_ATTRIBUTES[key]}="${value ? "1" : "0"}"`];
|
|
50
|
-
})
|
|
63
|
+
});
|
|
51
64
|
const attrList = attrs.length > 0 ? ` ${attrs.join(" ")}` : "";
|
|
52
65
|
return `<wp:cNvGraphicFramePr><a:graphicFrameLocks ${DRAWINGML_NAMESPACE}${attrList}/></wp:cNvGraphicFramePr>`;
|
|
53
66
|
};
|
|
54
67
|
//#endregion
|
|
55
|
-
export { GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
|
|
68
|
+
export { FOLIO_INSERTED_PICTURE_FRAME_LOCKS, GRAPHIC_FRAME_LOCK_KEYS, parseGraphicFrameLocks, serializeGraphicFrameLocks };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { emuToPixels } from "../utils/units.js";
|
|
2
2
|
import { parseImage, resolveImageData } from "./imageParser.js";
|
|
3
3
|
import { findAllDeep, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getLocalName, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
4
|
+
import { escapeXmlAttribute, escapeXmlText } from "@stll/docx-core";
|
|
4
5
|
//#region src/docx/groupDrawingParser.ts
|
|
5
6
|
const HEX_COLOR = /^[0-9A-Fa-f]{6}$/u;
|
|
6
7
|
const DEFAULT_TEXT_COLOR = "000000";
|
|
@@ -12,7 +13,6 @@ const CROP_SCALE = 1e5;
|
|
|
12
13
|
const MAX_PATH_COMMANDS = 1e4;
|
|
13
14
|
const MAX_TEXT_CHARACTERS = 2e4;
|
|
14
15
|
const MAX_SVG_CHARACTERS = 1e6;
|
|
15
|
-
const escapeXml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
16
16
|
const numericAttr = (element, name) => {
|
|
17
17
|
const direct = parseNumericAttribute(element, null, name);
|
|
18
18
|
if (direct !== void 0) return direct;
|
|
@@ -108,7 +108,7 @@ const renderTextBox = (wsp) => {
|
|
|
108
108
|
const color = colorFrom(findAllDeep(wsp, "w", "color").at(0) ?? null, DEFAULT_TEXT_COLOR);
|
|
109
109
|
const fontSize = halfPoints * HALF_POINT_TO_EMU;
|
|
110
110
|
const maxCharacters = Math.max(1, Math.floor(width / (fontSize * .38)));
|
|
111
|
-
const lines = paragraphs.flatMap((paragraph) => wrapLine(getTextContent(paragraph).slice(0, MAX_TEXT_CHARACTERS), maxCharacters)).map(
|
|
111
|
+
const lines = paragraphs.flatMap((paragraph) => wrapLine(getTextContent(paragraph).slice(0, MAX_TEXT_CHARACTERS), maxCharacters)).map(escapeXmlText);
|
|
112
112
|
if (lines.length === 0) return "";
|
|
113
113
|
const lineHeight = fontSize * 1.15;
|
|
114
114
|
const svgFontSize = 1e3;
|
|
@@ -131,7 +131,7 @@ const renderPicture = (picture, index, rels, media) => {
|
|
|
131
131
|
const visibleWidth = 1 - left - right;
|
|
132
132
|
const visibleHeight = 1 - top - bottom;
|
|
133
133
|
if (visibleWidth <= 0 || visibleHeight <= 0) return "";
|
|
134
|
-
const image = `<image x="${x - width * left / visibleWidth}" y="${y - height * top / visibleHeight}" width="${width / visibleWidth}" height="${height / visibleHeight}" href="${
|
|
134
|
+
const image = `<image x="${x - width * left / visibleWidth}" y="${y - height * top / visibleHeight}" width="${width / visibleWidth}" height="${height / visibleHeight}" href="${escapeXmlAttribute(src)}" preserveAspectRatio="none"/>`;
|
|
135
135
|
if (left === 0 && top === 0 && right === 0 && bottom === 0) return image;
|
|
136
136
|
const clipId = `group-picture-${index}`;
|
|
137
137
|
return `<defs><clipPath id="${clipId}"><rect x="${x}" y="${y}" width="${width}" height="${height}"/></clipPath></defs><g clip-path="url(#${clipId})">${image}</g>`;
|
|
@@ -155,7 +155,7 @@ function getHeaderFooterText(hf) {
|
|
|
155
155
|
function isEmptyHeaderFooter(hf) {
|
|
156
156
|
if (hf.content.length === 0) return true;
|
|
157
157
|
for (const item of hf.content) {
|
|
158
|
-
if (item.type
|
|
158
|
+
if (item.type !== "paragraph") return false;
|
|
159
159
|
if (item.content.length > 0) for (const content of item.content) {
|
|
160
160
|
if (content.type !== "run") return false;
|
|
161
161
|
for (const rc of content.content) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
|
-
import { StyleMap } from "./styleParser.js";
|
|
3
2
|
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
import { StyleMap } from "./styleParser.js";
|
|
4
|
+
import { ChildHandlers } from "./containerChildren.js";
|
|
4
5
|
//#region src/docx/hyperlinkParser.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* Parse a hyperlink element (w:hyperlink)
|
|
@@ -16,14 +17,32 @@ import { XmlElement } from "./xmlParser.js";
|
|
|
16
17
|
* @returns Parsed Hyperlink object
|
|
17
18
|
*/
|
|
18
19
|
declare function parseHyperlink(node: XmlElement, rels: document_d_exports.RelationshipMap | null, styles?: StyleMap | null, theme?: document_d_exports.Theme | null, media?: Map<string, document_d_exports.MediaFile> | null, rootXmlns?: Record<string, string>): document_d_exports.Hyperlink;
|
|
20
|
+
/** What {@link hyperlinkChildHandlers} needs to read one child of a link. */
|
|
21
|
+
type HyperlinkChildContext = {
|
|
22
|
+
/** Where a parsed or captured child lands, in source order. */
|
|
23
|
+
push: (child: document_d_exports.Hyperlink["children"][number]) => void;
|
|
24
|
+
styles: StyleMap | null;
|
|
25
|
+
theme: document_d_exports.Theme | null;
|
|
26
|
+
rels: document_d_exports.RelationshipMap | null;
|
|
27
|
+
media: Map<string, document_d_exports.MediaFile> | null;
|
|
28
|
+
inScopeXmlns: Record<string, string>;
|
|
29
|
+
};
|
|
19
30
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
31
|
+
* What a `w:hyperlink` does with every child its content model declares.
|
|
32
|
+
*
|
|
33
|
+
* `CT_Hyperlink` is `EG_PContent`, so a link may hold a permission range, a
|
|
34
|
+
* proofing error, a nested field or one of the eight custom-XML revision
|
|
35
|
+
* ranges between its runs; folio models three of the thirty-two names and
|
|
36
|
+
* used to drop the other twenty-nine off the end of a `switch`.
|
|
37
|
+
*
|
|
38
|
+
* Two callers read this one map: {@link parseHyperlink}, and the paragraph
|
|
39
|
+
* parser's revision-segmenting walk, which overrides the four
|
|
40
|
+
* `CT_RunTrackChange` wrappers because OOXML nests a revision inside a link
|
|
41
|
+
* and the model nests the link inside the revision. Everything else is
|
|
42
|
+
* decided here once, so a child one caller starts recognising is recognised
|
|
43
|
+
* by both rather than by whichever list somebody remembered to update.
|
|
25
44
|
*/
|
|
26
|
-
declare
|
|
45
|
+
declare const hyperlinkChildHandlers: ({ push, styles, theme, rels, media, inScopeXmlns }: HyperlinkChildContext) => ChildHandlers<"w:hyperlink">;
|
|
27
46
|
/**
|
|
28
47
|
* Get the display text of a hyperlink
|
|
29
48
|
*
|
|
@@ -112,4 +131,4 @@ declare function createExternalHyperlink(url: string, children: document_d_expor
|
|
|
112
131
|
target?: string;
|
|
113
132
|
}): document_d_exports.Hyperlink;
|
|
114
133
|
//#endregion
|
|
115
|
-
export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink,
|
|
134
|
+
export { HyperlinkChildContext, createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { sanitizeExternalUrl
|
|
1
|
+
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
2
|
+
import { CAPTURE, dispatchChildren, withPreservedChildren } from "./containerChildren.js";
|
|
3
|
+
import { preserveInlineChild, preservedInlineCapture } from "./preservedRunContent.js";
|
|
2
4
|
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
|
|
3
5
|
import { parseRun } from "./runParser.js";
|
|
4
|
-
import { getAttribute,
|
|
6
|
+
import { getAttribute, mergeXmlnsDeclarations, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
5
7
|
//#region src/docx/hyperlinkParser.ts
|
|
6
8
|
/**
|
|
7
9
|
* Parse bookmark start (w:bookmarkStart)
|
|
@@ -63,32 +65,88 @@ function parseHyperlink(node, rels, styles = null, theme = null, media = null, r
|
|
|
63
65
|
const tooltip = getAttribute(node, "w", "tooltip");
|
|
64
66
|
if (tooltip) hyperlink.tooltip = tooltip;
|
|
65
67
|
const tgtFrame = getAttribute(node, "w", "tgtFrame");
|
|
66
|
-
if (tgtFrame) hyperlink.target =
|
|
68
|
+
if (tgtFrame) hyperlink.target = tgtFrame;
|
|
67
69
|
if (parseOnOffAttribute(node, "w", "history") === true) hyperlink.history = true;
|
|
68
70
|
const docLocation = getAttribute(node, "w", "docLocation");
|
|
69
71
|
if (docLocation) hyperlink.docLocation = docLocation;
|
|
70
72
|
const inScopeXmlns = mergeXmlnsDeclarations(rootXmlns, node);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
const children = [];
|
|
74
|
+
hyperlink.children = withPreservedChildren(children, dispatchChildren({
|
|
75
|
+
element: node,
|
|
76
|
+
container: "w:hyperlink",
|
|
77
|
+
modelledCount: () => children.length,
|
|
78
|
+
handlers: hyperlinkChildHandlers({
|
|
79
|
+
push: (child) => {
|
|
80
|
+
children.push(child);
|
|
81
|
+
},
|
|
82
|
+
styles,
|
|
83
|
+
theme,
|
|
84
|
+
rels,
|
|
85
|
+
media,
|
|
86
|
+
inScopeXmlns
|
|
87
|
+
})
|
|
88
|
+
}), preservedInlineCapture);
|
|
75
89
|
return hyperlink;
|
|
76
90
|
}
|
|
77
91
|
/**
|
|
78
|
-
*
|
|
92
|
+
* What a `w:hyperlink` does with every child its content model declares.
|
|
93
|
+
*
|
|
94
|
+
* `CT_Hyperlink` is `EG_PContent`, so a link may hold a permission range, a
|
|
95
|
+
* proofing error, a nested field or one of the eight custom-XML revision
|
|
96
|
+
* ranges between its runs; folio models three of the thirty-two names and
|
|
97
|
+
* used to drop the other twenty-nine off the end of a `switch`.
|
|
79
98
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
99
|
+
* Two callers read this one map: {@link parseHyperlink}, and the paragraph
|
|
100
|
+
* parser's revision-segmenting walk, which overrides the four
|
|
101
|
+
* `CT_RunTrackChange` wrappers because OOXML nests a revision inside a link
|
|
102
|
+
* and the model nests the link inside the revision. Everything else is
|
|
103
|
+
* decided here once, so a child one caller starts recognising is recognised
|
|
104
|
+
* by both rather than by whichever list somebody remembered to update.
|
|
83
105
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
106
|
+
const hyperlinkChildHandlers = ({ push, styles, theme, rels, media, inScopeXmlns }) => ({
|
|
107
|
+
r: (child) => {
|
|
108
|
+
push(parseRun(child, styles, theme, rels, media, inScopeXmlns));
|
|
109
|
+
},
|
|
110
|
+
bookmarkStart: (child) => {
|
|
111
|
+
push(parseBookmarkStart(child));
|
|
112
|
+
},
|
|
113
|
+
bookmarkEnd: (child) => {
|
|
114
|
+
push(parseBookmarkEnd(child));
|
|
115
|
+
},
|
|
116
|
+
customXml: (child) => {
|
|
117
|
+
push(preserveInlineChild(child));
|
|
118
|
+
},
|
|
119
|
+
smartTag: (child) => {
|
|
120
|
+
push(preserveInlineChild(child));
|
|
121
|
+
},
|
|
122
|
+
del: CAPTURE,
|
|
123
|
+
ins: CAPTURE,
|
|
124
|
+
moveFrom: CAPTURE,
|
|
125
|
+
moveTo: CAPTURE,
|
|
126
|
+
bdo: CAPTURE,
|
|
127
|
+
commentRangeEnd: CAPTURE,
|
|
128
|
+
commentRangeStart: CAPTURE,
|
|
129
|
+
customXmlDelRangeEnd: CAPTURE,
|
|
130
|
+
customXmlDelRangeStart: CAPTURE,
|
|
131
|
+
customXmlInsRangeEnd: CAPTURE,
|
|
132
|
+
customXmlInsRangeStart: CAPTURE,
|
|
133
|
+
customXmlMoveFromRangeEnd: CAPTURE,
|
|
134
|
+
customXmlMoveFromRangeStart: CAPTURE,
|
|
135
|
+
customXmlMoveToRangeEnd: CAPTURE,
|
|
136
|
+
customXmlMoveToRangeStart: CAPTURE,
|
|
137
|
+
dir: CAPTURE,
|
|
138
|
+
fldSimple: CAPTURE,
|
|
139
|
+
hyperlink: CAPTURE,
|
|
140
|
+
moveFromRangeEnd: CAPTURE,
|
|
141
|
+
moveFromRangeStart: CAPTURE,
|
|
142
|
+
moveToRangeEnd: CAPTURE,
|
|
143
|
+
moveToRangeStart: CAPTURE,
|
|
144
|
+
permEnd: CAPTURE,
|
|
145
|
+
permStart: CAPTURE,
|
|
146
|
+
proofErr: CAPTURE,
|
|
147
|
+
sdt: CAPTURE,
|
|
148
|
+
subDoc: CAPTURE
|
|
149
|
+
});
|
|
92
150
|
/**
|
|
93
151
|
* Get the display text of a hyperlink
|
|
94
152
|
*
|
|
@@ -219,4 +277,4 @@ function createExternalHyperlink(url, children, options) {
|
|
|
219
277
|
};
|
|
220
278
|
}
|
|
221
279
|
//#endregion
|
|
222
|
-
export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, isExternalLink, isInternalLink, parseHyperlink,
|
|
280
|
+
export { createExternalHyperlink, createInternalHyperlink, getHyperlinkRuns, getHyperlinkText, getHyperlinkUrl, hasContent, hyperlinkChildHandlers, isExternalLink, isInternalLink, parseHyperlink, resolveHyperlinkUrl };
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
import { XmlElement } from "./xmlParser.js";
|
|
3
3
|
//#region src/docx/imageParser.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The `a:ext` uri under which Word records that a drawing is decorative. The
|
|
6
|
+
* extension holds `<adec:decorative val="…"/>`; `CT_NonVisualDrawingProps` has
|
|
7
|
+
* no `@decorative` attribute for it to be written as.
|
|
8
|
+
*/
|
|
9
|
+
declare const DECORATIVE_EXTENSION_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}";
|
|
10
|
+
/** The namespace the decorative extension's element is bound to. */
|
|
11
|
+
declare const DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative";
|
|
4
12
|
/**
|
|
5
13
|
* Resolve image data from relationships and media map
|
|
6
14
|
*
|
|
@@ -89,4 +97,4 @@ declare function getWrapDistancesPx(image: document_d_exports.Image): {
|
|
|
89
97
|
*/
|
|
90
98
|
declare function needsTextWrapping(image: document_d_exports.Image): boolean;
|
|
91
99
|
//#endregion
|
|
92
|
-
export { getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
100
|
+
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
package/dist/docx/imageParser.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { normalizeImageLuminancePercent } from "../utils/imageLuminance.js";
|
|
1
2
|
import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
|
|
2
3
|
import { emuToPixels } from "../utils/units.js";
|
|
3
4
|
import { sanitizeExternalUrl } from "../utils/urlSecurity.js";
|
|
4
5
|
import { WRAP_ELEMENT_NAMES, parseAnchorBehindDoc, parsePositionH, parsePositionV, parseWrapElement } from "./drawingUtils.js";
|
|
5
6
|
import { parseGraphicFrameLocks } from "./graphicFrameLocks.js";
|
|
7
|
+
import { parseNonVisualDrawingNames } from "./nonVisualDrawingProps.js";
|
|
6
8
|
import { RELATIONSHIP_TYPES, resolveRelationshipIdOfType } from "./relsParser.js";
|
|
7
9
|
import { isTextBoxDrawing } from "./textBoxParser.js";
|
|
8
|
-
import {
|
|
10
|
+
import { percentageSpelling } from "./transitionalSpelling.js";
|
|
11
|
+
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
12
|
+
import { findByFullName, findChild, findChildByNamespaceUri, findChildrenByNamespaceUri, getAttribute, getChildElements, getLocalName, getNamespaceUri, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue } from "./xmlParser.js";
|
|
9
13
|
//#region src/docx/imageParser.ts
|
|
14
|
+
const DRAWINGML_MAIN_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/main", "http://purl.oclc.org/ooxml/drawingml/main"]);
|
|
15
|
+
const FIXED_PERCENTAGE = /^-?\d+$/u;
|
|
10
16
|
/**
|
|
11
17
|
* Convert rotation value (1/60000 of a degree) to degrees
|
|
12
18
|
*
|
|
@@ -14,7 +20,7 @@ import { findByFullName, findChild, getAttribute, getChildElements, parseNumeric
|
|
|
14
20
|
* @returns Rotation in degrees
|
|
15
21
|
*/
|
|
16
22
|
function rotToDegrees(rot) {
|
|
17
|
-
if (
|
|
23
|
+
if (rot === null || rot === void 0) return;
|
|
18
24
|
const val = Number.parseInt(rot, 10);
|
|
19
25
|
if (Number.isNaN(val)) return;
|
|
20
26
|
return val / 6e4;
|
|
@@ -64,6 +70,47 @@ function parseEffectExtent(effectExtent) {
|
|
|
64
70
|
};
|
|
65
71
|
}
|
|
66
72
|
/**
|
|
73
|
+
* The `a:ext` uri under which Word records that a drawing is decorative. The
|
|
74
|
+
* extension holds `<adec:decorative val="…"/>`; `CT_NonVisualDrawingProps` has
|
|
75
|
+
* no `@decorative` attribute for it to be written as.
|
|
76
|
+
*/
|
|
77
|
+
const DECORATIVE_EXTENSION_URI = "{C183D7F6-B498-43B3-948B-1728B52AA6E4}";
|
|
78
|
+
/** The namespace the decorative extension's element is bound to. */
|
|
79
|
+
const DECORATIVE_NAMESPACE = "http://schemas.microsoft.com/office/drawing/2017/decorative";
|
|
80
|
+
/**
|
|
81
|
+
* `wp:docPr`'s extension list is DrawingML's (`a:extLst` holding `a:ext`), in
|
|
82
|
+
* the Transitional or the Strict namespace. Matching on the local name alone
|
|
83
|
+
* would take an `extLst` some other namespace owns and replay its children
|
|
84
|
+
* inside an `a:extLst`, which is a different container than the source wrote.
|
|
85
|
+
*/
|
|
86
|
+
const DRAWINGML_NAMESPACE_URIS = /* @__PURE__ */ new Set(["http://schemas.openxmlformats.org/drawingml/2006/main", "http://purl.oclc.org/ooxml/drawingml/main"]);
|
|
87
|
+
/**
|
|
88
|
+
* Read the `wp:docPr` extension list.
|
|
89
|
+
*
|
|
90
|
+
* Only the decorative extension is modeled. The rest — a creation id, a
|
|
91
|
+
* local-DPI hint, whatever a later Word writes — are captured as they were
|
|
92
|
+
* written so the save path can put them back: an extension folio drops is a
|
|
93
|
+
* fact the document had and no longer does.
|
|
94
|
+
*/
|
|
95
|
+
const parseDocPropsExtensions = (docPr) => {
|
|
96
|
+
const extLst = findChildByNamespaceUri(docPr, DRAWINGML_NAMESPACE_URIS, "extLst");
|
|
97
|
+
if (!extLst) return { other: [] };
|
|
98
|
+
const result = { other: [] };
|
|
99
|
+
for (const ext of findChildrenByNamespaceUri(extLst, DRAWINGML_NAMESPACE_URIS, "ext")) {
|
|
100
|
+
if (getAttribute(ext, null, "uri")?.toUpperCase() !== "{C183D7F6-B498-43B3-948B-1728B52AA6E4}") {
|
|
101
|
+
result.other.push(captureVerbatimXml(ext));
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const flag = getChildElements(ext).find((child) => getLocalName(child.name) === "decorative" && getNamespaceUri(child) === "http://schemas.microsoft.com/office/drawing/2017/decorative");
|
|
105
|
+
if (!flag) {
|
|
106
|
+
result.other.push(captureVerbatimXml(ext));
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
result.decorative = parseOnOffValue(getAttribute(flag, null, "val")) ?? true;
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
67
114
|
* Parse document properties (wp:docPr)
|
|
68
115
|
*
|
|
69
116
|
* @param docPr - wp:docPr element
|
|
@@ -72,18 +119,17 @@ function parseEffectExtent(effectExtent) {
|
|
|
72
119
|
function parseDocProps(docPr) {
|
|
73
120
|
if (!docPr) return {};
|
|
74
121
|
const id = getAttribute(docPr, null, "id");
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const decorative = parseOnOffValue(getAttribute(docPr, null, "decorative")) === true;
|
|
122
|
+
const names = parseNonVisualDrawingNames(docPr);
|
|
123
|
+
const hidden = parseOnOffAttribute(docPr, null, "hidden");
|
|
124
|
+
const { decorative, other: docPrExtensions } = parseDocPropsExtensions(docPr);
|
|
79
125
|
const hlinkClickEl = findChild(docPr, "a", "hlinkClick");
|
|
80
126
|
const hlinkRId = hlinkClickEl ? getAttribute(hlinkClickEl, "r", "id") : null;
|
|
81
127
|
return {
|
|
82
128
|
...id != null ? { id } : {},
|
|
83
|
-
...
|
|
84
|
-
...
|
|
85
|
-
...
|
|
86
|
-
...
|
|
129
|
+
...names,
|
|
130
|
+
...decorative === void 0 ? {} : { decorative },
|
|
131
|
+
...hidden === void 0 ? {} : { hidden },
|
|
132
|
+
...docPrExtensions.length > 0 ? { docPrExtensions } : {},
|
|
87
133
|
...hlinkRId != null ? { hlinkRId } : {}
|
|
88
134
|
};
|
|
89
135
|
}
|
|
@@ -92,15 +138,14 @@ function parseDocProps(docPr) {
|
|
|
92
138
|
*/
|
|
93
139
|
function parseTransform(xfrm) {
|
|
94
140
|
if (!xfrm) return;
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
if (rotation === void 0 && !flipH && !flipV) return;
|
|
141
|
+
const flipH = parseOnOffValue(getAttribute(xfrm, null, "flipH"));
|
|
142
|
+
const flipV = parseOnOffValue(getAttribute(xfrm, null, "flipV"));
|
|
143
|
+
const rotation = rotToDegrees(getAttribute(xfrm, null, "rot"));
|
|
144
|
+
if (rotation === void 0 && flipH === void 0 && flipV === void 0) return;
|
|
100
145
|
const transform = {};
|
|
101
146
|
if (rotation !== void 0) transform.rotation = rotation;
|
|
102
|
-
if (flipH) transform.flipH =
|
|
103
|
-
if (flipV) transform.flipV =
|
|
147
|
+
if (flipH !== void 0) transform.flipH = flipH;
|
|
148
|
+
if (flipV !== void 0) transform.flipV = flipV;
|
|
104
149
|
return transform;
|
|
105
150
|
}
|
|
106
151
|
/**
|
|
@@ -177,6 +222,24 @@ function parseImageOpacity(blip) {
|
|
|
177
222
|
if (amt === void 0 || amt >= 1e5) return;
|
|
178
223
|
return Math.max(0, amt / 1e5);
|
|
179
224
|
}
|
|
225
|
+
const parseLuminancePercent = (luminance, attribute) => {
|
|
226
|
+
const raw = getAttribute(luminance, null, attribute);
|
|
227
|
+
if (raw === null) return;
|
|
228
|
+
const percent = percentageSpelling(raw) ?? (FIXED_PERCENTAGE.test(raw.trim()) ? Number(raw) / 1e3 : void 0);
|
|
229
|
+
return percent === void 0 || !Number.isFinite(percent) ? void 0 : normalizeImageLuminancePercent(percent);
|
|
230
|
+
};
|
|
231
|
+
/** Parse DrawingML `a:lum` into signed percentage values, preserving explicit zeroes. */
|
|
232
|
+
function parseImageLuminance(blip) {
|
|
233
|
+
const luminance = findChildByNamespaceUri(blip, DRAWINGML_MAIN_NAMESPACE_URIS, "lum");
|
|
234
|
+
if (!luminance) return;
|
|
235
|
+
const brightness = parseLuminancePercent(luminance, "bright");
|
|
236
|
+
const contrast = parseLuminancePercent(luminance, "contrast");
|
|
237
|
+
if (brightness === void 0 && contrast === void 0) return;
|
|
238
|
+
return {
|
|
239
|
+
...brightness === void 0 ? {} : { brightness },
|
|
240
|
+
...contrast === void 0 ? {} : { contrast }
|
|
241
|
+
};
|
|
242
|
+
}
|
|
180
243
|
/**
|
|
181
244
|
* Extract rId from a:blip element.
|
|
182
245
|
*
|
|
@@ -308,6 +371,7 @@ function parseInline(inlineEl, rels, media) {
|
|
|
308
371
|
const rId = extractBlipRId(blip);
|
|
309
372
|
const crop = parseImageCrop(blipFill);
|
|
310
373
|
const opacity = parseImageOpacity(blip);
|
|
374
|
+
const effects = parseImageLuminance(blip);
|
|
311
375
|
const imageData = resolveImageData(rId, rels, media);
|
|
312
376
|
const transform = parseTransform(findPictureTransform(inlineEl));
|
|
313
377
|
const distT = parseNumericAttribute(inlineEl, null, "distT") ?? void 0;
|
|
@@ -329,7 +393,9 @@ function parseInline(inlineEl, rels, media) {
|
|
|
329
393
|
if (props.name !== void 0) image.docPrName = props.name;
|
|
330
394
|
if (props.alt !== void 0) image.alt = props.alt;
|
|
331
395
|
if (props.title !== void 0) image.title = props.title;
|
|
332
|
-
if (props.decorative) image.decorative =
|
|
396
|
+
if (props.decorative !== void 0) image.decorative = props.decorative;
|
|
397
|
+
if (props.hidden !== void 0) image.hidden = props.hidden;
|
|
398
|
+
if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
|
|
333
399
|
const safeSrc = sanitizeImageSrc(imageData.src);
|
|
334
400
|
if (safeSrc) image.src = safeSrc;
|
|
335
401
|
if (imageData.mimeType) image.mimeType = imageData.mimeType;
|
|
@@ -338,6 +404,7 @@ function parseInline(inlineEl, rels, media) {
|
|
|
338
404
|
if (transform) image.transform = transform;
|
|
339
405
|
if (crop) image.crop = crop;
|
|
340
406
|
if (opacity !== void 0) image.opacity = opacity;
|
|
407
|
+
if (effects !== void 0) image.effects = effects;
|
|
341
408
|
if (frameLocks) image.frameLocks = frameLocks;
|
|
342
409
|
const hlink = resolveRelationshipIdOfType(rels, props.hlinkRId, RELATIONSHIP_TYPES.hyperlink);
|
|
343
410
|
if (hlink.status === "resolved") {
|
|
@@ -390,6 +457,7 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
390
457
|
const rId = extractBlipRId(blip);
|
|
391
458
|
const crop = parseImageCrop(blipFill);
|
|
392
459
|
const opacity = parseImageOpacity(blip);
|
|
460
|
+
const effects = parseImageLuminance(blip);
|
|
393
461
|
const imageData = resolveImageData(rId, rels, media);
|
|
394
462
|
const transform = parseTransform(findPictureTransform(anchorEl));
|
|
395
463
|
const image = {
|
|
@@ -402,7 +470,9 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
402
470
|
if (props.name !== void 0) image.docPrName = props.name;
|
|
403
471
|
if (props.alt !== void 0) image.alt = props.alt;
|
|
404
472
|
if (props.title !== void 0) image.title = props.title;
|
|
405
|
-
if (props.decorative) image.decorative =
|
|
473
|
+
if (props.decorative !== void 0) image.decorative = props.decorative;
|
|
474
|
+
if (props.hidden !== void 0) image.hidden = props.hidden;
|
|
475
|
+
if (props.docPrExtensions !== void 0) image.docPrExtensions = props.docPrExtensions;
|
|
406
476
|
const safeSrc = sanitizeImageSrc(imageData.src);
|
|
407
477
|
if (safeSrc) image.src = safeSrc;
|
|
408
478
|
if (imageData.mimeType) image.mimeType = imageData.mimeType;
|
|
@@ -412,6 +482,7 @@ function parseAnchor(anchorEl, rels, media) {
|
|
|
412
482
|
if (transform) image.transform = transform;
|
|
413
483
|
if (crop) image.crop = crop;
|
|
414
484
|
if (opacity !== void 0) image.opacity = opacity;
|
|
485
|
+
if (effects !== void 0) image.effects = effects;
|
|
415
486
|
if (frameLocks) image.frameLocks = frameLocks;
|
|
416
487
|
if (layoutInCell !== void 0) image.layoutInCell = layoutInCell;
|
|
417
488
|
if (allowOverlap !== void 0) image.allowOverlap = allowOverlap;
|
|
@@ -537,4 +608,4 @@ function needsTextWrapping(image) {
|
|
|
537
608
|
].includes(image.wrap.type);
|
|
538
609
|
}
|
|
539
610
|
//#endregion
|
|
540
|
-
export { getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
611
|
+
export { DECORATIVE_EXTENSION_URI, DECORATIVE_NAMESPACE, getImageDimensionsPx, getImageHeightPx, getImageWidthPx, getWrapDistancesPx, hasAltText, isBehindText, isDecorativeImage, isFloatingImage, isInFrontOfText, isInlineImage, needsTextWrapping, parseDrawing, parseImage, resolveImageData };
|
|
@@ -12,7 +12,20 @@ declare const isDrawingRawXmlMode: (value: unknown) => value is document_d_expor
|
|
|
12
12
|
declare const EDITED_PREVIEW_FINGERPRINT = "editedPreview";
|
|
13
13
|
/** Fingerprints modeled image fields which make raw DrawingML stale when edited. */
|
|
14
14
|
declare const imageRawXmlFingerprint: (image: document_d_exports.Image) => string;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Whether the serializer writes the captured raw XML back.
|
|
17
|
+
*
|
|
18
|
+
* For an unclassified drawing the capture is a cache of the model, so it
|
|
19
|
+
* replays only while the two agree. For a classified one the capture *is* the
|
|
20
|
+
* drawing: a preserve-only drawing has a placeholder image, and a preview-only
|
|
21
|
+
* group has a raster render of shapes the model cannot hold. Regenerating
|
|
22
|
+
* either writes something the source never contained — for the group, at best
|
|
23
|
+
* the one child picture the rasterizer saw first under that child's
|
|
24
|
+
* relationship, in place of the whole group. So a classified capture is always
|
|
25
|
+
* written back; a stale fingerprint means the edit that made it stale is lost,
|
|
26
|
+
* which {@link classifyDrawingSafety} reports as `opaque`, and never that
|
|
27
|
+
* folio may build a replacement.
|
|
28
|
+
*/
|
|
16
29
|
declare const canReplayEditableImageRawXml: (drawing: document_d_exports.DrawingContent) => boolean;
|
|
17
30
|
/**
|
|
18
31
|
* What a drawing costs the document when Folio writes it back.
|