ooxml.js 1.3.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -4
- package/dist/index.cjs +1333 -136
- package/dist/index.d.cts +280 -131
- package/dist/index.d.ts +280 -131
- package/dist/index.js +1305 -124
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -28,14 +28,14 @@ const XmlPiSchema = zod.z.object({
|
|
|
28
28
|
target: zod.z.string(),
|
|
29
29
|
content: zod.z.string()
|
|
30
30
|
});
|
|
31
|
-
function isRecord$
|
|
31
|
+
function isRecord$2(value) {
|
|
32
32
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33
33
|
}
|
|
34
34
|
function isAttribute(value) {
|
|
35
|
-
return isRecord$
|
|
35
|
+
return isRecord$2(value) && typeof value.name === "string" && typeof value.value === "string";
|
|
36
36
|
}
|
|
37
37
|
function isXmlNode(value) {
|
|
38
|
-
if (!isRecord$
|
|
38
|
+
if (!isRecord$2(value)) return false;
|
|
39
39
|
const t = value.type;
|
|
40
40
|
if (t === "text" || t === "cdata" || t === "comment") return typeof value.value === "string";
|
|
41
41
|
if (t === "declaration") return Array.isArray(value.attributes) && value.attributes.every(isAttribute);
|
|
@@ -130,7 +130,7 @@ const PARSER = new fast_xml_parser.XMLParser({
|
|
|
130
130
|
function parseXml(xml) {
|
|
131
131
|
return parseNodes(PARSER.parse(xml));
|
|
132
132
|
}
|
|
133
|
-
function isRecord(value) {
|
|
133
|
+
function isRecord$1(value) {
|
|
134
134
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
135
135
|
}
|
|
136
136
|
function isUnknownArray$1(value) {
|
|
@@ -145,7 +145,7 @@ function parseNodes(raw) {
|
|
|
145
145
|
return raw.map(parseNode);
|
|
146
146
|
}
|
|
147
147
|
function parseNode(raw) {
|
|
148
|
-
if (!isRecord(raw)) throw new Error("fast-xml-parser node was not an object");
|
|
148
|
+
if (!isRecord$1(raw)) throw new Error("fast-xml-parser node was not an object");
|
|
149
149
|
let tagKey;
|
|
150
150
|
for (const key of Object.keys(raw)) if (key !== ":@") {
|
|
151
151
|
if (tagKey !== void 0) throw new Error("XML node had multiple tag keys");
|
|
@@ -183,7 +183,7 @@ function parseNode(raw) {
|
|
|
183
183
|
}
|
|
184
184
|
function parseAttributes(raw) {
|
|
185
185
|
if (raw === void 0) return [];
|
|
186
|
-
if (!isRecord(raw)) throw new Error("XML attributes were not an object");
|
|
186
|
+
if (!isRecord$1(raw)) throw new Error("XML attributes were not an object");
|
|
187
187
|
const attrs = [];
|
|
188
188
|
for (const key of Object.keys(raw)) {
|
|
189
189
|
if (!key.startsWith("@_")) throw new Error(`unexpected attribute key without @_ prefix: ${key}`);
|
|
@@ -197,7 +197,7 @@ function parseAttributes(raw) {
|
|
|
197
197
|
function scalarText(raw) {
|
|
198
198
|
if (!isUnknownArray$1(raw) || raw.length === 0) throw new Error("expected a scalar-text wrapper array");
|
|
199
199
|
const first = raw[0];
|
|
200
|
-
if (!isRecord(first)) throw new Error("scalar-text wrapper was not an object");
|
|
200
|
+
if (!isRecord$1(first)) throw new Error("scalar-text wrapper was not an object");
|
|
201
201
|
return asString(first["#text"]);
|
|
202
202
|
}
|
|
203
203
|
//#endregion
|
|
@@ -534,27 +534,659 @@ function encodeCompactPackage(cpkg) {
|
|
|
534
534
|
return zod.z.encode(compactPackageCodec, cpkg);
|
|
535
535
|
}
|
|
536
536
|
//#endregion
|
|
537
|
-
//#region src/typed/
|
|
538
|
-
const
|
|
537
|
+
//#region src/typed/shared/geometry.ts
|
|
538
|
+
const BoxSchema = zod.z.object({
|
|
539
|
+
xPt: zod.z.number(),
|
|
540
|
+
yPt: zod.z.number(),
|
|
541
|
+
widthPt: zod.z.number().nonnegative(),
|
|
542
|
+
heightPt: zod.z.number().nonnegative()
|
|
543
|
+
});
|
|
544
|
+
const PageSizeSchema = zod.z.object({
|
|
545
|
+
widthPt: zod.z.number().positive(),
|
|
546
|
+
heightPt: zod.z.number().positive()
|
|
547
|
+
});
|
|
548
|
+
const MarginsSchema = zod.z.object({
|
|
549
|
+
topPt: zod.z.number().nonnegative(),
|
|
550
|
+
rightPt: zod.z.number().nonnegative(),
|
|
551
|
+
bottomPt: zod.z.number().nonnegative(),
|
|
552
|
+
leftPt: zod.z.number().nonnegative()
|
|
553
|
+
});
|
|
554
|
+
const PAGE_SIZE_LETTER = {
|
|
555
|
+
widthPt: 612,
|
|
556
|
+
heightPt: 792
|
|
557
|
+
};
|
|
558
|
+
const PAGE_SIZE_A4 = {
|
|
559
|
+
widthPt: 595.28,
|
|
560
|
+
heightPt: 841.89
|
|
561
|
+
};
|
|
562
|
+
const SLIDE_SIZE_WIDESCREEN = {
|
|
563
|
+
widthPt: 960,
|
|
564
|
+
heightPt: 540
|
|
565
|
+
};
|
|
566
|
+
const SLIDE_SIZE_STANDARD = {
|
|
567
|
+
widthPt: 720,
|
|
568
|
+
heightPt: 540
|
|
569
|
+
};
|
|
570
|
+
//#endregion
|
|
571
|
+
//#region src/typed/shared/color.ts
|
|
572
|
+
const ColorSchema = zod.z.object({
|
|
573
|
+
r: zod.z.number().min(0).max(1),
|
|
574
|
+
g: zod.z.number().min(0).max(1),
|
|
575
|
+
b: zod.z.number().min(0).max(1)
|
|
576
|
+
});
|
|
577
|
+
const COLOR_BLACK = {
|
|
578
|
+
r: 0,
|
|
579
|
+
g: 0,
|
|
580
|
+
b: 0
|
|
581
|
+
};
|
|
582
|
+
const HEX_COLOR_PATTERN = /^#?([0-9a-fA-F]{6})$/;
|
|
583
|
+
const HEX_BYTE_MAX = 255;
|
|
584
|
+
function rgbHexToColor(hex) {
|
|
585
|
+
const match = HEX_COLOR_PATTERN.exec(hex);
|
|
586
|
+
if (match === null) throw new Error(`not a 6-digit hex colour: ${hex}`);
|
|
587
|
+
const digits = match[1];
|
|
588
|
+
if (digits === void 0) throw new Error(`not a 6-digit hex colour: ${hex}`);
|
|
589
|
+
const r = Number.parseInt(digits.slice(0, 2), 16);
|
|
590
|
+
const g = Number.parseInt(digits.slice(2, 4), 16);
|
|
591
|
+
const b = Number.parseInt(digits.slice(4, 6), 16);
|
|
592
|
+
return {
|
|
593
|
+
r: r / HEX_BYTE_MAX,
|
|
594
|
+
g: g / HEX_BYTE_MAX,
|
|
595
|
+
b: b / HEX_BYTE_MAX
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function toHexByte(component) {
|
|
599
|
+
return Math.round(component * HEX_BYTE_MAX).toString(16).padStart(2, "0");
|
|
600
|
+
}
|
|
601
|
+
function colorToRgbHex(color) {
|
|
602
|
+
return `${toHexByte(color.r)}${toHexByte(color.g)}${toHexByte(color.b)}`;
|
|
603
|
+
}
|
|
604
|
+
const OOXML_PERCENT_SCALE = 1e5;
|
|
605
|
+
function clamp01(x) {
|
|
606
|
+
return Math.max(0, Math.min(1, x));
|
|
607
|
+
}
|
|
608
|
+
function srgbToLinear(c) {
|
|
609
|
+
return c <= .04045 ? c / 12.92 : ((c + .055) / 1.055) ** 2.4;
|
|
610
|
+
}
|
|
611
|
+
function linearToSrgb(c) {
|
|
612
|
+
return c <= .0031308 ? c * 12.92 : 1.055 * c ** (1 / 2.4) - .055;
|
|
613
|
+
}
|
|
614
|
+
function applyShadeOrTint(color, kind, value) {
|
|
615
|
+
const pct = value / OOXML_PERCENT_SCALE;
|
|
616
|
+
const transform = kind === "shade" ? (linear) => linear * pct : (linear) => 1 - (1 - linear) * pct;
|
|
617
|
+
return {
|
|
618
|
+
r: clamp01(linearToSrgb(transform(srgbToLinear(color.r)))),
|
|
619
|
+
g: clamp01(linearToSrgb(transform(srgbToLinear(color.g)))),
|
|
620
|
+
b: clamp01(linearToSrgb(transform(srgbToLinear(color.b))))
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
function rgbToHsl(color) {
|
|
624
|
+
const { r, g, b } = color;
|
|
625
|
+
const max = Math.max(r, g, b);
|
|
626
|
+
const min = Math.min(r, g, b);
|
|
627
|
+
const l = (max + min) / 2;
|
|
628
|
+
if (max === min) return {
|
|
629
|
+
h: 0,
|
|
630
|
+
s: 0,
|
|
631
|
+
l
|
|
632
|
+
};
|
|
633
|
+
const d = max - min;
|
|
634
|
+
const s = l > .5 ? d / (2 - max - min) : d / (max + min);
|
|
635
|
+
let h;
|
|
636
|
+
if (max === r) h = (g - b) / d + (g < b ? 6 : 0);
|
|
637
|
+
else if (max === g) h = (b - r) / d + 2;
|
|
638
|
+
else h = (r - g) / d + 4;
|
|
639
|
+
return {
|
|
640
|
+
h: h * 60,
|
|
641
|
+
s,
|
|
642
|
+
l
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function hueToRgbComponent(p, q, hue) {
|
|
646
|
+
let t = hue;
|
|
647
|
+
if (t < 0) t += 1;
|
|
648
|
+
if (t > 1) t -= 1;
|
|
649
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
650
|
+
if (t < 1 / 2) return q;
|
|
651
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
652
|
+
return p;
|
|
653
|
+
}
|
|
654
|
+
function hslToRgb(hsl) {
|
|
655
|
+
const { h, s, l } = hsl;
|
|
656
|
+
if (s === 0) return {
|
|
657
|
+
r: l,
|
|
658
|
+
g: l,
|
|
659
|
+
b: l
|
|
660
|
+
};
|
|
661
|
+
const q = l < .5 ? l * (1 + s) : l + s - l * s;
|
|
662
|
+
const p = 2 * l - q;
|
|
663
|
+
const hk = h / 360;
|
|
664
|
+
return {
|
|
665
|
+
r: clamp01(hueToRgbComponent(p, q, hk + 1 / 3)),
|
|
666
|
+
g: clamp01(hueToRgbComponent(p, q, hk)),
|
|
667
|
+
b: clamp01(hueToRgbComponent(p, q, hk - 1 / 3))
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
function applyLumModOrOff(color, kind, value) {
|
|
671
|
+
const hsl = rgbToHsl(color);
|
|
672
|
+
const pct = value / OOXML_PERCENT_SCALE;
|
|
673
|
+
const l = clamp01(kind === "lumMod" ? hsl.l * pct : hsl.l + pct);
|
|
674
|
+
return hslToRgb({
|
|
675
|
+
...hsl,
|
|
676
|
+
l
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
function applyColorTransforms(base, transforms) {
|
|
680
|
+
let color = base;
|
|
681
|
+
for (const t of transforms) if (t.kind === "shade" || t.kind === "tint") color = applyShadeOrTint(color, t.kind, t.value);
|
|
682
|
+
for (const t of transforms) if (t.kind === "lumMod" || t.kind === "lumOff") color = applyLumModOrOff(color, t.kind, t.value);
|
|
683
|
+
return color;
|
|
684
|
+
}
|
|
685
|
+
//#endregion
|
|
686
|
+
//#region src/typed/shared/style.ts
|
|
687
|
+
const AlignmentSchema = zod.z.enum([
|
|
688
|
+
"left",
|
|
689
|
+
"center",
|
|
690
|
+
"right",
|
|
691
|
+
"justify"
|
|
692
|
+
]);
|
|
693
|
+
//#endregion
|
|
694
|
+
//#region src/typed/shared/metadata.ts
|
|
695
|
+
const DocumentMetadataSchema = zod.z.object({
|
|
696
|
+
title: zod.z.string().optional(),
|
|
697
|
+
author: zod.z.string().optional(),
|
|
698
|
+
subject: zod.z.string().optional(),
|
|
699
|
+
keywords: zod.z.array(zod.z.string()).optional(),
|
|
700
|
+
creator: zod.z.string().optional(),
|
|
701
|
+
createdIso: zod.z.string().optional(),
|
|
702
|
+
modifiedIso: zod.z.string().optional()
|
|
703
|
+
});
|
|
704
|
+
const CORE_PROPERTIES_PATH = "docProps/core.xml";
|
|
705
|
+
const APP_PROPERTIES_PATH = "docProps/app.xml";
|
|
706
|
+
function firstElementText(root, tag) {
|
|
707
|
+
if (root === void 0) return;
|
|
708
|
+
const element = childrenWithTag(root, tag)[0];
|
|
709
|
+
if (element === void 0) return;
|
|
710
|
+
const text = textContent(element);
|
|
711
|
+
return text.length > 0 ? text : void 0;
|
|
712
|
+
}
|
|
713
|
+
function readKeywords(core) {
|
|
714
|
+
const raw = firstElementText(core, "cp:keywords");
|
|
715
|
+
if (raw === void 0) return;
|
|
716
|
+
const parts = raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
717
|
+
return parts.length > 0 ? parts : void 0;
|
|
718
|
+
}
|
|
719
|
+
function readCoreProperties(pkg) {
|
|
720
|
+
const core = rootElement(pkg.parts[CORE_PROPERTIES_PATH]);
|
|
721
|
+
const app = rootElement(pkg.parts[APP_PROPERTIES_PATH]);
|
|
722
|
+
return {
|
|
723
|
+
title: firstElementText(core, "dc:title"),
|
|
724
|
+
author: firstElementText(core, "dc:creator"),
|
|
725
|
+
subject: firstElementText(core, "dc:subject"),
|
|
726
|
+
keywords: readKeywords(core),
|
|
727
|
+
creator: firstElementText(app, "Application"),
|
|
728
|
+
createdIso: firstElementText(core, "dcterms:created"),
|
|
729
|
+
modifiedIso: firstElementText(core, "dcterms:modified")
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
//#endregion
|
|
733
|
+
//#region src/typed/shared/content.ts
|
|
734
|
+
const ContentRunSchema = zod.z.object({
|
|
539
735
|
text: zod.z.string(),
|
|
540
736
|
bold: zod.z.boolean().optional(),
|
|
541
|
-
italic: zod.z.boolean().optional()
|
|
737
|
+
italic: zod.z.boolean().optional(),
|
|
738
|
+
underline: zod.z.boolean().optional(),
|
|
739
|
+
strike: zod.z.boolean().optional(),
|
|
740
|
+
fontFamily: zod.z.string().optional(),
|
|
741
|
+
sizePt: zod.z.number().positive().optional(),
|
|
742
|
+
color: ColorSchema.optional(),
|
|
743
|
+
hyperlink: zod.z.string().optional()
|
|
542
744
|
});
|
|
543
|
-
const
|
|
745
|
+
const ContentListMembershipSchema = zod.z.object({
|
|
544
746
|
numId: zod.z.string(),
|
|
545
|
-
level: zod.z.number()
|
|
747
|
+
level: zod.z.number().int().nonnegative()
|
|
546
748
|
});
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
749
|
+
const ContentParagraphSchema = zod.z.object({
|
|
750
|
+
kind: zod.z.literal("paragraph"),
|
|
751
|
+
runs: zod.z.array(ContentRunSchema),
|
|
752
|
+
styleId: zod.z.string().optional(),
|
|
753
|
+
alignment: AlignmentSchema.optional(),
|
|
754
|
+
list: ContentListMembershipSchema.optional(),
|
|
755
|
+
spacingBeforePt: zod.z.number().optional(),
|
|
756
|
+
spacingAfterPt: zod.z.number().optional(),
|
|
757
|
+
lineSpacing: zod.z.number().positive().optional(),
|
|
758
|
+
indentLeftPt: zod.z.number().optional(),
|
|
759
|
+
indentFirstLinePt: zod.z.number().optional()
|
|
550
760
|
});
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
761
|
+
const ContentImageBlockSchema = zod.z.object({
|
|
762
|
+
kind: zod.z.literal("image"),
|
|
763
|
+
format: zod.z.enum(["png", "jpeg"]),
|
|
764
|
+
base64: zod.z.string(),
|
|
765
|
+
widthPt: zod.z.number().positive(),
|
|
766
|
+
heightPt: zod.z.number().positive(),
|
|
767
|
+
altText: zod.z.string().optional()
|
|
768
|
+
});
|
|
769
|
+
const ContentPageBreakSchema = zod.z.object({ kind: zod.z.literal("pageBreak") });
|
|
770
|
+
function isRecord(value) {
|
|
771
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
772
|
+
}
|
|
773
|
+
function isContentRun(value) {
|
|
774
|
+
return isRecord(value) && typeof value.text === "string";
|
|
775
|
+
}
|
|
776
|
+
function isContentTableCell(value) {
|
|
777
|
+
return isRecord(value) && Array.isArray(value.blocks) && value.blocks.every(isContentBlock);
|
|
778
|
+
}
|
|
779
|
+
function isContentTableRow(value) {
|
|
780
|
+
return isRecord(value) && Array.isArray(value.cells) && value.cells.every(isContentTableCell) && (value.heightPt === void 0 || typeof value.heightPt === "number");
|
|
781
|
+
}
|
|
782
|
+
function isContentBlock(value) {
|
|
783
|
+
if (!isRecord(value)) return false;
|
|
784
|
+
const kind = value.kind;
|
|
785
|
+
if (kind === "paragraph") return Array.isArray(value.runs) && value.runs.every(isContentRun);
|
|
786
|
+
if (kind === "image") return (value.format === "png" || value.format === "jpeg") && typeof value.base64 === "string" && typeof value.widthPt === "number" && typeof value.heightPt === "number";
|
|
787
|
+
if (kind === "pageBreak") return true;
|
|
788
|
+
if (kind === "table") return Array.isArray(value.rows) && value.rows.every(isContentTableRow) && Array.isArray(value.columnWidthsPt) && value.columnWidthsPt.every((w) => typeof w === "number");
|
|
789
|
+
return false;
|
|
790
|
+
}
|
|
791
|
+
const ContentBlockSchema = zod.z.custom(isContentBlock);
|
|
792
|
+
const ContentTableCellSchema = zod.z.object({
|
|
793
|
+
blocks: zod.z.array(ContentBlockSchema),
|
|
794
|
+
colSpan: zod.z.number().int().positive().optional(),
|
|
795
|
+
rowSpan: zod.z.number().int().positive().optional(),
|
|
796
|
+
background: ColorSchema.optional()
|
|
797
|
+
});
|
|
798
|
+
const ContentTableRowSchema = zod.z.object({
|
|
799
|
+
cells: zod.z.array(ContentTableCellSchema),
|
|
800
|
+
heightPt: zod.z.number().positive().optional()
|
|
801
|
+
});
|
|
802
|
+
const ContentTableSchema = zod.z.object({
|
|
803
|
+
kind: zod.z.literal("table"),
|
|
804
|
+
rows: zod.z.array(ContentTableRowSchema),
|
|
805
|
+
columnWidthsPt: zod.z.array(zod.z.number().positive())
|
|
557
806
|
});
|
|
807
|
+
const ContentSectionSchema = zod.z.object({
|
|
808
|
+
pageSize: PageSizeSchema,
|
|
809
|
+
margins: MarginsSchema,
|
|
810
|
+
blocks: zod.z.array(ContentBlockSchema)
|
|
811
|
+
});
|
|
812
|
+
const ContentShapeSchema = zod.z.object({
|
|
813
|
+
name: zod.z.string().optional(),
|
|
814
|
+
frame: BoxSchema,
|
|
815
|
+
rotationDeg: zod.z.number().optional(),
|
|
816
|
+
insetLeftPt: zod.z.number().nonnegative(),
|
|
817
|
+
insetTopPt: zod.z.number().nonnegative(),
|
|
818
|
+
insetRightPt: zod.z.number().nonnegative(),
|
|
819
|
+
insetBottomPt: zod.z.number().nonnegative(),
|
|
820
|
+
fontScale: zod.z.number().positive().optional(),
|
|
821
|
+
lineSpacingReduction: zod.z.number().nonnegative().optional(),
|
|
822
|
+
blocks: zod.z.array(ContentBlockSchema)
|
|
823
|
+
});
|
|
824
|
+
const ContentSlideSchema = zod.z.object({
|
|
825
|
+
size: PageSizeSchema,
|
|
826
|
+
shapes: zod.z.array(ContentShapeSchema),
|
|
827
|
+
notes: zod.z.string()
|
|
828
|
+
});
|
|
829
|
+
//#endregion
|
|
830
|
+
//#region src/image/sniff.ts
|
|
831
|
+
const PNG_SIGNATURE = [
|
|
832
|
+
137,
|
|
833
|
+
80,
|
|
834
|
+
78,
|
|
835
|
+
71,
|
|
836
|
+
13,
|
|
837
|
+
10,
|
|
838
|
+
26,
|
|
839
|
+
10
|
|
840
|
+
];
|
|
841
|
+
const JPEG_SIGNATURE = [
|
|
842
|
+
255,
|
|
843
|
+
216,
|
|
844
|
+
255
|
|
845
|
+
];
|
|
846
|
+
function startsWith(bytes, signature) {
|
|
847
|
+
if (bytes.length < signature.length) return false;
|
|
848
|
+
for (let i = 0; i < signature.length; i++) if (bytes[i] !== signature[i]) return false;
|
|
849
|
+
return true;
|
|
850
|
+
}
|
|
851
|
+
function sniffImageFormat(bytes) {
|
|
852
|
+
if (startsWith(bytes, PNG_SIGNATURE)) return "png";
|
|
853
|
+
if (startsWith(bytes, JPEG_SIGNATURE)) return "jpeg";
|
|
854
|
+
}
|
|
855
|
+
const EMU_PER_POINT = 914400 / 72;
|
|
856
|
+
function emuToPt(emu) {
|
|
857
|
+
return emu / EMU_PER_POINT;
|
|
858
|
+
}
|
|
859
|
+
function twipsToPt(twips) {
|
|
860
|
+
return twips / 20;
|
|
861
|
+
}
|
|
862
|
+
function halfPointsToPt(halfPoints) {
|
|
863
|
+
return halfPoints / 2;
|
|
864
|
+
}
|
|
865
|
+
function drawingMlFontSizeToPt(hundredths) {
|
|
866
|
+
return hundredths / 100;
|
|
867
|
+
}
|
|
868
|
+
function lineUnitsToMultiplier(lineUnits) {
|
|
869
|
+
return lineUnits / 240;
|
|
870
|
+
}
|
|
871
|
+
//#endregion
|
|
872
|
+
//#region src/typed/shared/drawingml.ts
|
|
873
|
+
const ROTATION_UNITS_PER_DEGREE = 6e4;
|
|
874
|
+
function readXfrm(xfrm) {
|
|
875
|
+
if (xfrm === void 0) return;
|
|
876
|
+
const off = childrenWithTag(xfrm, "a:off")[0];
|
|
877
|
+
const ext = childrenWithTag(xfrm, "a:ext")[0];
|
|
878
|
+
if (off === void 0 || ext === void 0) return;
|
|
879
|
+
const x = attr(off, "x");
|
|
880
|
+
const y = attr(off, "y");
|
|
881
|
+
const cx = attr(ext, "cx");
|
|
882
|
+
const cy = attr(ext, "cy");
|
|
883
|
+
if (x === void 0 || y === void 0 || cx === void 0 || cy === void 0) return;
|
|
884
|
+
const rot = attr(xfrm, "rot");
|
|
885
|
+
return {
|
|
886
|
+
xPt: emuToPt(Number(x)),
|
|
887
|
+
yPt: emuToPt(Number(y)),
|
|
888
|
+
widthPt: emuToPt(Number(cx)),
|
|
889
|
+
heightPt: emuToPt(Number(cy)),
|
|
890
|
+
rotationDeg: rot === void 0 ? 0 : Number(rot) / ROTATION_UNITS_PER_DEGREE,
|
|
891
|
+
flipH: attr(xfrm, "flipH") === "1",
|
|
892
|
+
flipV: attr(xfrm, "flipV") === "1"
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
const CLR_SCHEME_SLOTS = [
|
|
896
|
+
"dk1",
|
|
897
|
+
"lt1",
|
|
898
|
+
"dk2",
|
|
899
|
+
"lt2",
|
|
900
|
+
"accent1",
|
|
901
|
+
"accent2",
|
|
902
|
+
"accent3",
|
|
903
|
+
"accent4",
|
|
904
|
+
"accent5",
|
|
905
|
+
"accent6",
|
|
906
|
+
"hlink",
|
|
907
|
+
"folHlink"
|
|
908
|
+
];
|
|
909
|
+
function readThemeSlotColor(colorEl) {
|
|
910
|
+
if (colorEl.tag === "a:srgbClr") {
|
|
911
|
+
const val = attr(colorEl, "val");
|
|
912
|
+
return val === void 0 ? void 0 : rgbHexToColor(val);
|
|
913
|
+
}
|
|
914
|
+
if (colorEl.tag === "a:sysClr") {
|
|
915
|
+
const lastClr = attr(colorEl, "lastClr");
|
|
916
|
+
if (lastClr !== void 0) return rgbHexToColor(lastClr);
|
|
917
|
+
return attr(colorEl, "val") === "window" ? {
|
|
918
|
+
r: 1,
|
|
919
|
+
g: 1,
|
|
920
|
+
b: 1
|
|
921
|
+
} : {
|
|
922
|
+
r: 0,
|
|
923
|
+
g: 0,
|
|
924
|
+
b: 0
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
function readClrScheme(clrSchemeEl) {
|
|
929
|
+
const map = /* @__PURE__ */ new Map();
|
|
930
|
+
for (const slot of CLR_SCHEME_SLOTS) {
|
|
931
|
+
const wrapper = childrenWithTag(clrSchemeEl, `a:${slot}`)[0];
|
|
932
|
+
if (wrapper === void 0) continue;
|
|
933
|
+
const colorEl = wrapper.children.find((c) => c.type === "element");
|
|
934
|
+
if (colorEl === void 0) continue;
|
|
935
|
+
const color = readThemeSlotColor(colorEl);
|
|
936
|
+
if (color !== void 0) map.set(slot, color);
|
|
937
|
+
}
|
|
938
|
+
return map;
|
|
939
|
+
}
|
|
940
|
+
function readSchemeFont(fontSchemeEl, tag) {
|
|
941
|
+
if (fontSchemeEl === void 0) return;
|
|
942
|
+
const fontEl = childrenWithTag(fontSchemeEl, tag)[0];
|
|
943
|
+
const latin = fontEl === void 0 ? void 0 : childrenWithTag(fontEl, "a:latin")[0];
|
|
944
|
+
return latin === void 0 ? void 0 : attr(latin, "typeface");
|
|
945
|
+
}
|
|
946
|
+
const DEFAULT_THEME_FONT = "Calibri";
|
|
947
|
+
const EMPTY_THEME = {
|
|
948
|
+
colorScheme: /* @__PURE__ */ new Map(),
|
|
949
|
+
majorFont: DEFAULT_THEME_FONT,
|
|
950
|
+
minorFont: DEFAULT_THEME_FONT
|
|
951
|
+
};
|
|
952
|
+
function readTheme(themeRoot) {
|
|
953
|
+
const clrSchemeEl = elementsWithTag([themeRoot], "a:clrScheme")[0];
|
|
954
|
+
const colorScheme = clrSchemeEl === void 0 ? /* @__PURE__ */ new Map() : readClrScheme(clrSchemeEl);
|
|
955
|
+
const fontSchemeEl = elementsWithTag([themeRoot], "a:fontScheme")[0];
|
|
956
|
+
return {
|
|
957
|
+
colorScheme,
|
|
958
|
+
majorFont: readSchemeFont(fontSchemeEl, "a:majorFont") ?? DEFAULT_THEME_FONT,
|
|
959
|
+
minorFont: readSchemeFont(fontSchemeEl, "a:minorFont") ?? DEFAULT_THEME_FONT
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
function resolveThemeFontReference(typeface, theme) {
|
|
963
|
+
if (typeface === "+mj-lt") return theme.majorFont;
|
|
964
|
+
if (typeface === "+mn-lt") return theme.minorFont;
|
|
965
|
+
return typeface;
|
|
966
|
+
}
|
|
967
|
+
function readColorMap(clrMapEl) {
|
|
968
|
+
const map = /* @__PURE__ */ new Map();
|
|
969
|
+
if (clrMapEl === void 0) return map;
|
|
970
|
+
for (const a of clrMapEl.attributes) map.set(a.name, a.value);
|
|
971
|
+
return map;
|
|
972
|
+
}
|
|
973
|
+
function resolveSchemeColorSlot(schemeVal, colorMap) {
|
|
974
|
+
return colorMap.get(schemeVal) ?? schemeVal;
|
|
975
|
+
}
|
|
976
|
+
const COLOR_TRANSFORM_TAGS = /* @__PURE__ */ new Map([
|
|
977
|
+
["a:shade", "shade"],
|
|
978
|
+
["a:tint", "tint"],
|
|
979
|
+
["a:lumMod", "lumMod"],
|
|
980
|
+
["a:lumOff", "lumOff"]
|
|
981
|
+
]);
|
|
982
|
+
function readColorTransforms(container) {
|
|
983
|
+
const transforms = [];
|
|
984
|
+
for (const child of container.children) {
|
|
985
|
+
if (child.type !== "element") continue;
|
|
986
|
+
const kind = COLOR_TRANSFORM_TAGS.get(child.tag);
|
|
987
|
+
if (kind === void 0) continue;
|
|
988
|
+
const val = attr(child, "val");
|
|
989
|
+
if (val === void 0) continue;
|
|
990
|
+
transforms.push({
|
|
991
|
+
kind,
|
|
992
|
+
value: Number(val)
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
return transforms;
|
|
996
|
+
}
|
|
997
|
+
function readSchemeColor(schemeClrEl, colorMap, theme) {
|
|
998
|
+
const val = attr(schemeClrEl, "val");
|
|
999
|
+
if (val === void 0) return;
|
|
1000
|
+
const base = theme.colorScheme.get(resolveSchemeColorSlot(val, colorMap));
|
|
1001
|
+
return base === void 0 ? void 0 : applyColorTransforms(base, readColorTransforms(schemeClrEl));
|
|
1002
|
+
}
|
|
1003
|
+
function readSrgbColor(srgbClrEl) {
|
|
1004
|
+
const val = attr(srgbClrEl, "val");
|
|
1005
|
+
return val === void 0 ? void 0 : applyColorTransforms(rgbHexToColor(val), readColorTransforms(srgbClrEl));
|
|
1006
|
+
}
|
|
1007
|
+
function readSolidFillColor(solidFillEl, colorMap, theme) {
|
|
1008
|
+
if (solidFillEl === void 0) return;
|
|
1009
|
+
const schemeClr = childrenWithTag(solidFillEl, "a:schemeClr")[0];
|
|
1010
|
+
if (schemeClr !== void 0) return readSchemeColor(schemeClr, colorMap, theme);
|
|
1011
|
+
const srgbClr = childrenWithTag(solidFillEl, "a:srgbClr")[0];
|
|
1012
|
+
return srgbClr === void 0 ? void 0 : readSrgbColor(srgbClr);
|
|
1013
|
+
}
|
|
1014
|
+
function readGroupXfrm(xfrm) {
|
|
1015
|
+
const base = readXfrm(xfrm);
|
|
1016
|
+
if (base === void 0 || xfrm === void 0) return;
|
|
1017
|
+
const chOff = childrenWithTag(xfrm, "a:chOff")[0];
|
|
1018
|
+
const chExt = childrenWithTag(xfrm, "a:chExt")[0];
|
|
1019
|
+
if (chOff === void 0 || chExt === void 0) return;
|
|
1020
|
+
const cx = attr(chOff, "x");
|
|
1021
|
+
const cy = attr(chOff, "y");
|
|
1022
|
+
const ccx = attr(chExt, "cx");
|
|
1023
|
+
const ccy = attr(chExt, "cy");
|
|
1024
|
+
if (cx === void 0 || cy === void 0 || ccx === void 0 || ccy === void 0) return;
|
|
1025
|
+
return {
|
|
1026
|
+
offXPt: base.xPt,
|
|
1027
|
+
offYPt: base.yPt,
|
|
1028
|
+
extWidthPt: base.widthPt,
|
|
1029
|
+
extHeightPt: base.heightPt,
|
|
1030
|
+
childOffXPt: emuToPt(Number(cx)),
|
|
1031
|
+
childOffYPt: emuToPt(Number(cy)),
|
|
1032
|
+
childExtWidthPt: emuToPt(Number(ccx)),
|
|
1033
|
+
childExtHeightPt: emuToPt(Number(ccy))
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
function applyGroupTransform(group, childFrame) {
|
|
1037
|
+
const scaleX = group.childExtWidthPt === 0 ? 1 : group.extWidthPt / group.childExtWidthPt;
|
|
1038
|
+
const scaleY = group.childExtHeightPt === 0 ? 1 : group.extHeightPt / group.childExtHeightPt;
|
|
1039
|
+
return {
|
|
1040
|
+
xPt: group.offXPt + (childFrame.xPt - group.childOffXPt) * scaleX,
|
|
1041
|
+
yPt: group.offYPt + (childFrame.yPt - group.childOffYPt) * scaleY,
|
|
1042
|
+
widthPt: childFrame.widthPt * scaleX,
|
|
1043
|
+
heightPt: childFrame.heightPt * scaleY
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
//#endregion
|
|
1047
|
+
//#region src/typed/docx/styles.ts
|
|
1048
|
+
function mergeParagraphLayer(base, layer) {
|
|
1049
|
+
return {
|
|
1050
|
+
alignment: layer.alignment ?? base.alignment,
|
|
1051
|
+
spacingBeforePt: layer.spacingBeforePt ?? base.spacingBeforePt,
|
|
1052
|
+
spacingAfterPt: layer.spacingAfterPt ?? base.spacingAfterPt,
|
|
1053
|
+
lineSpacing: layer.lineSpacing ?? base.lineSpacing,
|
|
1054
|
+
indentLeftPt: layer.indentLeftPt ?? base.indentLeftPt,
|
|
1055
|
+
indentFirstLinePt: layer.indentFirstLinePt ?? base.indentFirstLinePt
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
function mergeRunLayer(base, layer) {
|
|
1059
|
+
return {
|
|
1060
|
+
bold: layer.bold ?? base.bold,
|
|
1061
|
+
italic: layer.italic ?? base.italic,
|
|
1062
|
+
underline: layer.underline ?? base.underline,
|
|
1063
|
+
strike: layer.strike ?? base.strike,
|
|
1064
|
+
fontFamily: layer.fontFamily ?? base.fontFamily,
|
|
1065
|
+
sizePt: layer.sizePt ?? base.sizePt,
|
|
1066
|
+
color: layer.color ?? base.color
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
function readToggle$1(el) {
|
|
1070
|
+
if (el === void 0) return;
|
|
1071
|
+
const val = attr(el, "w:val");
|
|
1072
|
+
return val === void 0 || val !== "0" && val !== "false" && val !== "off";
|
|
1073
|
+
}
|
|
1074
|
+
function readUnderline(u) {
|
|
1075
|
+
if (u === void 0) return;
|
|
1076
|
+
const val = attr(u, "w:val");
|
|
1077
|
+
return val !== void 0 && val !== "none";
|
|
1078
|
+
}
|
|
1079
|
+
function readRunColor(colorEl) {
|
|
1080
|
+
if (colorEl === void 0) return;
|
|
1081
|
+
const val = attr(colorEl, "w:val");
|
|
1082
|
+
return val === void 0 || val === "auto" ? void 0 : rgbHexToColor(val);
|
|
1083
|
+
}
|
|
1084
|
+
function readRunFontFamily(rFonts, theme) {
|
|
1085
|
+
if (rFonts === void 0) return;
|
|
1086
|
+
const ascii = attr(rFonts, "w:ascii");
|
|
1087
|
+
if (ascii !== void 0) return ascii;
|
|
1088
|
+
const asciiTheme = attr(rFonts, "w:asciiTheme");
|
|
1089
|
+
if (asciiTheme === "majorHAnsi" || asciiTheme === "majorAscii") return theme.majorFont;
|
|
1090
|
+
if (asciiTheme === "minorHAnsi" || asciiTheme === "minorAscii") return theme.minorFont;
|
|
1091
|
+
}
|
|
1092
|
+
function readRunPropertiesLayer(rPr, theme) {
|
|
1093
|
+
if (rPr === void 0) return {};
|
|
1094
|
+
const sz = childrenWithTag(rPr, "w:sz")[0];
|
|
1095
|
+
const szVal = sz === void 0 ? void 0 : attr(sz, "w:val");
|
|
1096
|
+
return {
|
|
1097
|
+
bold: readToggle$1(childrenWithTag(rPr, "w:b")[0]),
|
|
1098
|
+
italic: readToggle$1(childrenWithTag(rPr, "w:i")[0]),
|
|
1099
|
+
underline: readUnderline(childrenWithTag(rPr, "w:u")[0]),
|
|
1100
|
+
strike: readToggle$1(childrenWithTag(rPr, "w:strike")[0]),
|
|
1101
|
+
fontFamily: readRunFontFamily(childrenWithTag(rPr, "w:rFonts")[0], theme),
|
|
1102
|
+
sizePt: szVal === void 0 ? void 0 : halfPointsToPt(Number(szVal)),
|
|
1103
|
+
color: readRunColor(childrenWithTag(rPr, "w:color")[0])
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
function readAlignment$1(jc) {
|
|
1107
|
+
const val = jc === void 0 ? void 0 : attr(jc, "w:val");
|
|
1108
|
+
if (val === "left" || val === "start") return "left";
|
|
1109
|
+
if (val === "center") return "center";
|
|
1110
|
+
if (val === "right" || val === "end") return "right";
|
|
1111
|
+
if (val === "both" || val === "distribute") return "justify";
|
|
1112
|
+
}
|
|
1113
|
+
function readParagraphPropertiesLayer(pPr) {
|
|
1114
|
+
if (pPr === void 0) return {};
|
|
1115
|
+
const spacing = childrenWithTag(pPr, "w:spacing")[0];
|
|
1116
|
+
const before = spacing === void 0 ? void 0 : attr(spacing, "w:before");
|
|
1117
|
+
const after = spacing === void 0 ? void 0 : attr(spacing, "w:after");
|
|
1118
|
+
const line = spacing === void 0 ? void 0 : attr(spacing, "w:line");
|
|
1119
|
+
const lineRule = spacing === void 0 ? void 0 : attr(spacing, "w:lineRule");
|
|
1120
|
+
const ind = childrenWithTag(pPr, "w:ind")[0];
|
|
1121
|
+
const left = ind === void 0 ? void 0 : attr(ind, "w:left") ?? attr(ind, "w:start");
|
|
1122
|
+
const firstLine = ind === void 0 ? void 0 : attr(ind, "w:firstLine");
|
|
1123
|
+
const hanging = ind === void 0 ? void 0 : attr(ind, "w:hanging");
|
|
1124
|
+
return {
|
|
1125
|
+
alignment: readAlignment$1(childrenWithTag(pPr, "w:jc")[0]),
|
|
1126
|
+
spacingBeforePt: before === void 0 ? void 0 : twipsToPt(Number(before)),
|
|
1127
|
+
spacingAfterPt: after === void 0 ? void 0 : twipsToPt(Number(after)),
|
|
1128
|
+
lineSpacing: line === void 0 || lineRule === "exact" || lineRule === "atLeast" ? void 0 : lineUnitsToMultiplier(Number(line)),
|
|
1129
|
+
indentLeftPt: left === void 0 ? void 0 : twipsToPt(Number(left)),
|
|
1130
|
+
indentFirstLinePt: firstLine !== void 0 ? twipsToPt(Number(firstLine)) : hanging !== void 0 ? -twipsToPt(Number(hanging)) : void 0
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
function findStyle(stylesRoot, styleId, type) {
|
|
1134
|
+
return elementsWithTag([stylesRoot], "w:style").find((s) => attr(s, "w:type") === type && attr(s, "w:styleId") === styleId);
|
|
1135
|
+
}
|
|
1136
|
+
function findDefaultStyle(stylesRoot, type) {
|
|
1137
|
+
return elementsWithTag([stylesRoot], "w:style").find((s) => attr(s, "w:type") === type && attr(s, "w:default") === "1");
|
|
1138
|
+
}
|
|
1139
|
+
function resolveBasedOnChain(stylesRoot, styleId, type) {
|
|
1140
|
+
const chain = [];
|
|
1141
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1142
|
+
let currentId = styleId;
|
|
1143
|
+
while (currentId !== void 0 && !visited.has(currentId)) {
|
|
1144
|
+
visited.add(currentId);
|
|
1145
|
+
const style = findStyle(stylesRoot, currentId, type);
|
|
1146
|
+
if (style === void 0) break;
|
|
1147
|
+
chain.unshift(style);
|
|
1148
|
+
const basedOn = childrenWithTag(style, "w:basedOn")[0];
|
|
1149
|
+
currentId = basedOn === void 0 ? void 0 : attr(basedOn, "w:val");
|
|
1150
|
+
}
|
|
1151
|
+
return chain;
|
|
1152
|
+
}
|
|
1153
|
+
function docDefaultsElement(stylesRoot, wrapperTag, innerTag) {
|
|
1154
|
+
const docDefaults = stylesRoot === void 0 ? void 0 : childrenWithTag(stylesRoot, "w:docDefaults")[0];
|
|
1155
|
+
const wrapper = docDefaults === void 0 ? void 0 : childrenWithTag(docDefaults, wrapperTag)[0];
|
|
1156
|
+
return wrapper === void 0 ? void 0 : childrenWithTag(wrapper, innerTag)[0];
|
|
1157
|
+
}
|
|
1158
|
+
function resolveParagraphProperties(paragraph, context) {
|
|
1159
|
+
const pPr = childrenWithTag(paragraph, "w:pPr")[0];
|
|
1160
|
+
const pStyleEl = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:pStyle")[0];
|
|
1161
|
+
const styleId = pStyleEl === void 0 ? void 0 : attr(pStyleEl, "w:val");
|
|
1162
|
+
let resolved = readParagraphPropertiesLayer(docDefaultsElement(context.stylesRoot, "w:pPrDefault", "w:pPr"));
|
|
1163
|
+
if (context.stylesRoot !== void 0) {
|
|
1164
|
+
const defaultStyle = findDefaultStyle(context.stylesRoot, "paragraph");
|
|
1165
|
+
if (defaultStyle !== void 0) resolved = mergeParagraphLayer(resolved, readParagraphPropertiesLayer(childrenWithTag(defaultStyle, "w:pPr")[0]));
|
|
1166
|
+
if (styleId !== void 0) for (const style of resolveBasedOnChain(context.stylesRoot, styleId, "paragraph")) resolved = mergeParagraphLayer(resolved, readParagraphPropertiesLayer(childrenWithTag(style, "w:pPr")[0]));
|
|
1167
|
+
}
|
|
1168
|
+
return mergeParagraphLayer(resolved, readParagraphPropertiesLayer(pPr));
|
|
1169
|
+
}
|
|
1170
|
+
function resolveRunProperties(run, paragraph, context) {
|
|
1171
|
+
const pPr = childrenWithTag(paragraph, "w:pPr")[0];
|
|
1172
|
+
const pStyleEl = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:pStyle")[0];
|
|
1173
|
+
const pStyleId = pStyleEl === void 0 ? void 0 : attr(pStyleEl, "w:val");
|
|
1174
|
+
let resolved = readRunPropertiesLayer(docDefaultsElement(context.stylesRoot, "w:rPrDefault", "w:rPr"), context.theme);
|
|
1175
|
+
if (context.stylesRoot !== void 0) {
|
|
1176
|
+
const defaultStyle = findDefaultStyle(context.stylesRoot, "paragraph");
|
|
1177
|
+
if (defaultStyle !== void 0) resolved = mergeRunLayer(resolved, readRunPropertiesLayer(childrenWithTag(defaultStyle, "w:rPr")[0], context.theme));
|
|
1178
|
+
if (pStyleId !== void 0) for (const style of resolveBasedOnChain(context.stylesRoot, pStyleId, "paragraph")) resolved = mergeRunLayer(resolved, readRunPropertiesLayer(childrenWithTag(style, "w:rPr")[0], context.theme));
|
|
1179
|
+
}
|
|
1180
|
+
const paragraphMarkRPr = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:rPr")[0];
|
|
1181
|
+
resolved = mergeRunLayer(resolved, readRunPropertiesLayer(paragraphMarkRPr, context.theme));
|
|
1182
|
+
const rPr = childrenWithTag(run, "w:rPr")[0];
|
|
1183
|
+
const rStyleEl = rPr === void 0 ? void 0 : childrenWithTag(rPr, "w:rStyle")[0];
|
|
1184
|
+
const rStyleId = rStyleEl === void 0 ? void 0 : attr(rStyleEl, "w:val");
|
|
1185
|
+
if (context.stylesRoot !== void 0 && rStyleId !== void 0) for (const style of resolveBasedOnChain(context.stylesRoot, rStyleId, "character")) resolved = mergeRunLayer(resolved, readRunPropertiesLayer(childrenWithTag(style, "w:rPr")[0], context.theme));
|
|
1186
|
+
return mergeRunLayer(resolved, readRunPropertiesLayer(rPr, context.theme));
|
|
1187
|
+
}
|
|
1188
|
+
//#endregion
|
|
1189
|
+
//#region src/typed/docx/read.ts
|
|
558
1190
|
const CommentSchema = zod.z.object({
|
|
559
1191
|
author: zod.z.string().optional(),
|
|
560
1192
|
text: zod.z.string()
|
|
@@ -564,73 +1196,256 @@ const FootnoteSchema = zod.z.object({
|
|
|
564
1196
|
text: zod.z.string()
|
|
565
1197
|
});
|
|
566
1198
|
const DocxDocumentSchema = zod.z.object({
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
hyperlinks: zod.z.array(HyperlinkSchema),
|
|
1199
|
+
metadata: DocumentMetadataSchema,
|
|
1200
|
+
sections: zod.z.array(ContentSectionSchema),
|
|
570
1201
|
comments: zod.z.array(CommentSchema),
|
|
571
1202
|
footnotes: zod.z.array(FootnoteSchema),
|
|
572
1203
|
headers: zod.z.array(zod.z.string()),
|
|
573
1204
|
footers: zod.z.array(zod.z.string())
|
|
574
1205
|
});
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
1206
|
+
const DOCUMENT_PART_PATH = "word/document.xml";
|
|
1207
|
+
const STYLES_PART_PATH = "word/styles.xml";
|
|
1208
|
+
const THEME_REL_SUFFIX$1 = "/theme";
|
|
1209
|
+
const DEFAULT_MARGIN_PT = 72;
|
|
1210
|
+
const DEFAULT_MARGINS = {
|
|
1211
|
+
topPt: DEFAULT_MARGIN_PT,
|
|
1212
|
+
rightPt: DEFAULT_MARGIN_PT,
|
|
1213
|
+
bottomPt: DEFAULT_MARGIN_PT,
|
|
1214
|
+
leftPt: DEFAULT_MARGIN_PT
|
|
1215
|
+
};
|
|
1216
|
+
function readPageSize(sectPr) {
|
|
1217
|
+
const pgSz = childrenWithTag(sectPr, "w:pgSz")[0];
|
|
1218
|
+
const w = pgSz === void 0 ? void 0 : attr(pgSz, "w:w");
|
|
1219
|
+
const h = pgSz === void 0 ? void 0 : attr(pgSz, "w:h");
|
|
1220
|
+
return w === void 0 || h === void 0 ? PAGE_SIZE_LETTER : {
|
|
1221
|
+
widthPt: twipsToPt(Number(w)),
|
|
1222
|
+
heightPt: twipsToPt(Number(h))
|
|
1223
|
+
};
|
|
578
1224
|
}
|
|
579
|
-
function
|
|
580
|
-
const
|
|
581
|
-
if (
|
|
582
|
-
|
|
583
|
-
|
|
1225
|
+
function readMargins(sectPr) {
|
|
1226
|
+
const pgMar = childrenWithTag(sectPr, "w:pgMar")[0];
|
|
1227
|
+
if (pgMar === void 0) return DEFAULT_MARGINS;
|
|
1228
|
+
const top = attr(pgMar, "w:top");
|
|
1229
|
+
const right = attr(pgMar, "w:right");
|
|
1230
|
+
const bottom = attr(pgMar, "w:bottom");
|
|
1231
|
+
const left = attr(pgMar, "w:left");
|
|
1232
|
+
return {
|
|
1233
|
+
topPt: top === void 0 ? DEFAULT_MARGIN_PT : twipsToPt(Number(top)),
|
|
1234
|
+
rightPt: right === void 0 ? DEFAULT_MARGIN_PT : twipsToPt(Number(right)),
|
|
1235
|
+
bottomPt: bottom === void 0 ? DEFAULT_MARGIN_PT : twipsToPt(Number(bottom)),
|
|
1236
|
+
leftPt: left === void 0 ? DEFAULT_MARGIN_PT : twipsToPt(Number(left))
|
|
1237
|
+
};
|
|
584
1238
|
}
|
|
585
|
-
function readListMembership(
|
|
586
|
-
const
|
|
587
|
-
if (pPr === void 0) return;
|
|
588
|
-
const numPr = childrenWithTag(pPr, "w:numPr")[0];
|
|
1239
|
+
function readListMembership(pPr) {
|
|
1240
|
+
const numPr = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:numPr")[0];
|
|
589
1241
|
if (numPr === void 0) return;
|
|
590
1242
|
const numIdEl = childrenWithTag(numPr, "w:numId")[0];
|
|
591
|
-
const numId = numIdEl
|
|
1243
|
+
const numId = numIdEl === void 0 ? void 0 : attr(numIdEl, "w:val");
|
|
592
1244
|
if (numId === void 0) return;
|
|
593
1245
|
const ilvlEl = childrenWithTag(numPr, "w:ilvl")[0];
|
|
594
|
-
const ilvlVal = ilvlEl
|
|
1246
|
+
const ilvlVal = ilvlEl === void 0 ? void 0 : attr(ilvlEl, "w:val");
|
|
595
1247
|
return {
|
|
596
1248
|
numId,
|
|
597
|
-
level: ilvlVal
|
|
1249
|
+
level: ilvlVal === void 0 ? 0 : Number(ilvlVal)
|
|
598
1250
|
};
|
|
599
1251
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
return result;
|
|
1252
|
+
function readToggle(el) {
|
|
1253
|
+
if (el === void 0) return false;
|
|
1254
|
+
const val = attr(el, "w:val");
|
|
1255
|
+
return val === void 0 || val !== "0" && val !== "false" && val !== "off";
|
|
605
1256
|
}
|
|
606
|
-
function
|
|
607
|
-
|
|
1257
|
+
function hasPageBreakBefore(paragraph) {
|
|
1258
|
+
const pPr = childrenWithTag(paragraph, "w:pPr")[0];
|
|
1259
|
+
return readToggle(pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:pageBreakBefore")[0]);
|
|
608
1260
|
}
|
|
609
|
-
function
|
|
610
|
-
|
|
1261
|
+
function readRunText(run) {
|
|
1262
|
+
let text = "";
|
|
1263
|
+
for (const child of run.children) {
|
|
1264
|
+
if (child.type !== "element") continue;
|
|
1265
|
+
if (child.tag === "w:t") text += textContent(child);
|
|
1266
|
+
else if (child.tag === "w:tab") text += " ";
|
|
1267
|
+
else if (child.tag === "w:br" || child.tag === "w:cr") text += "\n";
|
|
1268
|
+
}
|
|
1269
|
+
return text;
|
|
611
1270
|
}
|
|
612
|
-
function
|
|
613
|
-
|
|
1271
|
+
function readRun$1(run, paragraph, context) {
|
|
1272
|
+
const props = resolveRunProperties(run, paragraph, context);
|
|
1273
|
+
return {
|
|
1274
|
+
text: readRunText(run),
|
|
1275
|
+
bold: props.bold,
|
|
1276
|
+
italic: props.italic,
|
|
1277
|
+
underline: props.underline,
|
|
1278
|
+
strike: props.strike,
|
|
1279
|
+
fontFamily: props.fontFamily,
|
|
1280
|
+
sizePt: props.sizePt,
|
|
1281
|
+
color: props.color
|
|
1282
|
+
};
|
|
614
1283
|
}
|
|
615
|
-
function
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
1284
|
+
function readParagraphRuns(paragraph, context, rels) {
|
|
1285
|
+
const runs = [];
|
|
1286
|
+
let fieldState = "none";
|
|
1287
|
+
function walk(nodes, hyperlinkTarget) {
|
|
1288
|
+
for (const node of nodes) {
|
|
1289
|
+
if (node.type !== "element") continue;
|
|
1290
|
+
if (node.tag === "w:r") {
|
|
1291
|
+
const fldChar = childrenWithTag(node, "w:fldChar")[0];
|
|
1292
|
+
if (fldChar !== void 0) {
|
|
1293
|
+
const type = attr(fldChar, "w:fldCharType");
|
|
1294
|
+
if (type === "begin") fieldState = "code";
|
|
1295
|
+
else if (type === "separate") fieldState = "result";
|
|
1296
|
+
else if (type === "end") fieldState = "none";
|
|
1297
|
+
continue;
|
|
1298
|
+
}
|
|
1299
|
+
if (fieldState === "code") continue;
|
|
1300
|
+
const run = readRun$1(node, paragraph, context);
|
|
1301
|
+
runs.push(hyperlinkTarget === void 0 ? run : {
|
|
1302
|
+
...run,
|
|
1303
|
+
hyperlink: hyperlinkTarget
|
|
1304
|
+
});
|
|
1305
|
+
} else if (node.tag === "w:fldSimple") walk(node.children, hyperlinkTarget);
|
|
1306
|
+
else if (node.tag === "w:hyperlink") {
|
|
1307
|
+
const rId = attr(node, "r:id");
|
|
1308
|
+
const target = rId === void 0 ? void 0 : rels.get(rId)?.target;
|
|
1309
|
+
walk(node.children, target ?? hyperlinkTarget);
|
|
1310
|
+
} else if (node.tag === "w:ins") walk(node.children, hyperlinkTarget);
|
|
1311
|
+
}
|
|
619
1312
|
}
|
|
1313
|
+
walk(paragraph.children, void 0);
|
|
1314
|
+
return runs;
|
|
620
1315
|
}
|
|
621
|
-
function
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
1316
|
+
function readParagraph$1(paragraph, context, rels) {
|
|
1317
|
+
const pPr = childrenWithTag(paragraph, "w:pPr")[0];
|
|
1318
|
+
const pStyleEl = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:pStyle")[0];
|
|
1319
|
+
const props = resolveParagraphProperties(paragraph, context);
|
|
1320
|
+
return {
|
|
1321
|
+
kind: "paragraph",
|
|
1322
|
+
runs: readParagraphRuns(paragraph, context, rels),
|
|
1323
|
+
styleId: pStyleEl === void 0 ? void 0 : attr(pStyleEl, "w:val"),
|
|
1324
|
+
alignment: props.alignment,
|
|
1325
|
+
list: readListMembership(pPr),
|
|
1326
|
+
spacingBeforePt: props.spacingBeforePt,
|
|
1327
|
+
spacingAfterPt: props.spacingAfterPt,
|
|
1328
|
+
lineSpacing: props.lineSpacing,
|
|
1329
|
+
indentLeftPt: props.indentLeftPt,
|
|
1330
|
+
indentFirstLinePt: props.indentFirstLinePt
|
|
1331
|
+
};
|
|
625
1332
|
}
|
|
626
|
-
function
|
|
627
|
-
const
|
|
628
|
-
const
|
|
1333
|
+
function readCellShading(tcPr) {
|
|
1334
|
+
const shd = tcPr === void 0 ? void 0 : childrenWithTag(tcPr, "w:shd")[0];
|
|
1335
|
+
const fill = shd === void 0 ? void 0 : attr(shd, "w:fill");
|
|
1336
|
+
return fill === void 0 || fill === "auto" || fill === "none" ? void 0 : rgbHexToColor(fill);
|
|
1337
|
+
}
|
|
1338
|
+
function readRawCell(tc, context, rels) {
|
|
1339
|
+
const tcPr = childrenWithTag(tc, "w:tcPr")[0];
|
|
1340
|
+
const gridSpanEl = tcPr === void 0 ? void 0 : childrenWithTag(tcPr, "w:gridSpan")[0];
|
|
1341
|
+
const gridSpanVal = gridSpanEl === void 0 ? void 0 : attr(gridSpanEl, "w:val");
|
|
1342
|
+
const vMerge = tcPr === void 0 ? void 0 : childrenWithTag(tcPr, "w:vMerge")[0];
|
|
1343
|
+
const vMergeVal = vMerge === void 0 ? void 0 : attr(vMerge, "w:val") ?? "continue";
|
|
1344
|
+
return {
|
|
1345
|
+
gridSpan: gridSpanVal === void 0 ? 1 : Number(gridSpanVal),
|
|
1346
|
+
isVMergeContinuation: vMergeVal === "continue",
|
|
1347
|
+
background: readCellShading(tcPr),
|
|
1348
|
+
blocks: readBodyBlocks(tc.children, context, rels)
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
function readTable$1(tbl, context, rels) {
|
|
1352
|
+
const tblGrid = childrenWithTag(tbl, "w:tblGrid")[0];
|
|
1353
|
+
const columnWidthsPt = tblGrid === void 0 ? [] : childrenWithTag(tblGrid, "w:gridCol").map((col) => twipsToPt(Number(attr(col, "w:w") ?? "0")));
|
|
1354
|
+
const rawRows = childrenWithTag(tbl, "w:tr").map((tr) => childrenWithTag(tr, "w:tc").map((tc) => readRawCell(tc, context, rels)));
|
|
1355
|
+
const rowColumnIndices = rawRows.map((row) => {
|
|
1356
|
+
const indices = [];
|
|
1357
|
+
let col = 0;
|
|
1358
|
+
for (const cell of row) {
|
|
1359
|
+
indices.push(col);
|
|
1360
|
+
col += cell.gridSpan;
|
|
1361
|
+
}
|
|
1362
|
+
return indices;
|
|
1363
|
+
});
|
|
629
1364
|
return {
|
|
630
|
-
|
|
631
|
-
|
|
1365
|
+
kind: "table",
|
|
1366
|
+
columnWidthsPt,
|
|
1367
|
+
rows: rawRows.map((row, rowIndex) => ({ cells: row.map((cell, cellIndex) => {
|
|
1368
|
+
if (cell.isVMergeContinuation) return { blocks: [] };
|
|
1369
|
+
const colIndex = rowColumnIndices[rowIndex][cellIndex];
|
|
1370
|
+
let rowSpan = 1;
|
|
1371
|
+
for (let r = rowIndex + 1; r < rawRows.length; r++) {
|
|
1372
|
+
const matchIndex = rowColumnIndices[r].indexOf(colIndex);
|
|
1373
|
+
if (!(matchIndex === -1 ? void 0 : rawRows[r][matchIndex])?.isVMergeContinuation) break;
|
|
1374
|
+
rowSpan++;
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
blocks: cell.blocks,
|
|
1378
|
+
colSpan: cell.gridSpan > 1 ? cell.gridSpan : void 0,
|
|
1379
|
+
rowSpan: rowSpan > 1 ? rowSpan : void 0,
|
|
1380
|
+
background: cell.background
|
|
1381
|
+
};
|
|
1382
|
+
}) }))
|
|
632
1383
|
};
|
|
633
1384
|
}
|
|
1385
|
+
function readBodyBlocks(nodes, context, rels) {
|
|
1386
|
+
const blocks = [];
|
|
1387
|
+
for (const node of nodes) {
|
|
1388
|
+
if (node.type !== "element") continue;
|
|
1389
|
+
if (node.tag === "w:p") {
|
|
1390
|
+
if (hasPageBreakBefore(node)) blocks.push({ kind: "pageBreak" });
|
|
1391
|
+
blocks.push(readParagraph$1(node, context, rels));
|
|
1392
|
+
} else if (node.tag === "w:tbl") blocks.push(readTable$1(node, context, rels));
|
|
1393
|
+
else if (node.tag === "w:sdt") {
|
|
1394
|
+
const sdtContent = childrenWithTag(node, "w:sdtContent")[0];
|
|
1395
|
+
if (sdtContent !== void 0) blocks.push(...readBodyBlocks(sdtContent.children, context, rels));
|
|
1396
|
+
} else if (node.tag === "w:ins") blocks.push(...readBodyBlocks(node.children, context, rels));
|
|
1397
|
+
else if (node.tag === "mc:AlternateContent") {
|
|
1398
|
+
const target = childrenWithTag(node, "mc:Fallback")[0] ?? childrenWithTag(node, "mc:Choice")[0];
|
|
1399
|
+
if (target !== void 0) blocks.push(...readBodyBlocks(target.children, context, rels));
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
return blocks;
|
|
1403
|
+
}
|
|
1404
|
+
function readSections(body, context, rels) {
|
|
1405
|
+
const sections = [];
|
|
1406
|
+
let currentBlocks = [];
|
|
1407
|
+
for (const node of body.children) {
|
|
1408
|
+
if (node.type !== "element") continue;
|
|
1409
|
+
if (node.tag === "w:sectPr") {
|
|
1410
|
+
sections.push({
|
|
1411
|
+
pageSize: readPageSize(node),
|
|
1412
|
+
margins: readMargins(node),
|
|
1413
|
+
blocks: currentBlocks
|
|
1414
|
+
});
|
|
1415
|
+
currentBlocks = [];
|
|
1416
|
+
continue;
|
|
1417
|
+
}
|
|
1418
|
+
if (node.tag === "w:p") {
|
|
1419
|
+
const pPr = childrenWithTag(node, "w:pPr")[0];
|
|
1420
|
+
const sectPr = pPr === void 0 ? void 0 : childrenWithTag(pPr, "w:sectPr")[0];
|
|
1421
|
+
if (hasPageBreakBefore(node)) currentBlocks.push({ kind: "pageBreak" });
|
|
1422
|
+
currentBlocks.push(readParagraph$1(node, context, rels));
|
|
1423
|
+
if (sectPr !== void 0) {
|
|
1424
|
+
sections.push({
|
|
1425
|
+
pageSize: readPageSize(sectPr),
|
|
1426
|
+
margins: readMargins(sectPr),
|
|
1427
|
+
blocks: currentBlocks
|
|
1428
|
+
});
|
|
1429
|
+
currentBlocks = [];
|
|
1430
|
+
}
|
|
1431
|
+
continue;
|
|
1432
|
+
}
|
|
1433
|
+
currentBlocks.push(...readBodyBlocks([node], context, rels));
|
|
1434
|
+
}
|
|
1435
|
+
if (currentBlocks.length > 0 || sections.length === 0) sections.push({
|
|
1436
|
+
pageSize: PAGE_SIZE_LETTER,
|
|
1437
|
+
margins: DEFAULT_MARGINS,
|
|
1438
|
+
blocks: currentBlocks
|
|
1439
|
+
});
|
|
1440
|
+
return sections;
|
|
1441
|
+
}
|
|
1442
|
+
function readDocumentTheme(pkg, docRels) {
|
|
1443
|
+
for (const rel of docRels.values()) if (rel.type.endsWith(THEME_REL_SUFFIX$1)) {
|
|
1444
|
+
const themeRoot = rootElement(pkg.parts[rel.target]);
|
|
1445
|
+
if (themeRoot !== void 0) return readTheme(themeRoot);
|
|
1446
|
+
}
|
|
1447
|
+
return EMPTY_THEME;
|
|
1448
|
+
}
|
|
634
1449
|
function readComment(comment) {
|
|
635
1450
|
const author = attr(comment, "w:author");
|
|
636
1451
|
const result = { text: elementsWithTag(comment.children, "w:t").map(textContent).join("") };
|
|
@@ -670,14 +1485,18 @@ function readHeaderFooterText(pkg, prefix) {
|
|
|
670
1485
|
return out;
|
|
671
1486
|
}
|
|
672
1487
|
function readDocx(pkg) {
|
|
673
|
-
const
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1488
|
+
const documentRoot = rootElement(pkg.parts[DOCUMENT_PART_PATH]);
|
|
1489
|
+
if (documentRoot === void 0) throw new Error(`readDocx: package has no ${DOCUMENT_PART_PATH} part`);
|
|
1490
|
+
const body = childrenWithTag(documentRoot, "w:body")[0];
|
|
1491
|
+
if (body === void 0) throw new Error(`readDocx: ${DOCUMENT_PART_PATH} has no w:body element`);
|
|
1492
|
+
const docRels = resolveRelationships(pkg, DOCUMENT_PART_PATH);
|
|
1493
|
+
const context = {
|
|
1494
|
+
stylesRoot: rootElement(pkg.parts[STYLES_PART_PATH]),
|
|
1495
|
+
theme: readDocumentTheme(pkg, docRels)
|
|
1496
|
+
};
|
|
1497
|
+
return {
|
|
1498
|
+
metadata: readCoreProperties(pkg),
|
|
1499
|
+
sections: readSections(body, context, docRels),
|
|
681
1500
|
comments: readComments(pkg),
|
|
682
1501
|
footnotes: readFootnotes(pkg),
|
|
683
1502
|
headers: readHeaderFooterText(pkg, "word/header"),
|
|
@@ -685,72 +1504,434 @@ function readDocx(pkg) {
|
|
|
685
1504
|
};
|
|
686
1505
|
}
|
|
687
1506
|
//#endregion
|
|
688
|
-
//#region src/typed/pptx.ts
|
|
689
|
-
const
|
|
690
|
-
const
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
1507
|
+
//#region src/typed/pptx/inherit.ts
|
|
1508
|
+
const SLIDE_LAYOUT_REL_SUFFIX = "/slideLayout";
|
|
1509
|
+
const SLIDE_MASTER_REL_SUFFIX = "/slideMaster";
|
|
1510
|
+
const THEME_REL_SUFFIX = "/theme";
|
|
1511
|
+
function findRelTarget(pkg, partPath, typeSuffix) {
|
|
1512
|
+
for (const rel of resolveRelationships(pkg, partPath).values()) if (rel.type.endsWith(typeSuffix)) return rel.target;
|
|
1513
|
+
}
|
|
1514
|
+
function resolveSlideInheritance(pkg, slidePath) {
|
|
1515
|
+
const layoutPath = findRelTarget(pkg, slidePath, SLIDE_LAYOUT_REL_SUFFIX);
|
|
1516
|
+
const layoutRoot = layoutPath === void 0 ? void 0 : rootElement(pkg.parts[layoutPath]);
|
|
1517
|
+
const masterPath = layoutPath === void 0 ? void 0 : findRelTarget(pkg, layoutPath, SLIDE_MASTER_REL_SUFFIX);
|
|
1518
|
+
const masterRoot = masterPath === void 0 ? void 0 : rootElement(pkg.parts[masterPath]);
|
|
1519
|
+
const themePath = masterPath === void 0 ? void 0 : findRelTarget(pkg, masterPath, THEME_REL_SUFFIX);
|
|
1520
|
+
const themeRoot = themePath === void 0 ? void 0 : rootElement(pkg.parts[themePath]);
|
|
1521
|
+
return {
|
|
1522
|
+
layoutRoot,
|
|
1523
|
+
masterRoot,
|
|
1524
|
+
theme: themeRoot === void 0 ? EMPTY_THEME : readTheme(themeRoot),
|
|
1525
|
+
colorMap: readColorMap(masterRoot === void 0 ? void 0 : childrenWithTag(masterRoot, "p:clrMap")[0])
|
|
1526
|
+
};
|
|
1527
|
+
}
|
|
1528
|
+
const TYPE_NORMALIZATION = /* @__PURE__ */ new Map([["ctrTitle", "title"], ["subTitle", "body"]]);
|
|
1529
|
+
function normalizePlaceholderType(type) {
|
|
1530
|
+
return type === void 0 ? void 0 : TYPE_NORMALIZATION.get(type) ?? type;
|
|
1531
|
+
}
|
|
1532
|
+
function readPlaceholderKey(shape) {
|
|
1533
|
+
const ph = elementsWithTag([shape], "p:ph")[0];
|
|
1534
|
+
return ph === void 0 ? void 0 : {
|
|
1535
|
+
type: attr(ph, "type"),
|
|
1536
|
+
idx: attr(ph, "idx")
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
function shapesOf(root) {
|
|
1540
|
+
return root === void 0 ? [] : elementsWithTag([root], "p:sp");
|
|
1541
|
+
}
|
|
1542
|
+
function findMatchingPlaceholder(root, key) {
|
|
1543
|
+
const shapes = shapesOf(root);
|
|
1544
|
+
if (key.idx !== void 0) {
|
|
1545
|
+
const byIdx = shapes.find((shape) => readPlaceholderKey(shape)?.idx === key.idx);
|
|
1546
|
+
if (byIdx !== void 0) return byIdx;
|
|
1547
|
+
}
|
|
1548
|
+
const normalizedTarget = normalizePlaceholderType(key.type);
|
|
1549
|
+
if (normalizedTarget === void 0) return;
|
|
1550
|
+
return shapes.find((shape) => normalizePlaceholderType(readPlaceholderKey(shape)?.type) === normalizedTarget);
|
|
1551
|
+
}
|
|
1552
|
+
function shapeXfrm(shape) {
|
|
1553
|
+
if (shape === void 0) return;
|
|
1554
|
+
const spPr = childrenWithTag(shape, "p:spPr")[0];
|
|
1555
|
+
return spPr === void 0 ? void 0 : readXfrm(childrenWithTag(spPr, "a:xfrm")[0]);
|
|
1556
|
+
}
|
|
1557
|
+
function resolvePlaceholderXfrm(key, context) {
|
|
1558
|
+
return shapeXfrm(findMatchingPlaceholder(context.layoutRoot, key)) ?? shapeXfrm(findMatchingPlaceholder(context.masterRoot, key));
|
|
1559
|
+
}
|
|
1560
|
+
function readRunPropertiesFromElement(rPr, context) {
|
|
1561
|
+
const sz = attr(rPr, "sz");
|
|
1562
|
+
const latin = childrenWithTag(rPr, "a:latin")[0];
|
|
1563
|
+
const typeface = latin === void 0 ? void 0 : attr(latin, "typeface");
|
|
1564
|
+
const solidFill = childrenWithTag(rPr, "a:solidFill")[0];
|
|
1565
|
+
const bold = attr(rPr, "b");
|
|
1566
|
+
const italic = attr(rPr, "i");
|
|
1567
|
+
return {
|
|
1568
|
+
fontFamily: typeface === void 0 ? void 0 : resolveThemeFontReference(typeface, context.theme),
|
|
1569
|
+
sizePt: sz === void 0 ? void 0 : drawingMlFontSizeToPt(Number(sz)),
|
|
1570
|
+
bold: bold === void 0 ? void 0 : bold === "1",
|
|
1571
|
+
italic: italic === void 0 ? void 0 : italic === "1",
|
|
1572
|
+
color: readSolidFillColor(solidFill, context.colorMap, context.theme)
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
function txStyleTagFor(placeholderType) {
|
|
1576
|
+
const normalized = normalizePlaceholderType(placeholderType);
|
|
1577
|
+
if (normalized === "title") return "p:titleStyle";
|
|
1578
|
+
if (normalized === "body") return "p:bodyStyle";
|
|
1579
|
+
return "p:otherStyle";
|
|
1580
|
+
}
|
|
1581
|
+
function levelTag(level) {
|
|
1582
|
+
return `a:lvl${Math.min(Math.max(level, 0), 8) + 1}pPr`;
|
|
1583
|
+
}
|
|
1584
|
+
function resolveDefaultRunProperties(placeholderType, level, context) {
|
|
1585
|
+
if (context.masterRoot === void 0) return {};
|
|
1586
|
+
const txStyles = childrenWithTag(context.masterRoot, "p:txStyles")[0];
|
|
1587
|
+
const styleEl = txStyles === void 0 ? void 0 : childrenWithTag(txStyles, txStyleTagFor(placeholderType))[0];
|
|
1588
|
+
const lvlPPr = styleEl === void 0 ? void 0 : childrenWithTag(styleEl, levelTag(level))[0];
|
|
1589
|
+
const defRPr = lvlPPr === void 0 ? void 0 : childrenWithTag(lvlPPr, "a:defRPr")[0];
|
|
1590
|
+
return defRPr === void 0 ? {} : readRunPropertiesFromElement(defRPr, context);
|
|
1591
|
+
}
|
|
1592
|
+
//#endregion
|
|
1593
|
+
//#region src/typed/pptx/read.ts
|
|
1594
|
+
const PptxDocumentSchema = zod.z.object({
|
|
1595
|
+
metadata: DocumentMetadataSchema,
|
|
1596
|
+
slides: zod.z.array(ContentSlideSchema)
|
|
699
1597
|
});
|
|
700
|
-
const
|
|
701
|
-
const
|
|
702
|
-
function
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
1598
|
+
const PRESENTATION_PATH = "ppt/presentation.xml";
|
|
1599
|
+
const TABLE_GRAPHIC_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
|
|
1600
|
+
function readSlideSize(presentationRoot) {
|
|
1601
|
+
const sldSz = presentationRoot === void 0 ? void 0 : childrenWithTag(presentationRoot, "p:sldSz")[0];
|
|
1602
|
+
const cx = sldSz === void 0 ? void 0 : attr(sldSz, "cx");
|
|
1603
|
+
const cy = sldSz === void 0 ? void 0 : attr(sldSz, "cy");
|
|
1604
|
+
return cx === void 0 || cy === void 0 ? SLIDE_SIZE_WIDESCREEN : {
|
|
1605
|
+
widthPt: emuToPt(Number(cx)),
|
|
1606
|
+
heightPt: emuToPt(Number(cy))
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1609
|
+
function readSlidePathsInOrder(pkg, presentationRoot) {
|
|
1610
|
+
if (presentationRoot === void 0) return [];
|
|
1611
|
+
const sldIdLst = childrenWithTag(presentationRoot, "p:sldIdLst")[0];
|
|
1612
|
+
if (sldIdLst === void 0) return [];
|
|
1613
|
+
const presentationRels = resolveRelationships(pkg, PRESENTATION_PATH);
|
|
1614
|
+
const paths = [];
|
|
1615
|
+
for (const sldId of childrenWithTag(sldIdLst, "p:sldId")) {
|
|
1616
|
+
const rId = attr(sldId, "r:id");
|
|
1617
|
+
const rel = rId === void 0 ? void 0 : presentationRels.get(rId);
|
|
1618
|
+
if (rel !== void 0) paths.push(rel.target);
|
|
1619
|
+
}
|
|
1620
|
+
return paths;
|
|
1621
|
+
}
|
|
1622
|
+
function shapeName(shape) {
|
|
1623
|
+
const cNvPr = elementsWithTag([shape], "p:cNvPr")[0];
|
|
1624
|
+
return cNvPr === void 0 ? void 0 : attr(cNvPr, "name");
|
|
1625
|
+
}
|
|
1626
|
+
function mergeRunProperties(base, override) {
|
|
1627
|
+
return {
|
|
1628
|
+
fontFamily: override.fontFamily ?? base.fontFamily,
|
|
1629
|
+
sizePt: override.sizePt ?? base.sizePt,
|
|
1630
|
+
bold: override.bold ?? base.bold,
|
|
1631
|
+
italic: override.italic ?? base.italic,
|
|
1632
|
+
color: override.color ?? base.color
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
function isUnderlined(rPr) {
|
|
1636
|
+
if (rPr === void 0) return;
|
|
1637
|
+
const u = attr(rPr, "u");
|
|
1638
|
+
return u === void 0 ? void 0 : u !== "none";
|
|
1639
|
+
}
|
|
1640
|
+
function isStrikethrough(rPr) {
|
|
1641
|
+
if (rPr === void 0) return;
|
|
1642
|
+
const strike = attr(rPr, "strike");
|
|
1643
|
+
return strike === void 0 ? void 0 : strike !== "noStrike";
|
|
1644
|
+
}
|
|
1645
|
+
function readHyperlink(rPr, slideRels) {
|
|
1646
|
+
if (rPr === void 0) return;
|
|
1647
|
+
const hlink = childrenWithTag(rPr, "a:hlinkClick")[0];
|
|
1648
|
+
const rId = hlink === void 0 ? void 0 : attr(hlink, "r:id");
|
|
1649
|
+
const rel = rId === void 0 ? void 0 : slideRels.get(rId);
|
|
1650
|
+
return rel?.targetMode === "External" ? rel.target : void 0;
|
|
1651
|
+
}
|
|
1652
|
+
function readRun(runEl, cascadeBase, context, slideRels) {
|
|
1653
|
+
const rPr = childrenWithTag(runEl, "a:rPr")[0];
|
|
1654
|
+
const merged = mergeRunProperties(cascadeBase, rPr === void 0 ? {} : readRunPropertiesFromElement(rPr, context));
|
|
1655
|
+
const tEl = childrenWithTag(runEl, "a:t")[0];
|
|
1656
|
+
return {
|
|
1657
|
+
text: tEl === void 0 ? "" : textContent(tEl),
|
|
1658
|
+
bold: merged.bold,
|
|
1659
|
+
italic: merged.italic,
|
|
1660
|
+
underline: isUnderlined(rPr),
|
|
1661
|
+
strike: isStrikethrough(rPr),
|
|
1662
|
+
fontFamily: merged.fontFamily,
|
|
1663
|
+
sizePt: merged.sizePt,
|
|
1664
|
+
color: merged.color,
|
|
1665
|
+
hyperlink: readHyperlink(rPr, slideRels)
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
function readAlignment(algn) {
|
|
1669
|
+
if (algn === "l") return "left";
|
|
1670
|
+
if (algn === "ctr") return "center";
|
|
1671
|
+
if (algn === "r") return "right";
|
|
1672
|
+
if (algn === "just" || algn === "justLow") return "justify";
|
|
1673
|
+
}
|
|
1674
|
+
function readAbsoluteSpacingPt(spc) {
|
|
1675
|
+
if (spc === void 0) return;
|
|
1676
|
+
const pts = childrenWithTag(spc, "a:spcPts")[0];
|
|
1677
|
+
const val = pts === void 0 ? void 0 : attr(pts, "val");
|
|
1678
|
+
return val === void 0 ? void 0 : drawingMlFontSizeToPt(Number(val));
|
|
1679
|
+
}
|
|
1680
|
+
function readLineSpacingMultiplier(pPr) {
|
|
1681
|
+
const lnSpc = pPr === void 0 ? void 0 : childrenWithTag(pPr, "a:lnSpc")[0];
|
|
1682
|
+
const pct = lnSpc === void 0 ? void 0 : childrenWithTag(lnSpc, "a:spcPct")[0];
|
|
1683
|
+
const val = pct === void 0 ? void 0 : attr(pct, "val");
|
|
1684
|
+
return val === void 0 ? void 0 : Number(val) / 1e5;
|
|
1685
|
+
}
|
|
1686
|
+
function readParagraph(pEl, placeholderType, context, slideRels) {
|
|
1687
|
+
const pPr = childrenWithTag(pEl, "a:pPr")[0];
|
|
1688
|
+
const masterDefaults = resolveDefaultRunProperties(placeholderType, pPr === void 0 ? 0 : Number(attr(pPr, "lvl") ?? "0"), context);
|
|
1689
|
+
const pPrDefRPr = pPr === void 0 ? void 0 : childrenWithTag(pPr, "a:defRPr")[0];
|
|
1690
|
+
const paragraphDefaults = pPrDefRPr === void 0 ? masterDefaults : mergeRunProperties(masterDefaults, readRunPropertiesFromElement(pPrDefRPr, context));
|
|
1691
|
+
const runs = [];
|
|
1692
|
+
for (const child of pEl.children) {
|
|
1693
|
+
if (child.type !== "element") continue;
|
|
1694
|
+
if (child.tag === "a:r" || child.tag === "a:fld") runs.push(readRun(child, paragraphDefaults, context, slideRels));
|
|
1695
|
+
else if (child.tag === "a:br") runs.push({ text: "\n" });
|
|
1696
|
+
}
|
|
1697
|
+
const marL = pPr === void 0 ? void 0 : attr(pPr, "marL");
|
|
1698
|
+
const indent = pPr === void 0 ? void 0 : attr(pPr, "indent");
|
|
1699
|
+
return {
|
|
1700
|
+
kind: "paragraph",
|
|
1701
|
+
runs,
|
|
1702
|
+
alignment: pPr === void 0 ? void 0 : readAlignment(attr(pPr, "algn")),
|
|
1703
|
+
spacingBeforePt: readAbsoluteSpacingPt(pPr === void 0 ? void 0 : childrenWithTag(pPr, "a:spcBef")[0]),
|
|
1704
|
+
spacingAfterPt: readAbsoluteSpacingPt(pPr === void 0 ? void 0 : childrenWithTag(pPr, "a:spcAft")[0]),
|
|
1705
|
+
lineSpacing: readLineSpacingMultiplier(pPr),
|
|
1706
|
+
indentLeftPt: marL === void 0 ? void 0 : emuToPt(Number(marL)),
|
|
1707
|
+
indentFirstLinePt: indent === void 0 ? void 0 : emuToPt(Number(indent))
|
|
1708
|
+
};
|
|
1709
|
+
}
|
|
1710
|
+
function textBodyParagraphs(txBody, placeholderType, context, slideRels) {
|
|
1711
|
+
return txBody === void 0 ? [] : childrenWithTag(txBody, "a:p").map((p) => readParagraph(p, placeholderType, context, slideRels));
|
|
1712
|
+
}
|
|
1713
|
+
const DEFAULT_INSET_LEFT_RIGHT_EMU = 91440;
|
|
1714
|
+
const DEFAULT_INSET_TOP_BOTTOM_EMU = 45720;
|
|
1715
|
+
const NO_TEXT_BODY_EXTRAS = {
|
|
1716
|
+
insetLeftPt: 0,
|
|
1717
|
+
insetTopPt: 0,
|
|
1718
|
+
insetRightPt: 0,
|
|
1719
|
+
insetBottomPt: 0,
|
|
1720
|
+
fontScale: void 0,
|
|
1721
|
+
lineSpacingReduction: void 0
|
|
1722
|
+
};
|
|
1723
|
+
function readShapeTextExtras(txBody) {
|
|
1724
|
+
if (txBody === void 0) return NO_TEXT_BODY_EXTRAS;
|
|
1725
|
+
const bodyPr = childrenWithTag(txBody, "a:bodyPr")[0];
|
|
1726
|
+
const lIns = bodyPr === void 0 ? void 0 : attr(bodyPr, "lIns");
|
|
1727
|
+
const tIns = bodyPr === void 0 ? void 0 : attr(bodyPr, "tIns");
|
|
1728
|
+
const rIns = bodyPr === void 0 ? void 0 : attr(bodyPr, "rIns");
|
|
1729
|
+
const bIns = bodyPr === void 0 ? void 0 : attr(bodyPr, "bIns");
|
|
1730
|
+
const normAutofit = bodyPr === void 0 ? void 0 : childrenWithTag(bodyPr, "a:normAutofit")[0];
|
|
1731
|
+
const fontScale = normAutofit === void 0 ? void 0 : attr(normAutofit, "fontScale");
|
|
1732
|
+
const lnSpcReduction = normAutofit === void 0 ? void 0 : attr(normAutofit, "lnSpcReduction");
|
|
1733
|
+
return {
|
|
1734
|
+
insetLeftPt: emuToPt(lIns === void 0 ? DEFAULT_INSET_LEFT_RIGHT_EMU : Number(lIns)),
|
|
1735
|
+
insetTopPt: emuToPt(tIns === void 0 ? DEFAULT_INSET_TOP_BOTTOM_EMU : Number(tIns)),
|
|
1736
|
+
insetRightPt: emuToPt(rIns === void 0 ? DEFAULT_INSET_LEFT_RIGHT_EMU : Number(rIns)),
|
|
1737
|
+
insetBottomPt: emuToPt(bIns === void 0 ? DEFAULT_INSET_TOP_BOTTOM_EMU : Number(bIns)),
|
|
1738
|
+
fontScale: fontScale === void 0 ? void 0 : Number(fontScale) / 1e5,
|
|
1739
|
+
lineSpacingReduction: lnSpcReduction === void 0 ? void 0 : Number(lnSpcReduction) / 1e5
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
function resolveShapeFrame(shape, context, parentTransform) {
|
|
1743
|
+
const key = readPlaceholderKey(shape);
|
|
1744
|
+
const spPr = childrenWithTag(shape, "p:spPr")[0];
|
|
1745
|
+
const xfrm = (spPr === void 0 ? void 0 : readXfrm(childrenWithTag(spPr, "a:xfrm")[0])) ?? (key === void 0 ? void 0 : resolvePlaceholderXfrm(key, context));
|
|
1746
|
+
if (xfrm === void 0) return;
|
|
1747
|
+
const localFrame = {
|
|
1748
|
+
xPt: xfrm.xPt,
|
|
1749
|
+
yPt: xfrm.yPt,
|
|
1750
|
+
widthPt: xfrm.widthPt,
|
|
1751
|
+
heightPt: xfrm.heightPt
|
|
1752
|
+
};
|
|
1753
|
+
return {
|
|
1754
|
+
frame: parentTransform === void 0 ? localFrame : applyGroupTransform(parentTransform, localFrame),
|
|
1755
|
+
rotationDeg: xfrm.rotationDeg === 0 ? void 0 : xfrm.rotationDeg
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
function readSpShape(sp, context, slideRels, parentTransform) {
|
|
1759
|
+
const resolved = resolveShapeFrame(sp, context, parentTransform);
|
|
1760
|
+
if (resolved === void 0) return;
|
|
1761
|
+
const key = readPlaceholderKey(sp);
|
|
1762
|
+
const txBody = childrenWithTag(sp, "p:txBody")[0];
|
|
1763
|
+
const blocks = textBodyParagraphs(txBody, key?.type, context, slideRels);
|
|
1764
|
+
const extras = readShapeTextExtras(txBody);
|
|
1765
|
+
return {
|
|
1766
|
+
name: shapeName(sp),
|
|
1767
|
+
frame: resolved.frame,
|
|
1768
|
+
rotationDeg: resolved.rotationDeg,
|
|
1769
|
+
...extras,
|
|
1770
|
+
blocks
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
function readPicShape(pic, context, slideRels, pkg, parentTransform) {
|
|
1774
|
+
const resolved = resolveShapeFrame(pic, context, parentTransform);
|
|
1775
|
+
if (resolved === void 0) return;
|
|
1776
|
+
const blipFill = childrenWithTag(pic, "p:blipFill")[0];
|
|
1777
|
+
const blip = blipFill === void 0 ? void 0 : childrenWithTag(blipFill, "a:blip")[0];
|
|
1778
|
+
const rId = blip === void 0 ? void 0 : attr(blip, "r:embed");
|
|
1779
|
+
const rel = rId === void 0 ? void 0 : slideRels.get(rId);
|
|
1780
|
+
const mediaPart = rel === void 0 ? void 0 : pkg.parts[rel.target];
|
|
1781
|
+
const blocks = [];
|
|
1782
|
+
if (mediaPart?.kind === "binary") {
|
|
1783
|
+
const format = sniffImageFormat(base64ToBytes(mediaPart.base64));
|
|
1784
|
+
if (format !== void 0) {
|
|
1785
|
+
const image = {
|
|
1786
|
+
kind: "image",
|
|
1787
|
+
format,
|
|
1788
|
+
base64: mediaPart.base64,
|
|
1789
|
+
widthPt: resolved.frame.widthPt,
|
|
1790
|
+
heightPt: resolved.frame.heightPt
|
|
1791
|
+
};
|
|
1792
|
+
blocks.push(image);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
return {
|
|
1796
|
+
name: shapeName(pic),
|
|
1797
|
+
frame: resolved.frame,
|
|
1798
|
+
rotationDeg: resolved.rotationDeg,
|
|
1799
|
+
...NO_TEXT_BODY_EXTRAS,
|
|
1800
|
+
blocks
|
|
1801
|
+
};
|
|
706
1802
|
}
|
|
707
|
-
function
|
|
708
|
-
|
|
1803
|
+
function readTableCell(tc, context, slideRels) {
|
|
1804
|
+
const hMerge = attr(tc, "hMerge");
|
|
1805
|
+
const vMerge = attr(tc, "vMerge");
|
|
1806
|
+
if (hMerge === "1" || vMerge === "1") return { blocks: [] };
|
|
1807
|
+
const tcPr = childrenWithTag(tc, "a:tcPr")[0];
|
|
1808
|
+
const background = readSolidFillColor(tcPr === void 0 ? void 0 : childrenWithTag(tcPr, "a:solidFill")[0], context.colorMap, context.theme);
|
|
1809
|
+
const txBody = childrenWithTag(tc, "a:txBody")[0];
|
|
1810
|
+
const gridSpan = attr(tc, "gridSpan");
|
|
1811
|
+
const rowSpan = attr(tc, "rowSpan");
|
|
1812
|
+
return {
|
|
1813
|
+
blocks: textBodyParagraphs(txBody, void 0, context, slideRels),
|
|
1814
|
+
colSpan: gridSpan === void 0 ? void 0 : Number(gridSpan),
|
|
1815
|
+
rowSpan: rowSpan === void 0 ? void 0 : Number(rowSpan),
|
|
1816
|
+
background
|
|
1817
|
+
};
|
|
709
1818
|
}
|
|
710
|
-
function
|
|
711
|
-
|
|
1819
|
+
function readTable(tbl, context, slideRels) {
|
|
1820
|
+
const tblGrid = childrenWithTag(tbl, "a:tblGrid")[0];
|
|
1821
|
+
const columnWidthsPt = tblGrid === void 0 ? [] : childrenWithTag(tblGrid, "a:gridCol").map((col) => emuToPt(Number(attr(col, "w") ?? "0")));
|
|
1822
|
+
return {
|
|
1823
|
+
kind: "table",
|
|
1824
|
+
rows: childrenWithTag(tbl, "a:tr").map((tr) => {
|
|
1825
|
+
const h = attr(tr, "h");
|
|
1826
|
+
return {
|
|
1827
|
+
cells: childrenWithTag(tr, "a:tc").map((tc) => readTableCell(tc, context, slideRels)),
|
|
1828
|
+
heightPt: h === void 0 ? void 0 : emuToPt(Number(h))
|
|
1829
|
+
};
|
|
1830
|
+
}),
|
|
1831
|
+
columnWidthsPt
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
function readGraphicFrameShape(gf, context, slideRels, parentTransform) {
|
|
1835
|
+
const xfrm = readXfrm(childrenWithTag(gf, "p:xfrm")[0]);
|
|
1836
|
+
if (xfrm === void 0) return;
|
|
1837
|
+
const localFrame = {
|
|
1838
|
+
xPt: xfrm.xPt,
|
|
1839
|
+
yPt: xfrm.yPt,
|
|
1840
|
+
widthPt: xfrm.widthPt,
|
|
1841
|
+
heightPt: xfrm.heightPt
|
|
1842
|
+
};
|
|
1843
|
+
const frame = parentTransform === void 0 ? localFrame : applyGroupTransform(parentTransform, localFrame);
|
|
1844
|
+
const rotationDeg = xfrm.rotationDeg === 0 ? void 0 : xfrm.rotationDeg;
|
|
1845
|
+
const graphic = childrenWithTag(gf, "a:graphic")[0];
|
|
1846
|
+
const graphicData = graphic === void 0 ? void 0 : childrenWithTag(graphic, "a:graphicData")[0];
|
|
1847
|
+
const tbl = (graphicData === void 0 ? void 0 : attr(graphicData, "uri")) === TABLE_GRAPHIC_URI && graphicData !== void 0 ? childrenWithTag(graphicData, "a:tbl")[0] : void 0;
|
|
1848
|
+
const blocks = tbl === void 0 ? [] : [readTable(tbl, context, slideRels)];
|
|
1849
|
+
return {
|
|
1850
|
+
name: shapeName(gf),
|
|
1851
|
+
frame,
|
|
1852
|
+
rotationDeg,
|
|
1853
|
+
...NO_TEXT_BODY_EXTRAS,
|
|
1854
|
+
blocks
|
|
1855
|
+
};
|
|
712
1856
|
}
|
|
713
|
-
function
|
|
714
|
-
|
|
1857
|
+
function walkShapeTreeChildren(children, parentTransform, context, slideRels, pkg, out) {
|
|
1858
|
+
for (const node of children) {
|
|
1859
|
+
if (node.type !== "element") continue;
|
|
1860
|
+
if (node.tag === "p:sp") {
|
|
1861
|
+
const shape = readSpShape(node, context, slideRels, parentTransform);
|
|
1862
|
+
if (shape !== void 0) out.push(shape);
|
|
1863
|
+
} else if (node.tag === "p:pic") {
|
|
1864
|
+
const shape = readPicShape(node, context, slideRels, pkg, parentTransform);
|
|
1865
|
+
if (shape !== void 0) out.push(shape);
|
|
1866
|
+
} else if (node.tag === "p:graphicFrame") {
|
|
1867
|
+
const shape = readGraphicFrameShape(node, context, slideRels, parentTransform);
|
|
1868
|
+
if (shape !== void 0) out.push(shape);
|
|
1869
|
+
} else if (node.tag === "p:grpSp") {
|
|
1870
|
+
const grpSpPr = childrenWithTag(node, "p:grpSpPr")[0];
|
|
1871
|
+
const composed = composeGroupTransform(readGroupXfrm(grpSpPr === void 0 ? void 0 : childrenWithTag(grpSpPr, "a:xfrm")[0]), parentTransform);
|
|
1872
|
+
walkShapeTreeChildren(node.children, composed, context, slideRels, pkg, out);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
715
1875
|
}
|
|
716
|
-
function
|
|
717
|
-
|
|
1876
|
+
function composeGroupTransform(own, parent) {
|
|
1877
|
+
if (own === void 0) return;
|
|
1878
|
+
if (parent === void 0) return own;
|
|
1879
|
+
const absolute = applyGroupTransform(parent, {
|
|
1880
|
+
xPt: own.offXPt,
|
|
1881
|
+
yPt: own.offYPt,
|
|
1882
|
+
widthPt: own.extWidthPt,
|
|
1883
|
+
heightPt: own.extHeightPt
|
|
1884
|
+
});
|
|
1885
|
+
return {
|
|
1886
|
+
...own,
|
|
1887
|
+
offXPt: absolute.xPt,
|
|
1888
|
+
offYPt: absolute.yPt,
|
|
1889
|
+
extWidthPt: absolute.widthPt,
|
|
1890
|
+
extHeightPt: absolute.heightPt
|
|
1891
|
+
};
|
|
718
1892
|
}
|
|
1893
|
+
const NOTES_SLIDE_REL_SUFFIX = "/notesSlide";
|
|
719
1894
|
function readNotes(pkg, slidePath) {
|
|
720
|
-
const rels = resolveRelationships(pkg, slidePath);
|
|
721
1895
|
let notesPath;
|
|
722
|
-
for (const rel of
|
|
1896
|
+
for (const rel of resolveRelationships(pkg, slidePath).values()) if (rel.type.endsWith(NOTES_SLIDE_REL_SUFFIX)) {
|
|
723
1897
|
notesPath = rel.target;
|
|
724
1898
|
break;
|
|
725
1899
|
}
|
|
726
1900
|
if (notesPath === void 0) return "";
|
|
727
|
-
const
|
|
728
|
-
if (
|
|
729
|
-
|
|
1901
|
+
const notesRoot = rootElement(pkg.parts[notesPath]);
|
|
1902
|
+
if (notesRoot === void 0) return "";
|
|
1903
|
+
const bodyShape = elementsWithTag([notesRoot], "p:sp").find((shape) => {
|
|
1904
|
+
const key = readPlaceholderKey(shape);
|
|
1905
|
+
return key !== void 0 && (key.type === void 0 || key.type === "body");
|
|
1906
|
+
});
|
|
1907
|
+
if (bodyShape !== void 0) {
|
|
1908
|
+
const txBody = childrenWithTag(bodyShape, "p:txBody")[0];
|
|
1909
|
+
if (txBody !== void 0) return elementsWithTag(txBody.children, "a:t").map(textContent).join("");
|
|
1910
|
+
}
|
|
1911
|
+
return elementsWithTag([notesRoot], "a:t").map(textContent).join("");
|
|
1912
|
+
}
|
|
1913
|
+
function readSlide(pkg, slidePath, size) {
|
|
1914
|
+
const slideRoot = rootElement(pkg.parts[slidePath]);
|
|
1915
|
+
const context = resolveSlideInheritance(pkg, slidePath);
|
|
1916
|
+
const slideRels = resolveRelationships(pkg, slidePath);
|
|
1917
|
+
const cSld = slideRoot === void 0 ? void 0 : childrenWithTag(slideRoot, "p:cSld")[0];
|
|
1918
|
+
const spTree = cSld === void 0 ? void 0 : childrenWithTag(cSld, "p:spTree")[0];
|
|
1919
|
+
const shapes = [];
|
|
1920
|
+
if (spTree !== void 0) walkShapeTreeChildren(spTree.children, void 0, context, slideRels, pkg, shapes);
|
|
1921
|
+
return {
|
|
1922
|
+
size,
|
|
1923
|
+
shapes,
|
|
1924
|
+
notes: readNotes(pkg, slidePath)
|
|
1925
|
+
};
|
|
730
1926
|
}
|
|
731
1927
|
function readPptx(pkg) {
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
const index = Number(captured);
|
|
740
|
-
const text = elementsWithTag(part.nodes, "a:t").map(textContent).join("");
|
|
741
|
-
const shapes = elementsWithTag(part.nodes, "p:sp").map(readShape);
|
|
742
|
-
const tables = elementsWithTag(part.nodes, "a:tbl").map(readTable);
|
|
743
|
-
const notes = readNotes(pkg, path);
|
|
744
|
-
found.push({
|
|
745
|
-
index,
|
|
746
|
-
text,
|
|
747
|
-
shapes,
|
|
748
|
-
tables,
|
|
749
|
-
notes
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
|
-
found.sort((a, b) => a.index - b.index);
|
|
753
|
-
return { slides: found };
|
|
1928
|
+
const presentationRoot = rootElement(pkg.parts[PRESENTATION_PATH]);
|
|
1929
|
+
const size = readSlideSize(presentationRoot);
|
|
1930
|
+
const slides = readSlidePathsInOrder(pkg, presentationRoot).map((slidePath) => readSlide(pkg, slidePath, size));
|
|
1931
|
+
return {
|
|
1932
|
+
metadata: readCoreProperties(pkg),
|
|
1933
|
+
slides
|
|
1934
|
+
};
|
|
754
1935
|
}
|
|
755
1936
|
//#endregion
|
|
756
1937
|
//#region src/typed/xlsx.ts
|
|
@@ -895,30 +2076,41 @@ function readXlsx(pkg) {
|
|
|
895
2076
|
};
|
|
896
2077
|
}
|
|
897
2078
|
//#endregion
|
|
2079
|
+
exports.AlignmentSchema = AlignmentSchema;
|
|
898
2080
|
exports.AttributeSchema = AttributeSchema;
|
|
899
2081
|
exports.BinaryPartSchema = BinaryPartSchema;
|
|
2082
|
+
exports.BoxSchema = BoxSchema;
|
|
2083
|
+
exports.COLOR_BLACK = COLOR_BLACK;
|
|
2084
|
+
exports.ColorSchema = ColorSchema;
|
|
900
2085
|
exports.CommentSchema = CommentSchema;
|
|
901
2086
|
exports.CompactPackageSchema = CompactPackageSchema;
|
|
902
2087
|
exports.CompactPartSchema = CompactPartSchema;
|
|
903
2088
|
exports.CompactXmlNodeSchema = CompactXmlNodeSchema;
|
|
2089
|
+
exports.ContentBlockSchema = ContentBlockSchema;
|
|
2090
|
+
exports.ContentImageBlockSchema = ContentImageBlockSchema;
|
|
2091
|
+
exports.ContentListMembershipSchema = ContentListMembershipSchema;
|
|
2092
|
+
exports.ContentPageBreakSchema = ContentPageBreakSchema;
|
|
2093
|
+
exports.ContentParagraphSchema = ContentParagraphSchema;
|
|
2094
|
+
exports.ContentRunSchema = ContentRunSchema;
|
|
2095
|
+
exports.ContentSectionSchema = ContentSectionSchema;
|
|
2096
|
+
exports.ContentShapeSchema = ContentShapeSchema;
|
|
2097
|
+
exports.ContentSlideSchema = ContentSlideSchema;
|
|
2098
|
+
exports.ContentTableCellSchema = ContentTableCellSchema;
|
|
2099
|
+
exports.ContentTableRowSchema = ContentTableRowSchema;
|
|
2100
|
+
exports.ContentTableSchema = ContentTableSchema;
|
|
904
2101
|
exports.DefinedNameSchema = DefinedNameSchema;
|
|
2102
|
+
exports.DocumentMetadataSchema = DocumentMetadataSchema;
|
|
905
2103
|
exports.DocxDocumentSchema = DocxDocumentSchema;
|
|
906
2104
|
exports.FootnoteSchema = FootnoteSchema;
|
|
907
|
-
exports.
|
|
908
|
-
exports.
|
|
2105
|
+
exports.MarginsSchema = MarginsSchema;
|
|
2106
|
+
exports.PAGE_SIZE_A4 = PAGE_SIZE_A4;
|
|
2107
|
+
exports.PAGE_SIZE_LETTER = PAGE_SIZE_LETTER;
|
|
909
2108
|
exports.PackageSchema = PackageSchema;
|
|
910
|
-
exports.
|
|
2109
|
+
exports.PageSizeSchema = PageSizeSchema;
|
|
911
2110
|
exports.PartSchema = PartSchema;
|
|
912
|
-
exports.
|
|
913
|
-
exports.
|
|
914
|
-
exports.
|
|
915
|
-
exports.PptxTableSchema = PptxTableSchema;
|
|
916
|
-
exports.RunSchema = RunSchema;
|
|
917
|
-
exports.ShapeSchema = ShapeSchema;
|
|
918
|
-
exports.SlideSchema = SlideSchema;
|
|
919
|
-
exports.TableCellSchema = TableCellSchema;
|
|
920
|
-
exports.TableRowSchema = TableRowSchema;
|
|
921
|
-
exports.TableSchema = TableSchema;
|
|
2111
|
+
exports.PptxDocumentSchema = PptxDocumentSchema;
|
|
2112
|
+
exports.SLIDE_SIZE_STANDARD = SLIDE_SIZE_STANDARD;
|
|
2113
|
+
exports.SLIDE_SIZE_WIDESCREEN = SLIDE_SIZE_WIDESCREEN;
|
|
922
2114
|
exports.XlsxCellSchema = XlsxCellSchema;
|
|
923
2115
|
exports.XlsxSheetSchema = XlsxSheetSchema;
|
|
924
2116
|
exports.XlsxWorkbookSchema = XlsxWorkbookSchema;
|
|
@@ -930,11 +2122,13 @@ exports.XmlNodeSchema = XmlNodeSchema;
|
|
|
930
2122
|
exports.XmlPartSchema = XmlPartSchema;
|
|
931
2123
|
exports.XmlPiSchema = XmlPiSchema;
|
|
932
2124
|
exports.XmlTextSchema = XmlTextSchema;
|
|
2125
|
+
exports.applyColorTransforms = applyColorTransforms;
|
|
933
2126
|
exports.attr = attr;
|
|
934
2127
|
exports.base64ToBytes = base64ToBytes;
|
|
935
2128
|
exports.buildXml = buildXml;
|
|
936
2129
|
exports.bytesToBase64 = bytesToBase64;
|
|
937
2130
|
exports.childrenWithTag = childrenWithTag;
|
|
2131
|
+
exports.colorToRgbHex = colorToRgbHex;
|
|
938
2132
|
exports.compactCodec = compactCodec;
|
|
939
2133
|
exports.compactPackageCodec = compactPackageCodec;
|
|
940
2134
|
exports.decodeCompactPackage = decodeCompactPackage;
|
|
@@ -945,6 +2139,7 @@ exports.encodeCompactPackage = encodeCompactPackage;
|
|
|
945
2139
|
exports.encodePackage = encodePackage;
|
|
946
2140
|
exports.fromCompact = fromCompact;
|
|
947
2141
|
exports.isCompactXmlNode = isCompactXmlNode;
|
|
2142
|
+
exports.isContentBlock = isContentBlock;
|
|
948
2143
|
exports.isXmlNode = isXmlNode;
|
|
949
2144
|
exports.packageCodec = packageCodec;
|
|
950
2145
|
exports.parsePackage = parsePackage;
|
|
@@ -953,8 +2148,10 @@ exports.readDocx = readDocx;
|
|
|
953
2148
|
exports.readPptx = readPptx;
|
|
954
2149
|
exports.readXlsx = readXlsx;
|
|
955
2150
|
exports.resolveRelationships = resolveRelationships;
|
|
2151
|
+
exports.rgbHexToColor = rgbHexToColor;
|
|
956
2152
|
exports.rootElement = rootElement;
|
|
957
2153
|
exports.serializePackage = serializePackage;
|
|
2154
|
+
exports.sniffImageFormat = sniffImageFormat;
|
|
958
2155
|
exports.textContent = textContent;
|
|
959
2156
|
exports.toCompact = toCompact;
|
|
960
2157
|
exports.unzipPackage = unzipPackage;
|