@bendyline/squisq-formats 2.0.1 → 2.1.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/{chunk-2KPARF2P.js → chunk-74GO3FVS.js} +3 -3
- package/dist/{chunk-WC7WULGV.js → chunk-7ARKUCQT.js} +9 -1
- package/dist/chunk-7ARKUCQT.js.map +1 -0
- package/dist/{chunk-LXYLOOST.js → chunk-DTDF6QDP.js} +3 -3
- package/dist/chunk-DTDF6QDP.js.map +1 -0
- package/dist/{chunk-QRVN6A6E.js → chunk-EW54IRRS.js} +4 -4
- package/dist/{chunk-U32AG3G3.js → chunk-KURGXM4I.js} +2 -2
- package/dist/{chunk-CRAVSMPZ.js → chunk-NNHKUXKA.js} +292 -70
- package/dist/chunk-NNHKUXKA.js.map +1 -0
- package/dist/{chunk-VSYHZECT.js → chunk-QFLDYKCR.js} +2 -2
- package/dist/{chunk-ABVI556T.js → chunk-RLU7UFYU.js} +5 -5
- package/dist/{chunk-XKUMNGBW.js → chunk-SC67HYQJ.js} +2 -2
- package/dist/{chunk-VJJM2SSH.js → chunk-UGYF5AZE.js} +3 -3
- package/dist/{chunk-HTW2M27H.js → chunk-WQSHGBLN.js} +1 -1
- package/dist/docx/index.js +4 -3
- package/dist/{extract-H6RXJMHP.js → extract-OJ7ZQV6P.js} +4 -4
- package/dist/html/index.js +1 -1
- package/dist/index.js +11 -11
- package/dist/infer/index.js +4 -4
- package/dist/{layouts-QVPK3ZCU.js → layouts-5VDIRPIJ.js} +3 -3
- package/dist/ooxml/index.js +3 -3
- package/dist/pptx/index.js +4 -4
- package/dist/registry/index.js +1 -1
- package/dist/xlsx/index.js +3 -3
- package/package.json +2 -2
- package/src/__tests__/docxExport.test.ts +34 -0
- package/src/__tests__/docxImport.test.ts +121 -0
- package/src/__tests__/html.test.ts +4 -0
- package/src/docx/export.ts +113 -5
- package/src/docx/import.ts +324 -69
- package/src/html/htmlTemplate.ts +2 -2
- package/src/ooxml/namespaces.ts +21 -0
- package/dist/chunk-CRAVSMPZ.js.map +0 -1
- package/dist/chunk-LXYLOOST.js.map +0 -1
- package/dist/chunk-WC7WULGV.js.map +0 -1
- /package/dist/{chunk-2KPARF2P.js.map → chunk-74GO3FVS.js.map} +0 -0
- /package/dist/{chunk-QRVN6A6E.js.map → chunk-EW54IRRS.js.map} +0 -0
- /package/dist/{chunk-U32AG3G3.js.map → chunk-KURGXM4I.js.map} +0 -0
- /package/dist/{chunk-VSYHZECT.js.map → chunk-QFLDYKCR.js.map} +0 -0
- /package/dist/{chunk-ABVI556T.js.map → chunk-RLU7UFYU.js.map} +0 -0
- /package/dist/{chunk-XKUMNGBW.js.map → chunk-SC67HYQJ.js.map} +0 -0
- /package/dist/{chunk-VJJM2SSH.js.map → chunk-UGYF5AZE.js.map} +0 -0
- /package/dist/{chunk-HTW2M27H.js.map → chunk-WQSHGBLN.js.map} +0 -0
- /package/dist/{extract-H6RXJMHP.js.map → extract-OJ7ZQV6P.js.map} +0 -0
- /package/dist/{layouts-QVPK3ZCU.js.map → layouts-5VDIRPIJ.js.map} +0 -0
|
@@ -5,9 +5,13 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
stripHtmlTags
|
|
7
7
|
} from "./chunk-PN52A5AA.js";
|
|
8
|
+
import {
|
|
9
|
+
baseDirOf,
|
|
10
|
+
resolveTarget
|
|
11
|
+
} from "./chunk-YRT7GQ5Y.js";
|
|
8
12
|
import {
|
|
9
13
|
createPackage
|
|
10
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KURGXM4I.js";
|
|
11
15
|
import {
|
|
12
16
|
escapeXml,
|
|
13
17
|
xmlDeclaration
|
|
@@ -15,7 +19,9 @@ import {
|
|
|
15
19
|
import {
|
|
16
20
|
CONTENT_TYPE_DOCX_DOCUMENT,
|
|
17
21
|
CONTENT_TYPE_DOCX_FONT_TABLE,
|
|
22
|
+
CONTENT_TYPE_DOCX_FOOTER,
|
|
18
23
|
CONTENT_TYPE_DOCX_FOOTNOTES,
|
|
24
|
+
CONTENT_TYPE_DOCX_HEADER,
|
|
19
25
|
CONTENT_TYPE_DOCX_NUMBERING,
|
|
20
26
|
CONTENT_TYPE_DOCX_SETTINGS,
|
|
21
27
|
CONTENT_TYPE_DOCX_STYLES,
|
|
@@ -23,7 +29,9 @@ import {
|
|
|
23
29
|
NS_R,
|
|
24
30
|
NS_WML,
|
|
25
31
|
REL_FONT_TABLE,
|
|
32
|
+
REL_FOOTER,
|
|
26
33
|
REL_FOOTNOTES,
|
|
34
|
+
REL_HEADER,
|
|
27
35
|
REL_HYPERLINK,
|
|
28
36
|
REL_IMAGE,
|
|
29
37
|
REL_NUMBERING,
|
|
@@ -34,7 +42,7 @@ import {
|
|
|
34
42
|
getPartRelationships,
|
|
35
43
|
getPartXml,
|
|
36
44
|
openPackage
|
|
37
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-7ARKUCQT.js";
|
|
38
46
|
import {
|
|
39
47
|
buildContainer
|
|
40
48
|
} from "./chunk-SSUPBUF5.js";
|
|
@@ -105,8 +113,28 @@ function pointsToTwips(points) {
|
|
|
105
113
|
async function markdownDocToDocx(doc, options = {}) {
|
|
106
114
|
const resolvedOptions = options.themeId !== void 0 ? options : { ...options, themeId: readFrontmatterThemeId(doc.frontmatter) };
|
|
107
115
|
const ctx = new ExportContext(resolvedOptions, doc);
|
|
108
|
-
const
|
|
109
|
-
|
|
116
|
+
const stories = partitionDocumentStories(doc.children);
|
|
117
|
+
ctx.setRelationshipSource("document");
|
|
118
|
+
const bodyXml = convertBlocks(stories.body, ctx);
|
|
119
|
+
ctx.setRelationshipSource("header");
|
|
120
|
+
const headerXml = convertBlocks(stories.header, ctx);
|
|
121
|
+
ctx.setRelationshipSource("footer");
|
|
122
|
+
const footerXml = convertBlocks(stories.footer, ctx);
|
|
123
|
+
ctx.setRelationshipSource("document");
|
|
124
|
+
return buildDocxPackage(bodyXml, headerXml, footerXml, ctx, resolvedOptions);
|
|
125
|
+
}
|
|
126
|
+
function partitionDocumentStories(nodes) {
|
|
127
|
+
const stories = { body: [], header: [], footer: [] };
|
|
128
|
+
for (const node of nodes) {
|
|
129
|
+
if (node.type === "containerDirective" && node.name === "docx-header") {
|
|
130
|
+
stories.header.push(...node.children);
|
|
131
|
+
} else if (node.type === "containerDirective" && node.name === "docx-footer") {
|
|
132
|
+
stories.footer.push(...node.children);
|
|
133
|
+
} else {
|
|
134
|
+
stories.body.push(node);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return stories;
|
|
110
138
|
}
|
|
111
139
|
async function docToDocx(doc, options = {}) {
|
|
112
140
|
const markdownDoc = docToMarkdown(doc);
|
|
@@ -120,6 +148,7 @@ var ExportContext = class {
|
|
|
120
148
|
// 0 is separator, start user footnotes at 1
|
|
121
149
|
/** Relationships for word/_rels/document.xml.rels */
|
|
122
150
|
this.relationships = [];
|
|
151
|
+
this.relationshipSource = "document";
|
|
123
152
|
/** Numbering definitions (abstract + num) */
|
|
124
153
|
this.numberingDefs = [];
|
|
125
154
|
/** Footnote XML bodies (keyed by footnote id) */
|
|
@@ -162,6 +191,9 @@ var ExportContext = class {
|
|
|
162
191
|
allocRelId() {
|
|
163
192
|
return `rId${this.nextRelId++}`;
|
|
164
193
|
}
|
|
194
|
+
setRelationshipSource(source) {
|
|
195
|
+
this.relationshipSource = source;
|
|
196
|
+
}
|
|
165
197
|
/** Add a hyperlink relationship and return the rId */
|
|
166
198
|
addHyperlink(url) {
|
|
167
199
|
const id = this.allocRelId();
|
|
@@ -169,7 +201,8 @@ var ExportContext = class {
|
|
|
169
201
|
id,
|
|
170
202
|
type: REL_HYPERLINK,
|
|
171
203
|
target: url,
|
|
172
|
-
targetMode: "External"
|
|
204
|
+
targetMode: "External",
|
|
205
|
+
source: this.relationshipSource
|
|
173
206
|
});
|
|
174
207
|
return id;
|
|
175
208
|
}
|
|
@@ -182,7 +215,8 @@ var ExportContext = class {
|
|
|
182
215
|
this.relationships.push({
|
|
183
216
|
id: relId,
|
|
184
217
|
type: REL_IMAGE,
|
|
185
|
-
target: `media/${filename}
|
|
218
|
+
target: `media/${filename}`,
|
|
219
|
+
source: this.relationshipSource
|
|
186
220
|
});
|
|
187
221
|
return { relId, docPrId };
|
|
188
222
|
}
|
|
@@ -257,6 +291,8 @@ function convertBlock(node, ctx, listDepth) {
|
|
|
257
291
|
return convertMathBlock(node);
|
|
258
292
|
case "footnoteDefinition":
|
|
259
293
|
return convertFootnoteDefinition(node, ctx);
|
|
294
|
+
case "containerDirective":
|
|
295
|
+
return convertBlocks(node.children, ctx);
|
|
260
296
|
default:
|
|
261
297
|
return "";
|
|
262
298
|
}
|
|
@@ -498,7 +534,7 @@ function convertFootnoteRef(node, ctx) {
|
|
|
498
534
|
const fnId = ctx.getFootnoteId(node.identifier);
|
|
499
535
|
return `<w:r><w:rPr><w:rStyle w:val="FootnoteReference"/><w:vertAlign w:val="superscript"/></w:rPr><w:footnoteReference w:id="${fnId}"/></w:r>`;
|
|
500
536
|
}
|
|
501
|
-
async function buildDocxPackage(bodyXml, ctx, options) {
|
|
537
|
+
async function buildDocxPackage(bodyXml, headerXml, footerXml, ctx, options) {
|
|
502
538
|
const pkg = createPackage();
|
|
503
539
|
let relCounter = 100;
|
|
504
540
|
const stylesRelId = `rId${relCounter++}`;
|
|
@@ -506,8 +542,23 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
506
542
|
const settingsRelId = `rId${relCounter++}`;
|
|
507
543
|
const fontTableRelId = `rId${relCounter++}`;
|
|
508
544
|
const footnotesRelId = `rId${relCounter++}`;
|
|
509
|
-
const
|
|
545
|
+
const headerRelId = `rId${relCounter++}`;
|
|
546
|
+
const footerRelId = `rId${relCounter++}`;
|
|
547
|
+
const hasHeader = headerXml.trim().length > 0;
|
|
548
|
+
const hasFooter = footerXml.trim().length > 0;
|
|
549
|
+
const documentXml = buildDocumentXml(
|
|
550
|
+
bodyXml,
|
|
551
|
+
ctx.backgroundColor,
|
|
552
|
+
hasHeader ? headerRelId : void 0,
|
|
553
|
+
hasFooter ? footerRelId : void 0
|
|
554
|
+
);
|
|
510
555
|
pkg.addPart("word/document.xml", documentXml, CONTENT_TYPE_DOCX_DOCUMENT);
|
|
556
|
+
if (hasHeader) {
|
|
557
|
+
pkg.addPart("word/header1.xml", buildStoryXml("header", headerXml), CONTENT_TYPE_DOCX_HEADER);
|
|
558
|
+
}
|
|
559
|
+
if (hasFooter) {
|
|
560
|
+
pkg.addPart("word/footer1.xml", buildStoryXml("footer", footerXml), CONTENT_TYPE_DOCX_FOOTER);
|
|
561
|
+
}
|
|
511
562
|
const stylesXml = buildStylesXml(options, ctx);
|
|
512
563
|
pkg.addPart("word/styles.xml", stylesXml, CONTENT_TYPE_DOCX_STYLES);
|
|
513
564
|
const settingsXml = buildSettingsXml(ctx.backgroundColor !== void 0);
|
|
@@ -556,8 +607,23 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
556
607
|
target: "footnotes.xml"
|
|
557
608
|
});
|
|
558
609
|
}
|
|
559
|
-
|
|
610
|
+
if (hasHeader) {
|
|
560
611
|
pkg.addRelationship("word/document.xml", {
|
|
612
|
+
id: headerRelId,
|
|
613
|
+
type: REL_HEADER,
|
|
614
|
+
target: "header1.xml"
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
if (hasFooter) {
|
|
618
|
+
pkg.addRelationship("word/document.xml", {
|
|
619
|
+
id: footerRelId,
|
|
620
|
+
type: REL_FOOTER,
|
|
621
|
+
target: "footer1.xml"
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
for (const rel of ctx.relationships) {
|
|
625
|
+
const sourcePart = rel.source === "header" ? "word/header1.xml" : rel.source === "footer" ? "word/footer1.xml" : "word/document.xml";
|
|
626
|
+
pkg.addRelationship(sourcePart, {
|
|
561
627
|
id: rel.id,
|
|
562
628
|
type: rel.type,
|
|
563
629
|
target: rel.target,
|
|
@@ -578,9 +644,14 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
578
644
|
}
|
|
579
645
|
return pkg.toArrayBuffer();
|
|
580
646
|
}
|
|
581
|
-
function buildDocumentXml(bodyXml, backgroundColor) {
|
|
647
|
+
function buildDocumentXml(bodyXml, backgroundColor, headerRelId, footerRelId) {
|
|
582
648
|
const backgroundEl = backgroundColor ? `<w:background w:color="${backgroundColor}"/>` : "";
|
|
583
|
-
|
|
649
|
+
const storyReferences = (headerRelId ? `<w:headerReference w:type="default" r:id="${headerRelId}"/>` : "") + (footerRelId ? `<w:footerReference w:type="default" r:id="${footerRelId}"/>` : "");
|
|
650
|
+
return xmlDeclaration() + `<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="${NS_MC}" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="${NS_R}" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="${NS_WML}" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml">` + backgroundEl + `<w:body>` + bodyXml + `<w:sectPr>` + storyReferences + `<w:pgSz w:w="12240" w:h="15840"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440" w:header="720" w:footer="720" w:gutter="0"/><w:cols w:space="720"/></w:sectPr></w:body></w:document>`;
|
|
651
|
+
}
|
|
652
|
+
function buildStoryXml(kind, bodyXml) {
|
|
653
|
+
const element = kind === "header" ? "hdr" : "ftr";
|
|
654
|
+
return xmlDeclaration() + `<w:${element} xmlns:w="${NS_WML}" xmlns:r="${NS_R}" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">` + bodyXml + `</w:${element}>`;
|
|
584
655
|
}
|
|
585
656
|
function buildStylesXml(options, ctx) {
|
|
586
657
|
const font = ctx.font;
|
|
@@ -666,7 +737,7 @@ async function docxToMarkdownDoc(data, options = {}) {
|
|
|
666
737
|
if (!body) {
|
|
667
738
|
return { type: "document", children: [] };
|
|
668
739
|
}
|
|
669
|
-
const blocks = await
|
|
740
|
+
const blocks = await convertDocumentStories(body, ctx);
|
|
670
741
|
return { type: "document", children: blocks };
|
|
671
742
|
}
|
|
672
743
|
async function docxToDoc(data, options = {}) {
|
|
@@ -680,7 +751,7 @@ async function docxToContainer(data, options = {}) {
|
|
|
680
751
|
if (!documentXml) return buildContainer("", []);
|
|
681
752
|
const body = getFirstElement(documentXml, "body");
|
|
682
753
|
if (!body) return buildContainer("", []);
|
|
683
|
-
const blocks = await
|
|
754
|
+
const blocks = await convertDocumentStories(body, ctx);
|
|
684
755
|
const markdownDoc = { type: "document", children: blocks };
|
|
685
756
|
return buildContainer(stringifyMarkdown(markdownDoc), ctx.extractedImages);
|
|
686
757
|
}
|
|
@@ -693,6 +764,8 @@ async function buildImportContext(pkg, options) {
|
|
|
693
764
|
documentRels: /* @__PURE__ */ new Map(),
|
|
694
765
|
numbering: /* @__PURE__ */ new Map(),
|
|
695
766
|
footnotes: /* @__PURE__ */ new Map(),
|
|
767
|
+
endnotes: /* @__PURE__ */ new Map(),
|
|
768
|
+
currentPartPath: "word/document.xml",
|
|
696
769
|
pkg,
|
|
697
770
|
options,
|
|
698
771
|
extractedImages: /* @__PURE__ */ new Map(),
|
|
@@ -717,6 +790,7 @@ async function buildImportContext(pkg, options) {
|
|
|
717
790
|
}
|
|
718
791
|
await parseNumbering(pkg, ctx);
|
|
719
792
|
await parseFootnotes(pkg, ctx);
|
|
793
|
+
await parseEndnotes(pkg, ctx);
|
|
720
794
|
return ctx;
|
|
721
795
|
}
|
|
722
796
|
async function parseStyles(pkg, ctx) {
|
|
@@ -797,9 +871,67 @@ async function parseFootnotes(pkg, ctx) {
|
|
|
797
871
|
ctx.footnotes.set(id, fn);
|
|
798
872
|
}
|
|
799
873
|
}
|
|
874
|
+
async function parseEndnotes(pkg, ctx) {
|
|
875
|
+
const doc = await getPartXml(pkg, "word/endnotes.xml");
|
|
876
|
+
if (!doc) return;
|
|
877
|
+
const endnoteEls = getAllElements(doc, "endnote");
|
|
878
|
+
for (const note of endnoteEls) {
|
|
879
|
+
const id = getAttr(note, "id");
|
|
880
|
+
const type = getAttr(note, "type");
|
|
881
|
+
if (!id || type === "separator" || type === "continuationSeparator") continue;
|
|
882
|
+
ctx.endnotes.set(id, note);
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
async function convertDocumentStories(body, ctx) {
|
|
886
|
+
const bodyBlocks = await convertBody(body, ctx);
|
|
887
|
+
const headers = await convertRelatedStories(body, ctx, "header");
|
|
888
|
+
const footers = await convertRelatedStories(body, ctx, "footer");
|
|
889
|
+
const noteDefinitions = await convertNoteDefinitions(ctx);
|
|
890
|
+
return [...bodyBlocks, ...headers, ...footers, ...noteDefinitions];
|
|
891
|
+
}
|
|
892
|
+
async function convertRelatedStories(body, ctx, kind) {
|
|
893
|
+
const relationshipTypeSuffix = `/${kind}`;
|
|
894
|
+
const referenceName = `${kind}Reference`;
|
|
895
|
+
const referenceTypes = /* @__PURE__ */ new Map();
|
|
896
|
+
for (const reference of getAllElements(body, referenceName)) {
|
|
897
|
+
const id = reference.getAttributeNS(NS_R, "id") ?? reference.getAttribute("r:id");
|
|
898
|
+
if (id) referenceTypes.set(id, getAttr(reference, "type") ?? "default");
|
|
899
|
+
}
|
|
900
|
+
const documentRelationships = ctx.documentRels;
|
|
901
|
+
const previousPartPath = ctx.currentPartPath;
|
|
902
|
+
const results = [];
|
|
903
|
+
for (const relationship of documentRelationships.values()) {
|
|
904
|
+
if (!relationship.type.endsWith(relationshipTypeSuffix)) continue;
|
|
905
|
+
const partPath = resolveTarget(baseDirOf("word/document.xml"), relationship.target);
|
|
906
|
+
const part = await getPartXml(ctx.pkg, partPath);
|
|
907
|
+
if (!part?.documentElement) continue;
|
|
908
|
+
const partRelationships = await getPartRelationships(ctx.pkg, partPath);
|
|
909
|
+
ctx.documentRels = new Map(partRelationships.map((rel) => [rel.id, rel]));
|
|
910
|
+
ctx.currentPartPath = partPath;
|
|
911
|
+
try {
|
|
912
|
+
const children = await convertBody(part.documentElement, ctx);
|
|
913
|
+
if (children.length === 0) continue;
|
|
914
|
+
results.push({
|
|
915
|
+
type: "containerDirective",
|
|
916
|
+
name: `docx-${kind}`,
|
|
917
|
+
attributes: {
|
|
918
|
+
type: referenceTypes.get(relationship.id) ?? "default",
|
|
919
|
+
source: partPath
|
|
920
|
+
},
|
|
921
|
+
children
|
|
922
|
+
});
|
|
923
|
+
} finally {
|
|
924
|
+
ctx.documentRels = documentRelationships;
|
|
925
|
+
ctx.currentPartPath = previousPartPath;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return results;
|
|
929
|
+
}
|
|
800
930
|
async function convertBody(body, ctx) {
|
|
931
|
+
return convertBlockElements(Array.from(body.children), ctx);
|
|
932
|
+
}
|
|
933
|
+
async function convertBlockElements(children, ctx) {
|
|
801
934
|
const result = [];
|
|
802
|
-
const children = Array.from(body.children);
|
|
803
935
|
let i = 0;
|
|
804
936
|
while (i < children.length) {
|
|
805
937
|
const el = children[i];
|
|
@@ -821,12 +953,22 @@ async function convertBody(body, ctx) {
|
|
|
821
953
|
const table = await convertTable2(el, ctx);
|
|
822
954
|
if (table) result.push(table);
|
|
823
955
|
i++;
|
|
956
|
+
} else if (localName === "sdt") {
|
|
957
|
+
const content = getFirstChildElement(el, "sdtContent");
|
|
958
|
+
if (content) result.push(...await convertBlockElements(Array.from(content.children), ctx));
|
|
959
|
+
i++;
|
|
960
|
+
} else if (localName === "ins" || localName === "moveTo" || localName === "customXml" || localName === "smartTag" || localName === "fldSimple") {
|
|
961
|
+
result.push(...await convertBlockElements(Array.from(el.children), ctx));
|
|
962
|
+
i++;
|
|
963
|
+
} else if (localName === "AlternateContent") {
|
|
964
|
+
const selected = getFirstChildElement(el, "Choice") ?? getFirstChildElement(el, "Fallback");
|
|
965
|
+
if (selected)
|
|
966
|
+
result.push(...await convertBlockElements(Array.from(selected.children), ctx));
|
|
967
|
+
i++;
|
|
824
968
|
} else {
|
|
825
969
|
i++;
|
|
826
970
|
}
|
|
827
971
|
}
|
|
828
|
-
const footnoteNodes = await convertFootnoteDefinitions(ctx);
|
|
829
|
-
result.push(...footnoteNodes);
|
|
830
972
|
return result;
|
|
831
973
|
}
|
|
832
974
|
async function convertParagraph2(el, ctx) {
|
|
@@ -857,8 +999,10 @@ async function convertParagraph2(el, ctx) {
|
|
|
857
999
|
return { type: "paragraph", children: inlines };
|
|
858
1000
|
}
|
|
859
1001
|
async function convertRuns(paragraphEl, ctx) {
|
|
1002
|
+
return mergeAdjacentText(await convertInlineElements(Array.from(paragraphEl.children), ctx));
|
|
1003
|
+
}
|
|
1004
|
+
async function convertInlineElements(children, ctx) {
|
|
860
1005
|
const result = [];
|
|
861
|
-
const children = Array.from(paragraphEl.children);
|
|
862
1006
|
for (const child of children) {
|
|
863
1007
|
const localName = child.localName;
|
|
864
1008
|
if (localName === "r") {
|
|
@@ -867,9 +1011,23 @@ async function convertRuns(paragraphEl, ctx) {
|
|
|
867
1011
|
} else if (localName === "hyperlink") {
|
|
868
1012
|
const link = await convertHyperlink(child, ctx);
|
|
869
1013
|
if (link) result.push(link);
|
|
1014
|
+
} else if (localName === "sdt") {
|
|
1015
|
+
const content = getFirstChildElement(child, "sdtContent");
|
|
1016
|
+
if (content) {
|
|
1017
|
+
result.push(...await convertInlineElements(Array.from(content.children), ctx));
|
|
1018
|
+
}
|
|
1019
|
+
} else if (localName === "ins" || localName === "moveTo" || localName === "customXml" || localName === "smartTag" || localName === "fldSimple") {
|
|
1020
|
+
result.push(...await convertInlineElements(Array.from(child.children), ctx));
|
|
1021
|
+
} else if (localName === "AlternateContent") {
|
|
1022
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1023
|
+
if (selected) {
|
|
1024
|
+
result.push(...await convertInlineElements(Array.from(selected.children), ctx));
|
|
1025
|
+
}
|
|
1026
|
+
} else if (localName === "drawing" || localName === "pict") {
|
|
1027
|
+
result.push(...await convertDrawingContent(child, ctx));
|
|
870
1028
|
}
|
|
871
1029
|
}
|
|
872
|
-
return
|
|
1030
|
+
return result;
|
|
873
1031
|
}
|
|
874
1032
|
async function convertRun(runEl, ctx) {
|
|
875
1033
|
const result = [];
|
|
@@ -895,8 +1053,10 @@ async function convertRun(runEl, ctx) {
|
|
|
895
1053
|
}
|
|
896
1054
|
result.push(node);
|
|
897
1055
|
}
|
|
898
|
-
} else if (localName === "br") {
|
|
1056
|
+
} else if (localName === "br" || localName === "cr") {
|
|
899
1057
|
result.push({ type: "break" });
|
|
1058
|
+
} else if (localName === "tab") {
|
|
1059
|
+
result.push({ type: "text", value: " " });
|
|
900
1060
|
} else if (localName === "footnoteReference") {
|
|
901
1061
|
const fnId = getAttr(child, "id");
|
|
902
1062
|
if (fnId && fnId !== "0" && fnId !== "-1") {
|
|
@@ -905,13 +1065,79 @@ async function convertRun(runEl, ctx) {
|
|
|
905
1065
|
identifier: `fn${fnId}`
|
|
906
1066
|
});
|
|
907
1067
|
}
|
|
908
|
-
} else if (localName === "
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
1068
|
+
} else if (localName === "endnoteReference") {
|
|
1069
|
+
const noteId = getAttr(child, "id");
|
|
1070
|
+
if (noteId && noteId !== "0" && noteId !== "-1") {
|
|
1071
|
+
result.push({
|
|
1072
|
+
type: "footnoteReference",
|
|
1073
|
+
identifier: `endnote${noteId}`
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
} else if (localName === "drawing" || localName === "pict" || localName === "object") {
|
|
1077
|
+
result.push(...await convertDrawingContent(child, ctx));
|
|
1078
|
+
} else if (localName === "AlternateContent") {
|
|
1079
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1080
|
+
if (selected) {
|
|
1081
|
+
result.push(...await convertInlineElements(Array.from(selected.children), ctx));
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
return result;
|
|
1086
|
+
}
|
|
1087
|
+
async function convertDrawingContent(el, ctx) {
|
|
1088
|
+
const result = [];
|
|
1089
|
+
const textBoxes = findDescendants(el, "txbxContent");
|
|
1090
|
+
for (const textBox of textBoxes) {
|
|
1091
|
+
const inlines = await flattenContainerToInlines(textBox, ctx);
|
|
1092
|
+
appendInlineGroup(result, inlines);
|
|
1093
|
+
}
|
|
1094
|
+
const image = await extractImage(el, ctx);
|
|
1095
|
+
if (image) result.push(image);
|
|
1096
|
+
if (textBoxes.length > 0 && result.length > 0) {
|
|
1097
|
+
if (result[0]?.type !== "break") result.unshift({ type: "break" });
|
|
1098
|
+
if (result[result.length - 1]?.type !== "break") {
|
|
1099
|
+
result.push({ type: "break" });
|
|
911
1100
|
}
|
|
912
1101
|
}
|
|
913
1102
|
return result;
|
|
914
1103
|
}
|
|
1104
|
+
async function flattenContainerToInlines(container, ctx) {
|
|
1105
|
+
const result = [];
|
|
1106
|
+
for (const child of Array.from(container.children)) {
|
|
1107
|
+
if (child.localName === "p") {
|
|
1108
|
+
appendInlineGroup(result, await convertRuns(child, ctx));
|
|
1109
|
+
} else if (child.localName === "tbl") {
|
|
1110
|
+
appendInlineGroup(result, await flattenTableToInlines(child, ctx));
|
|
1111
|
+
} else if (child.localName === "sdt") {
|
|
1112
|
+
const content = getFirstChildElement(child, "sdtContent");
|
|
1113
|
+
if (content) appendInlineGroup(result, await flattenContainerToInlines(content, ctx));
|
|
1114
|
+
} else if (child.localName === "ins" || child.localName === "moveTo" || child.localName === "customXml" || child.localName === "smartTag" || child.localName === "fldSimple") {
|
|
1115
|
+
appendInlineGroup(result, await flattenContainerToInlines(child, ctx));
|
|
1116
|
+
} else if (child.localName === "AlternateContent") {
|
|
1117
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1118
|
+
if (selected) appendInlineGroup(result, await flattenContainerToInlines(selected, ctx));
|
|
1119
|
+
} else if (child.localName === "r" || child.localName === "hyperlink") {
|
|
1120
|
+
appendInlineGroup(result, await convertInlineElements([child], ctx));
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
return mergeAdjacentText(result);
|
|
1124
|
+
}
|
|
1125
|
+
async function flattenTableToInlines(table, ctx) {
|
|
1126
|
+
const result = [];
|
|
1127
|
+
for (const row of getAllChildElements(table, "tr")) {
|
|
1128
|
+
for (const cell of getAllChildElements(row, "tc")) {
|
|
1129
|
+
appendInlineGroup(result, await flattenContainerToInlines(cell, ctx));
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
return mergeAdjacentText(result);
|
|
1133
|
+
}
|
|
1134
|
+
function appendInlineGroup(target, group) {
|
|
1135
|
+
if (group.length === 0) return;
|
|
1136
|
+
if (target.length > 0 && target[target.length - 1]?.type !== "break") {
|
|
1137
|
+
target.push({ type: "break" });
|
|
1138
|
+
}
|
|
1139
|
+
target.push(...group);
|
|
1140
|
+
}
|
|
915
1141
|
function parseRunFormat(rPr, ctx) {
|
|
916
1142
|
if (!rPr) return { bold: false, italic: false, strike: false, code: false };
|
|
917
1143
|
const bold = hasChildElement(rPr, "b") && !isFalseToggle(getFirstChildElement(rPr, "b"));
|
|
@@ -940,12 +1166,7 @@ async function convertHyperlink(el, ctx) {
|
|
|
940
1166
|
const anchor = el.getAttributeNS(NS_WML, "anchor") ?? el.getAttribute("w:anchor");
|
|
941
1167
|
if (anchor) url = `#${anchor}`;
|
|
942
1168
|
}
|
|
943
|
-
const inlines =
|
|
944
|
-
for (const child of Array.from(el.children)) {
|
|
945
|
-
if (child.localName === "r") {
|
|
946
|
-
inlines.push(...await convertRun(child, ctx));
|
|
947
|
-
}
|
|
948
|
-
}
|
|
1169
|
+
const inlines = await convertInlineElements(Array.from(el.children), ctx);
|
|
949
1170
|
if (inlines.length === 0) return null;
|
|
950
1171
|
return {
|
|
951
1172
|
type: "link",
|
|
@@ -955,22 +1176,14 @@ async function convertHyperlink(el, ctx) {
|
|
|
955
1176
|
}
|
|
956
1177
|
async function extractImage(el, ctx) {
|
|
957
1178
|
const blip = findDescendant(el, "blip");
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
const rId = blip.getAttributeNS(NS_R, "embed") ?? blip.getAttribute("r:embed");
|
|
962
|
-
if (!rId) {
|
|
963
|
-
return { type: "image", url: "", alt: "Image" };
|
|
964
|
-
}
|
|
1179
|
+
const imageData = findDescendant(el, "imagedata");
|
|
1180
|
+
const rId = blip ? blip.getAttributeNS(NS_R, "embed") ?? blip.getAttribute("r:embed") : imageData?.getAttributeNS(NS_R, "id") ?? imageData?.getAttribute("r:id") ?? imageData?.getAttribute("o:relid");
|
|
1181
|
+
if (!rId) return null;
|
|
965
1182
|
const rel = ctx.documentRels.get(rId);
|
|
966
|
-
if (!rel)
|
|
967
|
-
|
|
968
|
-
}
|
|
969
|
-
const target = rel.target.startsWith("/") ? rel.target.slice(1) : `word/${rel.target}`;
|
|
1183
|
+
if (!rel || rel.targetMode === "External") return null;
|
|
1184
|
+
const target = resolveTarget(baseDirOf(ctx.currentPartPath), rel.target);
|
|
970
1185
|
const data = await getPartBinary(ctx.pkg, target);
|
|
971
|
-
if (!data)
|
|
972
|
-
return { type: "image", url: "", alt: "Image" };
|
|
973
|
-
}
|
|
1186
|
+
if (!data) return null;
|
|
974
1187
|
const dot = target.lastIndexOf(".");
|
|
975
1188
|
const ext = dot !== -1 ? target.slice(dot).toLowerCase() : ".png";
|
|
976
1189
|
const mimeType = extToMime(ext);
|
|
@@ -978,7 +1191,8 @@ async function extractImage(el, ctx) {
|
|
|
978
1191
|
const imagePath = `images/image${ctx.imageCounter}${ext}`;
|
|
979
1192
|
ctx.extractedImages.set(imagePath, { data, mimeType });
|
|
980
1193
|
const docPr = findDescendant(el, "docPr");
|
|
981
|
-
const
|
|
1194
|
+
const shape = findDescendant(el, "shape");
|
|
1195
|
+
const alt = docPr?.getAttribute("descr") || docPr?.getAttribute("title") || shape?.getAttribute("alt") || shape?.getAttribute("title") || "Image";
|
|
982
1196
|
return {
|
|
983
1197
|
type: "image",
|
|
984
1198
|
url: imagePath,
|
|
@@ -993,6 +1207,14 @@ function findDescendant(el, localName) {
|
|
|
993
1207
|
}
|
|
994
1208
|
return null;
|
|
995
1209
|
}
|
|
1210
|
+
function findDescendants(el, localName) {
|
|
1211
|
+
const results = [];
|
|
1212
|
+
for (const child of Array.from(el.children)) {
|
|
1213
|
+
if (child.localName === localName) results.push(child);
|
|
1214
|
+
results.push(...findDescendants(child, localName));
|
|
1215
|
+
}
|
|
1216
|
+
return results;
|
|
1217
|
+
}
|
|
996
1218
|
async function collectList(elements, startIdx, ctx) {
|
|
997
1219
|
const firstNumPr = getNumPr(elements[startIdx]);
|
|
998
1220
|
const { numId } = firstNumPr;
|
|
@@ -1020,6 +1242,8 @@ async function collectList(elements, startIdx, ctx) {
|
|
|
1020
1242
|
children: nested.items
|
|
1021
1243
|
};
|
|
1022
1244
|
lastItem.children.push(nestedList);
|
|
1245
|
+
} else {
|
|
1246
|
+
items.push(...nested.items);
|
|
1023
1247
|
}
|
|
1024
1248
|
i += nested.consumed;
|
|
1025
1249
|
consumed += nested.consumed;
|
|
@@ -1100,42 +1324,40 @@ async function convertTableRow2(trEl, ctx, isHeader) {
|
|
|
1100
1324
|
return { type: "tableRow", children: cells };
|
|
1101
1325
|
}
|
|
1102
1326
|
async function convertTableCell2(tcEl, ctx, isHeader) {
|
|
1103
|
-
const inlines =
|
|
1104
|
-
const paragraphs = getAllChildElements(tcEl, "p");
|
|
1105
|
-
for (let pi = 0; pi < paragraphs.length; pi++) {
|
|
1106
|
-
if (pi > 0) {
|
|
1107
|
-
inlines.push({ type: "break" });
|
|
1108
|
-
}
|
|
1109
|
-
const runs = await convertRuns(paragraphs[pi], ctx);
|
|
1110
|
-
inlines.push(...runs);
|
|
1111
|
-
}
|
|
1327
|
+
const inlines = await flattenContainerToInlines(tcEl, ctx);
|
|
1112
1328
|
return {
|
|
1113
1329
|
type: "tableCell",
|
|
1114
1330
|
isHeader,
|
|
1115
1331
|
children: mergeAdjacentText(inlines)
|
|
1116
1332
|
};
|
|
1117
1333
|
}
|
|
1118
|
-
async function
|
|
1334
|
+
async function convertNoteDefinitions(ctx) {
|
|
1335
|
+
return [
|
|
1336
|
+
...await convertNotePartDefinitions(ctx, ctx.footnotes, "fn", "word/footnotes.xml"),
|
|
1337
|
+
...await convertNotePartDefinitions(ctx, ctx.endnotes, "endnote", "word/endnotes.xml")
|
|
1338
|
+
];
|
|
1339
|
+
}
|
|
1340
|
+
async function convertNotePartDefinitions(ctx, notes, identifierPrefix, partPath) {
|
|
1119
1341
|
const results = [];
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1342
|
+
const previousRelationships = ctx.documentRels;
|
|
1343
|
+
const previousPartPath = ctx.currentPartPath;
|
|
1344
|
+
const partRelationships = await getPartRelationships(ctx.pkg, partPath);
|
|
1345
|
+
ctx.documentRels = new Map(partRelationships.map((rel) => [rel.id, rel]));
|
|
1346
|
+
ctx.currentPartPath = partPath;
|
|
1347
|
+
try {
|
|
1348
|
+
for (const [id, el] of notes) {
|
|
1349
|
+
const children = await convertBody(el, ctx);
|
|
1350
|
+
if (children.length > 0) {
|
|
1351
|
+
results.push({
|
|
1352
|
+
type: "footnoteDefinition",
|
|
1353
|
+
identifier: `${identifierPrefix}${id}`,
|
|
1354
|
+
children
|
|
1129
1355
|
});
|
|
1130
1356
|
}
|
|
1131
1357
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
identifier: `fn${id}`,
|
|
1136
|
-
children
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1358
|
+
} finally {
|
|
1359
|
+
ctx.documentRels = previousRelationships;
|
|
1360
|
+
ctx.currentPartPath = previousPartPath;
|
|
1139
1361
|
}
|
|
1140
1362
|
return results;
|
|
1141
1363
|
}
|
|
@@ -1209,4 +1431,4 @@ export {
|
|
|
1209
1431
|
docxToDoc,
|
|
1210
1432
|
docxToContainer
|
|
1211
1433
|
};
|
|
1212
|
-
//# sourceMappingURL=chunk-
|
|
1434
|
+
//# sourceMappingURL=chunk-NNHKUXKA.js.map
|