@bendyline/squisq-formats 2.0.1 → 2.2.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/LICENSE +21 -0
- package/NOTICE.md +20 -0
- package/README.md +1 -1
- package/dist/{chunk-CRAVSMPZ.js → chunk-26ISNJ7Y.js} +356 -114
- package/dist/{chunk-NKAJPJ4G.js → chunk-2JJ5RFDZ.js} +0 -1
- package/dist/{chunk-HTW2M27H.js → chunk-3NKXBZSR.js} +193 -42
- package/dist/{chunk-U32AG3G3.js → chunk-4V3KCHAP.js} +3 -4
- package/dist/{chunk-MLX2BOJC.js → chunk-6RQOV3B3.js} +1 -2
- package/dist/{chunk-QRVN6A6E.js → chunk-6S6GU3ZG.js} +5 -6
- package/dist/{chunk-FE6OJV6O.js → chunk-7AWFHP5U.js} +1 -1
- package/dist/{chunk-RFAPOKHJ.js → chunk-AD2WT564.js} +59 -9
- package/dist/{chunk-O3GVVND4.js → chunk-AONELFLA.js} +0 -1
- package/dist/{chunk-XKUMNGBW.js → chunk-EJTNGKEA.js} +5 -8
- package/dist/chunk-GX7RAUME.js +121 -0
- package/dist/{chunk-SSUPBUF5.js → chunk-IIQYS2YH.js} +0 -1
- package/dist/{chunk-ABVI556T.js → chunk-IPN56VLW.js} +83 -58
- package/dist/{chunk-LXYLOOST.js → chunk-JE6LSIHE.js} +83 -22
- package/dist/{chunk-U4MRIFKL.js → chunk-JU2RHXUB.js} +0 -1
- package/dist/{chunk-4VUWTSGM.js → chunk-K6XRMVPW.js} +64 -31
- package/dist/{chunk-ODL3SSPT.js → chunk-KXOZMWBS.js} +0 -1
- package/dist/chunk-OGS5VCGJ.js +446 -0
- package/dist/{chunk-GVS2XXV6.js → chunk-PJXJI2LY.js} +449 -57
- package/dist/{chunk-2KPARF2P.js → chunk-PU7REGWV.js} +5 -8
- package/dist/{chunk-PN52A5AA.js → chunk-SBUW7NHR.js} +0 -1
- package/dist/{chunk-VSYHZECT.js → chunk-TAAENIRB.js} +5 -8
- package/dist/{chunk-WC7WULGV.js → chunk-X2DEAXNK.js} +62 -2
- package/dist/container/index.js +1 -2
- package/dist/csv/index.d.ts +27 -2
- package/dist/csv/index.js +1 -2
- package/dist/docx/index.d.ts +5 -1
- package/dist/docx/index.js +9 -10
- package/dist/epub/index.d.ts +2 -0
- package/dist/epub/index.js +5 -6
- package/dist/{export-D2NkylDT.d.ts → export-D9msROJS.d.ts} +18 -6
- package/dist/extract-MN7LA3NL.js +13 -0
- package/dist/html/index.d.ts +11 -4
- package/dist/html/index.js +3 -4
- package/dist/images-ESPQKVTW.js +6 -0
- package/dist/{import-K8mfc0fz.d.ts → import-C3htUTss.d.ts} +5 -1
- package/dist/{import-DTkDxHmZ.d.ts → import-C8whCC7_.d.ts} +6 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +28 -26
- package/dist/infer/index.d.ts +3 -3
- package/dist/infer/index.js +7 -9
- package/dist/{layouts-BHrgZ5FS.d.ts → layouts-CTdPlB-u.d.ts} +1 -1
- package/dist/layouts-DRWZGSPD.js +10 -0
- package/dist/{mapTheme-IR27S6IV.js → mapTheme-4TWH25FT.js} +1 -2
- package/dist/ooxml/index.d.ts +3 -3
- package/dist/ooxml/index.js +14 -13
- package/dist/pdf/index.d.ts +18 -0
- package/dist/pdf/index.js +2 -3
- package/dist/pptx/index.d.ts +4 -4
- package/dist/pptx/index.js +11 -13
- package/dist/{reader-B9L8Ucbj.d.ts → reader-B_m1aKZC.d.ts} +30 -1
- package/dist/registry/index.d.ts +21 -5
- package/dist/registry/index.js +9 -6
- package/dist/{themeReader-DJKErl_j.d.ts → themeReader-DCtwC83Q.d.ts} +1 -1
- package/dist/xlsx/index.d.ts +3 -3
- package/dist/xlsx/index.js +6 -7
- package/package.json +6 -3
- package/dist/chunk-2KPARF2P.js.map +0 -1
- package/dist/chunk-4VUWTSGM.js.map +0 -1
- package/dist/chunk-6M7Z25LA.js +0 -46
- package/dist/chunk-6M7Z25LA.js.map +0 -1
- package/dist/chunk-ABVI556T.js.map +0 -1
- package/dist/chunk-CRAVSMPZ.js.map +0 -1
- package/dist/chunk-FE6OJV6O.js.map +0 -1
- package/dist/chunk-GVS2XXV6.js.map +0 -1
- package/dist/chunk-HTW2M27H.js.map +0 -1
- package/dist/chunk-LXYLOOST.js.map +0 -1
- package/dist/chunk-MLX2BOJC.js.map +0 -1
- package/dist/chunk-NKAJPJ4G.js.map +0 -1
- package/dist/chunk-O3GVVND4.js.map +0 -1
- package/dist/chunk-ODL3SSPT.js.map +0 -1
- package/dist/chunk-PN52A5AA.js.map +0 -1
- package/dist/chunk-QRVN6A6E.js.map +0 -1
- package/dist/chunk-RFAPOKHJ.js.map +0 -1
- package/dist/chunk-SSUPBUF5.js.map +0 -1
- package/dist/chunk-U32AG3G3.js.map +0 -1
- package/dist/chunk-U4MRIFKL.js.map +0 -1
- package/dist/chunk-VJJM2SSH.js +0 -275
- package/dist/chunk-VJJM2SSH.js.map +0 -1
- package/dist/chunk-VSYHZECT.js.map +0 -1
- package/dist/chunk-WC7WULGV.js.map +0 -1
- package/dist/chunk-XKUMNGBW.js.map +0 -1
- package/dist/chunk-YRT7GQ5Y.js +0 -28
- package/dist/chunk-YRT7GQ5Y.js.map +0 -1
- package/dist/container/index.js.map +0 -1
- package/dist/csv/index.js.map +0 -1
- package/dist/docx/index.js.map +0 -1
- package/dist/epub/index.js.map +0 -1
- package/dist/extract-H6RXJMHP.js +0 -15
- package/dist/extract-H6RXJMHP.js.map +0 -1
- package/dist/html/index.js.map +0 -1
- package/dist/images-7FBWPKE3.js +0 -7
- package/dist/images-7FBWPKE3.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/infer/index.js.map +0 -1
- package/dist/layouts-QVPK3ZCU.js +0 -12
- package/dist/layouts-QVPK3ZCU.js.map +0 -1
- package/dist/mapTheme-IR27S6IV.js.map +0 -1
- package/dist/ooxml/index.js.map +0 -1
- package/dist/pdf/index.js.map +0 -1
- package/dist/pptx/index.js.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/xlsx/index.js.map +0 -1
- package/src/__tests__/container.test.ts +0 -230
- package/src/__tests__/convert.test.ts +0 -495
- package/src/__tests__/csvImport.test.ts +0 -84
- package/src/__tests__/docxExport.test.ts +0 -457
- package/src/__tests__/docxImport.test.ts +0 -410
- package/src/__tests__/epub.test.ts +0 -649
- package/src/__tests__/exportThemeReconciliation.test.ts +0 -87
- package/src/__tests__/formatRegistry.test.ts +0 -174
- package/src/__tests__/html.test.ts +0 -435
- package/src/__tests__/htmlImport.test.ts +0 -57
- package/src/__tests__/inferTheme.test.ts +0 -135
- package/src/__tests__/lossyWarnings.test.ts +0 -146
- package/src/__tests__/ooxml.test.ts +0 -271
- package/src/__tests__/ooxmlCancellation.test.ts +0 -113
- package/src/__tests__/ooxmlThemeReader.test.ts +0 -92
- package/src/__tests__/pdfExport.test.ts +0 -322
- package/src/__tests__/pdfImport.test.ts +0 -384
- package/src/__tests__/plainHtml.test.ts +0 -417
- package/src/__tests__/plainHtmlBundle.test.ts +0 -253
- package/src/__tests__/pptxExport.test.ts +0 -138
- package/src/__tests__/pptxImport.test.ts +0 -145
- package/src/__tests__/pptxInferFixtures.ts +0 -314
- package/src/__tests__/pptxLayoutInfer.test.ts +0 -395
- package/src/__tests__/roundTrip.test.ts +0 -201
- package/src/__tests__/roundTripAssets.test.ts +0 -50
- package/src/__tests__/roundTripMatrix.fixtures.ts +0 -86
- package/src/__tests__/roundTripMatrix.helpers.ts +0 -154
- package/src/__tests__/roundTripMatrix.test.ts +0 -142
- package/src/__tests__/sharedContainer.test.ts +0 -41
- package/src/__tests__/sharedImages.test.ts +0 -61
- package/src/__tests__/xlsxExport.test.ts +0 -164
- package/src/__tests__/xlsxImport.test.ts +0 -80
- package/src/__tests__/zipSafety.test.ts +0 -317
- package/src/container/index.ts +0 -94
- package/src/csv/index.ts +0 -188
- package/src/docx/export.ts +0 -1267
- package/src/docx/import.ts +0 -995
- package/src/docx/index.ts +0 -26
- package/src/docx/styles.ts +0 -145
- package/src/epub/export.ts +0 -968
- package/src/epub/index.ts +0 -20
- package/src/html/docsHtmlBundle.ts +0 -373
- package/src/html/htmlTemplate.ts +0 -385
- package/src/html/imageUtils.ts +0 -61
- package/src/html/import.ts +0 -297
- package/src/html/index.ts +0 -212
- package/src/html/plainHtml.ts +0 -790
- package/src/html/plainHtmlBundle.ts +0 -421
- package/src/index.ts +0 -109
- package/src/infer/extract.ts +0 -127
- package/src/infer/index.ts +0 -199
- package/src/infer/mapTheme.ts +0 -176
- package/src/infer/types.ts +0 -27
- package/src/ooxml/index.ts +0 -111
- package/src/ooxml/namespaces.ts +0 -196
- package/src/ooxml/readUtils.ts +0 -44
- package/src/ooxml/reader.ts +0 -318
- package/src/ooxml/themeReader.ts +0 -197
- package/src/ooxml/types.ts +0 -103
- package/src/ooxml/writer.ts +0 -339
- package/src/ooxml/xmlUtils.ts +0 -123
- package/src/pdf/export.ts +0 -1084
- package/src/pdf/import.ts +0 -1164
- package/src/pdf/index.ts +0 -29
- package/src/pdf/styles.ts +0 -180
- package/src/pptx/export.ts +0 -1184
- package/src/pptx/import.ts +0 -455
- package/src/pptx/index.ts +0 -52
- package/src/pptx/layouts.ts +0 -1222
- package/src/pptx/styles.ts +0 -96
- package/src/pptx/templates.ts +0 -187
- package/src/registry/convert.ts +0 -433
- package/src/registry/defaultFormats.ts +0 -413
- package/src/registry/errors.ts +0 -46
- package/src/registry/index.ts +0 -43
- package/src/registry/registry.ts +0 -48
- package/src/registry/types.ts +0 -170
- package/src/shared/boundedZipArchive.ts +0 -383
- package/src/shared/container.ts +0 -28
- package/src/shared/fidelity.ts +0 -130
- package/src/shared/images.ts +0 -44
- package/src/shared/inlineRuns.ts +0 -99
- package/src/shared/text.ts +0 -41
- package/src/shared/zipEntryCount.ts +0 -151
- package/src/shared/zipLimits.ts +0 -296
- package/src/shared/zipSafety.ts +0 -19
- package/src/xlsx/export.ts +0 -253
- package/src/xlsx/import.ts +0 -160
- package/src/xlsx/index.ts +0 -35
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
|
+
RelIdAllocator,
|
|
2
3
|
inlineNodeToRuns,
|
|
3
|
-
inlineNodesToRuns
|
|
4
|
-
|
|
4
|
+
inlineNodesToRuns,
|
|
5
|
+
normalizeOoxmlHex,
|
|
6
|
+
sanitizeOfficeHyperlink
|
|
7
|
+
} from "./chunk-GX7RAUME.js";
|
|
5
8
|
import {
|
|
6
9
|
stripHtmlTags
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-SBUW7NHR.js";
|
|
8
11
|
import {
|
|
9
12
|
createPackage
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-4V3KCHAP.js";
|
|
11
14
|
import {
|
|
12
15
|
escapeXml,
|
|
13
16
|
xmlDeclaration
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JU2RHXUB.js";
|
|
15
18
|
import {
|
|
16
19
|
CONTENT_TYPE_DOCX_DOCUMENT,
|
|
17
20
|
CONTENT_TYPE_DOCX_FONT_TABLE,
|
|
21
|
+
CONTENT_TYPE_DOCX_FOOTER,
|
|
18
22
|
CONTENT_TYPE_DOCX_FOOTNOTES,
|
|
23
|
+
CONTENT_TYPE_DOCX_HEADER,
|
|
19
24
|
CONTENT_TYPE_DOCX_NUMBERING,
|
|
20
25
|
CONTENT_TYPE_DOCX_SETTINGS,
|
|
21
26
|
CONTENT_TYPE_DOCX_STYLES,
|
|
@@ -23,24 +28,29 @@ import {
|
|
|
23
28
|
NS_R,
|
|
24
29
|
NS_WML,
|
|
25
30
|
REL_FONT_TABLE,
|
|
31
|
+
REL_FOOTER,
|
|
26
32
|
REL_FOOTNOTES,
|
|
33
|
+
REL_HEADER,
|
|
27
34
|
REL_HYPERLINK,
|
|
28
35
|
REL_IMAGE,
|
|
29
36
|
REL_NUMBERING,
|
|
30
37
|
REL_OFFICE_DOCUMENT,
|
|
31
38
|
REL_SETTINGS,
|
|
32
39
|
REL_STYLES,
|
|
40
|
+
baseDirOf,
|
|
33
41
|
getPartBinary,
|
|
34
42
|
getPartRelationships,
|
|
35
43
|
getPartXml,
|
|
36
|
-
openPackage
|
|
37
|
-
|
|
44
|
+
openPackage,
|
|
45
|
+
requireMainPartPath,
|
|
46
|
+
resolveTarget
|
|
47
|
+
} from "./chunk-X2DEAXNK.js";
|
|
38
48
|
import {
|
|
39
49
|
buildContainer
|
|
40
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-IIQYS2YH.js";
|
|
41
51
|
import {
|
|
42
52
|
extToMime
|
|
43
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-AONELFLA.js";
|
|
44
54
|
|
|
45
55
|
// src/docx/export.ts
|
|
46
56
|
import { resolveFontFamily } from "@bendyline/squisq/schemas";
|
|
@@ -103,10 +113,31 @@ function pointsToTwips(points) {
|
|
|
103
113
|
|
|
104
114
|
// src/docx/export.ts
|
|
105
115
|
async function markdownDocToDocx(doc, options = {}) {
|
|
116
|
+
options.signal?.throwIfAborted();
|
|
106
117
|
const resolvedOptions = options.themeId !== void 0 ? options : { ...options, themeId: readFrontmatterThemeId(doc.frontmatter) };
|
|
107
118
|
const ctx = new ExportContext(resolvedOptions, doc);
|
|
108
|
-
const
|
|
109
|
-
|
|
119
|
+
const stories = partitionDocumentStories(doc.children);
|
|
120
|
+
ctx.setRelationshipSource("document");
|
|
121
|
+
const bodyXml = convertBlocks(stories.body, ctx);
|
|
122
|
+
ctx.setRelationshipSource("header");
|
|
123
|
+
const headerXml = convertBlocks(stories.header, ctx);
|
|
124
|
+
ctx.setRelationshipSource("footer");
|
|
125
|
+
const footerXml = convertBlocks(stories.footer, ctx);
|
|
126
|
+
ctx.setRelationshipSource("document");
|
|
127
|
+
return buildDocxPackage(bodyXml, headerXml, footerXml, ctx, resolvedOptions);
|
|
128
|
+
}
|
|
129
|
+
function partitionDocumentStories(nodes) {
|
|
130
|
+
const stories = { body: [], header: [], footer: [] };
|
|
131
|
+
for (const node of nodes) {
|
|
132
|
+
if (node.type === "containerDirective" && node.name === "docx-header") {
|
|
133
|
+
stories.header.push(...node.children);
|
|
134
|
+
} else if (node.type === "containerDirective" && node.name === "docx-footer") {
|
|
135
|
+
stories.footer.push(...node.children);
|
|
136
|
+
} else {
|
|
137
|
+
stories.body.push(node);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return stories;
|
|
110
141
|
}
|
|
111
142
|
async function docToDocx(doc, options = {}) {
|
|
112
143
|
const markdownDoc = docToMarkdown(doc);
|
|
@@ -114,12 +145,20 @@ async function docToDocx(doc, options = {}) {
|
|
|
114
145
|
}
|
|
115
146
|
var ExportContext = class {
|
|
116
147
|
constructor(options, doc) {
|
|
117
|
-
|
|
148
|
+
/**
|
|
149
|
+
* One id source per rels part — see `RelIdAllocator`. Hyperlink, image AND
|
|
150
|
+
* fixed (styles/numbering/settings/…) rels all draw from this, keyed by the
|
|
151
|
+
* story part they belong to, so `word/_rels/document.xml.rels` cannot
|
|
152
|
+
* contain a duplicate `Id` no matter how many hyperlinks/images a document
|
|
153
|
+
* has.
|
|
154
|
+
*/
|
|
155
|
+
this.relIds = new RelIdAllocator();
|
|
118
156
|
this.nextNumId = 1;
|
|
119
157
|
this.nextFootnoteId = 1;
|
|
120
158
|
// 0 is separator, start user footnotes at 1
|
|
121
159
|
/** Relationships for word/_rels/document.xml.rels */
|
|
122
160
|
this.relationships = [];
|
|
161
|
+
this.relationshipSource = "document";
|
|
123
162
|
/** Numbering definitions (abstract + num) */
|
|
124
163
|
this.numberingDefs = [];
|
|
125
164
|
/** Footnote XML bodies (keyed by footnote id) */
|
|
@@ -143,11 +182,10 @@ var ExportContext = class {
|
|
|
143
182
|
const theme = resolveThemeForDoc(doc, options.themeId, options.themeRegistry);
|
|
144
183
|
themeFont = firstFontFromStack(resolveFontFamily(theme.typography?.bodyFont, ""));
|
|
145
184
|
themeTitleFont = firstFontFromStack(resolveFontFamily(theme.typography?.titleFont, ""));
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (theme.colors?.background) themeBackgroundColor = stripHash(theme.colors.background);
|
|
185
|
+
themeHeadingColor = normalizeOoxmlHex(theme.colors?.primary);
|
|
186
|
+
themeBodyColor = normalizeOoxmlHex(theme.colors?.text);
|
|
187
|
+
themeMutedColor = normalizeOoxmlHex(theme.colors?.textMuted);
|
|
188
|
+
themeBackgroundColor = normalizeOoxmlHex(theme.colors?.background);
|
|
151
189
|
}
|
|
152
190
|
this.font = options.defaultFont ?? themeFont ?? DEFAULT_FONT;
|
|
153
191
|
this.headingFont = themeTitleFont ?? this.font;
|
|
@@ -157,19 +195,33 @@ var ExportContext = class {
|
|
|
157
195
|
this.mutedColor = themeMutedColor;
|
|
158
196
|
this.backgroundColor = themeBackgroundColor;
|
|
159
197
|
this.resolvedImages = options.images ?? /* @__PURE__ */ new Map();
|
|
198
|
+
this.allowRelativeHyperlinks = options.allowRelativeHyperlinks ?? false;
|
|
199
|
+
this.signal = options.signal;
|
|
160
200
|
}
|
|
161
|
-
/** Allocate a
|
|
201
|
+
/** Allocate a relationship ID on the story part currently being converted. */
|
|
162
202
|
allocRelId() {
|
|
163
|
-
return
|
|
203
|
+
return this.allocRelIdFor(this.relationshipSource);
|
|
204
|
+
}
|
|
205
|
+
/** Allocate a relationship ID on a specific story part. */
|
|
206
|
+
allocRelIdFor(source) {
|
|
207
|
+
return this.relIds.alloc(docxStoryPartPath(source));
|
|
208
|
+
}
|
|
209
|
+
setRelationshipSource(source) {
|
|
210
|
+
this.relationshipSource = source;
|
|
164
211
|
}
|
|
165
212
|
/** Add a hyperlink relationship and return the rId */
|
|
166
213
|
addHyperlink(url) {
|
|
214
|
+
const target = sanitizeOfficeHyperlink(url, {
|
|
215
|
+
allowRelative: this.allowRelativeHyperlinks
|
|
216
|
+
});
|
|
217
|
+
if (!target) return null;
|
|
167
218
|
const id = this.allocRelId();
|
|
168
219
|
this.relationships.push({
|
|
169
220
|
id,
|
|
170
221
|
type: REL_HYPERLINK,
|
|
171
|
-
target
|
|
172
|
-
targetMode: "External"
|
|
222
|
+
target,
|
|
223
|
+
targetMode: "External",
|
|
224
|
+
source: this.relationshipSource
|
|
173
225
|
});
|
|
174
226
|
return id;
|
|
175
227
|
}
|
|
@@ -182,7 +234,8 @@ var ExportContext = class {
|
|
|
182
234
|
this.relationships.push({
|
|
183
235
|
id: relId,
|
|
184
236
|
type: REL_IMAGE,
|
|
185
|
-
target: `media/${filename}
|
|
237
|
+
target: `media/${filename}`,
|
|
238
|
+
source: this.relationshipSource
|
|
186
239
|
});
|
|
187
240
|
return { relId, docPrId };
|
|
188
241
|
}
|
|
@@ -204,6 +257,11 @@ var ExportContext = class {
|
|
|
204
257
|
return id;
|
|
205
258
|
}
|
|
206
259
|
};
|
|
260
|
+
function docxStoryPartPath(source) {
|
|
261
|
+
if (source === "header") return "word/header1.xml";
|
|
262
|
+
if (source === "footer") return "word/footer1.xml";
|
|
263
|
+
return "word/document.xml";
|
|
264
|
+
}
|
|
207
265
|
function firstFontFromStack(stack) {
|
|
208
266
|
if (!stack) return "";
|
|
209
267
|
const generics = /* @__PURE__ */ new Set([
|
|
@@ -230,7 +288,9 @@ function firstFontFromStack(stack) {
|
|
|
230
288
|
}
|
|
231
289
|
function convertBlocks(nodes, ctx) {
|
|
232
290
|
const parts = [];
|
|
233
|
-
for (
|
|
291
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
292
|
+
if ((index & 255) === 0) ctx.signal?.throwIfAborted();
|
|
293
|
+
const node = nodes[index];
|
|
234
294
|
parts.push(convertBlock(node, ctx, 0));
|
|
235
295
|
}
|
|
236
296
|
return parts.join("");
|
|
@@ -257,6 +317,8 @@ function convertBlock(node, ctx, listDepth) {
|
|
|
257
317
|
return convertMathBlock(node);
|
|
258
318
|
case "footnoteDefinition":
|
|
259
319
|
return convertFootnoteDefinition(node, ctx);
|
|
320
|
+
case "containerDirective":
|
|
321
|
+
return convertBlocks(node.children, ctx);
|
|
260
322
|
default:
|
|
261
323
|
return "";
|
|
262
324
|
}
|
|
@@ -390,21 +452,20 @@ function convertInline(node, ctx, format) {
|
|
|
390
452
|
function makeRun(text, format) {
|
|
391
453
|
if (!text) return "";
|
|
392
454
|
const rPrParts = [];
|
|
455
|
+
if (format.code) {
|
|
456
|
+
rPrParts.push(`<w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/>`);
|
|
457
|
+
}
|
|
393
458
|
if (format.bold) rPrParts.push("<w:b/>");
|
|
394
459
|
if (format.italic) rPrParts.push("<w:i/>");
|
|
395
460
|
if (format.strike) rPrParts.push("<w:strike/>");
|
|
396
461
|
if (format.color) rPrParts.push(`<w:color w:val="${format.color}"/>`);
|
|
397
|
-
if (format.code) {
|
|
398
|
-
rPrParts.push(
|
|
399
|
-
`<w:rFonts w:ascii="${DEFAULT_CODE_FONT}" w:hAnsi="${DEFAULT_CODE_FONT}"/>`,
|
|
400
|
-
`<w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/>`
|
|
401
|
-
);
|
|
402
|
-
}
|
|
462
|
+
if (format.code) rPrParts.push(`<w:sz w:val="${DEFAULT_CODE_FONT_SIZE}"/>`);
|
|
403
463
|
const rPr = rPrParts.length > 0 ? `<w:rPr>${rPrParts.join("")}</w:rPr>` : "";
|
|
404
464
|
return `<w:r>${rPr}<w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>`;
|
|
405
465
|
}
|
|
406
466
|
function convertLink(node, ctx, format) {
|
|
407
467
|
const rId = ctx.addHyperlink(node.url);
|
|
468
|
+
if (!rId) return convertInlines(node.children, ctx, format);
|
|
408
469
|
const styledRuns = convertInlinesWithHyperlinkStyle(node.children, ctx, format);
|
|
409
470
|
return `<w:hyperlink r:id="${rId}">${styledRuns}</w:hyperlink>`;
|
|
410
471
|
}
|
|
@@ -421,13 +482,10 @@ function convertInlinesWithHyperlinkStyle(nodes, ctx, format) {
|
|
|
421
482
|
}
|
|
422
483
|
function makeHyperlinkRun(text, format) {
|
|
423
484
|
if (!text) return "";
|
|
424
|
-
const rPrParts = [
|
|
425
|
-
'<w:rStyle w:val="Hyperlink"/>',
|
|
426
|
-
`<w:color w:val="${HYPERLINK_COLOR}"/>`,
|
|
427
|
-
'<w:u w:val="single"/>'
|
|
428
|
-
];
|
|
485
|
+
const rPrParts = ['<w:rStyle w:val="Hyperlink"/>'];
|
|
429
486
|
if (format.bold) rPrParts.push("<w:b/>");
|
|
430
487
|
if (format.italic) rPrParts.push("<w:i/>");
|
|
488
|
+
rPrParts.push(`<w:color w:val="${HYPERLINK_COLOR}"/>`, '<w:u w:val="single"/>');
|
|
431
489
|
return `<w:r><w:rPr>${rPrParts.join("")}</w:rPr><w:t xml:space="preserve">${escapeXml(text)}</w:t></w:r>`;
|
|
432
490
|
}
|
|
433
491
|
function convertImage(node, ctx) {
|
|
@@ -498,16 +556,25 @@ function convertFootnoteRef(node, ctx) {
|
|
|
498
556
|
const fnId = ctx.getFootnoteId(node.identifier);
|
|
499
557
|
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
558
|
}
|
|
501
|
-
async function buildDocxPackage(bodyXml, ctx, options) {
|
|
559
|
+
async function buildDocxPackage(bodyXml, headerXml, footerXml, ctx, options) {
|
|
502
560
|
const pkg = createPackage();
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
const
|
|
506
|
-
const settingsRelId =
|
|
507
|
-
const fontTableRelId =
|
|
508
|
-
const
|
|
509
|
-
const
|
|
561
|
+
const hasHeader = headerXml.trim().length > 0;
|
|
562
|
+
const hasFooter = footerXml.trim().length > 0;
|
|
563
|
+
const stylesRelId = ctx.allocRelIdFor("document");
|
|
564
|
+
const settingsRelId = ctx.allocRelIdFor("document");
|
|
565
|
+
const fontTableRelId = ctx.allocRelIdFor("document");
|
|
566
|
+
const numberingRelId = ctx.hasLists ? ctx.allocRelIdFor("document") : void 0;
|
|
567
|
+
const footnotesRelId = ctx.hasFootnotes ? ctx.allocRelIdFor("document") : void 0;
|
|
568
|
+
const headerRelId = hasHeader ? ctx.allocRelIdFor("document") : void 0;
|
|
569
|
+
const footerRelId = hasFooter ? ctx.allocRelIdFor("document") : void 0;
|
|
570
|
+
const documentXml = buildDocumentXml(bodyXml, ctx.backgroundColor, headerRelId, footerRelId);
|
|
510
571
|
pkg.addPart("word/document.xml", documentXml, CONTENT_TYPE_DOCX_DOCUMENT);
|
|
572
|
+
if (hasHeader) {
|
|
573
|
+
pkg.addPart("word/header1.xml", buildStoryXml("header", headerXml), CONTENT_TYPE_DOCX_HEADER);
|
|
574
|
+
}
|
|
575
|
+
if (hasFooter) {
|
|
576
|
+
pkg.addPart("word/footer1.xml", buildStoryXml("footer", footerXml), CONTENT_TYPE_DOCX_FOOTER);
|
|
577
|
+
}
|
|
511
578
|
const stylesXml = buildStylesXml(options, ctx);
|
|
512
579
|
pkg.addPart("word/styles.xml", stylesXml, CONTENT_TYPE_DOCX_STYLES);
|
|
513
580
|
const settingsXml = buildSettingsXml(ctx.backgroundColor !== void 0);
|
|
@@ -542,22 +609,36 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
542
609
|
type: REL_FONT_TABLE,
|
|
543
610
|
target: "fontTable.xml"
|
|
544
611
|
});
|
|
545
|
-
if (
|
|
612
|
+
if (numberingRelId) {
|
|
546
613
|
pkg.addRelationship("word/document.xml", {
|
|
547
614
|
id: numberingRelId,
|
|
548
615
|
type: REL_NUMBERING,
|
|
549
616
|
target: "numbering.xml"
|
|
550
617
|
});
|
|
551
618
|
}
|
|
552
|
-
if (
|
|
619
|
+
if (footnotesRelId) {
|
|
553
620
|
pkg.addRelationship("word/document.xml", {
|
|
554
621
|
id: footnotesRelId,
|
|
555
622
|
type: REL_FOOTNOTES,
|
|
556
623
|
target: "footnotes.xml"
|
|
557
624
|
});
|
|
558
625
|
}
|
|
559
|
-
|
|
626
|
+
if (headerRelId) {
|
|
627
|
+
pkg.addRelationship("word/document.xml", {
|
|
628
|
+
id: headerRelId,
|
|
629
|
+
type: REL_HEADER,
|
|
630
|
+
target: "header1.xml"
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
if (footerRelId) {
|
|
560
634
|
pkg.addRelationship("word/document.xml", {
|
|
635
|
+
id: footerRelId,
|
|
636
|
+
type: REL_FOOTER,
|
|
637
|
+
target: "footer1.xml"
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
for (const rel of ctx.relationships) {
|
|
641
|
+
pkg.addRelationship(docxStoryPartPath(rel.source), {
|
|
561
642
|
id: rel.id,
|
|
562
643
|
type: rel.type,
|
|
563
644
|
target: rel.target,
|
|
@@ -578,9 +659,14 @@ async function buildDocxPackage(bodyXml, ctx, options) {
|
|
|
578
659
|
}
|
|
579
660
|
return pkg.toArrayBuffer();
|
|
580
661
|
}
|
|
581
|
-
function buildDocumentXml(bodyXml, backgroundColor) {
|
|
662
|
+
function buildDocumentXml(bodyXml, backgroundColor, headerRelId, footerRelId) {
|
|
582
663
|
const backgroundEl = backgroundColor ? `<w:background w:color="${backgroundColor}"/>` : "";
|
|
583
|
-
|
|
664
|
+
const storyReferences = (headerRelId ? `<w:headerReference w:type="default" r:id="${headerRelId}"/>` : "") + (footerRelId ? `<w:footerReference w:type="default" r:id="${footerRelId}"/>` : "");
|
|
665
|
+
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>`;
|
|
666
|
+
}
|
|
667
|
+
function buildStoryXml(kind, bodyXml) {
|
|
668
|
+
const element = kind === "header" ? "hdr" : "ftr";
|
|
669
|
+
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
670
|
}
|
|
585
671
|
function buildStylesXml(options, ctx) {
|
|
586
672
|
const font = ctx.font;
|
|
@@ -655,18 +741,20 @@ function buildFootnotesXml(ctx) {
|
|
|
655
741
|
// src/docx/import.ts
|
|
656
742
|
import { markdownToDoc } from "@bendyline/squisq/doc";
|
|
657
743
|
import { stringifyMarkdown } from "@bendyline/squisq/markdown";
|
|
744
|
+
var DOCX_MAIN_PART = "word/document.xml";
|
|
658
745
|
async function docxToMarkdownDoc(data, options = {}) {
|
|
659
746
|
const pkg = await openPackage(data, options);
|
|
660
|
-
const
|
|
661
|
-
const
|
|
747
|
+
const mainPart = requireMainPartPath(pkg, DOCX_MAIN_PART, "DOCX");
|
|
748
|
+
const ctx = await buildImportContext(pkg, options, mainPart);
|
|
749
|
+
const documentXml = await getPartXml(pkg, mainPart);
|
|
662
750
|
if (!documentXml) {
|
|
663
|
-
|
|
751
|
+
throw new Error(`Invalid DOCX package: main document part "${mainPart}" could not be parsed.`);
|
|
664
752
|
}
|
|
665
753
|
const body = getFirstElement(documentXml, "body");
|
|
666
754
|
if (!body) {
|
|
667
755
|
return { type: "document", children: [] };
|
|
668
756
|
}
|
|
669
|
-
const blocks = await
|
|
757
|
+
const blocks = await convertDocumentStories(body, ctx);
|
|
670
758
|
return { type: "document", children: blocks };
|
|
671
759
|
}
|
|
672
760
|
async function docxToDoc(data, options = {}) {
|
|
@@ -675,16 +763,19 @@ async function docxToDoc(data, options = {}) {
|
|
|
675
763
|
}
|
|
676
764
|
async function docxToContainer(data, options = {}) {
|
|
677
765
|
const pkg = await openPackage(data, options);
|
|
678
|
-
const
|
|
679
|
-
const
|
|
680
|
-
|
|
766
|
+
const mainPart = requireMainPartPath(pkg, DOCX_MAIN_PART, "DOCX");
|
|
767
|
+
const ctx = await buildImportContext(pkg, { ...options, extractImages: true }, mainPart);
|
|
768
|
+
const documentXml = await getPartXml(pkg, mainPart);
|
|
769
|
+
if (!documentXml) {
|
|
770
|
+
throw new Error(`Invalid DOCX package: main document part "${mainPart}" could not be parsed.`);
|
|
771
|
+
}
|
|
681
772
|
const body = getFirstElement(documentXml, "body");
|
|
682
773
|
if (!body) return buildContainer("", []);
|
|
683
|
-
const blocks = await
|
|
774
|
+
const blocks = await convertDocumentStories(body, ctx);
|
|
684
775
|
const markdownDoc = { type: "document", children: blocks };
|
|
685
776
|
return buildContainer(stringifyMarkdown(markdownDoc), ctx.extractedImages);
|
|
686
777
|
}
|
|
687
|
-
async function buildImportContext(pkg, options) {
|
|
778
|
+
async function buildImportContext(pkg, options, mainPartPath = DOCX_MAIN_PART) {
|
|
688
779
|
const ctx = {
|
|
689
780
|
headingStyles: /* @__PURE__ */ new Map(),
|
|
690
781
|
quoteStyles: /* @__PURE__ */ new Set(),
|
|
@@ -693,6 +784,9 @@ async function buildImportContext(pkg, options) {
|
|
|
693
784
|
documentRels: /* @__PURE__ */ new Map(),
|
|
694
785
|
numbering: /* @__PURE__ */ new Map(),
|
|
695
786
|
footnotes: /* @__PURE__ */ new Map(),
|
|
787
|
+
endnotes: /* @__PURE__ */ new Map(),
|
|
788
|
+
currentPartPath: mainPartPath,
|
|
789
|
+
mainPartPath,
|
|
696
790
|
pkg,
|
|
697
791
|
options,
|
|
698
792
|
extractedImages: /* @__PURE__ */ new Map(),
|
|
@@ -711,12 +805,13 @@ async function buildImportContext(pkg, options) {
|
|
|
711
805
|
ctx.inlineCodeStyles.add(id);
|
|
712
806
|
}
|
|
713
807
|
await parseStyles(pkg, ctx);
|
|
714
|
-
const rels = await getPartRelationships(pkg,
|
|
808
|
+
const rels = await getPartRelationships(pkg, mainPartPath);
|
|
715
809
|
for (const rel of rels) {
|
|
716
810
|
ctx.documentRels.set(rel.id, rel);
|
|
717
811
|
}
|
|
718
812
|
await parseNumbering(pkg, ctx);
|
|
719
813
|
await parseFootnotes(pkg, ctx);
|
|
814
|
+
await parseEndnotes(pkg, ctx);
|
|
720
815
|
return ctx;
|
|
721
816
|
}
|
|
722
817
|
async function parseStyles(pkg, ctx) {
|
|
@@ -797,9 +892,67 @@ async function parseFootnotes(pkg, ctx) {
|
|
|
797
892
|
ctx.footnotes.set(id, fn);
|
|
798
893
|
}
|
|
799
894
|
}
|
|
895
|
+
async function parseEndnotes(pkg, ctx) {
|
|
896
|
+
const doc = await getPartXml(pkg, "word/endnotes.xml");
|
|
897
|
+
if (!doc) return;
|
|
898
|
+
const endnoteEls = getAllElements(doc, "endnote");
|
|
899
|
+
for (const note of endnoteEls) {
|
|
900
|
+
const id = getAttr(note, "id");
|
|
901
|
+
const type = getAttr(note, "type");
|
|
902
|
+
if (!id || type === "separator" || type === "continuationSeparator") continue;
|
|
903
|
+
ctx.endnotes.set(id, note);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
async function convertDocumentStories(body, ctx) {
|
|
907
|
+
const bodyBlocks = await convertBody(body, ctx);
|
|
908
|
+
const headers = await convertRelatedStories(body, ctx, "header");
|
|
909
|
+
const footers = await convertRelatedStories(body, ctx, "footer");
|
|
910
|
+
const noteDefinitions = await convertNoteDefinitions(ctx);
|
|
911
|
+
return [...bodyBlocks, ...headers, ...footers, ...noteDefinitions];
|
|
912
|
+
}
|
|
913
|
+
async function convertRelatedStories(body, ctx, kind) {
|
|
914
|
+
const relationshipTypeSuffix = `/${kind}`;
|
|
915
|
+
const referenceName = `${kind}Reference`;
|
|
916
|
+
const referenceTypes = /* @__PURE__ */ new Map();
|
|
917
|
+
for (const reference of getAllElements(body, referenceName)) {
|
|
918
|
+
const id = reference.getAttributeNS(NS_R, "id") ?? reference.getAttribute("r:id");
|
|
919
|
+
if (id) referenceTypes.set(id, getAttr(reference, "type") ?? "default");
|
|
920
|
+
}
|
|
921
|
+
const documentRelationships = ctx.documentRels;
|
|
922
|
+
const previousPartPath = ctx.currentPartPath;
|
|
923
|
+
const results = [];
|
|
924
|
+
for (const relationship of documentRelationships.values()) {
|
|
925
|
+
if (!relationship.type.endsWith(relationshipTypeSuffix)) continue;
|
|
926
|
+
const partPath = resolveTarget(baseDirOf(ctx.mainPartPath), relationship.target);
|
|
927
|
+
const part = await getPartXml(ctx.pkg, partPath);
|
|
928
|
+
if (!part?.documentElement) continue;
|
|
929
|
+
const partRelationships = await getPartRelationships(ctx.pkg, partPath);
|
|
930
|
+
ctx.documentRels = new Map(partRelationships.map((rel) => [rel.id, rel]));
|
|
931
|
+
ctx.currentPartPath = partPath;
|
|
932
|
+
try {
|
|
933
|
+
const children = await convertBody(part.documentElement, ctx);
|
|
934
|
+
if (children.length === 0) continue;
|
|
935
|
+
results.push({
|
|
936
|
+
type: "containerDirective",
|
|
937
|
+
name: `docx-${kind}`,
|
|
938
|
+
attributes: {
|
|
939
|
+
type: referenceTypes.get(relationship.id) ?? "default",
|
|
940
|
+
source: partPath
|
|
941
|
+
},
|
|
942
|
+
children
|
|
943
|
+
});
|
|
944
|
+
} finally {
|
|
945
|
+
ctx.documentRels = documentRelationships;
|
|
946
|
+
ctx.currentPartPath = previousPartPath;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return results;
|
|
950
|
+
}
|
|
800
951
|
async function convertBody(body, ctx) {
|
|
952
|
+
return convertBlockElements(Array.from(body.children), ctx);
|
|
953
|
+
}
|
|
954
|
+
async function convertBlockElements(children, ctx) {
|
|
801
955
|
const result = [];
|
|
802
|
-
const children = Array.from(body.children);
|
|
803
956
|
let i = 0;
|
|
804
957
|
while (i < children.length) {
|
|
805
958
|
const el = children[i];
|
|
@@ -821,12 +974,22 @@ async function convertBody(body, ctx) {
|
|
|
821
974
|
const table = await convertTable2(el, ctx);
|
|
822
975
|
if (table) result.push(table);
|
|
823
976
|
i++;
|
|
977
|
+
} else if (localName === "sdt") {
|
|
978
|
+
const content = getFirstChildElement(el, "sdtContent");
|
|
979
|
+
if (content) result.push(...await convertBlockElements(Array.from(content.children), ctx));
|
|
980
|
+
i++;
|
|
981
|
+
} else if (localName === "ins" || localName === "moveTo" || localName === "customXml" || localName === "smartTag" || localName === "fldSimple") {
|
|
982
|
+
result.push(...await convertBlockElements(Array.from(el.children), ctx));
|
|
983
|
+
i++;
|
|
984
|
+
} else if (localName === "AlternateContent") {
|
|
985
|
+
const selected = getFirstChildElement(el, "Choice") ?? getFirstChildElement(el, "Fallback");
|
|
986
|
+
if (selected)
|
|
987
|
+
result.push(...await convertBlockElements(Array.from(selected.children), ctx));
|
|
988
|
+
i++;
|
|
824
989
|
} else {
|
|
825
990
|
i++;
|
|
826
991
|
}
|
|
827
992
|
}
|
|
828
|
-
const footnoteNodes = await convertFootnoteDefinitions(ctx);
|
|
829
|
-
result.push(...footnoteNodes);
|
|
830
993
|
return result;
|
|
831
994
|
}
|
|
832
995
|
async function convertParagraph2(el, ctx) {
|
|
@@ -857,8 +1020,10 @@ async function convertParagraph2(el, ctx) {
|
|
|
857
1020
|
return { type: "paragraph", children: inlines };
|
|
858
1021
|
}
|
|
859
1022
|
async function convertRuns(paragraphEl, ctx) {
|
|
1023
|
+
return mergeAdjacentText(await convertInlineElements(Array.from(paragraphEl.children), ctx));
|
|
1024
|
+
}
|
|
1025
|
+
async function convertInlineElements(children, ctx) {
|
|
860
1026
|
const result = [];
|
|
861
|
-
const children = Array.from(paragraphEl.children);
|
|
862
1027
|
for (const child of children) {
|
|
863
1028
|
const localName = child.localName;
|
|
864
1029
|
if (localName === "r") {
|
|
@@ -867,9 +1032,23 @@ async function convertRuns(paragraphEl, ctx) {
|
|
|
867
1032
|
} else if (localName === "hyperlink") {
|
|
868
1033
|
const link = await convertHyperlink(child, ctx);
|
|
869
1034
|
if (link) result.push(link);
|
|
1035
|
+
} else if (localName === "sdt") {
|
|
1036
|
+
const content = getFirstChildElement(child, "sdtContent");
|
|
1037
|
+
if (content) {
|
|
1038
|
+
result.push(...await convertInlineElements(Array.from(content.children), ctx));
|
|
1039
|
+
}
|
|
1040
|
+
} else if (localName === "ins" || localName === "moveTo" || localName === "customXml" || localName === "smartTag" || localName === "fldSimple") {
|
|
1041
|
+
result.push(...await convertInlineElements(Array.from(child.children), ctx));
|
|
1042
|
+
} else if (localName === "AlternateContent") {
|
|
1043
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1044
|
+
if (selected) {
|
|
1045
|
+
result.push(...await convertInlineElements(Array.from(selected.children), ctx));
|
|
1046
|
+
}
|
|
1047
|
+
} else if (localName === "drawing" || localName === "pict") {
|
|
1048
|
+
result.push(...await convertDrawingContent(child, ctx));
|
|
870
1049
|
}
|
|
871
1050
|
}
|
|
872
|
-
return
|
|
1051
|
+
return result;
|
|
873
1052
|
}
|
|
874
1053
|
async function convertRun(runEl, ctx) {
|
|
875
1054
|
const result = [];
|
|
@@ -895,8 +1074,10 @@ async function convertRun(runEl, ctx) {
|
|
|
895
1074
|
}
|
|
896
1075
|
result.push(node);
|
|
897
1076
|
}
|
|
898
|
-
} else if (localName === "br") {
|
|
1077
|
+
} else if (localName === "br" || localName === "cr") {
|
|
899
1078
|
result.push({ type: "break" });
|
|
1079
|
+
} else if (localName === "tab") {
|
|
1080
|
+
result.push({ type: "text", value: " " });
|
|
900
1081
|
} else if (localName === "footnoteReference") {
|
|
901
1082
|
const fnId = getAttr(child, "id");
|
|
902
1083
|
if (fnId && fnId !== "0" && fnId !== "-1") {
|
|
@@ -905,13 +1086,79 @@ async function convertRun(runEl, ctx) {
|
|
|
905
1086
|
identifier: `fn${fnId}`
|
|
906
1087
|
});
|
|
907
1088
|
}
|
|
908
|
-
} else if (localName === "
|
|
909
|
-
const
|
|
910
|
-
if (
|
|
1089
|
+
} else if (localName === "endnoteReference") {
|
|
1090
|
+
const noteId = getAttr(child, "id");
|
|
1091
|
+
if (noteId && noteId !== "0" && noteId !== "-1") {
|
|
1092
|
+
result.push({
|
|
1093
|
+
type: "footnoteReference",
|
|
1094
|
+
identifier: `endnote${noteId}`
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
} else if (localName === "drawing" || localName === "pict" || localName === "object") {
|
|
1098
|
+
result.push(...await convertDrawingContent(child, ctx));
|
|
1099
|
+
} else if (localName === "AlternateContent") {
|
|
1100
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1101
|
+
if (selected) {
|
|
1102
|
+
result.push(...await convertInlineElements(Array.from(selected.children), ctx));
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return result;
|
|
1107
|
+
}
|
|
1108
|
+
async function convertDrawingContent(el, ctx) {
|
|
1109
|
+
const result = [];
|
|
1110
|
+
const textBoxes = findDescendants(el, "txbxContent");
|
|
1111
|
+
for (const textBox of textBoxes) {
|
|
1112
|
+
const inlines = await flattenContainerToInlines(textBox, ctx);
|
|
1113
|
+
appendInlineGroup(result, inlines);
|
|
1114
|
+
}
|
|
1115
|
+
const image = await extractImage(el, ctx);
|
|
1116
|
+
if (image) result.push(image);
|
|
1117
|
+
if (textBoxes.length > 0 && result.length > 0) {
|
|
1118
|
+
if (result[0]?.type !== "break") result.unshift({ type: "break" });
|
|
1119
|
+
if (result[result.length - 1]?.type !== "break") {
|
|
1120
|
+
result.push({ type: "break" });
|
|
911
1121
|
}
|
|
912
1122
|
}
|
|
913
1123
|
return result;
|
|
914
1124
|
}
|
|
1125
|
+
async function flattenContainerToInlines(container, ctx) {
|
|
1126
|
+
const result = [];
|
|
1127
|
+
for (const child of Array.from(container.children)) {
|
|
1128
|
+
if (child.localName === "p") {
|
|
1129
|
+
appendInlineGroup(result, await convertRuns(child, ctx));
|
|
1130
|
+
} else if (child.localName === "tbl") {
|
|
1131
|
+
appendInlineGroup(result, await flattenTableToInlines(child, ctx));
|
|
1132
|
+
} else if (child.localName === "sdt") {
|
|
1133
|
+
const content = getFirstChildElement(child, "sdtContent");
|
|
1134
|
+
if (content) appendInlineGroup(result, await flattenContainerToInlines(content, ctx));
|
|
1135
|
+
} else if (child.localName === "ins" || child.localName === "moveTo" || child.localName === "customXml" || child.localName === "smartTag" || child.localName === "fldSimple") {
|
|
1136
|
+
appendInlineGroup(result, await flattenContainerToInlines(child, ctx));
|
|
1137
|
+
} else if (child.localName === "AlternateContent") {
|
|
1138
|
+
const selected = getFirstChildElement(child, "Choice") ?? getFirstChildElement(child, "Fallback");
|
|
1139
|
+
if (selected) appendInlineGroup(result, await flattenContainerToInlines(selected, ctx));
|
|
1140
|
+
} else if (child.localName === "r" || child.localName === "hyperlink") {
|
|
1141
|
+
appendInlineGroup(result, await convertInlineElements([child], ctx));
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return mergeAdjacentText(result);
|
|
1145
|
+
}
|
|
1146
|
+
async function flattenTableToInlines(table, ctx) {
|
|
1147
|
+
const result = [];
|
|
1148
|
+
for (const row of getAllChildElements(table, "tr")) {
|
|
1149
|
+
for (const cell of getAllChildElements(row, "tc")) {
|
|
1150
|
+
appendInlineGroup(result, await flattenContainerToInlines(cell, ctx));
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return mergeAdjacentText(result);
|
|
1154
|
+
}
|
|
1155
|
+
function appendInlineGroup(target, group) {
|
|
1156
|
+
if (group.length === 0) return;
|
|
1157
|
+
if (target.length > 0 && target[target.length - 1]?.type !== "break") {
|
|
1158
|
+
target.push({ type: "break" });
|
|
1159
|
+
}
|
|
1160
|
+
target.push(...group);
|
|
1161
|
+
}
|
|
915
1162
|
function parseRunFormat(rPr, ctx) {
|
|
916
1163
|
if (!rPr) return { bold: false, italic: false, strike: false, code: false };
|
|
917
1164
|
const bold = hasChildElement(rPr, "b") && !isFalseToggle(getFirstChildElement(rPr, "b"));
|
|
@@ -940,12 +1187,7 @@ async function convertHyperlink(el, ctx) {
|
|
|
940
1187
|
const anchor = el.getAttributeNS(NS_WML, "anchor") ?? el.getAttribute("w:anchor");
|
|
941
1188
|
if (anchor) url = `#${anchor}`;
|
|
942
1189
|
}
|
|
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
|
-
}
|
|
1190
|
+
const inlines = await convertInlineElements(Array.from(el.children), ctx);
|
|
949
1191
|
if (inlines.length === 0) return null;
|
|
950
1192
|
return {
|
|
951
1193
|
type: "link",
|
|
@@ -955,22 +1197,14 @@ async function convertHyperlink(el, ctx) {
|
|
|
955
1197
|
}
|
|
956
1198
|
async function extractImage(el, ctx) {
|
|
957
1199
|
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
|
-
}
|
|
1200
|
+
const imageData = findDescendant(el, "imagedata");
|
|
1201
|
+
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");
|
|
1202
|
+
if (!rId) return null;
|
|
965
1203
|
const rel = ctx.documentRels.get(rId);
|
|
966
|
-
if (!rel)
|
|
967
|
-
|
|
968
|
-
}
|
|
969
|
-
const target = rel.target.startsWith("/") ? rel.target.slice(1) : `word/${rel.target}`;
|
|
1204
|
+
if (!rel || rel.targetMode === "External") return null;
|
|
1205
|
+
const target = resolveTarget(baseDirOf(ctx.currentPartPath), rel.target);
|
|
970
1206
|
const data = await getPartBinary(ctx.pkg, target);
|
|
971
|
-
if (!data)
|
|
972
|
-
return { type: "image", url: "", alt: "Image" };
|
|
973
|
-
}
|
|
1207
|
+
if (!data) return null;
|
|
974
1208
|
const dot = target.lastIndexOf(".");
|
|
975
1209
|
const ext = dot !== -1 ? target.slice(dot).toLowerCase() : ".png";
|
|
976
1210
|
const mimeType = extToMime(ext);
|
|
@@ -978,7 +1212,8 @@ async function extractImage(el, ctx) {
|
|
|
978
1212
|
const imagePath = `images/image${ctx.imageCounter}${ext}`;
|
|
979
1213
|
ctx.extractedImages.set(imagePath, { data, mimeType });
|
|
980
1214
|
const docPr = findDescendant(el, "docPr");
|
|
981
|
-
const
|
|
1215
|
+
const shape = findDescendant(el, "shape");
|
|
1216
|
+
const alt = docPr?.getAttribute("descr") || docPr?.getAttribute("title") || shape?.getAttribute("alt") || shape?.getAttribute("title") || "Image";
|
|
982
1217
|
return {
|
|
983
1218
|
type: "image",
|
|
984
1219
|
url: imagePath,
|
|
@@ -993,6 +1228,14 @@ function findDescendant(el, localName) {
|
|
|
993
1228
|
}
|
|
994
1229
|
return null;
|
|
995
1230
|
}
|
|
1231
|
+
function findDescendants(el, localName) {
|
|
1232
|
+
const results = [];
|
|
1233
|
+
for (const child of Array.from(el.children)) {
|
|
1234
|
+
if (child.localName === localName) results.push(child);
|
|
1235
|
+
results.push(...findDescendants(child, localName));
|
|
1236
|
+
}
|
|
1237
|
+
return results;
|
|
1238
|
+
}
|
|
996
1239
|
async function collectList(elements, startIdx, ctx) {
|
|
997
1240
|
const firstNumPr = getNumPr(elements[startIdx]);
|
|
998
1241
|
const { numId } = firstNumPr;
|
|
@@ -1020,6 +1263,8 @@ async function collectList(elements, startIdx, ctx) {
|
|
|
1020
1263
|
children: nested.items
|
|
1021
1264
|
};
|
|
1022
1265
|
lastItem.children.push(nestedList);
|
|
1266
|
+
} else {
|
|
1267
|
+
items.push(...nested.items);
|
|
1023
1268
|
}
|
|
1024
1269
|
i += nested.consumed;
|
|
1025
1270
|
consumed += nested.consumed;
|
|
@@ -1100,42 +1345,40 @@ async function convertTableRow2(trEl, ctx, isHeader) {
|
|
|
1100
1345
|
return { type: "tableRow", children: cells };
|
|
1101
1346
|
}
|
|
1102
1347
|
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
|
-
}
|
|
1348
|
+
const inlines = await flattenContainerToInlines(tcEl, ctx);
|
|
1112
1349
|
return {
|
|
1113
1350
|
type: "tableCell",
|
|
1114
1351
|
isHeader,
|
|
1115
1352
|
children: mergeAdjacentText(inlines)
|
|
1116
1353
|
};
|
|
1117
1354
|
}
|
|
1118
|
-
async function
|
|
1355
|
+
async function convertNoteDefinitions(ctx) {
|
|
1356
|
+
return [
|
|
1357
|
+
...await convertNotePartDefinitions(ctx, ctx.footnotes, "fn", "word/footnotes.xml"),
|
|
1358
|
+
...await convertNotePartDefinitions(ctx, ctx.endnotes, "endnote", "word/endnotes.xml")
|
|
1359
|
+
];
|
|
1360
|
+
}
|
|
1361
|
+
async function convertNotePartDefinitions(ctx, notes, identifierPrefix, partPath) {
|
|
1119
1362
|
const results = [];
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1363
|
+
const previousRelationships = ctx.documentRels;
|
|
1364
|
+
const previousPartPath = ctx.currentPartPath;
|
|
1365
|
+
const partRelationships = await getPartRelationships(ctx.pkg, partPath);
|
|
1366
|
+
ctx.documentRels = new Map(partRelationships.map((rel) => [rel.id, rel]));
|
|
1367
|
+
ctx.currentPartPath = partPath;
|
|
1368
|
+
try {
|
|
1369
|
+
for (const [id, el] of notes) {
|
|
1370
|
+
const children = await convertBody(el, ctx);
|
|
1371
|
+
if (children.length > 0) {
|
|
1372
|
+
results.push({
|
|
1373
|
+
type: "footnoteDefinition",
|
|
1374
|
+
identifier: `${identifierPrefix}${id}`,
|
|
1375
|
+
children
|
|
1129
1376
|
});
|
|
1130
1377
|
}
|
|
1131
1378
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
identifier: `fn${id}`,
|
|
1136
|
-
children
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1379
|
+
} finally {
|
|
1380
|
+
ctx.documentRels = previousRelationships;
|
|
1381
|
+
ctx.currentPartPath = previousPartPath;
|
|
1139
1382
|
}
|
|
1140
1383
|
return results;
|
|
1141
1384
|
}
|
|
@@ -1209,4 +1452,3 @@ export {
|
|
|
1209
1452
|
docxToDoc,
|
|
1210
1453
|
docxToContainer
|
|
1211
1454
|
};
|
|
1212
|
-
//# sourceMappingURL=chunk-CRAVSMPZ.js.map
|