@stll/folio-core 0.43.0 → 0.44.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/headless.js +6 -5
- package/dist/ai-edits/index.d.ts +2 -2
- package/dist/ai-edits/index.js +2 -2
- package/dist/ai-edits/snapshot.js +13 -9
- package/dist/compare/content-alignment.js +16 -1
- package/dist/compare/inline-atoms.js +1 -1
- package/dist/compare/style-resources.js +6 -0
- package/dist/docx/appVersionNormalization.d.ts +0 -18
- package/dist/docx/blockContentParser.js +8 -0
- package/dist/docx/blockRangeMarkers.d.ts +36 -0
- package/dist/docx/blockRangeMarkers.js +59 -0
- package/dist/docx/bookmarkParser.d.ts +2 -20
- package/dist/docx/bookmarkParser.js +6 -30
- package/dist/docx/borderParser.d.ts +13 -0
- package/dist/docx/borderParser.js +71 -0
- package/dist/docx/builtInStyles.d.ts +165 -0
- package/dist/docx/builtInStyles.js +239 -0
- package/dist/docx/commentIdNormalization.d.ts +3 -1
- package/dist/docx/commentIdNormalization.js +18 -1
- package/dist/docx/commentParser.d.ts +2 -1
- package/dist/docx/commentParser.js +34 -7
- package/dist/docx/commentReferenceNormalization.d.ts +4 -1
- package/dist/docx/commentReferenceNormalization.js +23 -14
- package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
- package/dist/docx/danglingRelationshipReferences.js +30 -0
- package/dist/docx/defaultParagraphStyle.d.ts +18 -1
- package/dist/docx/defaultParagraphStyle.js +23 -1
- package/dist/docx/documentParser.d.ts +2 -1
- package/dist/docx/documentParser.js +2 -2
- package/dist/docx/drawingUtils.d.ts +8 -1
- package/dist/docx/drawingUtils.js +12 -3
- package/dist/docx/fieldParser.js +3 -5
- package/dist/docx/footnoteParser.d.ts +3 -2
- package/dist/docx/footnoteParser.js +19 -4
- package/dist/docx/groupDrawingParser.js +1 -1
- package/dist/docx/headerFooterRefParser.d.ts +4 -3
- package/dist/docx/headerFooterRefParser.js +42 -12
- package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
- package/dist/docx/headerFooterReferenceNormalization.js +5 -1
- package/dist/docx/hyperlinkParser.js +11 -15
- package/dist/docx/imageParser.d.ts +1 -1
- package/dist/docx/imageParser.js +22 -18
- package/dist/docx/imageRawXml.js +5 -5
- package/dist/docx/markupRangeMarker.d.ts +15 -0
- package/dist/docx/markupRangeMarker.js +44 -0
- package/dist/docx/noteReferenceStyles.d.ts +29 -0
- package/dist/docx/noteReferenceStyles.js +70 -0
- package/dist/docx/numberingReferenceNormalization.d.ts +4 -1
- package/dist/docx/numberingReferenceNormalization.js +20 -1
- package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
- package/dist/docx/paragraphParser.js +66 -99
- package/dist/docx/paragraphPropertySource.js +1 -0
- package/dist/docx/paragraphTraversal.d.ts +37 -1
- package/dist/docx/paragraphTraversal.js +84 -1
- package/dist/docx/parseContext.d.ts +37 -0
- package/dist/docx/parseContext.js +67 -0
- package/dist/docx/parseWarningMessage.d.ts +6 -0
- package/dist/docx/parseWarningMessage.js +44 -0
- package/dist/docx/parser.js +81 -27
- package/dist/docx/relsParser.d.ts +28 -11
- package/dist/docx/relsParser.js +26 -13
- package/dist/docx/revisionIdNormalization.js +81 -7
- package/dist/docx/rezip.js +63 -22
- package/dist/docx/runConsolidator.js +1 -2
- package/dist/docx/runParser.d.ts +8 -1
- package/dist/docx/runParser.js +30 -48
- package/dist/docx/sectionParser.d.ts +2 -1
- package/dist/docx/sectionParser.js +21 -65
- package/dist/docx/serializer/borderSerializer.d.ts +1 -2
- package/dist/docx/serializer/commentSerializer.js +22 -9
- package/dist/docx/serializer/documentSerializer.d.ts +1 -5
- package/dist/docx/serializer/documentSerializer.js +6 -16
- package/dist/docx/serializer/headerFooterSerializer.js +5 -0
- package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
- package/dist/docx/serializer/markupRangeAttributes.js +24 -0
- package/dist/docx/serializer/noteSerializer.js +5 -0
- package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
- package/dist/docx/serializer/paragraphSerializer.js +29 -35
- package/dist/docx/serializer/runSerializer.js +13 -7
- package/dist/docx/serializer/tableSerializer.js +28 -13
- package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
- package/dist/docx/server/build.js +8 -1
- package/dist/docx/server/createBilingualDocument.js +10 -18
- package/dist/docx/server/extractDocxText.js +3 -4
- package/dist/docx/shadingParser.d.ts +6 -0
- package/dist/docx/shadingParser.js +32 -0
- package/dist/docx/shapeParser.js +3 -3
- package/dist/docx/styleParser.js +13 -87
- package/dist/docx/styleReferenceResolution.d.ts +36 -0
- package/dist/docx/styleReferenceResolution.js +51 -0
- package/dist/docx/tableLook.d.ts +57 -0
- package/dist/docx/tableLook.js +63 -0
- package/dist/docx/tableParser.d.ts +7 -9
- package/dist/docx/tableParser.js +64 -110
- package/dist/docx/textBoxParser.js +4 -4
- package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
- package/dist/docx/trackedMoveRangeNormalization.js +11 -21
- package/dist/docx/transitionalSpelling.d.ts +13 -2
- package/dist/docx/transitionalSpelling.js +23 -1
- package/dist/docx/verbatimCapture.js +4 -11
- package/dist/docx/vmlImageParser.js +2 -2
- package/dist/docx/watermarkParser.js +2 -2
- package/dist/docx/xmlParser.d.ts +22 -32
- package/dist/docx/xmlParser.js +36 -21
- package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
- package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
- package/dist/internal/paragraphFormattingSerialization.js +26 -6
- package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
- package/dist/layout-engine/index.d.ts +2 -2
- package/dist/layout-engine/index.js +2 -2
- package/dist/layout-engine/measure/measureBlocks.js +1 -6
- package/dist/layout-engine/types.d.ts +8 -2
- package/dist/layout-engine/types.js +35 -2
- package/dist/markdown/index.js +1 -1
- package/dist/markdown/internals.d.ts +6 -1
- package/dist/markdown/internals.js +14 -1
- package/dist/markdown/renderBlock.js +35 -21
- package/dist/markdown/renderParagraph.js +14 -5
- package/dist/markdown/renderRuns.js +4 -3
- package/dist/markdown/renderTable.js +4 -3
- package/dist/markdown/trailers.js +41 -7
- package/dist/markdown/types.d.ts +3 -7
- package/dist/prosemirror/attrs/index.js +2 -5
- package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
- package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
- package/dist/prosemirror/commands/index.d.ts +3 -3
- package/dist/prosemirror/commands/index.js +2 -2
- package/dist/prosemirror/commands/paragraph.d.ts +3 -3
- package/dist/prosemirror/commands/paragraph.js +2 -2
- package/dist/prosemirror/commentIdAllocator.js +2 -7
- package/dist/prosemirror/conversion/fromProseDoc.js +129 -40
- package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
- package/dist/prosemirror/conversion/toProseDoc.js +375 -316
- package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
- package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
- package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
- package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
- package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
- package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
- package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
- package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
- package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
- package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
- package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
- package/dist/prosemirror/extensions/types.d.ts +2 -2
- package/dist/prosemirror/index.d.ts +3 -3
- package/dist/prosemirror/index.js +3 -3
- package/dist/prosemirror/insertOperations.d.ts +9 -2
- package/dist/prosemirror/insertOperations.js +9 -4
- package/dist/prosemirror/paragraphFormattingProvenance.d.ts +159 -0
- package/dist/prosemirror/paragraphFormattingProvenance.js +106 -0
- package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
- package/dist/prosemirror/plugins/documentStyles.js +11 -1
- package/dist/prosemirror/plugins/index.d.ts +2 -2
- package/dist/prosemirror/plugins/index.js +2 -2
- package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
- package/dist/prosemirror/plugins/revisionIds.js +21 -6
- package/dist/prosemirror/runFormattingReconciliation.js +3 -2
- package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
- package/dist/prosemirror/schema/nodes.d.ts +31 -0
- package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
- package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
- package/dist/prosemirror/styles/styleResolver.js +12 -0
- package/dist/style-engine/styleEngine.d.ts +3 -0
- package/dist/style-engine/styleEngine.js +3 -0
- package/dist/style-sets/extract.js +1 -23
- package/dist/style-sets/stellaStyle.js +46 -39
- package/dist/style-sets/styleSetNormalization.d.ts +19 -0
- package/dist/style-sets/styleSetNormalization.js +99 -0
- package/dist/types/content.d.ts +2 -2
- package/dist/utils/createDocument.js +145 -20
- package/dist/utils/headingCollector.d.ts +8 -5
- package/dist/utils/headingCollector.js +23 -25
- package/dist/utils/tableOfContentsStyle.js +9 -2
- package/package.json +2 -2
- package/dist/docx/textWhitespace.d.ts +0 -4
- package/dist/docx/textWhitespace.js +0 -4
- package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
- package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
- package/dist/markdown/headings.d.ts +0 -13
- package/dist/markdown/headings.js +0 -20
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withBlockRangeMarkers } from "../blockRangeMarkers.js";
|
|
1
2
|
import { serializeBlockSdt } from "./blockSdtSerializer.js";
|
|
2
3
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
3
4
|
import { serializePartElement } from "./partNamespaces.js";
|
|
@@ -38,6 +39,10 @@ const serializeNotePart = (elementName, body) => "<?xml version=\"1.0\" encoding
|
|
|
38
39
|
* note body.
|
|
39
40
|
*/
|
|
40
41
|
function serializeBlock(block) {
|
|
42
|
+
return withBlockRangeMarkers(block, serializeBlockBody(block));
|
|
43
|
+
}
|
|
44
|
+
/** The block itself, without the range markers that stood around it. */
|
|
45
|
+
function serializeBlockBody(block) {
|
|
41
46
|
if (block.type === "paragraph") return serializeParagraph(block);
|
|
42
47
|
if (block.type === "table") return serializeTable(block, serializeParagraph);
|
|
43
48
|
return serializeBlockSdt(block, serializeBlock);
|
|
@@ -23,10 +23,6 @@ declare function hasParagraphContent(paragraph: document_d_exports.Paragraph): b
|
|
|
23
23
|
* Check if a paragraph has formatting
|
|
24
24
|
*/
|
|
25
25
|
declare function hasParagraphFormatting(paragraph: document_d_exports.Paragraph): boolean;
|
|
26
|
-
/**
|
|
27
|
-
* Get plain text from a paragraph (for comparison/debugging)
|
|
28
|
-
*/
|
|
29
|
-
declare function getParagraphPlainText(paragraph: document_d_exports.Paragraph): string;
|
|
30
26
|
/**
|
|
31
27
|
* Create an empty paragraph
|
|
32
28
|
*/
|
|
@@ -44,4 +40,4 @@ declare function isListParagraph(paragraph: document_d_exports.Paragraph): boole
|
|
|
44
40
|
*/
|
|
45
41
|
declare function getListLevel(paragraph: document_d_exports.Paragraph): number;
|
|
46
42
|
//#endregion
|
|
47
|
-
export { createEmptyParagraph, createTextParagraph, getListLevel,
|
|
43
|
+
export { createEmptyParagraph, createTextParagraph, getListLevel, hasParagraphContent, hasParagraphFormatting, isListParagraph, serializeParagraph, serializeParagraphFormatting, serializeParagraphs };
|
|
@@ -5,6 +5,7 @@ import { DATE_UTC_ATTRIBUTE } from "../trackedChangeInfo.js";
|
|
|
5
5
|
import { toTransitionalNamespaceUri } from "../transitionalSpelling.js";
|
|
6
6
|
import { captureVerbatimXml, sanitizeCapturedXmlElement } from "../verbatimCapture.js";
|
|
7
7
|
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, cloneElement, getChildElements, getLocalName, parseXml } from "../xmlParser.js";
|
|
8
|
+
import { bookmarkRangeAttributes, markupRangeAttributes, moveBookmarkAttributes } from "./markupRangeAttributes.js";
|
|
8
9
|
import { serializeRun } from "./runSerializer.js";
|
|
9
10
|
import { serializeSectionProperties } from "./sectionPropertiesSerializer.js";
|
|
10
11
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
@@ -21,13 +22,20 @@ function serializeParagraphMarkChange(mark) {
|
|
|
21
22
|
return `<w:${mark.kind} ${attrs}/>`;
|
|
22
23
|
}
|
|
23
24
|
const RESERVED_PARAGRAPH_PROPERTY_CHILDREN = /* @__PURE__ */ new Set(["pPrChange", "sectPr"]);
|
|
25
|
+
/**
|
|
26
|
+
* Revision records a captured `w:pPr` may not carry into a replay.
|
|
27
|
+
*
|
|
28
|
+
* `w:numberingChange` is not among them: the model holds it
|
|
29
|
+
* (`ParagraphFormatting.numberingChangeXml`) and the serializer writes it
|
|
30
|
+
* back, so both paths keep it. Refusing the capture used to force a rebuild
|
|
31
|
+
* that could not write it, which turned a replay gate into a lost revision.
|
|
32
|
+
*/
|
|
24
33
|
const RESERVED_PARAGRAPH_CAPTURE_CHILDREN = /* @__PURE__ */ new Set([
|
|
25
34
|
...RESERVED_PARAGRAPH_PROPERTY_CHILDREN,
|
|
26
35
|
...PARAGRAPH_MARK_CHANGE_KINDS,
|
|
27
36
|
"cellDel",
|
|
28
37
|
"cellIns",
|
|
29
38
|
"cellMerge",
|
|
30
|
-
"numberingChange",
|
|
31
39
|
"rPrChange",
|
|
32
40
|
"tblGridChange",
|
|
33
41
|
"tblPrChange",
|
|
@@ -119,7 +127,11 @@ const PARAGRAPH_MARK_BASE_CHILDREN = /* @__PURE__ */ new Set([
|
|
|
119
127
|
"oMath"
|
|
120
128
|
]);
|
|
121
129
|
const PARAGRAPH_NESTED_PROPERTY_CHILDREN = /* @__PURE__ */ new Map([
|
|
122
|
-
["numPr", /* @__PURE__ */ new Set([
|
|
130
|
+
["numPr", /* @__PURE__ */ new Set([
|
|
131
|
+
"ilvl",
|
|
132
|
+
"numId",
|
|
133
|
+
"numberingChange"
|
|
134
|
+
])],
|
|
123
135
|
["pBdr", /* @__PURE__ */ new Set([
|
|
124
136
|
"top",
|
|
125
137
|
"left",
|
|
@@ -344,16 +356,13 @@ function serializeHyperlink(hyperlink) {
|
|
|
344
356
|
* Serialize bookmark start (w:bookmarkStart)
|
|
345
357
|
*/
|
|
346
358
|
function serializeBookmarkStart(bookmark) {
|
|
347
|
-
|
|
348
|
-
if (bookmark.colFirst !== void 0) attrs.push(`w:colFirst="${bookmark.colFirst}"`);
|
|
349
|
-
if (bookmark.colLast !== void 0) attrs.push(`w:colLast="${bookmark.colLast}"`);
|
|
350
|
-
return `<w:bookmarkStart ${attrs.join(" ")}/>`;
|
|
359
|
+
return `<w:bookmarkStart ${bookmarkRangeAttributes(bookmark).join(" ")}/>`;
|
|
351
360
|
}
|
|
352
361
|
/**
|
|
353
362
|
* Serialize bookmark end (w:bookmarkEnd)
|
|
354
363
|
*/
|
|
355
364
|
function serializeBookmarkEnd(bookmark) {
|
|
356
|
-
return `<w:bookmarkEnd
|
|
365
|
+
return `<w:bookmarkEnd ${markupRangeAttributes(bookmark).join(" ")}/>`;
|
|
357
366
|
}
|
|
358
367
|
/** Serialize a simple field without changing its authored OOXML field form. */
|
|
359
368
|
function serializeSimpleField(field) {
|
|
@@ -471,7 +480,7 @@ function serializeInlineSdt(sdt) {
|
|
|
471
480
|
})}${props.rawEndPropertiesXml && isSingleWellFormedElement(props.rawEndPropertiesXml, "sdtEndPr") ? props.rawEndPropertiesXml : ""}<w:sdtContent>${contentXml}</w:sdtContent></w:sdt>`;
|
|
472
481
|
}
|
|
473
482
|
function serializeMoveRangeStart(tag, marker) {
|
|
474
|
-
return `<w:${tag} ${
|
|
483
|
+
return `<w:${tag} ${moveBookmarkAttributes(marker).join(" ")}/>`;
|
|
475
484
|
}
|
|
476
485
|
/**
|
|
477
486
|
* Serialize a tracked change wrapper (ins/del/moveFrom/moveTo)
|
|
@@ -560,17 +569,24 @@ function serializeParagraphContent(content, explicitCommentReferenceIds) {
|
|
|
560
569
|
case "simpleField": return serializeSimpleField(content);
|
|
561
570
|
case "complexField": return serializeComplexField(content);
|
|
562
571
|
case "inlineSdt": return serializeInlineSdt(content);
|
|
563
|
-
case "commentRangeStart": return `<w:commentRangeStart
|
|
564
|
-
case "commentRangeEnd":
|
|
572
|
+
case "commentRangeStart": return `<w:commentRangeStart ${markupRangeAttributes(content).join(" ")}/>`;
|
|
573
|
+
case "commentRangeEnd": {
|
|
574
|
+
const end = `<w:commentRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
575
|
+
return explicitCommentReferenceIds.has(content.id) ? end : `${end}${serializeCommentReferenceRun(content.id)}`;
|
|
576
|
+
}
|
|
565
577
|
case "commentReference": return serializeCommentReferenceRun(content.id);
|
|
566
578
|
case "insertion": return serializeTrackedChange("ins", content);
|
|
567
579
|
case "deletion": return serializeTrackedChange("del", content);
|
|
568
580
|
case "moveFrom": return serializeTrackedChange("moveFrom", content);
|
|
569
581
|
case "moveTo": return serializeTrackedChange("moveTo", content);
|
|
570
582
|
case "moveFromRangeStart": return serializeMoveRangeStart("moveFromRangeStart", content);
|
|
571
|
-
case "moveFromRangeEnd": return `<w:moveFromRangeEnd
|
|
583
|
+
case "moveFromRangeEnd": return `<w:moveFromRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
572
584
|
case "moveToRangeStart": return serializeMoveRangeStart("moveToRangeStart", content);
|
|
573
|
-
case "moveToRangeEnd": return `<w:moveToRangeEnd
|
|
585
|
+
case "moveToRangeEnd": return `<w:moveToRangeEnd ${markupRangeAttributes(content).join(" ")}/>`;
|
|
586
|
+
case "bidiWrapper": {
|
|
587
|
+
const tag = content.control === "override" ? "bdo" : "dir";
|
|
588
|
+
return `<w:${tag}${content.direction === void 0 ? "" : ` w:val="${escapeXml(content.direction)}"`}>${content.content.map((child) => serializeParagraphContent(child, explicitCommentReferenceIds)).join("")}</w:${tag}>`;
|
|
589
|
+
}
|
|
574
590
|
case "mathEquation": return content.ommlXml || "";
|
|
575
591
|
default: return "";
|
|
576
592
|
}
|
|
@@ -657,28 +673,6 @@ function hasParagraphFormatting(paragraph) {
|
|
|
657
673
|
return paragraph.formatting !== void 0 && Object.keys(paragraph.formatting).length > 0;
|
|
658
674
|
}
|
|
659
675
|
/**
|
|
660
|
-
* Get plain text from a paragraph (for comparison/debugging)
|
|
661
|
-
*/
|
|
662
|
-
function getParagraphPlainText(paragraph) {
|
|
663
|
-
const texts = [];
|
|
664
|
-
for (const content of paragraph.content) if (content.type === "run") {
|
|
665
|
-
for (const item of content.content) if (item.type === "text") texts.push(item.text);
|
|
666
|
-
else if (item.type === "tab") texts.push(" ");
|
|
667
|
-
else if (item.type === "break") texts.push("\n");
|
|
668
|
-
} else if (content.type === "hyperlink") {
|
|
669
|
-
for (const child of content.children) if (child.type === "run") {
|
|
670
|
-
for (const item of child.content) if (item.type === "text") texts.push(item.text);
|
|
671
|
-
}
|
|
672
|
-
} else if (content.type === "simpleField" || content.type === "inlineSdt" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo") {
|
|
673
|
-
for (const item of content.content) if (item.type === "run") {
|
|
674
|
-
for (const subItem of item.content) if (subItem.type === "text") texts.push(subItem.text);
|
|
675
|
-
}
|
|
676
|
-
} else if (content.type === "complexField") {
|
|
677
|
-
for (const run of content.fieldResult) for (const item of run.content) if (item.type === "text") texts.push(item.text);
|
|
678
|
-
}
|
|
679
|
-
return texts.join("");
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
676
|
* Create an empty paragraph
|
|
683
677
|
*/
|
|
684
678
|
function createEmptyParagraph(formatting) {
|
|
@@ -718,4 +712,4 @@ function getListLevel(paragraph) {
|
|
|
718
712
|
return paragraph.formatting?.numPr?.ilvl ?? -1;
|
|
719
713
|
}
|
|
720
714
|
//#endregion
|
|
721
|
-
export { createEmptyParagraph, createTextParagraph, getListLevel,
|
|
715
|
+
export { createEmptyParagraph, createTextParagraph, getListLevel, hasParagraphContent, hasParagraphFormatting, isListParagraph, serializeParagraph, serializeParagraphFormatting, serializeParagraphs };
|
|
@@ -2,13 +2,13 @@ import { isValidHexColor } from "../../utils/colorResolver.js";
|
|
|
2
2
|
import { THEME_COLOR_TO_DRAWING_SCHEME } from "../drawingUtils.js";
|
|
3
3
|
import { serializeGraphicFrameLocks } from "../graphicFrameLocks.js";
|
|
4
4
|
import { canReplayEditableImageRawXml } from "../imageRawXml.js";
|
|
5
|
-
import { requiresXmlSpacePreserve } from "../textWhitespace.js";
|
|
6
5
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
7
6
|
import { serializeTable } from "./tableSerializer.js";
|
|
8
7
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
9
8
|
import { getSingularRunPropertyChange, serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
|
|
10
9
|
import { escapeXml, intAttr } from "./xmlUtils.js";
|
|
11
10
|
import { panic } from "better-result";
|
|
11
|
+
import { requiresXmlSpacePreserve } from "@stll/docx-core";
|
|
12
12
|
//#region src/docx/serializer/runSerializer.ts
|
|
13
13
|
/**
|
|
14
14
|
* Run Serializer - Serialize runs to OOXML XML
|
|
@@ -59,7 +59,7 @@ function serializeRunProperties(formatting, propertyChanges) {
|
|
|
59
59
|
* Serialize text content (w:t)
|
|
60
60
|
*/
|
|
61
61
|
function serializeTextContent(content) {
|
|
62
|
-
return `<w:t${
|
|
62
|
+
return `<w:t${requiresXmlSpacePreserve(content.text) ? " xml:space=\"preserve\"" : ""}>${escapeXml(content.text)}</w:t>`;
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
65
|
* Serialize tab content (w:tab)
|
|
@@ -88,7 +88,7 @@ function serializeBreakContent(content) {
|
|
|
88
88
|
* Serialize symbol content (w:sym)
|
|
89
89
|
*/
|
|
90
90
|
function serializeSymbolContent(content) {
|
|
91
|
-
return `<w:sym w:font="${escapeXml(content.font)}" w:char="${escapeXml(content.char)}"/>`;
|
|
91
|
+
return `<w:sym${content.font === "" ? "" : ` w:font="${escapeXml(content.font)}"`}${content.char === "" ? "" : ` w:char="${escapeXml(content.char)}"`}/>`;
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* Serialize footnote/endnote reference
|
|
@@ -206,11 +206,17 @@ function serializeWrap(wrap) {
|
|
|
206
206
|
case "inline": return "<wp:wrapNone/>";
|
|
207
207
|
}
|
|
208
208
|
}
|
|
209
|
-
/**
|
|
210
|
-
|
|
209
|
+
/**
|
|
210
|
+
* Build the common a:graphic > pic:pic element for images.
|
|
211
|
+
*
|
|
212
|
+
* Takes the relationship id as a separate argument so the caller has to have
|
|
213
|
+
* one. There is no default: a picture written against an invented id binds to
|
|
214
|
+
* whichever relationship the part happens to hold under that name.
|
|
215
|
+
*/
|
|
216
|
+
function serializePicGraphic(image, imageRId, sharedId) {
|
|
211
217
|
const cx = image.size.width;
|
|
212
218
|
const cy = image.size.height;
|
|
213
|
-
const rId = escapeXml(
|
|
219
|
+
const rId = escapeXml(imageRId);
|
|
214
220
|
const id = sharedId;
|
|
215
221
|
const name = image.filename || `image${id}`;
|
|
216
222
|
let xfrmAttrs = "";
|
|
@@ -287,7 +293,7 @@ function serializeDrawingContent(content) {
|
|
|
287
293
|
const anchorDocPrAttrs = `id="${docPrId}" name="${escapeXml(docPrName)}"${docPrDescription}${docPrTitle}`;
|
|
288
294
|
const anchorDocPr = hlinkClick ? `<wp:docPr ${anchorDocPrAttrs}>${hlinkClick}</wp:docPr>` : `<wp:docPr ${anchorDocPrAttrs}/>`;
|
|
289
295
|
const graphicFramePr = serializeGraphicFrameLocks(image.frameLocks);
|
|
290
|
-
const graphic = serializePicGraphic(image, docPrId);
|
|
296
|
+
const graphic = image.rId === void 0 ? "" : serializePicGraphic(image, image.rId, docPrId);
|
|
291
297
|
if (!isFloating) return [
|
|
292
298
|
"<w:drawing>",
|
|
293
299
|
`<wp:inline${wrapDistanceAttrs}>`,
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { canonicalJson } from "../../utils/canonicalJson.js";
|
|
2
2
|
import { isValidHexColor } from "../../utils/colorResolver.js";
|
|
3
|
+
import { withBlockRangeMarkers } from "../blockRangeMarkers.js";
|
|
4
|
+
import { TABLE_LOOK_FLAGS } from "../tableLook.js";
|
|
3
5
|
import { parseTableCellProperties, parseTableGrid, parseTableProperties, parseTableRowProperties } from "../tableParser.js";
|
|
4
|
-
import {
|
|
6
|
+
import { sanitizeCapturedXmlElement } from "../verbatimCapture.js";
|
|
7
|
+
import { NAMESPACES, OOXML_NAMESPACE_SCOPE, parseXml } from "../xmlParser.js";
|
|
5
8
|
import { serializeBorder } from "./borderSerializer.js";
|
|
6
9
|
import { serializeTrackedChangeAttributes } from "./trackedChangeAttributes.js";
|
|
7
10
|
import { escapeXml, intAttr } from "./xmlUtils.js";
|
|
@@ -140,17 +143,22 @@ function serializeShading(shading) {
|
|
|
140
143
|
return `<w:shd ${attrs.join(" ")}/>`;
|
|
141
144
|
}
|
|
142
145
|
/**
|
|
143
|
-
* Serialize
|
|
146
|
+
* Serialize a `w:tblLook`: what the author wrote, in the order they wrote it.
|
|
147
|
+
*
|
|
148
|
+
* A flag is written when it was authored, true or false. Writing only the true
|
|
149
|
+
* ones drops an explicit `w:lastRow="0"`, and an absent flag is not an off one:
|
|
150
|
+
* it falls back to `w:val`'s bit, so the two spell different tables under the
|
|
151
|
+
* same table style. `w:val` leads, then the flags in `CT_TblLook` order, which
|
|
152
|
+
* is the order Word writes them.
|
|
144
153
|
*/
|
|
145
154
|
function serializeTableLook(look) {
|
|
146
155
|
if (!look) return "";
|
|
147
156
|
const attrs = [];
|
|
148
|
-
if (look.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (look.noVBand) attrs.push("w:noVBand=\"1\"");
|
|
157
|
+
if (look.val !== void 0) attrs.push(`w:val="${escapeXml(look.val)}"`);
|
|
158
|
+
for (const flag of TABLE_LOOK_FLAGS) {
|
|
159
|
+
const stated = look[flag];
|
|
160
|
+
if (stated !== void 0) attrs.push(`w:${flag}="${stated ? "1" : "0"}"`);
|
|
161
|
+
}
|
|
154
162
|
if (attrs.length === 0) return "";
|
|
155
163
|
return `<w:tblLook ${attrs.join(" ")}/>`;
|
|
156
164
|
}
|
|
@@ -344,17 +352,24 @@ function serializeTableGrid(table) {
|
|
|
344
352
|
if (gridSourceXml !== void 0) {
|
|
345
353
|
if (canonicalJson(parseTableGrid(parseXml(gridSourceXml, OOXML_NAMESPACE_SCOPE).elements?.[0] ?? null)) === canonicalJson(columnWidths)) return gridSourceXml;
|
|
346
354
|
}
|
|
347
|
-
|
|
355
|
+
const gridChange = replayableGridChangeXml(table.formatting?.gridChangeXml) ?? "";
|
|
356
|
+
if (columnWidths && columnWidths.length > 0) return `<w:tblGrid>${columnWidths.map((w) => `<w:gridCol w:w="${intAttr(w)}"/>`).join("")}${gridChange}</w:tblGrid>`;
|
|
348
357
|
const columns = gridColumnCount(table);
|
|
349
|
-
return columns === 0 ? "<w:tblGrid/>" : `<w:tblGrid>${"<w:gridCol/>".repeat(columns)}</w:tblGrid>`;
|
|
350
|
-
}
|
|
358
|
+
return columns === 0 && gridChange === "" ? "<w:tblGrid/>" : `<w:tblGrid>${"<w:gridCol/>".repeat(columns)}${gridChange}</w:tblGrid>`;
|
|
359
|
+
}
|
|
360
|
+
const GRID_CHANGE_ROOT_NAME = /* @__PURE__ */ new Set(["tblGridChange"]);
|
|
361
|
+
const WORDPROCESSINGML_NAMESPACE = /* @__PURE__ */ new Set([NAMESPACES.w]);
|
|
362
|
+
const replayableGridChangeXml = (gridChangeXml) => sanitizeCapturedXmlElement(gridChangeXml, {
|
|
363
|
+
allowedLocalNames: GRID_CHANGE_ROOT_NAME,
|
|
364
|
+
allowedNamespaceUris: WORDPROCESSINGML_NAMESPACE,
|
|
365
|
+
inheritedNamespaceScope: OOXML_NAMESPACE_SCOPE
|
|
366
|
+
});
|
|
351
367
|
/**
|
|
352
368
|
* Serialize cell content (paragraphs, nested tables)
|
|
353
369
|
*/
|
|
354
370
|
function serializeCellContent(content, serializeParagraph) {
|
|
355
371
|
const parts = [];
|
|
356
|
-
for (const item of content)
|
|
357
|
-
else parts.push(serializeTable(item, serializeParagraph));
|
|
372
|
+
for (const item of content) parts.push(withBlockRangeMarkers(item, item.type === "paragraph" ? serializeParagraph(item) : serializeTable(item, serializeParagraph)));
|
|
358
373
|
if (parts.length === 0) parts.push("<w:p/>");
|
|
359
374
|
return parts.join("");
|
|
360
375
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { document_d_exports } from "../../types/document.js";
|
|
2
2
|
//#region src/docx/serializer/textFormattingSerializer.d.ts
|
|
3
|
-
type ExhaustiveFields<Source, Classified extends keyof Source> = Exclude<keyof Source, Classified> extends never ? Source : never;
|
|
4
3
|
type ClassifiedShadingField = "color" | "fill" | "pattern";
|
|
5
|
-
type ExhaustiveShadingProperties = ExhaustiveFields<document_d_exports.ShadingProperties, ClassifiedShadingField>;
|
|
4
|
+
type ExhaustiveShadingProperties = document_d_exports.ExhaustiveFields<document_d_exports.ShadingProperties, ClassifiedShadingField>;
|
|
6
5
|
type ClassifiedTextFormattingField = "bold" | "boldCs" | "italic" | "italicCs" | "underline" | "strike" | "doubleStrike" | "vertAlign" | "smallCaps" | "allCaps" | "hidden" | "noProof" | "color" | "highlight" | "shading" | "fontSize" | "fontSizeCs" | "fontFamily" | "language" | "spacing" | "position" | "scale" | "kerning" | "effect" | "emphasisMark" | "emboss" | "imprint" | "outline" | "shadow" | "rtl" | "cs" | "styleId";
|
|
7
|
-
type ExhaustiveTextFormatting = ExhaustiveFields<document_d_exports.TextFormatting, ClassifiedTextFormattingField>;
|
|
6
|
+
type ExhaustiveTextFormatting = document_d_exports.ExhaustiveFields<document_d_exports.TextFormatting, ClassifiedTextFormattingField>;
|
|
8
7
|
/**
|
|
9
8
|
* Serialize shading properties (w:shd)
|
|
10
9
|
*/
|
|
@@ -26,7 +26,14 @@ const HEADING_LEVELS = [
|
|
|
26
26
|
5,
|
|
27
27
|
6
|
|
28
28
|
];
|
|
29
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* The heading levels a `TOC \o` field-argument may name (ECMA-376 17.16.5.68).
|
|
31
|
+
*
|
|
32
|
+
* `\o` selects by *style id* — "each integer corresponds to the style with a
|
|
33
|
+
* style ID of HeadingX" — not by outline level, which is what `\u` reads. The
|
|
34
|
+
* domain here is therefore the 1-9 of `Heading1`…`Heading9`, not the 0-8 of
|
|
35
|
+
* `w:outlineLvl`.
|
|
36
|
+
*/
|
|
30
37
|
const TOC_LEVEL_MIN = 1;
|
|
31
38
|
const TOC_LEVEL_MAX = 9;
|
|
32
39
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { deterministicHexId } from "../../utils/hexId.js";
|
|
2
|
+
import { createBuiltInStyleIndex, resolveHeadingLevel } from "../builtInStyles.js";
|
|
2
3
|
import { isNumberingReference } from "../numberingReference.js";
|
|
3
4
|
import { getParagraphText } from "../paragraphParser.js";
|
|
4
5
|
import { cloneParagraphWithoutPropertySource } from "../paragraphPropertySource.js";
|
|
@@ -77,6 +78,7 @@ function createBilingualDocument(source, options) {
|
|
|
77
78
|
const styles = source.package.styles;
|
|
78
79
|
const numbering = source.package.numbering;
|
|
79
80
|
const styleById = new Map((styles?.styles ?? []).map((style) => [style.styleId, style]));
|
|
81
|
+
const builtInStyles = createBuiltInStyleIndex(styleById.values(), styles?.docDefaults);
|
|
80
82
|
const blocks = flattenBlocks(source.package.document.content);
|
|
81
83
|
const cloner = createNumberingCloner({
|
|
82
84
|
numbering,
|
|
@@ -124,7 +126,7 @@ function createBilingualDocument(source, options) {
|
|
|
124
126
|
}
|
|
125
127
|
const { copy, ref } = copyParagraph(block);
|
|
126
128
|
rows.push({
|
|
127
|
-
kind: classifyParagraph(block, styleById),
|
|
129
|
+
kind: classifyParagraph(block, styleById, builtInStyles),
|
|
128
130
|
rowId: ref.targetParaId,
|
|
129
131
|
...ref
|
|
130
132
|
});
|
|
@@ -235,26 +237,15 @@ const isFieldOnlyParagraph = (paragraph) => {
|
|
|
235
237
|
* them would surface as a missing handle rather than as the rule it is.
|
|
236
238
|
*/
|
|
237
239
|
const isTranslatableParagraph = (paragraph, editableParagraphIds) => paragraph.paraId !== void 0 && editableParagraphIds.has(paragraph.paraId) && !isFieldOnlyParagraph(paragraph);
|
|
238
|
-
|
|
239
|
-
const HEADING_STYLE_PATTERN = /heading|nadpis|berschrift|titre|nag[łl]/iu;
|
|
240
|
-
const classifyParagraph = (paragraph, styleById) => {
|
|
240
|
+
const classifyParagraph = (paragraph, styleById, builtInStyles) => {
|
|
241
241
|
const formatting = paragraph.formatting;
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
242
|
+
if (resolveHeadingLevel({
|
|
243
|
+
outlineLevel: formatting?.outlineLevel,
|
|
244
|
+
styleId: formatting?.styleId
|
|
245
|
+
}, builtInStyles) !== void 0) return "heading";
|
|
246
246
|
if (effectiveNumPr(paragraph, styleById) !== void 0) return "listItem";
|
|
247
247
|
return "paragraph";
|
|
248
248
|
};
|
|
249
|
-
const resolveInheritedOutlineLevel = (style, styleById) => {
|
|
250
|
-
const seen = /* @__PURE__ */ new Set();
|
|
251
|
-
let current = style;
|
|
252
|
-
while (current && !seen.has(current.styleId)) {
|
|
253
|
-
seen.add(current.styleId);
|
|
254
|
-
if (current.pPr?.outlineLevel !== void 0) return current.pPr.outlineLevel;
|
|
255
|
-
current = current.basedOn ? styleById.get(current.basedOn) : void 0;
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
249
|
/** The numbering a paragraph renders with: direct `numPr`, else the style chain's. */
|
|
259
250
|
const effectiveNumPr = (paragraph, styleById) => {
|
|
260
251
|
const direct = paragraph.formatting?.numPr;
|
|
@@ -703,6 +694,7 @@ const createParaIdMinter = (taken) => {
|
|
|
703
694
|
*/
|
|
704
695
|
function readBilingualDocument(document, editableParagraphIds) {
|
|
705
696
|
const styleById = new Map((document.package.styles?.styles ?? []).map((style) => [style.styleId, style]));
|
|
697
|
+
const builtInStyles = createBuiltInStyleIndex(styleById.values(), document.package.styles?.docDefaults);
|
|
706
698
|
const rows = [];
|
|
707
699
|
let missingHandleCount = 0;
|
|
708
700
|
for (const block of flattenBlocks(document.package.document.content)) {
|
|
@@ -777,7 +769,7 @@ function readBilingualDocument(document, editableParagraphIds) {
|
|
|
777
769
|
if (targetMissing) missingHandleCount += 1;
|
|
778
770
|
if (sourceMissing || targetMissing) continue;
|
|
779
771
|
rows.push({
|
|
780
|
-
kind: classifyParagraph(source, styleById),
|
|
772
|
+
kind: classifyParagraph(source, styleById, builtInStyles),
|
|
781
773
|
rowId: target.paraId,
|
|
782
774
|
sourceParaId: source.paraId,
|
|
783
775
|
targetParaId: target.paraId,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { escapeTableCell } from "../../markdown/escape.js";
|
|
2
2
|
import { RELATIONSHIP_TYPES, parseRelationships } from "../relsParser.js";
|
|
3
|
-
import { findAllDeep, findDeep, getAttribute, getAttributeByNamespaceUri, getLocalName, getNamespaceUri, getTextContent, parseXml } from "../xmlParser.js";
|
|
3
|
+
import { findAllDeep, findDeep, getAttribute, getAttributeByNamespaceUri, getLocalName, getNamespaceUri, getTextContent, parseOnOffValue, parseXml } from "../xmlParser.js";
|
|
4
4
|
import { DocxArchiveError, loadDocxArchive } from "./boundedArchive.js";
|
|
5
5
|
//#region src/docx/server/extractDocxText.ts
|
|
6
6
|
const DOCUMENT_RELS_PATH = "word/_rels/document.xml.rels";
|
|
@@ -68,7 +68,7 @@ const readRunMetrics = (paragraph) => {
|
|
|
68
68
|
const properties = findWordChild(run, "rPr");
|
|
69
69
|
const boldProperty = findWordChild(properties, "b");
|
|
70
70
|
const boldValue = getWordAttribute(boldProperty, "val");
|
|
71
|
-
const bold = boldProperty !== null && boldValue
|
|
71
|
+
const bold = boldProperty !== null && (parseOnOffValue(boldValue) ?? true);
|
|
72
72
|
const sizeProperty = findWordChild(properties, "sz");
|
|
73
73
|
const sizeValue = getWordAttribute(sizeProperty, "val");
|
|
74
74
|
const parsedSize = sizeValue === null ? NaN : Number.parseInt(sizeValue, 10);
|
|
@@ -270,8 +270,7 @@ const readTableCell = (cell, { depth, budget }) => {
|
|
|
270
270
|
const declaresHeaderRow = (row) => {
|
|
271
271
|
const header = findWordChild(findWordChild(row, "trPr"), "tblHeader");
|
|
272
272
|
if (header === null) return false;
|
|
273
|
-
|
|
274
|
-
return value !== "0" && value !== "false";
|
|
273
|
+
return parseOnOffValue(getWordAttribute(header, "val")) ?? true;
|
|
275
274
|
};
|
|
276
275
|
const readRowGridOffset = (row, localName) => {
|
|
277
276
|
const properties = findWordChild(row, "trPr");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { document_d_exports } from "../types/document.js";
|
|
2
|
+
import { XmlElement } from "./xmlParser.js";
|
|
3
|
+
//#region src/docx/shadingParser.d.ts
|
|
4
|
+
declare function parseShading(shd: XmlElement | null): document_d_exports.ShadingProperties | undefined;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { parseShading };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { isValidHexColor } from "../utils/colorResolver.js";
|
|
2
|
+
import { ShadingPatternSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
|
|
3
|
+
import { getAttribute } from "./xmlParser.js";
|
|
4
|
+
//#region src/docx/shadingParser.ts
|
|
5
|
+
/** `ST_HexColor`'s reserved "let the consumer decide" token. */
|
|
6
|
+
const AUTOMATIC_COLOR = "auto";
|
|
7
|
+
const parseHexColor = (value) => {
|
|
8
|
+
if (value === AUTOMATIC_COLOR) return { auto: true };
|
|
9
|
+
if (value && isValidHexColor(value)) return { rgb: value };
|
|
10
|
+
};
|
|
11
|
+
function parseShading(shd) {
|
|
12
|
+
if (!shd) return;
|
|
13
|
+
const props = {};
|
|
14
|
+
const color = parseHexColor(getAttribute(shd, "w", "color"));
|
|
15
|
+
if (color) props.color = color;
|
|
16
|
+
const fill = parseHexColor(getAttribute(shd, "w", "fill"));
|
|
17
|
+
if (fill) props.fill = fill;
|
|
18
|
+
const themeFill = narrowEnum(getAttribute(shd, "w", "themeFill"), ThemeColorSlotSchema);
|
|
19
|
+
if (themeFill) {
|
|
20
|
+
props.fill ??= {};
|
|
21
|
+
props.fill.themeColor = themeFill;
|
|
22
|
+
}
|
|
23
|
+
const themeFillTint = getAttribute(shd, "w", "themeFillTint");
|
|
24
|
+
if (themeFillTint && props.fill) props.fill.themeTint = themeFillTint;
|
|
25
|
+
const themeFillShade = getAttribute(shd, "w", "themeFillShade");
|
|
26
|
+
if (themeFillShade && props.fill) props.fill.themeShade = themeFillShade;
|
|
27
|
+
const pattern = narrowEnum(getAttribute(shd, "w", "val"), ShadingPatternSchema);
|
|
28
|
+
if (pattern) props.pattern = pattern;
|
|
29
|
+
return Object.keys(props).length > 0 ? props : void 0;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { parseShading };
|
package/dist/docx/shapeParser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseAnchorPosition, parseAnchorWrap, parseFill, parseOutline } from "./drawingUtils.js";
|
|
2
2
|
import { ShapeTypeSchema, narrowEnum } from "./parserEnums.js";
|
|
3
|
-
import { findAllDeep, findChildByLocalName, findChildren, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
|
|
3
|
+
import { findAllDeep, findChildByLocalName, findChildren, getAttribute, getChildElements, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
|
|
4
4
|
//#region src/docx/shapeParser.ts
|
|
5
5
|
/** Convert OOXML rotation (1/60000ths of a degree) to degrees. */
|
|
6
6
|
function rotToDegrees(rot) {
|
|
@@ -26,8 +26,8 @@ function parseTransform(xfrm) {
|
|
|
26
26
|
height: parseNumericAttribute(ext, null, "cy") ?? 0
|
|
27
27
|
};
|
|
28
28
|
const rotation = rotToDegrees(getAttribute(xfrm, null, "rot"));
|
|
29
|
-
const flipH =
|
|
30
|
-
const flipV =
|
|
29
|
+
const flipH = parseOnOffAttribute(xfrm, null, "flipH") === true;
|
|
30
|
+
const flipV = parseOnOffAttribute(xfrm, null, "flipV") === true;
|
|
31
31
|
if (rotation === void 0 && !flipH && !flipV) return { size };
|
|
32
32
|
const transform = {};
|
|
33
33
|
if (rotation !== void 0) transform.rotation = rotation;
|