@bnsights/bbsf-utilities 1.0.69-beta.2 → 1.0.69-beta.3

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.
Files changed (83) hide show
  1. package/esm2022/lib/shared/models/index.mjs +1 -2
  2. package/esm2022/lib/shared/services/index.mjs +1 -2
  3. package/esm2022/public-api.mjs +3 -5
  4. package/fesm2022/bnsights-bbsf-utilities.mjs +1 -64
  5. package/fesm2022/bnsights-bbsf-utilities.mjs.map +1 -1
  6. package/lib/shared/models/index.d.ts +0 -1
  7. package/lib/shared/services/index.d.ts +0 -1
  8. package/package.json +1 -16
  9. package/public-api.d.ts +0 -2
  10. package/esm2022/lib/shared/config/word/constants.mjs +0 -105
  11. package/esm2022/lib/shared/config/word/docx-document.mjs +0 -348
  12. package/esm2022/lib/shared/config/word/helpers/index.mjs +0 -4
  13. package/esm2022/lib/shared/config/word/helpers/render-document-file.mjs +0 -154
  14. package/esm2022/lib/shared/config/word/helpers/xml-builder.mjs +0 -1836
  15. package/esm2022/lib/shared/config/word/html-to-docx.mjs +0 -187
  16. package/esm2022/lib/shared/config/word/index.mjs +0 -50
  17. package/esm2022/lib/shared/config/word/namespaces.mjs +0 -37
  18. package/esm2022/lib/shared/config/word/schemas/content-types.mjs +0 -26
  19. package/esm2022/lib/shared/config/word/schemas/core.mjs +0 -27
  20. package/esm2022/lib/shared/config/word/schemas/document-rels.mjs +0 -16
  21. package/esm2022/lib/shared/config/word/schemas/document.template.mjs +0 -107
  22. package/esm2022/lib/shared/config/word/schemas/font-table.mjs +0 -40
  23. package/esm2022/lib/shared/config/word/schemas/generic-rels.mjs +0 -11
  24. package/esm2022/lib/shared/config/word/schemas/index.mjs +0 -13
  25. package/esm2022/lib/shared/config/word/schemas/numbering.mjs +0 -17
  26. package/esm2022/lib/shared/config/word/schemas/rels.mjs +0 -11
  27. package/esm2022/lib/shared/config/word/schemas/settings.mjs +0 -13
  28. package/esm2022/lib/shared/config/word/schemas/styles.mjs +0 -147
  29. package/esm2022/lib/shared/config/word/schemas/theme.mjs +0 -198
  30. package/esm2022/lib/shared/config/word/schemas/web-settings.mjs +0 -9
  31. package/esm2022/lib/shared/config/word/utils/color-conversion.mjs +0 -60
  32. package/esm2022/lib/shared/config/word/utils/list.mjs +0 -51
  33. package/esm2022/lib/shared/config/word/utils/unit-conversion.mjs +0 -30
  34. package/esm2022/lib/shared/config/word/utils/url.mjs +0 -7
  35. package/esm2022/lib/shared/config/word/utils/vnode.mjs +0 -3
  36. package/esm2022/lib/shared/config/word/word-work/templates/documentTemplate.mjs +0 -54
  37. package/esm2022/lib/shared/config/word/word-work/templates/index.mjs +0 -4
  38. package/esm2022/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.mjs +0 -22
  39. package/esm2022/lib/shared/config/word/word-work/templates/mhtPartTemplate.mjs +0 -10
  40. package/esm2022/lib/shared/config/word/word-work/utils.mjs +0 -26
  41. package/esm2022/lib/shared/models/word-document-model.mjs +0 -8
  42. package/esm2022/lib/shared/services/word-document.service.mjs +0 -57
  43. package/esm2022/word/bnsights-bbsf-utilities-word.mjs +0 -5
  44. package/esm2022/word/public-api.mjs +0 -9
  45. package/fesm2022/bnsights-bbsf-utilities-index-C3Twnewr.mjs +0 -3536
  46. package/fesm2022/bnsights-bbsf-utilities-index-C3Twnewr.mjs.map +0 -1
  47. package/fesm2022/bnsights-bbsf-utilities-word.mjs +0 -13
  48. package/fesm2022/bnsights-bbsf-utilities-word.mjs.map +0 -1
  49. package/lib/shared/config/word/constants.d.ts +0 -124
  50. package/lib/shared/config/word/docx-document.d.ts +0 -73
  51. package/lib/shared/config/word/helpers/index.d.ts +0 -1
  52. package/lib/shared/config/word/helpers/render-document-file.d.ts +0 -2
  53. package/lib/shared/config/word/helpers/xml-builder.d.ts +0 -16
  54. package/lib/shared/config/word/html-to-docx.d.ts +0 -1
  55. package/lib/shared/config/word/index.d.ts +0 -1
  56. package/lib/shared/config/word/namespaces.d.ts +0 -36
  57. package/lib/shared/config/word/schemas/content-types.d.ts +0 -1
  58. package/lib/shared/config/word/schemas/core.d.ts +0 -1
  59. package/lib/shared/config/word/schemas/document-rels.d.ts +0 -1
  60. package/lib/shared/config/word/schemas/document.template.d.ts +0 -4
  61. package/lib/shared/config/word/schemas/font-table.d.ts +0 -1
  62. package/lib/shared/config/word/schemas/generic-rels.d.ts +0 -1
  63. package/lib/shared/config/word/schemas/index.d.ts +0 -12
  64. package/lib/shared/config/word/schemas/numbering.d.ts +0 -1
  65. package/lib/shared/config/word/schemas/rels.d.ts +0 -1
  66. package/lib/shared/config/word/schemas/settings.d.ts +0 -1
  67. package/lib/shared/config/word/schemas/styles.d.ts +0 -1
  68. package/lib/shared/config/word/schemas/theme.d.ts +0 -1
  69. package/lib/shared/config/word/schemas/web-settings.d.ts +0 -1
  70. package/lib/shared/config/word/utils/color-conversion.d.ts +0 -7
  71. package/lib/shared/config/word/utils/list.d.ts +0 -6
  72. package/lib/shared/config/word/utils/unit-conversion.d.ts +0 -29
  73. package/lib/shared/config/word/utils/url.d.ts +0 -1
  74. package/lib/shared/config/word/utils/vnode.d.ts +0 -1
  75. package/lib/shared/config/word/word-work/templates/documentTemplate.d.ts +0 -12
  76. package/lib/shared/config/word/word-work/templates/index.d.ts +0 -3
  77. package/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.d.ts +0 -1
  78. package/lib/shared/config/word/word-work/templates/mhtPartTemplate.d.ts +0 -1
  79. package/lib/shared/config/word/word-work/utils.d.ts +0 -1
  80. package/lib/shared/models/word-document-model.d.ts +0 -16
  81. package/lib/shared/services/word-document.service.d.ts +0 -25
  82. package/word/index.d.ts +0 -5
  83. package/word/public-api.d.ts +0 -2
@@ -1,3536 +0,0 @@
1
- import JSZip from 'jszip';
2
- import { fragment, create } from 'xmlbuilder2';
3
- import VNode$1 from 'virtual-dom/vnode/vnode';
4
- import VText from 'virtual-dom/vnode/vtext';
5
- import HTMLToVDOM from 'html-to-vdom';
6
- import { cloneDeep } from 'lodash';
7
- import { nanoid } from 'nanoid';
8
- import isVNode from 'virtual-dom/vnode/is-vnode';
9
- import isVText from 'virtual-dom/vnode/is-vtext';
10
- import escape from 'escape-html';
11
- import colorNames from 'color-name';
12
- import imageToBase64 from 'image-to-base64';
13
- import mimeTypes from 'mime-types';
14
- import sizeOf from 'image-size';
15
-
16
- const contentTypesXML = `
17
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
18
-
19
- <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
20
- <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
21
- <Default Extension="jpeg" ContentType="image/jpeg"/>
22
- <Default Extension="png" ContentType="image/png"/>
23
- <Default Extension="xml" ContentType="application/xml"/>
24
- <Override PartName="/_rels/.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
25
- <Override PartName="/word/_rels/document.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
26
- <Override PartName="/word/_rels/footer1.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
27
- <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
28
- <Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"/>
29
- <Override PartName="/word/numbering.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"/>
30
- <Override PartName="/word/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
31
- <Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml"/>
32
- <Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
33
- <Override PartName="/word/settings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml"/>
34
- <Override PartName="/word/webSettings.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml"/>
35
- <Override PartName="/word/afchunk.mht" ContentType="message/rfc822"/>
36
- <Override PartName="/word/afchunkheader.mht" ContentType="message/rfc822"/>
37
- <Override PartName="/word/afchunkfooter.mht" ContentType="message/rfc822"/>
38
- </Types>
39
- `;
40
-
41
- const namespaces = {
42
- a: 'http://schemas.openxmlformats.org/drawingml/2006/main',
43
- b: 'http://schemas.openxmlformats.org/officeDocument/2006/bibliography',
44
- cdr: 'http://schemas.openxmlformats.org/drawingml/2006/chartDrawing',
45
- dc: 'http://purl.org/dc/elements/1.1/',
46
- dcmitype: 'http://purl.org/dc/dcmitype/',
47
- dcterms: 'http://purl.org/dc/terms/',
48
- o: 'urn:schemas-microsoft-com:office:office',
49
- pic: 'http://schemas.openxmlformats.org/drawingml/2006/picture',
50
- r: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
51
- v: 'urn:schemas-microsoft-com:vml',
52
- ve: 'http://schemas.openxmlformats.org/markup-compatibility/2006',
53
- vt: 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes',
54
- w: 'http://schemas.openxmlformats.org/wordprocessingml/2006/main',
55
- w10: 'urn:schemas-microsoft-com:office:word',
56
- wp: 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing',
57
- wne: 'http://schemas.microsoft.com/office/word/2006/wordml',
58
- xsd: 'http://www.w3.org/2001/XMLSchema',
59
- xsi: 'http://www.w3.org/2001/XMLSchema-instance',
60
- numbering: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering',
61
- hyperlinks: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink',
62
- images: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
63
- styles: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles',
64
- headers: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/header',
65
- footers: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer',
66
- themes: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme',
67
- coreProperties: 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties',
68
- officeDocumentRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument',
69
- corePropertiesRelation: 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties',
70
- settingsRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings',
71
- webSettingsRelation: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings',
72
- sl: 'http://schemas.openxmlformats.org/schemaLibrary/2006/main',
73
- contentTypes: 'http://schemas.openxmlformats.org/package/2006/content-types',
74
- relationship: 'http://schemas.openxmlformats.org/package/2006/relationships',
75
- };
76
-
77
- const applicationName = 'html-to-docx';
78
- const defaultOrientation = 'portrait';
79
- const landscapeWidth = 15840;
80
- const landscapeHeight = 12240;
81
- const landscapeMargins = {
82
- top: 1800,
83
- right: 1440,
84
- bottom: 1800,
85
- left: 1440,
86
- header: 720,
87
- footer: 720,
88
- gutter: 0,
89
- };
90
- const portraitMargins = {
91
- top: 1440,
92
- right: 1800,
93
- bottom: 1440,
94
- left: 1800,
95
- header: 720,
96
- footer: 720,
97
- gutter: 0,
98
- };
99
- const defaultFont = 'Times New Roman';
100
- const defaultFontSize = 22;
101
- const defaultDocumentOptions = {
102
- orientation: defaultOrientation,
103
- margins: cloneDeep(portraitMargins),
104
- title: '',
105
- subject: '',
106
- creator: applicationName,
107
- keywords: [applicationName],
108
- description: '',
109
- lastModifiedBy: applicationName,
110
- revision: 1,
111
- createdAt: new Date(),
112
- modifiedAt: new Date(),
113
- headerType: 'default',
114
- header: false,
115
- footerType: 'default',
116
- footer: false,
117
- font: defaultFont,
118
- fontSize: defaultFontSize,
119
- complexScriptFontSize: defaultFontSize,
120
- table: {
121
- row: {
122
- cantSplit: false,
123
- },
124
- },
125
- pageSize: {
126
- width: landscapeHeight,
127
- height: landscapeWidth,
128
- },
129
- pageNumber: false,
130
- skipFirstHeaderFooter: false,
131
- lineNumber: false,
132
- lineNumberOptions: {
133
- countBy: 1,
134
- start: 0,
135
- restart: 'continuous',
136
- },
137
- numbering: {
138
- defaultOrderedListStyleType: 'decimal',
139
- },
140
- };
141
- const defaultHTMLString = '<p></p>';
142
- const relsFolderName = '_rels';
143
- const headerFileName = 'header1';
144
- const footerFileName = 'footer1';
145
- const themeFileName = 'theme1';
146
- const documentFileName = 'document';
147
- const headerType = 'header';
148
- const footerType = 'footer';
149
- const themeType = 'theme';
150
- const hyperlinkType = 'hyperlink';
151
- const imageType = 'image';
152
- const internalRelationship = 'Internal';
153
- const wordFolder = 'word';
154
- const themeFolder = 'theme';
155
- const paragraphBordersObject = {
156
- top: {
157
- size: 0,
158
- spacing: 3,
159
- color: 'FFFFFF',
160
- },
161
- left: {
162
- size: 0,
163
- spacing: 3,
164
- color: 'FFFFFF',
165
- },
166
- bottom: {
167
- size: 0,
168
- spacing: 3,
169
- color: 'FFFFFF',
170
- },
171
- right: {
172
- size: 0,
173
- spacing: 3,
174
- color: 'FFFFFF',
175
- },
176
- };
177
- const colorlessColors = ['transparent', 'auto'];
178
- const verticalAlignValues = ['top', 'middle', 'bottom'];
179
-
180
- const generateCoreXML = (title = '', subject = '', creator = applicationName, keywords = [applicationName], description = '', lastModifiedBy = applicationName, revision = 1, createdAt = new Date(), modifiedAt = new Date()) => `
181
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
182
-
183
- <cp:coreProperties
184
- xmlns:cp="${namespaces.coreProperties}"
185
- xmlns:dc="${namespaces.dc}"
186
- xmlns:dcterms="${namespaces.dcterms}"
187
- xmlns:dcmitype="${namespaces.dcmitype}"
188
- xmlns:xsi="${namespaces.xsi}"
189
- >
190
- <dc:title>${title}</dc:title>
191
- <dc:subject>${subject}</dc:subject>
192
- <dc:creator>${creator}</dc:creator>
193
- ${keywords && Array.isArray(keywords)
194
- ? `<cp:keywords>${keywords.join(', ')}</cp:keywords>`
195
- : ''}
196
- <dc:description>${description}</dc:description>
197
- <cp:lastModifiedBy>${lastModifiedBy}</cp:lastModifiedBy>
198
- <cp:revision>${revision}</cp:revision>
199
- <dcterms:created xsi:type="dcterms:W3CDTF">${createdAt instanceof Date ? createdAt.toISOString() : new Date().toISOString()}</dcterms:created>
200
- <dcterms:modified xsi:type="dcterms:W3CDTF">${modifiedAt instanceof Date ? modifiedAt.toISOString() : new Date().toISOString()}</dcterms:modified>
201
- </cp:coreProperties>
202
- `;
203
-
204
- const documentRelsXML = `
205
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
206
-
207
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
208
- <Relationship Id="rId1" Type="${namespaces.numbering}" Target="numbering.xml"/>
209
- <Relationship Id="rId2" Type="${namespaces.styles}" Target="styles.xml"/>
210
- <Relationship Id="rId3" Type="${namespaces.settingsRelation}" Target="settings.xml"/>
211
- <Relationship Id="rId4" Type="${namespaces.webSettingsRelation}" Target="webSettings.xml"/>
212
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunk.mht" Id="htmlChunk" />
213
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkheader.mht" Id="htmlChunkHeader" />
214
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkfooter.mht" Id="htmlChunkFooter" />
215
- </Relationships>
216
- `;
217
-
218
- const relsXML = `
219
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
220
-
221
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
222
- <Relationship Id="rId1" Type="${namespaces.officeDocumentRelation}" Target="word/document.xml"/>
223
- <Relationship Id="rId2" Type="${namespaces.corePropertiesRelation}" Target="docProps/core.xml"/>
224
- </Relationships>
225
- `;
226
-
227
- const generateNumberingXMLTemplate = () => `
228
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
229
-
230
- <w:numbering
231
- xmlns:w="${namespaces.w}"
232
- xmlns:ve="${namespaces.ve}"
233
- xmlns:o="${namespaces.o}"
234
- xmlns:r="${namespaces.r}"
235
- xmlns:v="${namespaces.v}"
236
- xmlns:wp="${namespaces.wp}"
237
- xmlns:w10="${namespaces.w10}"
238
- xmlns:wne="${namespaces.wne}">
239
- </w:numbering>
240
- `;
241
-
242
- const generateStylesXML = (font = defaultFont, fontSize = defaultFontSize, complexScriptFontSize = defaultFontSize) => `
243
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
244
-
245
- <w:styles xmlns:w="${namespaces.w}" xmlns:r="${namespaces.r}">
246
- <w:docDefaults>
247
- <w:rPrDefault>
248
- <w:rPr>
249
- <w:rFonts w:ascii="${font}" w:eastAsiaTheme="minorHAnsi" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi" />
250
- <w:sz w:val="${fontSize}" />
251
- <w:szCs w:val="${complexScriptFontSize}" />
252
- <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA" />
253
- </w:rPr>
254
- </w:rPrDefault>
255
- <w:pPrDefault>
256
- <w:pPr>
257
- <w:spacing w:after="120" w:line="240" w:lineRule="atLeast" />
258
- </w:pPr>
259
- </w:pPrDefault>
260
- </w:docDefaults>
261
- <w:style w:type="character" w:styleId="Hyperlink">
262
- <w:name w:val="Hyperlink" />
263
- <w:rPr>
264
- <w:color w:val="0000FF" />
265
- <w:u w:val="single" />
266
- </w:rPr>
267
- </w:style>
268
- <w:style w:type="paragraph" w:styleId="Heading1">
269
- <w:name w:val="heading 1" />
270
- <w:basedOn w:val="Normal" />
271
- <w:next w:val="Normal" />
272
- <w:uiPriority w:val="9" />
273
- <w:qFormat />
274
- <w:pPr>
275
- <w:keepNext />
276
- <w:keepLines />
277
- <w:spacing w:before="480" />
278
- <w:outlineLvl w:val="0" />
279
- </w:pPr>
280
- <w:rPr>
281
- <w:b />
282
- <w:sz w:val="48" />
283
- <w:szCs w:val="48" />
284
- </w:rPr>
285
- </w:style>
286
- <w:style w:type="paragraph" w:styleId="Heading2">
287
- <w:name w:val="heading 2" />
288
- <w:basedOn w:val="Normal" />
289
- <w:next w:val="Normal" />
290
- <w:uiPriority w:val="9" />
291
- <w:unhideWhenUsed />
292
- <w:qFormat />
293
- <w:pPr>
294
- <w:keepNext />
295
- <w:keepLines />
296
- <w:spacing w:before="360" w:after="80" />
297
- <w:outlineLvl w:val="1" />
298
- </w:pPr>
299
- <w:rPr>
300
- <w:b />
301
- <w:sz w:val="36" />
302
- <w:szCs w:val="36" />
303
- </w:rPr>
304
- </w:style>
305
- <w:style w:type="paragraph" w:styleId="Heading3">
306
- <w:name w:val="heading 3" />
307
- <w:basedOn w:val="Normal" />
308
- <w:next w:val="Normal" />
309
- <w:uiPriority w:val="9" />
310
- <w:semiHidden />
311
- <w:unhideWhenUsed />
312
- <w:qFormat />
313
- <w:pPr>
314
- <w:keepNext />
315
- <w:keepLines />
316
- <w:spacing w:before="280" w:after="80" />
317
- <w:outlineLvl w:val="2" />
318
- </w:pPr>
319
- <w:rPr>
320
- <w:b />
321
- <w:sz w:val="28" />
322
- <w:szCs w:val="28" />
323
- </w:rPr>
324
- </w:style>
325
- <w:style w:type="paragraph" w:styleId="Heading4">
326
- <w:name w:val="heading 4" />
327
- <w:basedOn w:val="Normal" />
328
- <w:next w:val="Normal" />
329
- <w:uiPriority w:val="9" />
330
- <w:semiHidden />
331
- <w:unhideWhenUsed />
332
- <w:qFormat />
333
- <w:pPr>
334
- <w:keepNext />
335
- <w:keepLines />
336
- <w:spacing w:before="240" w:after="40" />
337
- <w:outlineLvl w:val="3" />
338
- </w:pPr>
339
- <w:rPr>
340
- <w:b />
341
- <w:sz w:val="24" />
342
- <w:szCs w:val="24" />
343
- </w:rPr>
344
- </w:style>
345
- <w:style w:type="paragraph" w:styleId="Heading5">
346
- <w:name w:val="heading 5" />
347
- <w:basedOn w:val="Normal" />
348
- <w:next w:val="Normal" />
349
- <w:uiPriority w:val="9" />
350
- <w:semiHidden />
351
- <w:unhideWhenUsed />
352
- <w:qFormat />
353
- <w:pPr>
354
- <w:keepNext />
355
- <w:keepLines />
356
- <w:spacing w:before="220" w:after="40" />
357
- <w:outlineLvl w:val="4" />
358
- </w:pPr>
359
- <w:rPr>
360
- <w:b />
361
- </w:rPr>
362
- </w:style>
363
- <w:style w:type="paragraph" w:styleId="Heading6">
364
- <w:name w:val="heading 6" />
365
- <w:basedOn w:val="Normal" />
366
- <w:next w:val="Normal" />
367
- <w:uiPriority w:val="9" />
368
- <w:semiHidden />
369
- <w:unhideWhenUsed />
370
- <w:qFormat />
371
- <w:pPr>
372
- <w:keepNext />
373
- <w:keepLines />
374
- <w:spacing w:before="200" w:after="40" />
375
- <w:outlineLvl w:val="5" />
376
- </w:pPr>
377
- <w:rPr>
378
- <w:b />
379
- <w:sz w:val="20" />
380
- <w:szCs w:val="20" />
381
- </w:rPr>
382
- </w:style>
383
- </w:styles>
384
- `;
385
-
386
- const fontTableXML = `
387
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
388
-
389
- <w:fonts
390
- xmlns:r="${namespaces.r}"
391
- xmlns:w="${namespaces.w}"
392
- >
393
- <w:font w:name="Symbol">
394
- <w:panose1 w:val="05050102010706020507"/>
395
- <w:charset w:val="02"/>
396
- <w:family w:val="decorative"/>
397
- <w:pitch w:val="variable"/>
398
- <w:sig w:usb0="00000000" w:usb1="10000000" w:usb2="00000000" w:usb3="00000000" w:csb0="80000000" w:csb1="00000000"/>
399
- </w:font>
400
- <w:font w:name="Calibri">
401
- <w:panose1 w:val="020F0502020204030204"/>
402
- <w:charset w:val="00"/>
403
- <w:family w:val="swiss"/>
404
- <w:pitch w:val="variable"/>
405
- <w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
406
- </w:font>
407
- <w:font w:name="Times New Roman">
408
- <w:panose1 w:val="02020603050405020304"/>
409
- <w:charset w:val="00"/>
410
- <w:family w:val="roman"/>
411
- <w:pitch w:val="variable"/>
412
- <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
413
- </w:font>
414
- <w:font w:name="Calibri Light">
415
- <w:panose1 w:val="020F0302020204030204"/>
416
- <w:charset w:val="00"/>
417
- <w:family w:val="swiss"/>
418
- <w:pitch w:val="variable"/>
419
- <w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000" w:csb0="000001FF" w:csb1="00000000"/>
420
- </w:font>
421
- </w:fonts>
422
- `;
423
-
424
- const generateThemeXML = (font = defaultFont) => `
425
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
426
-
427
- <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">
428
- <a:themeElements>
429
- <a:clrScheme name="Office">
430
- <a:dk1>
431
- <a:sysClr val="windowText" lastClr="000000"/>
432
- </a:dk1>
433
- <a:lt1>
434
- <a:sysClr val="window" lastClr="FFFFFF"/>
435
- </a:lt1>
436
- <a:dk2>
437
- <a:srgbClr val="44546A"/>
438
- </a:dk2>
439
- <a:lt2>
440
- <a:srgbClr val="E7E6E6"/>
441
- </a:lt2>
442
- <a:accent1>
443
- <a:srgbClr val="4472C4"/>
444
- </a:accent1>
445
- <a:accent2>
446
- <a:srgbClr val="ED7D31"/>
447
- </a:accent2>
448
- <a:accent3>
449
- <a:srgbClr val="A5A5A5"/>
450
- </a:accent3>
451
- <a:accent4>
452
- <a:srgbClr val="FFC000"/>
453
- </a:accent4>
454
- <a:accent5>
455
- <a:srgbClr val="5B9BD5"/>
456
- </a:accent5>
457
- <a:accent6>
458
- <a:srgbClr val="70AD47"/>
459
- </a:accent6>
460
- <a:hlink>
461
- <a:srgbClr val="0563C1"/>
462
- </a:hlink>
463
- <a:folHlink>
464
- <a:srgbClr val="954F72"/>
465
- </a:folHlink>
466
- </a:clrScheme>
467
- <a:fontScheme name="Office">
468
- <a:majorFont>
469
- <a:latin typeface="${font}"/>
470
- <a:ea typeface="${font}"/>
471
- <a:cs typeface=""/>
472
- </a:majorFont>
473
- <a:minorFont>
474
- <a:latin typeface="${font}"/>
475
- <a:ea typeface="${font}"/>
476
- <a:cs typeface=""/>
477
- </a:minorFont>
478
- </a:fontScheme>
479
- <a:fmtScheme name="Office">
480
- <a:fillStyleLst>
481
- <a:solidFill>
482
- <a:schemeClr val="phClr"/>
483
- </a:solidFill>
484
- <a:gradFill rotWithShape="1">
485
- <a:gsLst>
486
- <a:gs pos="0">
487
- <a:schemeClr val="phClr">
488
- <a:lumMod val="110000"/>
489
- <a:satMod val="105000"/>
490
- <a:tint val="67000"/>
491
- </a:schemeClr>
492
- </a:gs>
493
- <a:gs pos="50000">
494
- <a:schemeClr val="phClr">
495
- <a:lumMod val="105000"/>
496
- <a:satMod val="103000"/>
497
- <a:tint val="73000"/>
498
- </a:schemeClr>
499
- </a:gs>
500
- <a:gs pos="100000">
501
- <a:schemeClr val="phClr">
502
- <a:lumMod val="105000"/>
503
- <a:satMod val="109000"/>
504
- <a:tint val="81000"/>
505
- </a:schemeClr>
506
- </a:gs>
507
- </a:gsLst>
508
- <a:lin ang="5400000" scaled="0"/>
509
- </a:gradFill>
510
- <a:gradFill rotWithShape="1">
511
- <a:gsLst>
512
- <a:gs pos="0">
513
- <a:schemeClr val="phClr">
514
- <a:satMod val="103000"/>
515
- <a:lumMod val="102000"/>
516
- <a:tint val="94000"/>
517
- </a:schemeClr>
518
- </a:gs>
519
- <a:gs pos="50000">
520
- <a:schemeClr val="phClr">
521
- <a:satMod val="110000"/>
522
- <a:lumMod val="100000"/>
523
- <a:shade val="100000"/>
524
- </a:schemeClr>
525
- </a:gs>
526
- <a:gs pos="100000">
527
- <a:schemeClr val="phClr">
528
- <a:lumMod val="99000"/>
529
- <a:satMod val="120000"/>
530
- <a:shade val="78000"/>
531
- </a:schemeClr>
532
- </a:gs>
533
- </a:gsLst>
534
- <a:lin ang="5400000" scaled="0"/>
535
- </a:gradFill>
536
- </a:fillStyleLst>
537
- <a:lnStyleLst>
538
- <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">
539
- <a:solidFill>
540
- <a:schemeClr val="phClr"/>
541
- </a:solidFill>
542
- <a:prstDash val="solid"/>
543
- <a:miter lim="800000"/>
544
- </a:ln>
545
- <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
546
- <a:solidFill>
547
- <a:schemeClr val="phClr"/>
548
- </a:solidFill>
549
- <a:prstDash val="solid"/>
550
- <a:miter lim="800000"/>
551
- </a:ln>
552
- <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">
553
- <a:solidFill>
554
- <a:schemeClr val="phClr"/>
555
- </a:solidFill>
556
- <a:prstDash val="solid"/>
557
- <a:miter lim="800000"/>
558
- </a:ln>
559
- </a:lnStyleLst>
560
- <a:effectStyleLst>
561
- <a:effectStyle>
562
- <a:effectLst/>
563
- </a:effectStyle>
564
- <a:effectStyle>
565
- <a:effectLst/>
566
- </a:effectStyle>
567
- <a:effectStyle>
568
- <a:effectLst>
569
- <a:outerShdw blurRad="57150" dist="19050" dir="5400000" algn="ctr" rotWithShape="0">
570
- <a:srgbClr val="000000">
571
- <a:alpha val="63000"/>
572
- </a:srgbClr>
573
- </a:outerShdw>
574
- </a:effectLst>
575
- </a:effectStyle>
576
- </a:effectStyleLst>
577
- <a:bgFillStyleLst>
578
- <a:solidFill>
579
- <a:schemeClr val="phClr"/>
580
- </a:solidFill>
581
- <a:solidFill>
582
- <a:schemeClr val="phClr">
583
- <a:tint val="95000"/>
584
- <a:satMod val="170000"/>
585
- </a:schemeClr>
586
- </a:solidFill>
587
- <a:gradFill rotWithShape="1">
588
- <a:gsLst>
589
- <a:gs pos="0">
590
- <a:schemeClr val="phClr">
591
- <a:tint val="93000"/>
592
- <a:satMod val="150000"/>
593
- <a:shade val="98000"/>
594
- <a:lumMod val="102000"/>
595
- </a:schemeClr>
596
- </a:gs>
597
- <a:gs pos="50000">
598
- <a:schemeClr val="phClr">
599
- <a:tint val="98000"/>
600
- <a:satMod val="130000"/>
601
- <a:shade val="90000"/>
602
- <a:lumMod val="103000"/>
603
- </a:schemeClr>
604
- </a:gs>
605
- <a:gs pos="100000">
606
- <a:schemeClr val="phClr">
607
- <a:shade val="63000"/>
608
- <a:satMod val="120000"/>
609
- </a:schemeClr>
610
- </a:gs>
611
- </a:gsLst>
612
- <a:lin ang="5400000" scaled="0"/>
613
- </a:gradFill>
614
- </a:bgFillStyleLst>
615
- </a:fmtScheme>
616
- </a:themeElements>
617
- </a:theme>
618
- `;
619
-
620
- const settingsXML = `
621
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
622
-
623
- <w:settings xmlns:w="${namespaces.w}" xmlns:o="${namespaces.o}" xmlns:r="${namespaces.r}" xmlns:v="${namespaces.v}" xmlns:w10="${namespaces.w10}" xmlns:sl="${namespaces.sl}">
624
- <w:zoom w:percent="100"/>
625
- <w:defaultTabStop w:val="720"/>
626
- <w:decimalSymbol w:val="."/>
627
- <w:listSeparator w:val=","/>
628
- </w:settings>
629
- `;
630
-
631
- const webSettingsXML = `
632
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
633
-
634
- <w:webSettings xmlns:w="${namespaces.w}" xmlns:r="${namespaces.r}">
635
- </w:webSettings>
636
- `;
637
-
638
- const genericRelsXML = `
639
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
640
-
641
- <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
642
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunk.mht" Id="htmlChunk" />
643
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkheader.mht" Id="htmlChunkHeader" />
644
- <Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/aFChunk" Target="/word/afchunkfooter.mht" Id="htmlChunkFooter" />
645
- </Relationships>
646
- `;
647
-
648
- const generateDocumentTemplate = (width, height, orientation, margins) => `
649
- <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
650
- <w:document
651
- xmlns:a="${namespaces.a}"
652
- xmlns:cdr="${namespaces.cdr}"
653
- xmlns:o="${namespaces.o}"
654
- xmlns:pic="${namespaces.pic}"
655
- xmlns:r="${namespaces.r}"
656
- xmlns:v="${namespaces.v}"
657
- xmlns:ve="${namespaces.ve}"
658
- xmlns:vt="${namespaces.vt}"
659
- xmlns:w="${namespaces.w}"
660
- xmlns:w10="${namespaces.w10}"
661
- xmlns:wp="${namespaces.wp}"
662
- xmlns:wne="${namespaces.wne}"
663
- >
664
- <w:body>
665
-
666
- <w:altChunk r:id="htmlChunk" />
667
- <w:sectPr>
668
- <w:pgSz w:w="${width}" w:h="${height}" w:orient="${orientation}" />
669
- <w:pgMar w:top="${margins.top}"
670
- w:right="${margins.right}"
671
- w:bottom="${margins.bottom}"
672
- w:left="${margins.left}"
673
- w:header="${margins.header}"
674
- w:footer="${margins.footer}"
675
- w:gutter="${margins.gutter}"/>
676
- </w:sectPr>
677
- </w:body>
678
- </w:document>
679
- `;
680
- const generateDocumentTemplateHeader = `
681
- <w:hdr
682
- xmlns:a="${namespaces.a}"
683
- xmlns:cdr="${namespaces.cdr}"
684
- xmlns:o="${namespaces.o}"
685
- xmlns:pic="${namespaces.pic}"
686
- xmlns:r="${namespaces.r}"
687
- xmlns:v="${namespaces.v}"
688
- xmlns:ve="${namespaces.ve}"
689
- xmlns:vt="${namespaces.vt}"
690
- xmlns:w="${namespaces.w}"
691
- xmlns:w10="${namespaces.w10}"
692
- xmlns:wp="${namespaces.wp}"
693
- xmlns:wne="${namespaces.wne}"
694
- >
695
- <w:altChunk r:id="htmlChunkHeader" />
696
- </w:hdr>
697
- `;
698
- const generateDocumentTemplateFooter = `
699
- <w:ftr
700
- xmlns:a="${namespaces.a}"
701
- xmlns:cdr="${namespaces.cdr}"
702
- xmlns:o="${namespaces.o}"
703
- xmlns:pic="${namespaces.pic}"
704
- xmlns:r="${namespaces.r}"
705
- xmlns:v="${namespaces.v}"
706
- xmlns:ve="${namespaces.ve}"
707
- xmlns:vt="${namespaces.vt}"
708
- xmlns:w="${namespaces.w}"
709
- xmlns:w10="${namespaces.w10}"
710
- xmlns:wp="${namespaces.wp}"
711
- >
712
- <w:altChunk r:id="htmlChunkFooter" />
713
- <w:p w:rsidR="0014021C" w:rsidRDefault="0014021C" w:rsidP="0014021C">
714
- <w:pPr>
715
- <w:pStyle w:val="Footer"/>
716
- <w:jc w:val="center"/>
717
- </w:pPr>
718
- <w:fldSimple xmlns:ns2="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns2:instr="PAGE">
719
- <w:r/>
720
- </w:fldSimple>
721
- </w:p>
722
- </w:ftr>
723
- `;
724
- const generateDocumentTemplateFooterWithoutPaging = `
725
- <w:ftr
726
- xmlns:a="${namespaces.a}"
727
- xmlns:cdr="${namespaces.cdr}"
728
- xmlns:o="${namespaces.o}"
729
- xmlns:pic="${namespaces.pic}"
730
- xmlns:r="${namespaces.r}"
731
- xmlns:v="${namespaces.v}"
732
- xmlns:ve="${namespaces.ve}"
733
- xmlns:vt="${namespaces.vt}"
734
- xmlns:w="${namespaces.w}"
735
- xmlns:w10="${namespaces.w10}"
736
- xmlns:wp="${namespaces.wp}"
737
- >
738
- <w:altChunk r:id="htmlChunkFooter" />
739
- </w:ftr>
740
- `;
741
- { /* <w:altChunk r:id="htmlChunkFooter" /> */ }
742
- {
743
- /* <w:altChunk r:id="htmlChunkFooter" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" /> */
744
- }
745
- {
746
- /* <w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
747
- <fldSimple xmlns:ns2="http://schemas.openxmlformats.org/wordprocessingml/2006/main" ns2:instr="PAGE">
748
- </fldSimple>
749
- <w:altChunk r:id="htmlChunkFooter" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
750
- </w:ftr> */
751
- }
752
-
753
- /* eslint-disable no-param-reassign */
754
- const rgbRegex = /rgb\((\d+),\s*([\d.]+),\s*([\d.]+)\)/i;
755
- const hslRegex = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/i;
756
- const hexRegex = /#([0-9A-F]{6})/i;
757
- const hex3Regex = /#([0-9A-F])([0-9A-F])([0-9A-F])/i;
758
- // eslint-disable-next-line import/prefer-default-export
759
- const rgbToHex = (red, green, blue) => {
760
- const hexColorCode = [red, green, blue]
761
- .map((x) => {
762
- // eslint-disable-next-line radix, no-param-reassign
763
- x = parseInt(x).toString(16);
764
- return x.length === 1 ? `0${x}` : x;
765
- })
766
- .join('');
767
- return hexColorCode;
768
- };
769
- const hslToHex = (hue, saturation, luminosity) => {
770
- hue /= 360;
771
- saturation /= 100;
772
- luminosity /= 100;
773
- // eslint-disable-next-line one-var
774
- let red, green, blue;
775
- if (saturation === 0) {
776
- // eslint-disable-next-line no-multi-assign
777
- red = green = blue = luminosity; // achromatic
778
- }
779
- else {
780
- const hue2rgb = (p, q, t) => {
781
- if (t < 0)
782
- t += 1;
783
- if (t > 1)
784
- t -= 1;
785
- if (t < 1 / 6)
786
- return p + (q - p) * 6 * t;
787
- if (t < 1 / 2)
788
- return q;
789
- if (t < 2 / 3)
790
- return p + (q - p) * (2 / 3 - t) * 6;
791
- return p;
792
- };
793
- const q = luminosity < 0.5
794
- ? luminosity * (1 + saturation)
795
- : luminosity + saturation - luminosity * saturation;
796
- const p = 2 * luminosity - q;
797
- red = hue2rgb(p, q, hue + 1 / 3);
798
- green = hue2rgb(p, q, hue);
799
- blue = hue2rgb(p, q, hue - 1 / 3);
800
- }
801
- return [red, green, blue]
802
- .map((x) => {
803
- const hex = Math.round(x * 255).toString(16);
804
- return hex.length === 1 ? `0${hex}` : hex;
805
- })
806
- .join('');
807
- };
808
- const hex3ToHex = (red, green, blue) => {
809
- const hexColorCode = [red, green, blue].map((x) => `${x}${x}`).join('');
810
- return hexColorCode;
811
- };
812
-
813
- const pixelRegex = /([\d.]+)px/i;
814
- const percentageRegex = /([\d.]+)%/i;
815
- const pointRegex = /([\d.]+)pt/i;
816
- const cmRegex = /([\d.]+)cm/i;
817
- const inchRegex = /([\d.]+)in/i;
818
- const pixelToEMU = (pixelValue) => Math.round(pixelValue * 9525);
819
- const EMUToPixel = (EMUValue) => Math.round(EMUValue / 9525);
820
- const TWIPToEMU = (TWIPValue) => Math.round(TWIPValue * 635);
821
- const EMUToTWIP = (EMUValue) => Math.round(EMUValue / 635);
822
- const pointToTWIP = (pointValue) => Math.round(pointValue * 20);
823
- const TWIPToPoint = (TWIPValue) => Math.round(TWIPValue / 20);
824
- const pointToHIP = (pointValue) => Math.round(pointValue * 2);
825
- const HIPToPoint = (HIPValue) => Math.round(HIPValue / 2);
826
- const HIPToTWIP = (HIPValue) => Math.round(HIPValue * 10);
827
- const TWIPToHIP = (TWIPValue) => Math.round(TWIPValue / 10);
828
- const pixelToTWIP = (pixelValue) => EMUToTWIP(pixelToEMU(pixelValue));
829
- const TWIPToPixel = (TWIPValue) => EMUToPixel(TWIPToEMU(TWIPValue));
830
- const pixelToHIP = (pixelValue) => TWIPToHIP(EMUToTWIP(pixelToEMU(pixelValue)));
831
- const HIPToPixel = (HIPValue) => EMUToPixel(TWIPToEMU(HIPToTWIP(HIPValue)));
832
- const inchToPoint = (inchValue) => Math.round(inchValue * 72);
833
- const inchToTWIP = (inchValue) => pointToTWIP(inchToPoint(inchValue));
834
- const cmToInch = (cmValue) => cmValue * 0.3937008;
835
- const cmToTWIP = (cmValue) => inchToTWIP(cmToInch(cmValue));
836
- const pixelToPoint = (pixelValue) => HIPToPoint(pixelToHIP(pixelValue));
837
- const pointToPixel = (pointValue) => HIPToPixel(pointToHIP(pointValue));
838
- const EIPToPoint = (EIPValue) => Math.round(EIPValue / 8);
839
- const pointToEIP = (PointValue) => Math.round(PointValue * 8);
840
- const pixelToEIP = (pixelValue) => pointToEIP(pixelToPoint(pixelValue));
841
- const EIPToPixel = (EIPValue) => pointToPixel(EIPToPoint(EIPValue));
842
-
843
- // eslint-disable-next-line import/prefer-default-export
844
- const vNodeHasChildren = (vNode) => vNode && vNode.children && Array.isArray(vNode.children) && vNode.children.length;
845
-
846
- const isValidUrl = (urlString) => {
847
- const urlRegex = /http(s)?:\/\/(\w+:?\w*@)?(\S+)(:\d+)?((?<=\.)\w+)+(\/([\w#!:.?+=&%@!\-/])*)?/gi;
848
- return Boolean(urlRegex.test(urlString));
849
- };
850
-
851
- /* eslint-disable no-await-in-loop */
852
- /* eslint-disable radix */
853
- /* eslint-disable no-param-reassign */
854
- /* eslint-disable no-case-declarations */
855
- /* eslint-disable no-plusplus */
856
- /* eslint-disable no-else-return */
857
- // eslint-disable-next-line consistent-return
858
- const fixupColorCode = (colorCodeString) => {
859
- if (Object.prototype.hasOwnProperty.call(colorNames, colorCodeString.toLowerCase())) {
860
- const [red, green, blue] = colorNames[colorCodeString.toLowerCase()];
861
- return rgbToHex(red, green, blue);
862
- }
863
- else if (rgbRegex.test(colorCodeString)) {
864
- const matchedParts = colorCodeString.match(rgbRegex);
865
- const red = matchedParts[1];
866
- const green = matchedParts[2];
867
- const blue = matchedParts[3];
868
- return rgbToHex(red, green, blue);
869
- }
870
- else if (hslRegex.test(colorCodeString)) {
871
- const matchedParts = colorCodeString.match(hslRegex);
872
- const hue = matchedParts[1];
873
- const saturation = matchedParts[2];
874
- const luminosity = matchedParts[3];
875
- return hslToHex(hue, saturation, luminosity);
876
- }
877
- else if (hexRegex.test(colorCodeString)) {
878
- const matchedParts = colorCodeString.match(hexRegex);
879
- return matchedParts[1];
880
- }
881
- else if (hex3Regex.test(colorCodeString)) {
882
- const matchedParts = colorCodeString.match(hex3Regex);
883
- const red = matchedParts[1];
884
- const green = matchedParts[2];
885
- const blue = matchedParts[3];
886
- return hex3ToHex(red, green, blue);
887
- }
888
- else {
889
- return '000000';
890
- }
891
- };
892
- const buildRunFontFragment = (fontName = defaultFont) => fragment({ namespaceAlias: { w: namespaces.w } })
893
- .ele('@w', 'rFonts')
894
- .att('@w', 'ascii', fontName)
895
- .att('@w', 'hAnsi', fontName)
896
- .up();
897
- const buildRunStyleFragment = (type = 'Hyperlink') => fragment({ namespaceAlias: { w: namespaces.w } })
898
- .ele('@w', 'rStyle')
899
- .att('@w', 'val', type)
900
- .up();
901
- const buildTableRowHeight = (tableRowHeight) => fragment({ namespaceAlias: { w: namespaces.w } })
902
- .ele('@w', 'trHeight')
903
- .att('@w', 'val', tableRowHeight)
904
- .att('@w', 'hRule', 'atLeast')
905
- .up();
906
- const buildVerticalAlignment = (verticalAlignment) => {
907
- if (verticalAlignment.toLowerCase() === 'middle') {
908
- verticalAlignment = 'center';
909
- }
910
- return fragment({ namespaceAlias: { w: namespaces.w } })
911
- .ele('@w', 'vAlign')
912
- .att('@w', 'val', verticalAlignment)
913
- .up();
914
- };
915
- const buildVerticalMerge = (verticalMerge = 'continue') => fragment({ namespaceAlias: { w: namespaces.w } })
916
- .ele('@w', 'vMerge')
917
- .att('@w', 'val', verticalMerge)
918
- .up();
919
- const buildColor = (colorCode) => fragment({ namespaceAlias: { w: namespaces.w } })
920
- .ele('@w', 'color')
921
- .att('@w', 'val', colorCode)
922
- .up();
923
- const buildFontSize = (fontSize) => fragment({ namespaceAlias: { w: namespaces.w } })
924
- .ele('@w', 'sz')
925
- .att('@w', 'val', fontSize)
926
- .up();
927
- const buildShading = (colorCode) => fragment({ namespaceAlias: { w: namespaces.w } })
928
- .ele('@w', 'shd')
929
- .att('@w', 'val', 'clear')
930
- .att('@w', 'fill', colorCode)
931
- .up();
932
- const buildHighlight = (color = 'yellow') => fragment({ namespaceAlias: { w: namespaces.w } })
933
- .ele('@w', 'highlight')
934
- .att('@w', 'val', color)
935
- .up();
936
- const buildVertAlign = (type = 'baseline') => fragment({ namespaceAlias: { w: namespaces.w } })
937
- .ele('@w', 'vertAlign')
938
- .att('@w', 'val', type)
939
- .up();
940
- const buildStrike = () => fragment({ namespaceAlias: { w: namespaces.w } })
941
- .ele('@w', 'strike')
942
- .att('@w', 'val', true)
943
- .up();
944
- const buildBold = () => fragment({ namespaceAlias: { w: namespaces.w } })
945
- .ele('@w', 'b')
946
- .up();
947
- const buildItalics = () => fragment({ namespaceAlias: { w: namespaces.w } })
948
- .ele('@w', 'i')
949
- .up();
950
- const buildUnderline = (type = 'single') => fragment({ namespaceAlias: { w: namespaces.w } })
951
- .ele('@w', 'u')
952
- .att('@w', 'val', type)
953
- .up();
954
- const buildLineBreak = (type = 'textWrapping') => fragment({ namespaceAlias: { w: namespaces.w } })
955
- .ele('@w', 'br')
956
- .att('@w', 'type', type)
957
- .up();
958
- const buildBorder = (borderSide = 'top', borderSize = 0, borderSpacing = 0, borderColor = fixupColorCode('black'), borderStroke = 'single') => fragment({ namespaceAlias: { w: namespaces.w } })
959
- .ele('@w', borderSide)
960
- .att('@w', 'val', borderStroke)
961
- .att('@w', 'sz', borderSize)
962
- .att('@w', 'space', borderSpacing)
963
- .att('@w', 'color', borderColor)
964
- .up();
965
- const buildTextElement = (text) => fragment({ namespaceAlias: { w: namespaces.w } })
966
- .ele('@w', 't')
967
- .att('@xml', 'space', 'preserve')
968
- .txt(text)
969
- .up();
970
- // eslint-disable-next-line consistent-return
971
- const fixupLineHeight = (lineHeight, fontSize) => {
972
- // FIXME: If line height is anything other than a number
973
- // eslint-disable-next-line no-restricted-globals
974
- if (!isNaN(lineHeight)) {
975
- if (fontSize) {
976
- const actualLineHeight = +lineHeight * fontSize;
977
- return HIPToTWIP(actualLineHeight);
978
- }
979
- else {
980
- // 240 TWIP or 12 point is default line height
981
- return +lineHeight * 240;
982
- }
983
- }
984
- else {
985
- // 240 TWIP or 12 point is default line height
986
- return 240;
987
- }
988
- };
989
- // eslint-disable-next-line consistent-return
990
- const fixupFontSize$1 = (fontSizeString) => {
991
- if (pointRegex.test(fontSizeString)) {
992
- const matchedParts = fontSizeString.match(pointRegex);
993
- // convert point to half point
994
- return pointToHIP(matchedParts[1]);
995
- }
996
- else if (pixelRegex.test(fontSizeString)) {
997
- const matchedParts = fontSizeString.match(pixelRegex);
998
- // convert pixels to half point
999
- return pixelToHIP(matchedParts[1]);
1000
- }
1001
- };
1002
- // eslint-disable-next-line consistent-return
1003
- const fixupRowHeight = (rowHeightString) => {
1004
- if (pointRegex.test(rowHeightString)) {
1005
- const matchedParts = rowHeightString.match(pointRegex);
1006
- // convert point to half point
1007
- return pointToTWIP(matchedParts[1]);
1008
- }
1009
- else if (pixelRegex.test(rowHeightString)) {
1010
- const matchedParts = rowHeightString.match(pixelRegex);
1011
- // convert pixels to half point
1012
- return pixelToTWIP(matchedParts[1]);
1013
- }
1014
- else if (cmRegex.test(rowHeightString)) {
1015
- const matchedParts = rowHeightString.match(cmRegex);
1016
- return cmToTWIP(matchedParts[1]);
1017
- }
1018
- else if (inchRegex.test(rowHeightString)) {
1019
- const matchedParts = rowHeightString.match(inchRegex);
1020
- return inchToTWIP(matchedParts[1]);
1021
- }
1022
- };
1023
- // eslint-disable-next-line consistent-return
1024
- const fixupColumnWidth = (columnWidthString) => {
1025
- if (pointRegex.test(columnWidthString)) {
1026
- const matchedParts = columnWidthString.match(pointRegex);
1027
- return pointToTWIP(matchedParts[1]);
1028
- }
1029
- else if (pixelRegex.test(columnWidthString)) {
1030
- const matchedParts = columnWidthString.match(pixelRegex);
1031
- return pixelToTWIP(matchedParts[1]);
1032
- }
1033
- else if (cmRegex.test(columnWidthString)) {
1034
- const matchedParts = columnWidthString.match(cmRegex);
1035
- return cmToTWIP(matchedParts[1]);
1036
- }
1037
- else if (inchRegex.test(columnWidthString)) {
1038
- const matchedParts = columnWidthString.match(inchRegex);
1039
- return inchToTWIP(matchedParts[1]);
1040
- }
1041
- };
1042
- // eslint-disable-next-line consistent-return
1043
- const fixupMargin = (marginString) => {
1044
- if (pointRegex.test(marginString)) {
1045
- const matchedParts = marginString.match(pointRegex);
1046
- // convert point to half point
1047
- return pointToTWIP(matchedParts[1]);
1048
- }
1049
- else if (pixelRegex.test(marginString)) {
1050
- const matchedParts = marginString.match(pixelRegex);
1051
- // convert pixels to half point
1052
- return pixelToTWIP(matchedParts[1]);
1053
- }
1054
- };
1055
- const modifiedStyleAttributesBuilder = (vNode, attributes, options) => {
1056
- const modifiedAttributes = { ...attributes };
1057
- // styles
1058
- if (isVNode(vNode) && vNode.properties && vNode.properties.style) {
1059
- if (vNode.properties.style.color && !colorlessColors.includes(vNode.properties.style.color)) {
1060
- modifiedAttributes.color = fixupColorCode(vNode.properties.style.color);
1061
- }
1062
- if (vNode.properties.style['background-color'] &&
1063
- !colorlessColors.includes(vNode.properties.style['background-color'])) {
1064
- modifiedAttributes.backgroundColor = fixupColorCode(vNode.properties.style['background-color']);
1065
- }
1066
- if (vNode.properties.style['vertical-align'] &&
1067
- verticalAlignValues.includes(vNode.properties.style['vertical-align'])) {
1068
- modifiedAttributes.verticalAlign = vNode.properties.style['vertical-align'];
1069
- }
1070
- if (vNode.properties.style['text-align'] &&
1071
- ['left', 'right', 'center', 'justify'].includes(vNode.properties.style['text-align'])) {
1072
- modifiedAttributes.textAlign = vNode.properties.style['text-align'];
1073
- }
1074
- // FIXME: remove bold check when other font weights are handled.
1075
- if (vNode.properties.style['font-weight'] && vNode.properties.style['font-weight'] === 'bold') {
1076
- modifiedAttributes.strong = vNode.properties.style['font-weight'];
1077
- }
1078
- if (vNode.properties.style['font-size']) {
1079
- modifiedAttributes.fontSize = fixupFontSize$1(vNode.properties.style['font-size']);
1080
- }
1081
- if (vNode.properties.style['line-height']) {
1082
- modifiedAttributes.lineHeight = fixupLineHeight(vNode.properties.style['line-height'], vNode.properties.style['font-size']
1083
- ? fixupFontSize$1(vNode.properties.style['font-size'])
1084
- : null);
1085
- }
1086
- if (vNode.properties.style['margin-left'] || vNode.properties.style['margin-right']) {
1087
- const leftMargin = fixupMargin(vNode.properties.style['margin-left']);
1088
- const rightMargin = fixupMargin(vNode.properties.style['margin-right']);
1089
- const indentation = {};
1090
- if (leftMargin) {
1091
- indentation.left = leftMargin;
1092
- }
1093
- if (rightMargin) {
1094
- indentation.right = rightMargin;
1095
- }
1096
- if (leftMargin || rightMargin) {
1097
- modifiedAttributes.indentation = indentation;
1098
- }
1099
- }
1100
- if (vNode.properties.style.display) {
1101
- modifiedAttributes.display = vNode.properties.style.display;
1102
- }
1103
- if (vNode.properties.style.width) {
1104
- modifiedAttributes.width = vNode.properties.style.width;
1105
- }
1106
- }
1107
- // paragraph only
1108
- if (options && options.isParagraph) {
1109
- if (isVNode(vNode) && vNode.tagName === 'blockquote') {
1110
- modifiedAttributes.indentation = { left: 284 };
1111
- modifiedAttributes.textAlign = 'justify';
1112
- }
1113
- else if (isVNode(vNode) && vNode.tagName === 'code') {
1114
- modifiedAttributes.highlightColor = 'lightGray';
1115
- }
1116
- else if (isVNode(vNode) && vNode.tagName === 'pre') {
1117
- modifiedAttributes.font = 'Courier';
1118
- }
1119
- }
1120
- return modifiedAttributes;
1121
- };
1122
- // html tag to formatting function
1123
- // options are passed to the formatting function if needed
1124
- const buildFormatting = (htmlTag, options) => {
1125
- switch (htmlTag) {
1126
- case 'strong':
1127
- case 'b':
1128
- return buildBold();
1129
- case 'em':
1130
- case 'i':
1131
- return buildItalics();
1132
- case 'ins':
1133
- case 'u':
1134
- return buildUnderline();
1135
- case 'strike':
1136
- case 'del':
1137
- case 's':
1138
- return buildStrike();
1139
- case 'sub':
1140
- return buildVertAlign('subscript');
1141
- case 'sup':
1142
- return buildVertAlign('superscript');
1143
- case 'mark':
1144
- return buildHighlight();
1145
- case 'code':
1146
- return buildHighlight('lightGray');
1147
- case 'highlightColor':
1148
- return buildHighlight(options && options.color ? options.color : 'lightGray');
1149
- case 'font':
1150
- case 'pre':
1151
- return buildRunFontFragment('Courier');
1152
- case 'color':
1153
- return buildColor(options && options.color ? options.color : 'black');
1154
- case 'backgroundColor':
1155
- return buildShading(options && options.color ? options.color : 'black');
1156
- case 'fontSize':
1157
- // does this need a unit of measure?
1158
- return buildFontSize(options && options.fontSize ? options.fontSize : 10);
1159
- case 'hyperlink':
1160
- return buildRunStyleFragment('Hyperlink');
1161
- }
1162
- return null;
1163
- };
1164
- const buildRunProperties = (attributes) => {
1165
- const runPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'rPr');
1166
- if (attributes && attributes.constructor === Object) {
1167
- Object.keys(attributes).forEach((key) => {
1168
- const options = {};
1169
- if (key === 'color' || key === 'backgroundColor' || key === 'highlightColor') {
1170
- options.color = attributes[key];
1171
- }
1172
- if (key === 'fontSize') {
1173
- options.fontSize = attributes[key];
1174
- }
1175
- const formattingFragment = buildFormatting(key, options);
1176
- if (formattingFragment) {
1177
- runPropertiesFragment.import(formattingFragment);
1178
- }
1179
- });
1180
- }
1181
- runPropertiesFragment.up();
1182
- return runPropertiesFragment;
1183
- };
1184
- const buildRun = async (vNode, attributes, docxDocumentInstance) => {
1185
- const runFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
1186
- const runPropertiesFragment = buildRunProperties(cloneDeep(attributes));
1187
- // case where we have recursive spans representing font changes
1188
- if (isVNode(vNode) && vNode.tagName === 'span') {
1189
- // eslint-disable-next-line no-use-before-define
1190
- return buildRunOrRuns(vNode, attributes, docxDocumentInstance);
1191
- }
1192
- if (isVNode(vNode) &&
1193
- [
1194
- 'strong',
1195
- 'b',
1196
- 'em',
1197
- 'i',
1198
- 'u',
1199
- 'ins',
1200
- 'strike',
1201
- 'del',
1202
- 's',
1203
- 'sub',
1204
- 'sup',
1205
- 'mark',
1206
- 'blockquote',
1207
- 'code',
1208
- 'pre',
1209
- ].includes(vNode.tagName)) {
1210
- const runFragmentsArray = [];
1211
- let vNodes = [vNode];
1212
- // create temp run fragments to split the paragraph into different runs
1213
- let tempAttributes = cloneDeep(attributes);
1214
- let tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
1215
- while (vNodes.length) {
1216
- const tempVNode = vNodes.shift();
1217
- if (isVText(tempVNode)) {
1218
- const textFragment = buildTextElement(tempVNode.text);
1219
- const tempRunPropertiesFragment = buildRunProperties({ ...attributes, ...tempAttributes });
1220
- tempRunFragment.import(tempRunPropertiesFragment);
1221
- tempRunFragment.import(textFragment);
1222
- runFragmentsArray.push(tempRunFragment);
1223
- // re initialize temp run fragments with new fragment
1224
- tempAttributes = cloneDeep(attributes);
1225
- tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
1226
- }
1227
- else if (isVNode(tempVNode)) {
1228
- if ([
1229
- 'strong',
1230
- 'b',
1231
- 'em',
1232
- 'i',
1233
- 'u',
1234
- 'ins',
1235
- 'strike',
1236
- 'del',
1237
- 's',
1238
- 'sub',
1239
- 'sup',
1240
- 'mark',
1241
- 'code',
1242
- 'pre',
1243
- ].includes(tempVNode.tagName)) {
1244
- tempAttributes = {};
1245
- switch (tempVNode.tagName) {
1246
- case 'strong':
1247
- case 'b':
1248
- tempAttributes.strong = true;
1249
- break;
1250
- case 'i':
1251
- tempAttributes.i = true;
1252
- break;
1253
- case 'u':
1254
- tempAttributes.u = true;
1255
- break;
1256
- case 'sub':
1257
- tempAttributes.sub = true;
1258
- break;
1259
- case 'sup':
1260
- tempAttributes.sup = true;
1261
- break;
1262
- }
1263
- const formattingFragment = buildFormatting(tempVNode);
1264
- if (formattingFragment) {
1265
- runPropertiesFragment.import(formattingFragment);
1266
- }
1267
- // go a layer deeper if there is a span somewhere in the children
1268
- }
1269
- else if (tempVNode.tagName === 'span') {
1270
- // eslint-disable-next-line no-use-before-define
1271
- const spanFragment = await buildRunOrRuns(tempVNode, { ...attributes, ...tempAttributes }, docxDocumentInstance);
1272
- // if spanFragment is an array, we need to add each fragment to the runFragmentsArray. If the fragment is an array, perform a depth first search on the array to add each fragment to the runFragmentsArray
1273
- if (Array.isArray(spanFragment)) {
1274
- spanFragment.flat(Infinity);
1275
- runFragmentsArray.push(...spanFragment);
1276
- }
1277
- else {
1278
- runFragmentsArray.push(spanFragment);
1279
- }
1280
- // do not slice and concat children since this is already accounted for in the buildRunOrRuns function
1281
- // eslint-disable-next-line no-continue
1282
- continue;
1283
- }
1284
- }
1285
- if (tempVNode.children && tempVNode.children.length) {
1286
- if (tempVNode.children.length > 1) {
1287
- attributes = { ...attributes, ...tempAttributes };
1288
- }
1289
- vNodes = tempVNode.children.slice().concat(vNodes);
1290
- }
1291
- }
1292
- if (runFragmentsArray.length) {
1293
- return runFragmentsArray;
1294
- }
1295
- }
1296
- runFragment.import(runPropertiesFragment);
1297
- if (isVText(vNode)) {
1298
- const textFragment = buildTextElement(vNode.text);
1299
- runFragment.import(textFragment);
1300
- }
1301
- else if (attributes && attributes.type === 'picture') {
1302
- let response = null;
1303
- const base64Uri = decodeURIComponent(vNode.properties.src);
1304
- if (base64Uri) {
1305
- response = docxDocumentInstance.createMediaFile(base64Uri);
1306
- }
1307
- if (response) {
1308
- docxDocumentInstance.zip
1309
- .folder('word')
1310
- .folder('media')
1311
- .file(response.fileNameWithExtension, Buffer.from(response.fileContent, 'base64'), {
1312
- createFolders: false,
1313
- });
1314
- const documentRelsId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, imageType, `media/${response.fileNameWithExtension}`, internalRelationship);
1315
- attributes.inlineOrAnchored = true;
1316
- attributes.relationshipId = documentRelsId;
1317
- attributes.id = response.id;
1318
- attributes.fileContent = response.fileContent;
1319
- attributes.fileNameWithExtension = response.fileNameWithExtension;
1320
- }
1321
- const { type, inlineOrAnchored, ...otherAttributes } = attributes;
1322
- // eslint-disable-next-line no-use-before-define
1323
- const imageFragment = buildDrawing(inlineOrAnchored, type, otherAttributes);
1324
- runFragment.import(imageFragment);
1325
- }
1326
- else if (isVNode(vNode) && vNode.tagName === 'br') {
1327
- const lineBreakFragment = buildLineBreak();
1328
- runFragment.import(lineBreakFragment);
1329
- }
1330
- runFragment.up();
1331
- return runFragment;
1332
- };
1333
- const buildRunOrRuns = async (vNode, attributes, docxDocumentInstance) => {
1334
- if (isVNode(vNode) && vNode.tagName === 'span') {
1335
- let runFragments = [];
1336
- for (let index = 0; index < vNode.children.length; index++) {
1337
- const childVNode = vNode.children[index];
1338
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes);
1339
- const tempRunFragments = await buildRun(childVNode, modifiedAttributes, docxDocumentInstance);
1340
- runFragments = runFragments.concat(Array.isArray(tempRunFragments) ? tempRunFragments : [tempRunFragments]);
1341
- }
1342
- return runFragments;
1343
- }
1344
- else {
1345
- const tempRunFragments = await buildRun(vNode, attributes, docxDocumentInstance);
1346
- return tempRunFragments;
1347
- }
1348
- };
1349
- const buildRunOrHyperLink = async (vNode, attributes, docxDocumentInstance) => {
1350
- if (isVNode(vNode) && vNode.tagName === 'a') {
1351
- const relationshipId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, hyperlinkType, vNode.properties && vNode.properties.href ? vNode.properties.href : '');
1352
- const hyperlinkFragment = fragment({ namespaceAlias: { w: namespaces.w, r: namespaces.r } })
1353
- .ele('@w', 'hyperlink')
1354
- .att('@r', 'id', `rId${relationshipId}`);
1355
- const modifiedAttributes = { ...attributes };
1356
- modifiedAttributes.hyperlink = true;
1357
- const runFragments = await buildRunOrRuns(vNode.children[0], modifiedAttributes, docxDocumentInstance);
1358
- if (Array.isArray(runFragments)) {
1359
- for (let index = 0; index < runFragments.length; index++) {
1360
- const runFragment = runFragments[index];
1361
- hyperlinkFragment.import(runFragment);
1362
- }
1363
- }
1364
- else {
1365
- hyperlinkFragment.import(runFragments);
1366
- }
1367
- hyperlinkFragment.up();
1368
- return hyperlinkFragment;
1369
- }
1370
- const runFragments = await buildRunOrRuns(vNode, attributes, docxDocumentInstance);
1371
- return runFragments;
1372
- };
1373
- const buildNumberingProperties = (levelId, numberingId) => fragment({ namespaceAlias: { w: namespaces.w } })
1374
- .ele('@w', 'numPr')
1375
- .ele('@w', 'ilvl')
1376
- .att('@w', 'val', String(levelId))
1377
- .up()
1378
- .ele('@w', 'numId')
1379
- .att('@w', 'val', String(numberingId))
1380
- .up()
1381
- .up();
1382
- const buildNumberingInstances = () => fragment({ namespaceAlias: { w: namespaces.w } })
1383
- .ele('@w', 'num')
1384
- .ele('@w', 'abstractNumId')
1385
- .up()
1386
- .up();
1387
- const buildSpacing = (lineSpacing, beforeSpacing, afterSpacing) => {
1388
- const spacingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'spacing');
1389
- if (lineSpacing) {
1390
- spacingFragment.att('@w', 'line', lineSpacing);
1391
- }
1392
- if (beforeSpacing) {
1393
- spacingFragment.att('@w', 'before', beforeSpacing);
1394
- }
1395
- if (afterSpacing) {
1396
- spacingFragment.att('@w', 'after', afterSpacing);
1397
- }
1398
- spacingFragment.att('@w', 'lineRule', 'auto').up();
1399
- return spacingFragment;
1400
- };
1401
- const buildIndentation = ({ left, right }) => {
1402
- const indentationFragment = fragment({
1403
- namespaceAlias: { w: namespaces.w },
1404
- }).ele('@w', 'ind');
1405
- if (left) {
1406
- indentationFragment.att('@w', 'left', left);
1407
- }
1408
- if (right) {
1409
- indentationFragment.att('@w', 'right', right);
1410
- }
1411
- indentationFragment.up();
1412
- return indentationFragment;
1413
- };
1414
- const buildPStyle = (style = 'Normal') => fragment({ namespaceAlias: { w: namespaces.w } })
1415
- .ele('@w', 'pStyle')
1416
- .att('@w', 'val', style)
1417
- .up();
1418
- const buildHorizontalAlignment = (horizontalAlignment) => {
1419
- if (horizontalAlignment === 'justify') {
1420
- horizontalAlignment = 'both';
1421
- }
1422
- return fragment({ namespaceAlias: { w: namespaces.w } })
1423
- .ele('@w', 'jc')
1424
- .att('@w', 'val', horizontalAlignment)
1425
- .up();
1426
- };
1427
- const buildParagraphBorder = () => {
1428
- const paragraphBorderFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pBdr');
1429
- const bordersObject = cloneDeep(paragraphBordersObject);
1430
- Object.keys(bordersObject).forEach((borderName) => {
1431
- if (bordersObject[borderName]) {
1432
- const { size, spacing, color } = bordersObject[borderName];
1433
- const borderFragment = buildBorder(borderName, size, spacing, color);
1434
- paragraphBorderFragment.import(borderFragment);
1435
- }
1436
- });
1437
- paragraphBorderFragment.up();
1438
- return paragraphBorderFragment;
1439
- };
1440
- const buildParagraphProperties = (attributes) => {
1441
- const paragraphPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pPr');
1442
- if (attributes && attributes.constructor === Object) {
1443
- Object.keys(attributes).forEach((key) => {
1444
- switch (key) {
1445
- case 'numbering':
1446
- const { levelId, numberingId } = attributes[key];
1447
- const numberingPropertiesFragment = buildNumberingProperties(levelId, numberingId);
1448
- paragraphPropertiesFragment.import(numberingPropertiesFragment);
1449
- // eslint-disable-next-line no-param-reassign
1450
- delete attributes.numbering;
1451
- break;
1452
- case 'textAlign':
1453
- const horizontalAlignmentFragment = buildHorizontalAlignment(attributes[key]);
1454
- paragraphPropertiesFragment.import(horizontalAlignmentFragment);
1455
- // eslint-disable-next-line no-param-reassign
1456
- delete attributes.textAlign;
1457
- break;
1458
- case 'backgroundColor':
1459
- // Add shading to Paragraph Properties only if display is block
1460
- // Essentially if background color needs to be across the row
1461
- if (attributes.display === 'block') {
1462
- const shadingFragment = buildShading(attributes[key]);
1463
- paragraphPropertiesFragment.import(shadingFragment);
1464
- // FIXME: Inner padding in case of shaded paragraphs.
1465
- const paragraphBorderFragment = buildParagraphBorder();
1466
- paragraphPropertiesFragment.import(paragraphBorderFragment);
1467
- // eslint-disable-next-line no-param-reassign
1468
- delete attributes.backgroundColor;
1469
- }
1470
- break;
1471
- case 'paragraphStyle':
1472
- const pStyleFragment = buildPStyle(attributes.paragraphStyle);
1473
- paragraphPropertiesFragment.import(pStyleFragment);
1474
- delete attributes.paragraphStyle;
1475
- break;
1476
- case 'indentation':
1477
- const indentationFragment = buildIndentation(attributes[key]);
1478
- paragraphPropertiesFragment.import(indentationFragment);
1479
- // eslint-disable-next-line no-param-reassign
1480
- delete attributes.indentation;
1481
- break;
1482
- }
1483
- });
1484
- const spacingFragment = buildSpacing(attributes.lineHeight, attributes.beforeSpacing, attributes.afterSpacing);
1485
- // eslint-disable-next-line no-param-reassign
1486
- delete attributes.lineHeight;
1487
- // eslint-disable-next-line no-param-reassign
1488
- delete attributes.beforeSpacing;
1489
- // eslint-disable-next-line no-param-reassign
1490
- delete attributes.afterSpacing;
1491
- paragraphPropertiesFragment.import(spacingFragment);
1492
- }
1493
- paragraphPropertiesFragment.up();
1494
- return paragraphPropertiesFragment;
1495
- };
1496
- const computeImageDimensions = (vNode, attributes) => {
1497
- const { maximumWidth, originalWidth, originalHeight } = attributes;
1498
- const aspectRatio = originalWidth / originalHeight;
1499
- const maximumWidthInEMU = TWIPToEMU(maximumWidth);
1500
- let originalWidthInEMU = pixelToEMU(originalWidth);
1501
- let originalHeightInEMU = pixelToEMU(originalHeight);
1502
- if (originalWidthInEMU > maximumWidthInEMU) {
1503
- originalWidthInEMU = maximumWidthInEMU;
1504
- originalHeightInEMU = Math.round(originalWidthInEMU / aspectRatio);
1505
- }
1506
- let modifiedHeight;
1507
- let modifiedWidth;
1508
- if (vNode.properties && vNode.properties.style) {
1509
- if (vNode.properties.style.width) {
1510
- if (vNode.properties.style.width !== 'auto') {
1511
- if (pixelRegex.test(vNode.properties.style.width)) {
1512
- modifiedWidth = pixelToEMU(vNode.properties.style.width.match(pixelRegex)[1]);
1513
- }
1514
- else if (percentageRegex.test(vNode.properties.style.width)) {
1515
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
1516
- modifiedWidth = Math.round((percentageValue / 100) * originalWidthInEMU);
1517
- }
1518
- }
1519
- else {
1520
- // eslint-disable-next-line no-lonely-if
1521
- if (vNode.properties.style.height && vNode.properties.style.height === 'auto') {
1522
- modifiedWidth = originalWidthInEMU;
1523
- modifiedHeight = originalHeightInEMU;
1524
- }
1525
- }
1526
- }
1527
- if (vNode.properties.style.height) {
1528
- if (vNode.properties.style.height !== 'auto') {
1529
- if (pixelRegex.test(vNode.properties.style.height)) {
1530
- modifiedHeight = pixelToEMU(vNode.properties.style.height.match(pixelRegex)[1]);
1531
- }
1532
- else if (percentageRegex.test(vNode.properties.style.height)) {
1533
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
1534
- modifiedHeight = Math.round((percentageValue / 100) * originalHeightInEMU);
1535
- if (!modifiedWidth) {
1536
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
1537
- }
1538
- }
1539
- }
1540
- else {
1541
- // eslint-disable-next-line no-lonely-if
1542
- if (modifiedWidth) {
1543
- if (!modifiedHeight) {
1544
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
1545
- }
1546
- }
1547
- else {
1548
- modifiedHeight = originalHeightInEMU;
1549
- modifiedWidth = originalWidthInEMU;
1550
- }
1551
- }
1552
- }
1553
- if (modifiedWidth && !modifiedHeight) {
1554
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
1555
- }
1556
- else if (modifiedHeight && !modifiedWidth) {
1557
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
1558
- }
1559
- }
1560
- else {
1561
- modifiedWidth = originalWidthInEMU;
1562
- modifiedHeight = originalHeightInEMU;
1563
- }
1564
- // eslint-disable-next-line no-param-reassign
1565
- attributes.width = modifiedWidth;
1566
- // eslint-disable-next-line no-param-reassign
1567
- attributes.height = modifiedHeight;
1568
- };
1569
- const buildParagraph = async (vNode, attributes, docxDocumentInstance) => {
1570
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p');
1571
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes, {
1572
- isParagraph: true,
1573
- });
1574
- const paragraphPropertiesFragment = buildParagraphProperties(modifiedAttributes);
1575
- paragraphFragment.import(paragraphPropertiesFragment);
1576
- if (isVNode(vNode) && vNodeHasChildren(vNode)) {
1577
- if ([
1578
- 'span',
1579
- 'strong',
1580
- 'b',
1581
- 'em',
1582
- 'i',
1583
- 'u',
1584
- 'ins',
1585
- 'strike',
1586
- 'del',
1587
- 's',
1588
- 'sub',
1589
- 'sup',
1590
- 'mark',
1591
- 'a',
1592
- 'code',
1593
- 'pre',
1594
- ].includes(vNode.tagName)) {
1595
- const runOrHyperlinkFragments = await buildRunOrHyperLink(vNode, modifiedAttributes, docxDocumentInstance);
1596
- if (Array.isArray(runOrHyperlinkFragments)) {
1597
- for (let iteratorIndex = 0; iteratorIndex < runOrHyperlinkFragments.length; iteratorIndex++) {
1598
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
1599
- paragraphFragment.import(runOrHyperlinkFragment);
1600
- }
1601
- }
1602
- else {
1603
- paragraphFragment.import(runOrHyperlinkFragments);
1604
- }
1605
- }
1606
- else if (vNode.tagName === 'blockquote') {
1607
- const runFragmentOrFragments = await buildRun(vNode, attributes);
1608
- if (Array.isArray(runFragmentOrFragments)) {
1609
- for (let index = 0; index < runFragmentOrFragments.length; index++) {
1610
- paragraphFragment.import(runFragmentOrFragments[index]);
1611
- }
1612
- }
1613
- else {
1614
- paragraphFragment.import(runFragmentOrFragments);
1615
- }
1616
- }
1617
- else {
1618
- for (let index = 0; index < vNode.children.length; index++) {
1619
- const childVNode = vNode.children[index];
1620
- if (childVNode.tagName === 'img') {
1621
- let base64String;
1622
- const imageSource = childVNode.properties.src;
1623
- if (isValidUrl(imageSource)) {
1624
- base64String = await imageToBase64(imageSource).catch((error) => {
1625
- // eslint-disable-next-line no-console
1626
- console.warning(`skipping image download and conversion due to ${error}`);
1627
- });
1628
- if (base64String && mimeTypes.lookup(imageSource)) {
1629
- childVNode.properties.src = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
1630
- }
1631
- else {
1632
- break;
1633
- }
1634
- }
1635
- else {
1636
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
1637
- base64String = imageSource.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
1638
- }
1639
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
1640
- const imageProperties = sizeOf(imageBuffer);
1641
- modifiedAttributes.maximumWidth =
1642
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
1643
- modifiedAttributes.originalWidth = imageProperties.width;
1644
- modifiedAttributes.originalHeight = imageProperties.height;
1645
- computeImageDimensions(childVNode, modifiedAttributes);
1646
- }
1647
- const runOrHyperlinkFragments = await buildRunOrHyperLink(childVNode, isVNode(childVNode) && childVNode.tagName === 'img'
1648
- ? { ...modifiedAttributes, type: 'picture' }
1649
- : modifiedAttributes, docxDocumentInstance);
1650
- if (Array.isArray(runOrHyperlinkFragments)) {
1651
- for (let iteratorIndex = 0; iteratorIndex < runOrHyperlinkFragments.length; iteratorIndex++) {
1652
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
1653
- paragraphFragment.import(runOrHyperlinkFragment);
1654
- }
1655
- }
1656
- else {
1657
- paragraphFragment.import(runOrHyperlinkFragments);
1658
- }
1659
- }
1660
- }
1661
- }
1662
- else {
1663
- // In case paragraphs has to be rendered where vText is present. Eg. table-cell
1664
- // Or in case the vNode is something like img
1665
- if (isVNode(vNode) && vNode.tagName === 'img') {
1666
- const imageSource = vNode.properties.src;
1667
- let base64String = imageSource;
1668
- if (isValidUrl(imageSource)) {
1669
- base64String = await imageToBase64(imageSource).catch((error) => {
1670
- // eslint-disable-next-line no-console
1671
- console.warning(`skipping image download and conversion due to ${error}`);
1672
- });
1673
- if (base64String && mimeTypes.lookup(imageSource)) {
1674
- vNode.properties.src = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
1675
- }
1676
- else {
1677
- paragraphFragment.up();
1678
- return paragraphFragment;
1679
- }
1680
- }
1681
- else {
1682
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
1683
- base64String = base64String.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
1684
- }
1685
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
1686
- const imageProperties = sizeOf(imageBuffer);
1687
- modifiedAttributes.maximumWidth =
1688
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
1689
- modifiedAttributes.originalWidth = imageProperties.width;
1690
- modifiedAttributes.originalHeight = imageProperties.height;
1691
- computeImageDimensions(vNode, modifiedAttributes);
1692
- }
1693
- const runFragments = await buildRunOrRuns(vNode, modifiedAttributes, docxDocumentInstance);
1694
- if (Array.isArray(runFragments)) {
1695
- for (let index = 0; index < runFragments.length; index++) {
1696
- const runFragment = runFragments[index];
1697
- paragraphFragment.import(runFragment);
1698
- }
1699
- }
1700
- else {
1701
- paragraphFragment.import(runFragments);
1702
- }
1703
- }
1704
- paragraphFragment.up();
1705
- return paragraphFragment;
1706
- };
1707
- const buildGridSpanFragment = (spanValue) => fragment({ namespaceAlias: { w: namespaces.w } })
1708
- .ele('@w', 'gridSpan')
1709
- .att('@w', 'val', spanValue)
1710
- .up();
1711
- const buildTableCellSpacing = (cellSpacing = 0) => fragment({ namespaceAlias: { w: namespaces.w } })
1712
- .ele('@w', 'tblCellSpacing')
1713
- .att('@w', 'w', cellSpacing)
1714
- .att('@w', 'type', 'dxa')
1715
- .up();
1716
- const buildTableCellBorders = (tableCellBorder) => {
1717
- const tableCellBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tcBorders');
1718
- const { color, stroke, ...borders } = tableCellBorder;
1719
- Object.keys(borders).forEach((border) => {
1720
- if (tableCellBorder[border]) {
1721
- const borderFragment = buildBorder(border, tableCellBorder[border], 0, color, stroke);
1722
- tableCellBordersFragment.import(borderFragment);
1723
- }
1724
- });
1725
- tableCellBordersFragment.up();
1726
- return tableCellBordersFragment;
1727
- };
1728
- const buildTableCellWidth = (tableCellWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
1729
- .ele('@w', 'tcW')
1730
- .att('@w', 'w', fixupColumnWidth(tableCellWidth))
1731
- .att('@w', 'type', 'dxa')
1732
- .up();
1733
- const buildTableCellProperties = (attributes) => {
1734
- const tableCellPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tcPr');
1735
- if (attributes && attributes.constructor === Object) {
1736
- Object.keys(attributes).forEach((key) => {
1737
- switch (key) {
1738
- case 'backgroundColor':
1739
- const shadingFragment = buildShading(attributes[key]);
1740
- tableCellPropertiesFragment.import(shadingFragment);
1741
- // eslint-disable-next-line no-param-reassign
1742
- delete attributes.backgroundColor;
1743
- break;
1744
- case 'verticalAlign':
1745
- const verticalAlignmentFragment = buildVerticalAlignment(attributes[key]);
1746
- tableCellPropertiesFragment.import(verticalAlignmentFragment);
1747
- // eslint-disable-next-line no-param-reassign
1748
- delete attributes.verticalAlign;
1749
- break;
1750
- case 'colSpan':
1751
- const gridSpanFragment = buildGridSpanFragment(attributes[key]);
1752
- tableCellPropertiesFragment.import(gridSpanFragment);
1753
- // eslint-disable-next-line no-param-reassign
1754
- delete attributes.colSpan;
1755
- break;
1756
- case 'tableCellBorder':
1757
- const tableCellBorderFragment = buildTableCellBorders(attributes[key]);
1758
- tableCellPropertiesFragment.import(tableCellBorderFragment);
1759
- // eslint-disable-next-line no-param-reassign
1760
- delete attributes.tableCellBorder;
1761
- break;
1762
- case 'rowSpan':
1763
- const verticalMergeFragment = buildVerticalMerge(attributes[key]);
1764
- tableCellPropertiesFragment.import(verticalMergeFragment);
1765
- delete attributes.rowSpan;
1766
- break;
1767
- case 'width':
1768
- const widthFragment = buildTableCellWidth(attributes[key]);
1769
- tableCellPropertiesFragment.import(widthFragment);
1770
- delete attributes.width;
1771
- break;
1772
- }
1773
- });
1774
- }
1775
- tableCellPropertiesFragment.up();
1776
- return tableCellPropertiesFragment;
1777
- };
1778
- const fixupTableCellBorder = (vNode, attributes) => {
1779
- if (Object.prototype.hasOwnProperty.call(vNode.properties.style, 'border')) {
1780
- if (vNode.properties.style.border === 'none' || vNode.properties.style.border === 0) {
1781
- attributes.tableCellBorder = {};
1782
- }
1783
- else {
1784
- // eslint-disable-next-line no-use-before-define
1785
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style.border);
1786
- attributes.tableCellBorder = {
1787
- top: borderSize,
1788
- left: borderSize,
1789
- bottom: borderSize,
1790
- right: borderSize,
1791
- color: borderColor,
1792
- stroke: borderStroke,
1793
- };
1794
- }
1795
- }
1796
- if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] === '0') {
1797
- attributes.tableCellBorder = {
1798
- ...attributes.tableCellBorder,
1799
- top: 0,
1800
- };
1801
- }
1802
- else if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] !== '0') {
1803
- // eslint-disable-next-line no-use-before-define
1804
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-top']);
1805
- attributes.tableCellBorder = {
1806
- ...attributes.tableCellBorder,
1807
- top: borderSize,
1808
- color: borderColor,
1809
- stroke: borderStroke,
1810
- };
1811
- }
1812
- if (vNode.properties.style['border-left'] && vNode.properties.style['border-left'] === '0') {
1813
- attributes.tableCellBorder = {
1814
- ...attributes.tableCellBorder,
1815
- left: 0,
1816
- };
1817
- }
1818
- else if (vNode.properties.style['border-left'] &&
1819
- vNode.properties.style['border-left'] !== '0') {
1820
- // eslint-disable-next-line no-use-before-define
1821
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-left']);
1822
- attributes.tableCellBorder = {
1823
- ...attributes.tableCellBorder,
1824
- left: borderSize,
1825
- color: borderColor,
1826
- stroke: borderStroke,
1827
- };
1828
- }
1829
- if (vNode.properties.style['border-bottom'] && vNode.properties.style['border-bottom'] === '0') {
1830
- attributes.tableCellBorder = {
1831
- ...attributes.tableCellBorder,
1832
- bottom: 0,
1833
- };
1834
- }
1835
- else if (vNode.properties.style['border-bottom'] &&
1836
- vNode.properties.style['border-bottom'] !== '0') {
1837
- // eslint-disable-next-line no-use-before-define
1838
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-bottom']);
1839
- attributes.tableCellBorder = {
1840
- ...attributes.tableCellBorder,
1841
- bottom: borderSize,
1842
- color: borderColor,
1843
- stroke: borderStroke,
1844
- };
1845
- }
1846
- if (vNode.properties.style['border-right'] && vNode.properties.style['border-right'] === '0') {
1847
- attributes.tableCellBorder = {
1848
- ...attributes.tableCellBorder,
1849
- right: 0,
1850
- };
1851
- }
1852
- else if (vNode.properties.style['border-right'] &&
1853
- vNode.properties.style['border-right'] !== '0') {
1854
- // eslint-disable-next-line no-use-before-define
1855
- const [borderSize, borderStroke, borderColor] = cssBorderParser(vNode.properties.style['border-right']);
1856
- attributes.tableCellBorder = {
1857
- ...attributes.tableCellBorder,
1858
- right: borderSize,
1859
- color: borderColor,
1860
- stroke: borderStroke,
1861
- };
1862
- }
1863
- };
1864
- const buildTableCell = async (vNode, attributes, rowSpanMap, columnIndex, docxDocumentInstance) => {
1865
- const tableCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
1866
- let modifiedAttributes = { ...attributes };
1867
- if (isVNode(vNode) && vNode.properties) {
1868
- if (vNode.properties.rowSpan) {
1869
- rowSpanMap.set(columnIndex.index, { rowSpan: vNode.properties.rowSpan - 1, colSpan: 0 });
1870
- modifiedAttributes.rowSpan = 'restart';
1871
- }
1872
- else {
1873
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
1874
- rowSpanMap.set(columnIndex.index,
1875
- // eslint-disable-next-line prefer-object-spread
1876
- Object.assign({}, previousSpanObject, {
1877
- rowSpan: 0,
1878
- colSpan: (previousSpanObject && previousSpanObject.colSpan) || 0,
1879
- }));
1880
- }
1881
- if (vNode.properties.colSpan ||
1882
- (vNode.properties.style && vNode.properties.style['column-span'])) {
1883
- modifiedAttributes.colSpan =
1884
- vNode.properties.colSpan ||
1885
- (vNode.properties.style && vNode.properties.style['column-span']);
1886
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
1887
- rowSpanMap.set(columnIndex.index,
1888
- // eslint-disable-next-line prefer-object-spread
1889
- Object.assign({}, previousSpanObject, {
1890
- colSpan: parseInt(modifiedAttributes.colSpan) || 0,
1891
- }));
1892
- columnIndex.index += parseInt(modifiedAttributes.colSpan) - 1;
1893
- }
1894
- if (vNode.properties.style) {
1895
- modifiedAttributes = {
1896
- ...modifiedAttributes,
1897
- ...modifiedStyleAttributesBuilder(vNode, attributes),
1898
- };
1899
- fixupTableCellBorder(vNode, modifiedAttributes);
1900
- }
1901
- }
1902
- const tableCellPropertiesFragment = buildTableCellProperties(modifiedAttributes);
1903
- tableCellFragment.import(tableCellPropertiesFragment);
1904
- if (vNodeHasChildren(vNode)) {
1905
- for (let index = 0; index < vNode.children.length; index++) {
1906
- const childVNode = vNode.children[index];
1907
- if (isVNode(childVNode) && childVNode.tagName === 'img') {
1908
- const imageFragment = await buildImage(docxDocumentInstance, childVNode, modifiedAttributes.maximumWidth);
1909
- if (imageFragment) {
1910
- tableCellFragment.import(imageFragment);
1911
- }
1912
- }
1913
- else if (isVNode(childVNode) && childVNode.tagName === 'figure') {
1914
- if (vNodeHasChildren(childVNode)) {
1915
- // eslint-disable-next-line no-plusplus
1916
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
1917
- const grandChildVNode = childVNode.children[iteratorIndex];
1918
- if (grandChildVNode.tagName === 'img') {
1919
- const imageFragment = await buildImage(docxDocumentInstance, grandChildVNode, modifiedAttributes.maximumWidth);
1920
- if (imageFragment) {
1921
- tableCellFragment.import(imageFragment);
1922
- }
1923
- }
1924
- }
1925
- }
1926
- }
1927
- else if (isVNode(childVNode) && ['ul', 'ol'].includes(childVNode.tagName)) {
1928
- // render list in table
1929
- if (vNodeHasChildren(childVNode)) {
1930
- await buildList(childVNode, docxDocumentInstance, tableCellFragment);
1931
- }
1932
- }
1933
- else {
1934
- const paragraphFragment = await buildParagraph(childVNode, modifiedAttributes, docxDocumentInstance);
1935
- tableCellFragment.import(paragraphFragment);
1936
- }
1937
- }
1938
- }
1939
- else {
1940
- // TODO: Figure out why building with buildParagraph() isn't working
1941
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1942
- .ele('@w', 'p')
1943
- .up();
1944
- tableCellFragment.import(paragraphFragment);
1945
- }
1946
- tableCellFragment.up();
1947
- return tableCellFragment;
1948
- };
1949
- const buildRowSpanCell = (rowSpanMap, columnIndex, attributes) => {
1950
- const rowSpanCellFragments = [];
1951
- let spanObject = rowSpanMap.get(columnIndex.index);
1952
- while (spanObject && spanObject.rowSpan) {
1953
- const rowSpanCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
1954
- const tableCellPropertiesFragment = buildTableCellProperties({
1955
- ...attributes,
1956
- rowSpan: 'continue',
1957
- colSpan: spanObject.colSpan ? spanObject.colSpan : 0,
1958
- });
1959
- rowSpanCellFragment.import(tableCellPropertiesFragment);
1960
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1961
- .ele('@w', 'p')
1962
- .up();
1963
- rowSpanCellFragment.import(paragraphFragment);
1964
- rowSpanCellFragment.up();
1965
- rowSpanCellFragments.push(rowSpanCellFragment);
1966
- if (spanObject.rowSpan - 1 === 0) {
1967
- rowSpanMap.delete(columnIndex.index);
1968
- }
1969
- else {
1970
- rowSpanMap.set(columnIndex.index, {
1971
- rowSpan: spanObject.rowSpan - 1,
1972
- colSpan: spanObject.colSpan || 0,
1973
- });
1974
- }
1975
- columnIndex.index += spanObject.colSpan || 1;
1976
- spanObject = rowSpanMap.get(columnIndex.index);
1977
- }
1978
- return rowSpanCellFragments;
1979
- };
1980
- const buildTableRowProperties = (attributes) => {
1981
- const tableRowPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'trPr');
1982
- if (attributes && attributes.constructor === Object) {
1983
- Object.keys(attributes).forEach((key) => {
1984
- switch (key) {
1985
- case 'tableRowHeight':
1986
- const tableRowHeightFragment = buildTableRowHeight(attributes[key]);
1987
- tableRowPropertiesFragment.import(tableRowHeightFragment);
1988
- // eslint-disable-next-line no-param-reassign
1989
- delete attributes.tableRowHeight;
1990
- break;
1991
- case 'rowCantSplit':
1992
- if (attributes.rowCantSplit) {
1993
- const cantSplitFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1994
- .ele('@w', 'cantSplit')
1995
- .up();
1996
- tableRowPropertiesFragment.import(cantSplitFragment);
1997
- // eslint-disable-next-line no-param-reassign
1998
- delete attributes.rowCantSplit;
1999
- }
2000
- break;
2001
- }
2002
- });
2003
- }
2004
- tableRowPropertiesFragment.up();
2005
- return tableRowPropertiesFragment;
2006
- };
2007
- const buildTableRow = async (vNode, attributes, rowSpanMap, docxDocumentInstance) => {
2008
- const tableRowFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tr');
2009
- const modifiedAttributes = { ...attributes };
2010
- if (isVNode(vNode) && vNode.properties) {
2011
- // FIXME: find a better way to get row height from cell style
2012
- if ((vNode.properties.style && vNode.properties.style.height) ||
2013
- (vNode.children[0] &&
2014
- isVNode(vNode.children[0]) &&
2015
- vNode.children[0].properties.style &&
2016
- vNode.children[0].properties.style.height)) {
2017
- modifiedAttributes.tableRowHeight = fixupRowHeight((vNode.properties.style && vNode.properties.style.height) ||
2018
- (vNode.children[0] &&
2019
- isVNode(vNode.children[0]) &&
2020
- vNode.children[0].properties.style &&
2021
- vNode.children[0].properties.style.height
2022
- ? vNode.children[0].properties.style.height
2023
- : undefined));
2024
- }
2025
- if (vNode.properties.style) {
2026
- fixupTableCellBorder(vNode, modifiedAttributes);
2027
- }
2028
- }
2029
- const tableRowPropertiesFragment = buildTableRowProperties(modifiedAttributes);
2030
- tableRowFragment.import(tableRowPropertiesFragment);
2031
- const columnIndex = { index: 0 };
2032
- if (vNodeHasChildren(vNode)) {
2033
- const tableColumns = vNode.children.filter((childVNode) => ['td', 'th'].includes(childVNode.tagName));
2034
- const maximumColumnWidth = docxDocumentInstance.availableDocumentSpace / tableColumns.length;
2035
- // eslint-disable-next-line no-restricted-syntax
2036
- for (const column of tableColumns) {
2037
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
2038
- if (Array.isArray(rowSpanCellFragments)) {
2039
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
2040
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
2041
- tableRowFragment.import(rowSpanCellFragment);
2042
- }
2043
- }
2044
- const tableCellFragment = await buildTableCell(column, { ...modifiedAttributes, maximumWidth: maximumColumnWidth }, rowSpanMap, columnIndex, docxDocumentInstance);
2045
- columnIndex.index++;
2046
- tableRowFragment.import(tableCellFragment);
2047
- }
2048
- }
2049
- if (columnIndex.index < rowSpanMap.size) {
2050
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
2051
- if (Array.isArray(rowSpanCellFragments)) {
2052
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
2053
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
2054
- tableRowFragment.import(rowSpanCellFragment);
2055
- }
2056
- }
2057
- }
2058
- tableRowFragment.up();
2059
- return tableRowFragment;
2060
- };
2061
- const buildTableGridCol = (gridWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
2062
- .ele('@w', 'gridCol')
2063
- .att('@w', 'w', String(gridWidth));
2064
- const buildTableGrid = (vNode, attributes) => {
2065
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
2066
- if (vNodeHasChildren(vNode)) {
2067
- const gridColumns = vNode.children.filter((childVNode) => childVNode.tagName === 'col');
2068
- const gridWidth = attributes.maximumWidth / gridColumns.length;
2069
- for (let index = 0; index < gridColumns.length; index++) {
2070
- const tableGridColFragment = buildTableGridCol(gridWidth);
2071
- tableGridFragment.import(tableGridColFragment);
2072
- }
2073
- }
2074
- tableGridFragment.up();
2075
- return tableGridFragment;
2076
- };
2077
- const buildTableGridFromTableRow = (vNode, attributes) => {
2078
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
2079
- if (vNodeHasChildren(vNode)) {
2080
- const numberOfGridColumns = vNode.children.reduce((accumulator, childVNode) => {
2081
- const colSpan = childVNode.properties.colSpan ||
2082
- (childVNode.properties.style && childVNode.properties.style['column-span']);
2083
- return accumulator + (colSpan ? parseInt(colSpan) : 1);
2084
- }, 0);
2085
- const gridWidth = attributes.maximumWidth / numberOfGridColumns;
2086
- for (let index = 0; index < numberOfGridColumns; index++) {
2087
- const tableGridColFragment = buildTableGridCol(gridWidth);
2088
- tableGridFragment.import(tableGridColFragment);
2089
- }
2090
- }
2091
- tableGridFragment.up();
2092
- return tableGridFragment;
2093
- };
2094
- const buildTableBorders = (tableBorder) => {
2095
- const tableBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblBorders');
2096
- const { color, stroke, ...borders } = tableBorder;
2097
- Object.keys(borders).forEach((border) => {
2098
- if (borders[border]) {
2099
- const borderFragment = buildBorder(border, borders[border], 0, color, stroke);
2100
- tableBordersFragment.import(borderFragment);
2101
- }
2102
- });
2103
- tableBordersFragment.up();
2104
- return tableBordersFragment;
2105
- };
2106
- const buildTableWidth = (tableWidth) => fragment({ namespaceAlias: { w: namespaces.w } })
2107
- .ele('@w', 'tblW')
2108
- .att('@w', 'type', 'dxa')
2109
- .att('@w', 'w', String(tableWidth))
2110
- .up();
2111
- const buildCellMargin = (side, margin) => fragment({ namespaceAlias: { w: namespaces.w } })
2112
- .ele('@w', side)
2113
- .att('@w', 'type', 'dxa')
2114
- .att('@w', 'w', String(margin))
2115
- .up();
2116
- const buildTableCellMargins = (margin) => {
2117
- const tableCellMarFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblCellMar');
2118
- ['top', 'bottom'].forEach((side) => {
2119
- const marginFragment = buildCellMargin(side, margin / 2);
2120
- tableCellMarFragment.import(marginFragment);
2121
- });
2122
- ['left', 'right'].forEach((side) => {
2123
- const marginFragment = buildCellMargin(side, margin);
2124
- tableCellMarFragment.import(marginFragment);
2125
- });
2126
- return tableCellMarFragment;
2127
- };
2128
- const buildTableProperties = (attributes) => {
2129
- const tablePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblPr');
2130
- if (attributes && attributes.constructor === Object) {
2131
- Object.keys(attributes).forEach((key) => {
2132
- switch (key) {
2133
- case 'tableBorder':
2134
- const tableBordersFragment = buildTableBorders(attributes[key]);
2135
- tablePropertiesFragment.import(tableBordersFragment);
2136
- // eslint-disable-next-line no-param-reassign
2137
- delete attributes.tableBorder;
2138
- break;
2139
- case 'tableCellSpacing':
2140
- const tableCellSpacingFragment = buildTableCellSpacing(attributes[key]);
2141
- tablePropertiesFragment.import(tableCellSpacingFragment);
2142
- // eslint-disable-next-line no-param-reassign
2143
- delete attributes.tableCellSpacing;
2144
- break;
2145
- case 'width':
2146
- if (attributes[key]) {
2147
- const tableWidthFragment = buildTableWidth(attributes[key]);
2148
- tablePropertiesFragment.import(tableWidthFragment);
2149
- }
2150
- // eslint-disable-next-line no-param-reassign
2151
- delete attributes.width;
2152
- break;
2153
- }
2154
- });
2155
- }
2156
- const tableCellMarginFragment = buildTableCellMargins(160);
2157
- tablePropertiesFragment.import(tableCellMarginFragment);
2158
- // by default, all tables are center aligned.
2159
- const alignmentFragment = buildHorizontalAlignment('center');
2160
- tablePropertiesFragment.import(alignmentFragment);
2161
- tablePropertiesFragment.up();
2162
- return tablePropertiesFragment;
2163
- };
2164
- const cssBorderParser = (borderString) => {
2165
- let [size, stroke, color] = borderString.split(' ');
2166
- if (pointRegex.test(size)) {
2167
- const matchedParts = size.match(pointRegex);
2168
- // convert point to eighth of a point
2169
- size = pointToEIP(matchedParts[1]);
2170
- }
2171
- else if (pixelRegex.test(size)) {
2172
- const matchedParts = size.match(pixelRegex);
2173
- // convert pixels to eighth of a point
2174
- size = pixelToEIP(matchedParts[1]);
2175
- }
2176
- stroke = stroke && ['dashed', 'dotted', 'double'].includes(stroke) ? stroke : 'single';
2177
- color = color && fixupColorCode(color).toUpperCase();
2178
- return [size, stroke, color];
2179
- };
2180
- const buildTable = async (vNode, attributes, docxDocumentInstance) => {
2181
- const tableFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tbl');
2182
- const modifiedAttributes = { ...attributes };
2183
- if (isVNode(vNode) && vNode.properties) {
2184
- const tableAttributes = vNode.properties.attributes || {};
2185
- const tableStyles = vNode.properties.style || {};
2186
- const tableBorders = {};
2187
- const tableCellBorders = {};
2188
- let [borderSize, borderStrike, borderColor] = [2, 'single', '000000'];
2189
- // eslint-disable-next-line no-restricted-globals
2190
- if (!isNaN(tableAttributes.border)) {
2191
- borderSize = parseInt(tableAttributes.border, 10);
2192
- }
2193
- // css style overrides table border properties
2194
- if (tableStyles.border) {
2195
- const [cssSize, cssStroke, cssColor] = cssBorderParser(tableStyles.border);
2196
- borderSize = cssSize || borderSize;
2197
- borderColor = cssColor || borderColor;
2198
- borderStrike = cssStroke || borderStrike;
2199
- }
2200
- tableBorders.top = borderSize;
2201
- tableBorders.bottom = borderSize;
2202
- tableBorders.left = borderSize;
2203
- tableBorders.right = borderSize;
2204
- tableBorders.stroke = borderStrike;
2205
- tableBorders.color = borderColor;
2206
- if (tableStyles['border-collapse'] === 'collapse') {
2207
- tableBorders.insideV = borderSize;
2208
- tableBorders.insideH = borderSize;
2209
- }
2210
- else {
2211
- tableBorders.insideV = 0;
2212
- tableBorders.insideH = 0;
2213
- tableCellBorders.top = 1;
2214
- tableCellBorders.bottom = 1;
2215
- tableCellBorders.left = 1;
2216
- tableCellBorders.right = 1;
2217
- }
2218
- modifiedAttributes.tableBorder = tableBorders;
2219
- modifiedAttributes.tableCellSpacing = 0;
2220
- if (Object.keys(tableCellBorders).length) {
2221
- modifiedAttributes.tableCellBorder = tableCellBorders;
2222
- }
2223
- let minimumWidth;
2224
- let maximumWidth;
2225
- let width;
2226
- // Calculate minimum width of table
2227
- if (pixelRegex.test(tableStyles['min-width'])) {
2228
- minimumWidth = pixelToTWIP(tableStyles['min-width'].match(pixelRegex)[1]);
2229
- }
2230
- else if (percentageRegex.test(tableStyles['min-width'])) {
2231
- const percentageValue = tableStyles['min-width'].match(percentageRegex)[1];
2232
- minimumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
2233
- }
2234
- // Calculate maximum width of table
2235
- if (pixelRegex.test(tableStyles['max-width'])) {
2236
- pixelRegex.lastIndex = 0;
2237
- maximumWidth = pixelToTWIP(tableStyles['max-width'].match(pixelRegex)[1]);
2238
- }
2239
- else if (percentageRegex.test(tableStyles['max-width'])) {
2240
- percentageRegex.lastIndex = 0;
2241
- const percentageValue = tableStyles['max-width'].match(percentageRegex)[1];
2242
- maximumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
2243
- }
2244
- // Calculate specified width of table
2245
- if (pixelRegex.test(tableStyles.width)) {
2246
- pixelRegex.lastIndex = 0;
2247
- width = pixelToTWIP(tableStyles.width.match(pixelRegex)[1]);
2248
- }
2249
- else if (percentageRegex.test(tableStyles.width)) {
2250
- percentageRegex.lastIndex = 0;
2251
- const percentageValue = tableStyles.width.match(percentageRegex)[1];
2252
- width = Math.round((percentageValue / 100) * attributes.maximumWidth);
2253
- }
2254
- // If width isn't supplied, we should have min-width as the width.
2255
- if (width) {
2256
- modifiedAttributes.width = width;
2257
- if (maximumWidth) {
2258
- modifiedAttributes.width = Math.min(modifiedAttributes.width, maximumWidth);
2259
- }
2260
- if (minimumWidth) {
2261
- modifiedAttributes.width = Math.max(modifiedAttributes.width, minimumWidth);
2262
- }
2263
- }
2264
- else if (minimumWidth) {
2265
- modifiedAttributes.width = minimumWidth;
2266
- }
2267
- if (modifiedAttributes.width) {
2268
- modifiedAttributes.width = Math.min(modifiedAttributes.width, attributes.maximumWidth);
2269
- }
2270
- }
2271
- const tablePropertiesFragment = buildTableProperties(modifiedAttributes);
2272
- tableFragment.import(tablePropertiesFragment);
2273
- const rowSpanMap = new Map();
2274
- if (vNodeHasChildren(vNode)) {
2275
- for (let index = 0; index < vNode.children.length; index++) {
2276
- const childVNode = vNode.children[index];
2277
- if (childVNode.tagName === 'colgroup') {
2278
- const tableGridFragment = buildTableGrid(childVNode, modifiedAttributes);
2279
- tableFragment.import(tableGridFragment);
2280
- }
2281
- else if (childVNode.tagName === 'thead') {
2282
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
2283
- const grandChildVNode = childVNode.children[iteratorIndex];
2284
- if (grandChildVNode.tagName === 'tr') {
2285
- if (iteratorIndex === 0) {
2286
- const tableGridFragment = buildTableGridFromTableRow(grandChildVNode, modifiedAttributes);
2287
- tableFragment.import(tableGridFragment);
2288
- }
2289
- const tableRowFragment = await buildTableRow(grandChildVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
2290
- tableFragment.import(tableRowFragment);
2291
- }
2292
- }
2293
- }
2294
- else if (childVNode.tagName === 'tbody') {
2295
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
2296
- const grandChildVNode = childVNode.children[iteratorIndex];
2297
- if (grandChildVNode.tagName === 'tr') {
2298
- if (iteratorIndex === 0) {
2299
- const tableGridFragment = buildTableGridFromTableRow(grandChildVNode, modifiedAttributes);
2300
- tableFragment.import(tableGridFragment);
2301
- }
2302
- const tableRowFragment = await buildTableRow(grandChildVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
2303
- tableFragment.import(tableRowFragment);
2304
- }
2305
- }
2306
- }
2307
- else if (childVNode.tagName === 'tr') {
2308
- if (index === 0) {
2309
- const tableGridFragment = buildTableGridFromTableRow(childVNode, modifiedAttributes);
2310
- tableFragment.import(tableGridFragment);
2311
- }
2312
- const tableRowFragment = await buildTableRow(childVNode, modifiedAttributes, rowSpanMap, docxDocumentInstance);
2313
- tableFragment.import(tableRowFragment);
2314
- }
2315
- }
2316
- }
2317
- tableFragment.up();
2318
- return tableFragment;
2319
- };
2320
- const buildPresetGeometry = () => fragment({ namespaceAlias: { a: namespaces.a } })
2321
- .ele('@a', 'prstGeom')
2322
- .att('prst', 'rect')
2323
- .up();
2324
- const buildExtents = ({ width, height }) => fragment({ namespaceAlias: { a: namespaces.a } })
2325
- .ele('@a', 'ext')
2326
- .att('cx', width)
2327
- .att('cy', height)
2328
- .up();
2329
- const buildOffset = () => fragment({ namespaceAlias: { a: namespaces.a } })
2330
- .ele('@a', 'off')
2331
- .att('x', '0')
2332
- .att('y', '0')
2333
- .up();
2334
- const buildGraphicFrameTransform = (attributes) => {
2335
- const graphicFrameTransformFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'xfrm');
2336
- const offsetFragment = buildOffset();
2337
- graphicFrameTransformFragment.import(offsetFragment);
2338
- const extentsFragment = buildExtents(attributes);
2339
- graphicFrameTransformFragment.import(extentsFragment);
2340
- graphicFrameTransformFragment.up();
2341
- return graphicFrameTransformFragment;
2342
- };
2343
- const buildShapeProperties = (attributes) => {
2344
- const shapeProperties = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'spPr');
2345
- const graphicFrameTransformFragment = buildGraphicFrameTransform(attributes);
2346
- shapeProperties.import(graphicFrameTransformFragment);
2347
- const presetGeometryFragment = buildPresetGeometry();
2348
- shapeProperties.import(presetGeometryFragment);
2349
- shapeProperties.up();
2350
- return shapeProperties;
2351
- };
2352
- const buildFillRect = () => fragment({ namespaceAlias: { a: namespaces.a } })
2353
- .ele('@a', 'fillRect')
2354
- .up();
2355
- const buildStretch = () => {
2356
- const stretchFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'stretch');
2357
- const fillRectFragment = buildFillRect();
2358
- stretchFragment.import(fillRectFragment);
2359
- stretchFragment.up();
2360
- return stretchFragment;
2361
- };
2362
- const buildSrcRectFragment = () => fragment({ namespaceAlias: { a: namespaces.a } })
2363
- .ele('@a', 'srcRect')
2364
- .att('b', '0')
2365
- .att('l', '0')
2366
- .att('r', '0')
2367
- .att('t', '0')
2368
- .up();
2369
- const buildBinaryLargeImageOrPicture = (relationshipId) => fragment({
2370
- namespaceAlias: { a: namespaces.a, r: namespaces.r },
2371
- })
2372
- .ele('@a', 'blip')
2373
- .att('@r', 'embed', `rId${relationshipId}`)
2374
- // FIXME: possible values 'email', 'none', 'print', 'hqprint', 'screen'
2375
- .att('cstate', 'print')
2376
- .up();
2377
- const buildBinaryLargeImageOrPictureFill = (relationshipId) => {
2378
- const binaryLargeImageOrPictureFillFragment = fragment({
2379
- namespaceAlias: { pic: namespaces.pic },
2380
- }).ele('@pic', 'blipFill');
2381
- const binaryLargeImageOrPictureFragment = buildBinaryLargeImageOrPicture(relationshipId);
2382
- binaryLargeImageOrPictureFillFragment.import(binaryLargeImageOrPictureFragment);
2383
- const srcRectFragment = buildSrcRectFragment();
2384
- binaryLargeImageOrPictureFillFragment.import(srcRectFragment);
2385
- const stretchFragment = buildStretch();
2386
- binaryLargeImageOrPictureFillFragment.import(stretchFragment);
2387
- binaryLargeImageOrPictureFillFragment.up();
2388
- return binaryLargeImageOrPictureFillFragment;
2389
- };
2390
- const buildNonVisualPictureDrawingProperties = () => fragment({ namespaceAlias: { pic: namespaces.pic } })
2391
- .ele('@pic', 'cNvPicPr')
2392
- .up();
2393
- const buildNonVisualDrawingProperties = (pictureId, pictureNameWithExtension, pictureDescription = '') => fragment({ namespaceAlias: { pic: namespaces.pic } })
2394
- .ele('@pic', 'cNvPr')
2395
- .att('id', pictureId)
2396
- .att('name', pictureNameWithExtension)
2397
- .att('descr', pictureDescription)
2398
- .up();
2399
- const buildNonVisualPictureProperties = (pictureId, pictureNameWithExtension, pictureDescription) => {
2400
- const nonVisualPicturePropertiesFragment = fragment({
2401
- namespaceAlias: { pic: namespaces.pic },
2402
- }).ele('@pic', 'nvPicPr');
2403
- // TODO: Handle picture attributes
2404
- const nonVisualDrawingPropertiesFragment = buildNonVisualDrawingProperties(pictureId, pictureNameWithExtension, pictureDescription);
2405
- nonVisualPicturePropertiesFragment.import(nonVisualDrawingPropertiesFragment);
2406
- const nonVisualPictureDrawingPropertiesFragment = buildNonVisualPictureDrawingProperties();
2407
- nonVisualPicturePropertiesFragment.import(nonVisualPictureDrawingPropertiesFragment);
2408
- nonVisualPicturePropertiesFragment.up();
2409
- return nonVisualPicturePropertiesFragment;
2410
- };
2411
- const buildPicture = ({ id, fileNameWithExtension, description, relationshipId, width, height, }) => {
2412
- const pictureFragment = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'pic');
2413
- const nonVisualPicturePropertiesFragment = buildNonVisualPictureProperties(id, fileNameWithExtension, description);
2414
- pictureFragment.import(nonVisualPicturePropertiesFragment);
2415
- const binaryLargeImageOrPictureFill = buildBinaryLargeImageOrPictureFill(relationshipId);
2416
- pictureFragment.import(binaryLargeImageOrPictureFill);
2417
- const shapeProperties = buildShapeProperties({ width, height });
2418
- pictureFragment.import(shapeProperties);
2419
- pictureFragment.up();
2420
- return pictureFragment;
2421
- };
2422
- const buildGraphicData = (graphicType, attributes) => {
2423
- const graphicDataFragment = fragment({ namespaceAlias: { a: namespaces.a } })
2424
- .ele('@a', 'graphicData')
2425
- .att('uri', 'http://schemas.openxmlformats.org/drawingml/2006/picture');
2426
- if (graphicType === 'picture') {
2427
- const pictureFragment = buildPicture(attributes);
2428
- graphicDataFragment.import(pictureFragment);
2429
- }
2430
- graphicDataFragment.up();
2431
- return graphicDataFragment;
2432
- };
2433
- const buildGraphic = (graphicType, attributes) => {
2434
- const graphicFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'graphic');
2435
- // TODO: Handle drawing type
2436
- const graphicDataFragment = buildGraphicData(graphicType, attributes);
2437
- graphicFragment.import(graphicDataFragment);
2438
- graphicFragment.up();
2439
- return graphicFragment;
2440
- };
2441
- const buildDrawingObjectNonVisualProperties = (pictureId, pictureName) => fragment({ namespaceAlias: { wp: namespaces.wp } })
2442
- .ele('@wp', 'docPr')
2443
- .att('id', pictureId)
2444
- .att('name', pictureName)
2445
- .up();
2446
- const buildWrapSquare = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2447
- .ele('@wp', 'wrapSquare')
2448
- .att('wrapText', 'bothSides')
2449
- .att('distB', '228600')
2450
- .att('distT', '228600')
2451
- .att('distL', '228600')
2452
- .att('distR', '228600')
2453
- .up();
2454
- // eslint-disable-next-line no-unused-vars
2455
- const buildWrapNone = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2456
- .ele('@wp', 'wrapNone')
2457
- .up();
2458
- const buildEffectExtentFragment = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2459
- .ele('@wp', 'effectExtent')
2460
- .att('b', '0')
2461
- .att('l', '0')
2462
- .att('r', '0')
2463
- .att('t', '0')
2464
- .up();
2465
- const buildExtent = ({ width, height }) => fragment({ namespaceAlias: { wp: namespaces.wp } })
2466
- .ele('@wp', 'extent')
2467
- .att('cx', width)
2468
- .att('cy', height)
2469
- .up();
2470
- const buildPositionV = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2471
- .ele('@wp', 'positionV')
2472
- .att('relativeFrom', 'paragraph')
2473
- .ele('@wp', 'posOffset')
2474
- .txt('19050')
2475
- .up()
2476
- .up();
2477
- const buildPositionH = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2478
- .ele('@wp', 'positionH')
2479
- .att('relativeFrom', 'column')
2480
- .ele('@wp', 'posOffset')
2481
- .txt('19050')
2482
- .up()
2483
- .up();
2484
- const buildSimplePos = () => fragment({ namespaceAlias: { wp: namespaces.wp } })
2485
- .ele('@wp', 'simplePos')
2486
- .att('x', '0')
2487
- .att('y', '0')
2488
- .up();
2489
- const buildAnchoredDrawing = (graphicType, attributes) => {
2490
- const anchoredDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
2491
- .ele('@wp', 'anchor')
2492
- .att('distB', '0')
2493
- .att('distL', '0')
2494
- .att('distR', '0')
2495
- .att('distT', '0')
2496
- .att('relativeHeight', '0')
2497
- .att('behindDoc', 'false')
2498
- .att('locked', 'true')
2499
- .att('layoutInCell', 'true')
2500
- .att('allowOverlap', 'false')
2501
- .att('simplePos', 'false');
2502
- // Even though simplePos isnt supported by Word 2007 simplePos is required.
2503
- const simplePosFragment = buildSimplePos();
2504
- anchoredDrawingFragment.import(simplePosFragment);
2505
- const positionHFragment = buildPositionH();
2506
- anchoredDrawingFragment.import(positionHFragment);
2507
- const positionVFragment = buildPositionV();
2508
- anchoredDrawingFragment.import(positionVFragment);
2509
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
2510
- anchoredDrawingFragment.import(extentFragment);
2511
- const effectExtentFragment = buildEffectExtentFragment();
2512
- anchoredDrawingFragment.import(effectExtentFragment);
2513
- const wrapSquareFragment = buildWrapSquare();
2514
- anchoredDrawingFragment.import(wrapSquareFragment);
2515
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(attributes.id, attributes.fileNameWithExtension);
2516
- anchoredDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
2517
- const graphicFragment = buildGraphic(graphicType, attributes);
2518
- anchoredDrawingFragment.import(graphicFragment);
2519
- anchoredDrawingFragment.up();
2520
- return anchoredDrawingFragment;
2521
- };
2522
- const buildInlineDrawing = (graphicType, attributes) => {
2523
- const inlineDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
2524
- .ele('@wp', 'inline')
2525
- .att('distB', '0')
2526
- .att('distL', '0')
2527
- .att('distR', '0')
2528
- .att('distT', '0');
2529
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
2530
- inlineDrawingFragment.import(extentFragment);
2531
- const effectExtentFragment = buildEffectExtentFragment();
2532
- inlineDrawingFragment.import(effectExtentFragment);
2533
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(attributes.id, attributes.fileNameWithExtension);
2534
- inlineDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
2535
- const graphicFragment = buildGraphic(graphicType, attributes);
2536
- inlineDrawingFragment.import(graphicFragment);
2537
- inlineDrawingFragment.up();
2538
- return inlineDrawingFragment;
2539
- };
2540
- const buildDrawing = (inlineOrAnchored = false, graphicType, attributes) => {
2541
- const drawingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'drawing');
2542
- const inlineOrAnchoredDrawingFragment = inlineOrAnchored
2543
- ? buildInlineDrawing(graphicType, attributes)
2544
- : buildAnchoredDrawing(graphicType, attributes);
2545
- drawingFragment.import(inlineOrAnchoredDrawingFragment);
2546
- drawingFragment.up();
2547
- return drawingFragment;
2548
- };
2549
- // eslint-disable-next-line consistent-return, no-shadow
2550
- const buildImage = async (docxDocumentInstance, vNode, maximumWidth = null) => {
2551
- let response = null;
2552
- let base64Uri = null;
2553
- try {
2554
- const imageSource = vNode.properties.src;
2555
- if (isValidUrl(imageSource)) {
2556
- const base64String = await imageToBase64(imageSource).catch((error) => {
2557
- // eslint-disable-next-line no-console
2558
- console.warning(`skipping image download and conversion due to ${error}`);
2559
- });
2560
- if (base64String) {
2561
- base64Uri = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
2562
- }
2563
- }
2564
- else {
2565
- base64Uri = decodeURIComponent(vNode.properties.src);
2566
- }
2567
- if (base64Uri) {
2568
- response = docxDocumentInstance.createMediaFile(base64Uri);
2569
- }
2570
- }
2571
- catch (error) {
2572
- // NOOP
2573
- }
2574
- if (response) {
2575
- docxDocumentInstance.zip
2576
- .folder('word')
2577
- .folder('media')
2578
- .file(response.fileNameWithExtension, Buffer.from(response.fileContent, 'base64'), {
2579
- createFolders: false,
2580
- });
2581
- const documentRelsId = docxDocumentInstance.createDocumentRelationships(docxDocumentInstance.relationshipFilename, imageType, `media/${response.fileNameWithExtension}`, internalRelationship);
2582
- const imageBuffer = Buffer.from(response.fileContent, 'base64');
2583
- const imageProperties = sizeOf(imageBuffer);
2584
- const imageFragment = await xmlBuilder.buildParagraph(vNode, {
2585
- type: 'picture',
2586
- inlineOrAnchored: true,
2587
- relationshipId: documentRelsId,
2588
- ...response,
2589
- maximumWidth: maximumWidth || docxDocumentInstance.availableDocumentSpace,
2590
- originalWidth: imageProperties.width,
2591
- originalHeight: imageProperties.height,
2592
- }, docxDocumentInstance);
2593
- return imageFragment;
2594
- }
2595
- };
2596
- const buildList = async (vNode, docxDocumentInstance, xmlFragment) => {
2597
- const listElements = [];
2598
- let vNodeObjects = [
2599
- {
2600
- node: vNode,
2601
- level: 0,
2602
- type: vNode.tagName,
2603
- numberingId: docxDocumentInstance.createNumbering(vNode.tagName, vNode.properties),
2604
- },
2605
- ];
2606
- while (vNodeObjects.length) {
2607
- const tempVNodeObject = vNodeObjects.shift();
2608
- if (isVText(tempVNodeObject.node) ||
2609
- (isVNode(tempVNodeObject.node) && !['ul', 'ol', 'li'].includes(tempVNodeObject.node.tagName))) {
2610
- const paragraphFragment = await xmlBuilder.buildParagraph(tempVNodeObject.node, {
2611
- numbering: { levelId: tempVNodeObject.level, numberingId: tempVNodeObject.numberingId },
2612
- }, docxDocumentInstance);
2613
- xmlFragment.import(paragraphFragment);
2614
- }
2615
- if (tempVNodeObject.node.children &&
2616
- tempVNodeObject.node.children.length &&
2617
- ['ul', 'ol', 'li'].includes(tempVNodeObject.node.tagName)) {
2618
- const tempVNodeObjects = tempVNodeObject.node.children.reduce((accumulator, childVNode) => {
2619
- if (['ul', 'ol'].includes(childVNode.tagName)) {
2620
- accumulator.push({
2621
- node: childVNode,
2622
- level: tempVNodeObject.level + 1,
2623
- type: childVNode.tagName,
2624
- numberingId: docxDocumentInstance.createNumbering(childVNode.tagName, childVNode.properties),
2625
- });
2626
- }
2627
- else {
2628
- // eslint-disable-next-line no-lonely-if
2629
- if (accumulator.length > 0 &&
2630
- isVNode(accumulator[accumulator.length - 1].node) &&
2631
- accumulator[accumulator.length - 1].node.tagName.toLowerCase() === 'p') {
2632
- accumulator[accumulator.length - 1].node.children.push(childVNode);
2633
- }
2634
- else {
2635
- const paragraphVNode = new VNode('p', null,
2636
- // eslint-disable-next-line no-nested-ternary
2637
- isVText(childVNode)
2638
- ? [childVNode]
2639
- : // eslint-disable-next-line no-nested-ternary
2640
- isVNode(childVNode)
2641
- ? childVNode.tagName.toLowerCase() === 'li'
2642
- ? [...childVNode.children]
2643
- : [childVNode]
2644
- : []);
2645
- accumulator.push({
2646
- // eslint-disable-next-line prettier/prettier, no-nested-ternary
2647
- node: isVNode(childVNode)
2648
- ? // eslint-disable-next-line prettier/prettier, no-nested-ternary
2649
- childVNode.tagName.toLowerCase() === 'li'
2650
- ? childVNode
2651
- : childVNode.tagName.toLowerCase() !== 'p'
2652
- ? paragraphVNode
2653
- : childVNode
2654
- : // eslint-disable-next-line prettier/prettier
2655
- paragraphVNode,
2656
- level: tempVNodeObject.level,
2657
- type: tempVNodeObject.type,
2658
- numberingId: tempVNodeObject.numberingId,
2659
- });
2660
- }
2661
- }
2662
- return accumulator;
2663
- }, []);
2664
- vNodeObjects = tempVNodeObjects.concat(vNodeObjects);
2665
- }
2666
- }
2667
- return listElements;
2668
- };
2669
-
2670
- /* eslint-disable no-await-in-loop */
2671
- /* eslint-disable no-case-declarations */
2672
- const convertHTML$1 = HTMLToVDOM({
2673
- VNode: VNode$1,
2674
- VText,
2675
- });
2676
- async function findXMLEquivalent(docxDocumentInstance, vNode, xmlFragment) {
2677
- if (vNode.tagName === 'div' &&
2678
- (vNode.properties.attributes.class === 'page-break' ||
2679
- (vNode.properties.style && vNode.properties.style['page-break-after']))) {
2680
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
2681
- .ele('@w', 'p')
2682
- .ele('@w', 'r')
2683
- .ele('@w', 'br')
2684
- .att('@w', 'type', 'page')
2685
- .up()
2686
- .up()
2687
- .up();
2688
- xmlFragment.import(paragraphFragment);
2689
- return;
2690
- }
2691
- switch (vNode.tagName) {
2692
- case 'h1':
2693
- case 'h2':
2694
- case 'h3':
2695
- case 'h4':
2696
- case 'h5':
2697
- case 'h6':
2698
- const headingFragment = await buildParagraph(vNode, {
2699
- paragraphStyle: `Heading${vNode.tagName[1]}`,
2700
- }, docxDocumentInstance);
2701
- xmlFragment.import(headingFragment);
2702
- return;
2703
- case 'span':
2704
- case 'strong':
2705
- case 'b':
2706
- case 'em':
2707
- case 'i':
2708
- case 'u':
2709
- case 'ins':
2710
- case 'strike':
2711
- case 'del':
2712
- case 's':
2713
- case 'sub':
2714
- case 'sup':
2715
- case 'mark':
2716
- case 'p':
2717
- case 'a':
2718
- case 'blockquote':
2719
- case 'code':
2720
- case 'pre':
2721
- const paragraphFragment = await buildParagraph(vNode, {}, docxDocumentInstance);
2722
- xmlFragment.import(paragraphFragment);
2723
- return;
2724
- case 'figure':
2725
- if (vNodeHasChildren(vNode)) {
2726
- // eslint-disable-next-line no-plusplus
2727
- for (let index = 0; index < vNode.children.length; index++) {
2728
- const childVNode = vNode.children[index];
2729
- if (childVNode.tagName === 'table') {
2730
- const tableFragment = await buildTable(childVNode, {
2731
- maximumWidth: docxDocumentInstance.availableDocumentSpace,
2732
- rowCantSplit: docxDocumentInstance.tableRowCantSplit,
2733
- }, docxDocumentInstance);
2734
- xmlFragment.import(tableFragment);
2735
- // Adding empty paragraph for space after table
2736
- const emptyParagraphFragment = await buildParagraph(null, {});
2737
- xmlFragment.import(emptyParagraphFragment);
2738
- }
2739
- else if (childVNode.tagName === 'img') {
2740
- const imageFragment = await buildImage(docxDocumentInstance, childVNode);
2741
- if (imageFragment) {
2742
- xmlFragment.import(imageFragment);
2743
- }
2744
- }
2745
- }
2746
- }
2747
- return;
2748
- case 'table':
2749
- const tableFragment = await buildTable(vNode, {
2750
- maximumWidth: docxDocumentInstance.availableDocumentSpace,
2751
- rowCantSplit: docxDocumentInstance.tableRowCantSplit,
2752
- }, docxDocumentInstance);
2753
- xmlFragment.import(tableFragment);
2754
- // Adding empty paragraph for space after table
2755
- const emptyParagraphFragment = await buildParagraph(null, {});
2756
- xmlFragment.import(emptyParagraphFragment);
2757
- return;
2758
- case 'ol':
2759
- case 'ul':
2760
- await buildList(vNode, docxDocumentInstance, xmlFragment);
2761
- return;
2762
- case 'img':
2763
- const imageFragment = await buildImage(docxDocumentInstance, vNode);
2764
- if (imageFragment) {
2765
- xmlFragment.import(imageFragment);
2766
- }
2767
- return;
2768
- case 'br':
2769
- const linebreakFragment = await buildParagraph(null, {});
2770
- xmlFragment.import(linebreakFragment);
2771
- return;
2772
- }
2773
- if (vNodeHasChildren(vNode)) {
2774
- // eslint-disable-next-line no-plusplus
2775
- for (let index = 0; index < vNode.children.length; index++) {
2776
- const childVNode = vNode.children[index];
2777
- // eslint-disable-next-line no-use-before-define
2778
- await convertVTreeToXML(docxDocumentInstance, childVNode, xmlFragment);
2779
- }
2780
- }
2781
- }
2782
- // eslint-disable-next-line consistent-return
2783
- async function convertVTreeToXML(docxDocumentInstance, vTree, xmlFragment) {
2784
- if (!vTree) {
2785
- // eslint-disable-next-line no-useless-return
2786
- return '';
2787
- }
2788
- if (Array.isArray(vTree) && vTree.length) {
2789
- // eslint-disable-next-line no-plusplus
2790
- for (let index = 0; index < vTree.length; index++) {
2791
- const vNode = vTree[index];
2792
- await convertVTreeToXML(docxDocumentInstance, vNode, xmlFragment);
2793
- }
2794
- }
2795
- else if (isVNode(vTree)) {
2796
- await findXMLEquivalent(docxDocumentInstance, vTree, xmlFragment);
2797
- }
2798
- else if (isVText(vTree)) {
2799
- buildTextElement(xmlFragment, escape(String(vTree.text)));
2800
- }
2801
- return xmlFragment;
2802
- }
2803
- async function renderDocumentFile(docxDocumentInstance) {
2804
- const vTree = convertHTML$1(docxDocumentInstance.htmlString);
2805
- const xmlFragment = fragment({ namespaceAlias: { w: namespaces.w } });
2806
- const populatedXmlFragment = await convertVTreeToXML(docxDocumentInstance, vTree, xmlFragment);
2807
- return populatedXmlFragment;
2808
- }
2809
-
2810
- /* eslint-disable import/prefer-default-export */
2811
-
2812
- class ListStyleBuilder {
2813
- // defaults is an object passed in from constants.js / numbering with the following properties:
2814
- // defaultOrderedListStyleType: 'decimal' (unless otherwise specified)
2815
- constructor(defaults) {
2816
- this.defaults = defaults || { defaultOrderedListStyleType: 'decimal' };
2817
- }
2818
- // eslint-disable-next-line class-methods-use-this
2819
- getListStyleType(listType) {
2820
- switch (listType) {
2821
- case 'upper-roman':
2822
- return 'upperRoman';
2823
- case 'lower-roman':
2824
- return 'lowerRoman';
2825
- case 'upper-alpha':
2826
- case 'upper-alpha-bracket-end':
2827
- return 'upperLetter';
2828
- case 'lower-alpha':
2829
- case 'lower-alpha-bracket-end':
2830
- return 'lowerLetter';
2831
- case 'decimal':
2832
- case 'decimal-bracket':
2833
- return 'decimal';
2834
- default:
2835
- return this.defaults.defaultOrderedListStyleType;
2836
- }
2837
- }
2838
- getListPrefixSuffix(style, lvl) {
2839
- let listType = this.defaults.defaultOrderedListStyleType;
2840
- if (style && style['list-style-type']) {
2841
- listType = style['list-style-type'];
2842
- }
2843
- switch (listType) {
2844
- case 'upper-roman':
2845
- case 'lower-roman':
2846
- case 'upper-alpha':
2847
- case 'lower-alpha':
2848
- return `%${lvl + 1}.`;
2849
- case 'upper-alpha-bracket-end':
2850
- case 'lower-alpha-bracket-end':
2851
- case 'decimal-bracket-end':
2852
- return `%${lvl + 1})`;
2853
- case 'decimal-bracket':
2854
- return `(%${lvl + 1})`;
2855
- case 'decimal':
2856
- default:
2857
- return `%${lvl + 1}.`;
2858
- }
2859
- }
2860
- }
2861
-
2862
- function generateContentTypesFragments(contentTypesXML, type, objects) {
2863
- if (objects && Array.isArray(objects)) {
2864
- objects.forEach((object) => {
2865
- const contentTypesFragment = fragment({ defaultNamespace: { ele: namespaces.contentTypes } })
2866
- .ele('Override')
2867
- .att('PartName', `/word/${type}${object[`${type}Id`]}.xml`)
2868
- .att('ContentType', `application/vnd.openxmlformats-officedocument.wordprocessingml.${type}+xml`)
2869
- .up();
2870
- contentTypesXML.root().import(contentTypesFragment);
2871
- });
2872
- }
2873
- }
2874
- function generateSectionReferenceXML(documentXML, documentSectionType, objects, isEnabled) {
2875
- if (isEnabled && objects && Array.isArray(objects) && objects.length) {
2876
- const xmlFragment = fragment();
2877
- objects.forEach(({ relationshipId, type }) => {
2878
- const objectFragment = fragment({ namespaceAlias: { w: namespaces.w, r: namespaces.r } })
2879
- .ele('@w', `${documentSectionType}Reference`)
2880
- .att('@r', 'id', `rId${relationshipId}`)
2881
- .att('@w', 'type', type)
2882
- .up();
2883
- xmlFragment.import(objectFragment);
2884
- });
2885
- documentXML.root().first().first().import(xmlFragment);
2886
- }
2887
- }
2888
- function generateXMLString(xmlString) {
2889
- const xmlDocumentString = create({ encoding: 'UTF-8', standalone: true }, xmlString);
2890
- return xmlDocumentString.toString({ prettyPrint: true });
2891
- }
2892
- async function generateSectionXML(vTree, type = 'header') {
2893
- debugger;
2894
- const sectionXML = create({
2895
- encoding: 'UTF-8',
2896
- standalone: true,
2897
- namespaceAlias: {
2898
- a: namespaces.a,
2899
- cdr: namespaces.cdr,
2900
- o: namespaces.o,
2901
- pic: namespaces.pic,
2902
- r: namespaces.r,
2903
- v: namespaces.v,
2904
- ve: namespaces.ve,
2905
- vt: namespaces.vt,
2906
- w: namespaces.w,
2907
- w10: namespaces.w10,
2908
- wp: namespaces.wp,
2909
- wne: namespaces.wne
2910
- },
2911
- }).ele('@w', type === 'header' ? 'hdr' : 'ftr');
2912
- const XMLFragment = fragment();
2913
- await convertVTreeToXML(this, vTree, XMLFragment);
2914
- if (type === 'footer' && XMLFragment.first().node.tagName === 'p' && this.pageNumber) {
2915
- XMLFragment.first().import(fragment({ namespaceAlias: { w: namespaces.w } })
2916
- .ele('@w', 'fldSimple')
2917
- .att('@w', 'instr', 'PAGE')
2918
- .ele('@w', 'r')
2919
- .up()
2920
- .up());
2921
- }
2922
- sectionXML.root().import(XMLFragment);
2923
- const referenceName = type === 'header' ? 'Header' : 'Footer';
2924
- this[`last${referenceName}Id`] += 1;
2925
- return { [`${type}Id`]: this[`last${referenceName}Id`], [`${type}XML`]: sectionXML };
2926
- }
2927
- class DocxDocument {
2928
- constructor(properties) {
2929
- this.zip = properties.zip;
2930
- this.htmlString = properties.htmlString;
2931
- this.orientation = properties.orientation;
2932
- this.pageSize = properties.pageSize || defaultDocumentOptions.pageSize;
2933
- const isPortraitOrientation = this.orientation === defaultOrientation;
2934
- const height = this.pageSize.height ? this.pageSize.height : landscapeHeight;
2935
- const width = this.pageSize.width ? this.pageSize.width : landscapeWidth;
2936
- this.width = isPortraitOrientation ? width : height;
2937
- this.height = isPortraitOrientation ? height : width;
2938
- const marginsObject = properties.margins;
2939
- this.margins =
2940
- // eslint-disable-next-line no-nested-ternary
2941
- marginsObject && Object.keys(marginsObject).length
2942
- ? marginsObject
2943
- : isPortraitOrientation
2944
- ? portraitMargins
2945
- : landscapeMargins;
2946
- this.availableDocumentSpace = this.width - this.margins.left - this.margins.right;
2947
- this.title = properties.title || '';
2948
- this.subject = properties.subject || '';
2949
- this.creator = properties.creator || applicationName;
2950
- this.keywords = properties.keywords || [applicationName];
2951
- this.description = properties.description || '';
2952
- this.lastModifiedBy = properties.lastModifiedBy || applicationName;
2953
- this.revision = properties.revision || 1;
2954
- this.createdAt = properties.createdAt || new Date();
2955
- this.modifiedAt = properties.modifiedAt || new Date();
2956
- this.headerType = properties.headerType || 'default';
2957
- this.header = properties.header || false;
2958
- this.footerType = properties.footerType || 'default';
2959
- this.footer = properties.footer || false;
2960
- this.font = properties.font || defaultFont;
2961
- this.fontSize = properties.fontSize || defaultFontSize;
2962
- this.complexScriptFontSize = properties.complexScriptFontSize || defaultFontSize;
2963
- this.tableRowCantSplit =
2964
- (properties.table && properties.table.row && properties.table.row.cantSplit) || false;
2965
- this.pageNumber = properties.pageNumber || false;
2966
- this.skipFirstHeaderFooter = properties.skipFirstHeaderFooter || false;
2967
- this.lineNumber = properties.lineNumber ? properties.lineNumberOptions : null;
2968
- this.lastNumberingId = 0;
2969
- this.lastMediaId = 0;
2970
- this.lastHeaderId = 0;
2971
- this.lastFooterId = 0;
2972
- this.stylesObjects = [];
2973
- this.numberingObjects = [];
2974
- this.relationshipFilename = documentFileName;
2975
- this.relationships = [{ fileName: documentFileName, lastRelsId: 4, rels: [] }];
2976
- this.mediaFiles = [];
2977
- this.headerObjects = [];
2978
- this.footerObjects = [];
2979
- this.documentXML = null;
2980
- this.generateContentTypesXML = this.generateContentTypesXML.bind(this);
2981
- this.generateDocumentXML = this.generateDocumentXML.bind(this);
2982
- this.generateCoreXML = this.generateCoreXML.bind(this);
2983
- this.generateSettingsXML = this.generateSettingsXML.bind(this);
2984
- this.generateWebSettingsXML = this.generateWebSettingsXML.bind(this);
2985
- this.generateStylesXML = this.generateStylesXML.bind(this);
2986
- this.generateFontTableXML = this.generateFontTableXML.bind(this);
2987
- this.generateThemeXML = this.generateThemeXML.bind(this);
2988
- this.generateNumberingXML = this.generateNumberingXML.bind(this);
2989
- this.generateRelsXML = this.generateRelsXML.bind(this);
2990
- this.createMediaFile = this.createMediaFile.bind(this);
2991
- this.createDocumentRelationships = this.createDocumentRelationships.bind(this);
2992
- this.generateHeaderXML = this.generateHeaderXML.bind(this);
2993
- this.generateFooterXML = this.generateFooterXML.bind(this);
2994
- this.generateSectionXML = generateSectionXML.bind(this);
2995
- this.ListStyleBuilder = new ListStyleBuilder(properties.numbering);
2996
- }
2997
- generateContentTypesXML() {
2998
- const contentTypesXML$1 = create({ encoding: 'UTF-8', standalone: true }, contentTypesXML);
2999
- generateContentTypesFragments(contentTypesXML$1, 'header', this.headerObjects);
3000
- generateContentTypesFragments(contentTypesXML$1, 'footer', this.footerObjects);
3001
- return contentTypesXML$1.toString({ prettyPrint: true });
3002
- }
3003
- generateDocumentXML() {
3004
- const documentXML = create({ encoding: 'UTF-8', standalone: true }, generateDocumentTemplate(this.width, this.height, this.orientation, this.margins));
3005
- // documentXML.root().first().import(this.documentXML);
3006
- generateSectionReferenceXML(documentXML, 'header', this.headerObjects, this.header);
3007
- generateSectionReferenceXML(documentXML, 'footer', this.footerObjects, this.footer);
3008
- if ((this.header || this.footer) && this.skipFirstHeaderFooter) {
3009
- documentXML
3010
- .root()
3011
- .first()
3012
- .first()
3013
- .import(fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'titlePg'));
3014
- }
3015
- if (this.lineNumber) {
3016
- const { countBy, start, restart } = this.lineNumber;
3017
- documentXML
3018
- .root()
3019
- .first()
3020
- .first()
3021
- .import(fragment({ namespaceAlias: { w: namespaces.w } })
3022
- .ele('@w', 'lnNumType')
3023
- .att('@w', 'countBy', countBy)
3024
- .att('@w', 'start', start)
3025
- .att('@w', 'restart', restart));
3026
- }
3027
- return documentXML.toString({ prettyPrint: true });
3028
- }
3029
- generateCoreXML() {
3030
- return generateXMLString(generateCoreXML(this.title, this.subject, this.creator, this.keywords, this.description, this.lastModifiedBy, this.revision, this.createdAt, this.modifiedAt));
3031
- }
3032
- // eslint-disable-next-line class-methods-use-this
3033
- generateSettingsXML() {
3034
- return generateXMLString(settingsXML);
3035
- }
3036
- // eslint-disable-next-line class-methods-use-this
3037
- generateWebSettingsXML() {
3038
- return generateXMLString(webSettingsXML);
3039
- }
3040
- generateStylesXML() {
3041
- return generateXMLString(generateStylesXML(this.font, this.fontSize, this.complexScriptFontSize));
3042
- }
3043
- // eslint-disable-next-line class-methods-use-this
3044
- generateFontTableXML() {
3045
- return generateXMLString(fontTableXML);
3046
- }
3047
- generateThemeXML() {
3048
- return generateXMLString(generateThemeXML(this.font));
3049
- }
3050
- generateNumberingXML() {
3051
- const numberingXML = create({ encoding: 'UTF-8', standalone: true }, generateNumberingXMLTemplate());
3052
- const abstractNumberingFragments = fragment();
3053
- const numberingFragments = fragment();
3054
- this.numberingObjects.forEach(({ numberingId, type, properties }) => {
3055
- const abstractNumberingFragment = fragment({ namespaceAlias: { w: namespaces.w } })
3056
- .ele('@w', 'abstractNum')
3057
- .att('@w', 'abstractNumId', String(numberingId));
3058
- [...Array(8).keys()].forEach((level) => {
3059
- const levelFragment = fragment({ namespaceAlias: { w: namespaces.w } })
3060
- .ele('@w', 'lvl')
3061
- .att('@w', 'ilvl', level)
3062
- .ele('@w', 'start')
3063
- .att('@w', 'val', type === 'ol'
3064
- ? (properties.attributes && properties.attributes['data-start']) || 1
3065
- : '1')
3066
- .up()
3067
- .ele('@w', 'numFmt')
3068
- .att('@w', 'val', type === 'ol'
3069
- ? this.ListStyleBuilder.getListStyleType(properties.style && properties.style['list-style-type'])
3070
- : 'bullet')
3071
- .up()
3072
- .ele('@w', 'lvlText')
3073
- .att('@w', 'val', type === 'ol' ? this.ListStyleBuilder.getListPrefixSuffix(properties.style, level) : '')
3074
- .up()
3075
- .ele('@w', 'lvlJc')
3076
- .att('@w', 'val', 'left')
3077
- .up()
3078
- .ele('@w', 'pPr')
3079
- .ele('@w', 'tabs')
3080
- .ele('@w', 'tab')
3081
- .att('@w', 'val', 'num')
3082
- .att('@w', 'pos', (level + 1) * 720)
3083
- .up()
3084
- .up()
3085
- .ele('@w', 'ind')
3086
- .att('@w', 'left', (level + 1) * 720)
3087
- .att('@w', 'hanging', 360)
3088
- .up()
3089
- .up()
3090
- .up();
3091
- if (type === 'ul') {
3092
- levelFragment.last().import(fragment({ namespaceAlias: { w: namespaces.w } })
3093
- .ele('@w', 'rPr')
3094
- .ele('@w', 'rFonts')
3095
- .att('@w', 'ascii', 'Symbol')
3096
- .att('@w', 'hAnsi', 'Symbol')
3097
- .att('@w', 'hint', 'default')
3098
- .up()
3099
- .up());
3100
- }
3101
- abstractNumberingFragment.import(levelFragment);
3102
- });
3103
- abstractNumberingFragment.up();
3104
- abstractNumberingFragments.import(abstractNumberingFragment);
3105
- numberingFragments.import(fragment({ namespaceAlias: { w: namespaces.w } })
3106
- .ele('@w', 'num')
3107
- .att('@w', 'numId', String(numberingId))
3108
- .ele('@w', 'abstractNumId')
3109
- .att('@w', 'val', String(numberingId))
3110
- .up()
3111
- .up());
3112
- });
3113
- numberingXML.root().import(abstractNumberingFragments);
3114
- numberingXML.root().import(numberingFragments);
3115
- return numberingXML.toString({ prettyPrint: true });
3116
- }
3117
- // eslint-disable-next-line class-methods-use-this
3118
- appendRelationships(xmlFragment, relationships) {
3119
- relationships.forEach(({ relationshipId, type, target, targetMode }) => {
3120
- xmlFragment.import(fragment({ defaultNamespace: { ele: namespaces.relationship } })
3121
- .ele('Relationship')
3122
- .att('Id', `rId${relationshipId}`)
3123
- .att('Type', type)
3124
- .att('Target', target)
3125
- .att('TargetMode', targetMode)
3126
- .up());
3127
- });
3128
- }
3129
- generateRelsXML() {
3130
- const relationshipXMLStrings = this.relationships.map(({ fileName, rels }) => {
3131
- const xmlFragment = create({ encoding: 'UTF-8', standalone: true }, fileName === documentFileName ? documentRelsXML : genericRelsXML);
3132
- this.appendRelationships(xmlFragment.root(), rels);
3133
- return { fileName, xmlString: xmlFragment.toString({ prettyPrint: true }) };
3134
- });
3135
- return relationshipXMLStrings;
3136
- }
3137
- createNumbering(type, properties) {
3138
- this.lastNumberingId += 1;
3139
- this.numberingObjects.push({ numberingId: this.lastNumberingId, type, properties });
3140
- return this.lastNumberingId;
3141
- }
3142
- createMediaFile(base64String) {
3143
- // eslint-disable-next-line no-useless-escape
3144
- const matches = base64String.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
3145
- if (matches.length !== 3) {
3146
- throw new Error('Invalid base64 string');
3147
- }
3148
- const base64FileContent = matches[2];
3149
- // matches array contains file type in base64 format - image/jpeg and base64 stringified data
3150
- const fileExtension = matches[1].match(/\/(.*?)$/)[1] === 'octet-stream' ? 'png' : matches[1].match(/\/(.*?)$/)[1];
3151
- const fileNameWithExtension = `image-${nanoid()}.${fileExtension}`;
3152
- this.lastMediaId += 1;
3153
- return { id: this.lastMediaId, fileContent: base64FileContent, fileNameWithExtension };
3154
- }
3155
- createDocumentRelationships(fileName = 'document', type, target, targetMode = 'External') {
3156
- debugger;
3157
- let relationshipObject = this.relationships.find((relationship) => relationship.fileName === fileName);
3158
- let lastRelsId = 1;
3159
- if (relationshipObject) {
3160
- lastRelsId = relationshipObject.lastRelsId + 1;
3161
- relationshipObject.lastRelsId = lastRelsId;
3162
- }
3163
- else {
3164
- relationshipObject = { fileName, lastRelsId, rels: [] };
3165
- this.relationships.push(relationshipObject);
3166
- }
3167
- let relationshipType;
3168
- switch (type) {
3169
- case hyperlinkType:
3170
- relationshipType = namespaces.hyperlinks;
3171
- break;
3172
- case imageType:
3173
- relationshipType = namespaces.images;
3174
- break;
3175
- case headerType:
3176
- relationshipType = namespaces.headers;
3177
- break;
3178
- case footerType:
3179
- relationshipType = namespaces.footers;
3180
- break;
3181
- case themeType:
3182
- relationshipType = namespaces.themes;
3183
- break;
3184
- }
3185
- relationshipObject.rels.push({
3186
- relationshipId: lastRelsId,
3187
- type: relationshipType,
3188
- target,
3189
- targetMode,
3190
- });
3191
- console.log(fileName);
3192
- console.log(relationshipObject.rels);
3193
- return lastRelsId;
3194
- }
3195
- generateHeaderXML(vTree) {
3196
- return this.generateSectionXML(vTree, 'header');
3197
- }
3198
- generateFooterXML(vTree) {
3199
- return this.generateSectionXML(vTree, 'footer');
3200
- }
3201
- }
3202
-
3203
- const defaultMargins = {
3204
- top: 1440,
3205
- right: 1440,
3206
- bottom: 1440,
3207
- left: 1440,
3208
- header: 720,
3209
- footer: 720,
3210
- gutter: 0,
3211
- };
3212
- const documentTemplate = (width, height, orient, margins) => {
3213
- return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
3214
- <w:document
3215
- xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
3216
- xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
3217
- xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
3218
- xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
3219
- xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
3220
- xmlns:ns6="http://schemas.openxmlformats.org/schemaLibrary/2006/main"
3221
- xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"
3222
- xmlns:ns8="http://schemas.openxmlformats.org/drawingml/2006/chartDrawing"
3223
- xmlns:dgm="http://schemas.openxmlformats.org/drawingml/2006/diagram"
3224
- xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
3225
- xmlns:ns11="http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"
3226
- xmlns:dsp="http://schemas.microsoft.com/office/drawing/2008/diagram"
3227
- xmlns:ns13="urn:schemas-microsoft-com:office:excel"
3228
- xmlns:o="urn:schemas-microsoft-com:office:office"
3229
- xmlns:v="urn:schemas-microsoft-com:vml"
3230
- xmlns:w10="urn:schemas-microsoft-com:office:word"
3231
- xmlns:ns17="urn:schemas-microsoft-com:office:powerpoint"
3232
- xmlns:odx="http://opendope.org/xpaths"
3233
- xmlns:odc="http://opendope.org/conditions"
3234
- xmlns:odq="http://opendope.org/questions"
3235
- xmlns:odi="http://opendope.org/components"
3236
- xmlns:odgm="http://opendope.org/SmartArt/DataHierarchy"
3237
- xmlns:ns24="http://schemas.openxmlformats.org/officeDocument/2006/bibliography"
3238
- xmlns:ns25="http://schemas.openxmlformats.org/drawingml/2006/compatibility"
3239
- xmlns:ns26="http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas">
3240
- <w:body>
3241
- <w:altChunk r:id="htmlChunk" />
3242
- <w:sectPr>
3243
- <w:pgSz w:w="${width}" w:h="${height}" w:orient="${orient}" />
3244
- <w:pgMar w:top="${margins.top}"
3245
- w:right="${margins.right}"
3246
- w:bottom="${margins.bottom}"
3247
- w:left="${margins.left}"
3248
- w:header="${margins.header}"
3249
- w:footer="${margins.footer}"
3250
- w:gutter="${margins.gutter}"/>
3251
- </w:sectPr>
3252
- </w:body>
3253
- </w:document>
3254
- `;
3255
- };
3256
-
3257
- const mhtDocumentTemplate = (htmlSource, contentParts) => {
3258
- debugger;
3259
- return `MIME-Version: 1.0
3260
- Content-Type: multipart/related;
3261
- type="text/html";
3262
- boundary="----=mhtDocumentPart"
3263
-
3264
-
3265
- ------=mhtDocumentPart
3266
- Content-Type: text/html;
3267
- charset="utf-8"
3268
- Content-Transfer-Encoding: quoted-printable
3269
- Content-Location: file:///C:/fake/document.html
3270
-
3271
- ${htmlSource}
3272
-
3273
- ${contentParts}
3274
-
3275
- ------=mhtDocumentPart--
3276
- `;
3277
- };
3278
-
3279
- const mhtPartTemplate = (contentType, contentEncoding, contentLocation, encodedContent) => {
3280
- return `------=mhtDocumentPart
3281
- Content-Type: ${contentType}
3282
- Content-Transfer-Encoding: ${contentEncoding}
3283
- Content-Location: ${contentLocation}
3284
-
3285
- ${encodedContent}
3286
- `;
3287
- };
3288
-
3289
- function getMHTdocument(htmlSource) {
3290
- debugger;
3291
- const ref = _prepareImageParts(htmlSource);
3292
- const imageContentPartsString = ref.imageContentParts.join('\n');
3293
- htmlSource = ref.htmlSource.replace(/\=/g, '=3D');
3294
- return mhtDocumentTemplate(htmlSource, imageContentPartsString);
3295
- }
3296
- function _prepareImageParts(htmlSource) {
3297
- debugger;
3298
- const imageContentParts = [];
3299
- const inlinedSrcPattern = /"data:(\w+\/\w+);(\w+),(\S+)"/g;
3300
- const inlinedReplacer = (match, contentType, contentEncoding, encodedContent) => {
3301
- const index = imageContentParts.length;
3302
- const extension = contentType.split('/')[1];
3303
- const contentLocation = `file:///C:/fake/image${index}.${extension}`;
3304
- imageContentParts.push(mhtPartTemplate(contentType, contentEncoding, contentLocation, encodedContent));
3305
- return `\"${contentLocation}\"`;
3306
- };
3307
- if (!/<img/g.test(htmlSource)) {
3308
- return { htmlSource, imageContentParts };
3309
- }
3310
- htmlSource = htmlSource.replace(inlinedSrcPattern, inlinedReplacer);
3311
- return { htmlSource, imageContentParts };
3312
- }
3313
-
3314
- const convertHTML = HTMLToVDOM({
3315
- VNode: VNode$1,
3316
- VText,
3317
- });
3318
- const mergeOptions = (options, patch) => ({ ...options, ...patch });
3319
- const fixupFontSize = (fontSize) => {
3320
- let normalizedFontSize;
3321
- if (pointRegex.test(fontSize)) {
3322
- const matchedParts = fontSize.match(pointRegex);
3323
- normalizedFontSize = pointToHIP(matchedParts[1]);
3324
- }
3325
- else if (fontSize) {
3326
- // assuming it is already in HIP
3327
- normalizedFontSize = fontSize;
3328
- }
3329
- else {
3330
- normalizedFontSize = null;
3331
- }
3332
- return normalizedFontSize;
3333
- };
3334
- const normalizeUnits = (dimensioningObject, defaultDimensionsProperty) => {
3335
- let normalizedUnitResult = {};
3336
- if (typeof dimensioningObject === 'object' && dimensioningObject !== null) {
3337
- Object.keys(dimensioningObject).forEach((key) => {
3338
- if (pixelRegex.test(dimensioningObject[key])) {
3339
- const matchedParts = dimensioningObject[key].match(pixelRegex);
3340
- normalizedUnitResult[key] = pixelToTWIP(matchedParts[1]);
3341
- }
3342
- else if (cmRegex.test(dimensioningObject[key])) {
3343
- const matchedParts = dimensioningObject[key].match(cmRegex);
3344
- normalizedUnitResult[key] = cmToTWIP(matchedParts[1]);
3345
- }
3346
- else if (inchRegex.test(dimensioningObject[key])) {
3347
- const matchedParts = dimensioningObject[key].match(inchRegex);
3348
- normalizedUnitResult[key] = inchToTWIP(matchedParts[1]);
3349
- }
3350
- else if (dimensioningObject[key]) {
3351
- normalizedUnitResult[key] = dimensioningObject[key];
3352
- }
3353
- else {
3354
- // incase value is something like 0
3355
- normalizedUnitResult[key] = defaultDimensionsProperty[key];
3356
- }
3357
- });
3358
- }
3359
- else {
3360
- // eslint-disable-next-line no-param-reassign
3361
- normalizedUnitResult = null;
3362
- }
3363
- return normalizedUnitResult;
3364
- };
3365
- const normalizeDocumentOptions = (documentOptions) => {
3366
- const normalizedDocumentOptions = { ...documentOptions };
3367
- Object.keys(documentOptions).forEach((key) => {
3368
- // eslint-disable-next-line default-case
3369
- switch (key) {
3370
- case 'pageSize':
3371
- case 'margins':
3372
- normalizedDocumentOptions[key] = normalizeUnits(documentOptions[key], defaultDocumentOptions[key]);
3373
- break;
3374
- case 'fontSize':
3375
- case 'complexScriptFontSize':
3376
- normalizedDocumentOptions[key] = fixupFontSize(documentOptions[key]);
3377
- break;
3378
- }
3379
- });
3380
- return normalizedDocumentOptions;
3381
- };
3382
- // Ref: https://en.wikipedia.org/wiki/Office_Open_XML_file_formats
3383
- // http://officeopenxml.com/anatomyofOOXML.php
3384
- async function addFilesToContainer(zip, htmlString, suppliedDocumentOptions, headerHTMLString, footerHTMLString) {
3385
- debugger;
3386
- const normalizedDocumentOptions = normalizeDocumentOptions(suppliedDocumentOptions);
3387
- const documentOptions = mergeOptions(defaultDocumentOptions, normalizedDocumentOptions);
3388
- if (documentOptions.header && !headerHTMLString) {
3389
- // eslint-disable-next-line no-param-reassign
3390
- headerHTMLString = defaultHTMLString;
3391
- }
3392
- if (documentOptions.footer && !footerHTMLString) {
3393
- // eslint-disable-next-line no-param-reassign
3394
- footerHTMLString = defaultHTMLString;
3395
- }
3396
- const docxDocument = new DocxDocument({ zip, htmlString, ...documentOptions });
3397
- // Conversion to Word XML happens here
3398
- docxDocument.documentXML = await renderDocumentFile(docxDocument);
3399
- debugger;
3400
- zip
3401
- .folder(relsFolderName)
3402
- .file('.rels', create({ encoding: 'UTF-8', standalone: true }, relsXML).toString({ prettyPrint: true }), { createFolders: false });
3403
- zip.folder('docProps').file('core.xml', docxDocument.generateCoreXML(), {
3404
- createFolders: false,
3405
- });
3406
- if (docxDocument.header && headerHTMLString) {
3407
- const vTree = convertHTML(headerHTMLString);
3408
- docxDocument.relationshipFilename = headerFileName;
3409
- const { headerId, headerXML } = await docxDocument.generateHeaderXML(vTree);
3410
- docxDocument.relationshipFilename = documentFileName;
3411
- const fileNameWithExt = `${headerType}${headerId}.xml`;
3412
- const relationshipId = docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, headerType, fileNameWithExt, internalRelationship);
3413
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateHeader.toString({ prettyPrint: true }), {
3414
- createFolders: false,
3415
- });
3416
- docxDocument.headerObjects.push({ headerId, relationshipId, type: docxDocument.headerType });
3417
- }
3418
- if (docxDocument.footer && footerHTMLString) {
3419
- const vTree = convertHTML(footerHTMLString);
3420
- docxDocument.relationshipFilename = footerFileName;
3421
- const { footerId, footerXML } = await docxDocument.generateFooterXML(vTree);
3422
- docxDocument.relationshipFilename = documentFileName;
3423
- const fileNameWithExt = `${footerType}${footerId}.xml`;
3424
- const relationshipId = docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, footerType, fileNameWithExt, internalRelationship);
3425
- console.log(footerXML.toString({ prettyPrint: true }));
3426
- if (suppliedDocumentOptions.pageNumber)
3427
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateFooter.toString({ prettyPrint: true }), {
3428
- createFolders: false,
3429
- });
3430
- else
3431
- zip.folder(wordFolder).file(fileNameWithExt, generateDocumentTemplateFooterWithoutPaging.toString({ prettyPrint: true }), {
3432
- createFolders: false,
3433
- });
3434
- docxDocument.footerObjects.push({ footerId, relationshipId, type: docxDocument.footerType });
3435
- }
3436
- const themeFileNameWithExt = `${themeFileName}.xml`;
3437
- docxDocument.createDocumentRelationships(docxDocument.relationshipFilename, themeType, `${themeFolder}/${themeFileNameWithExt}`, internalRelationship);
3438
- zip
3439
- .folder(wordFolder)
3440
- .folder(themeFolder)
3441
- .file(themeFileNameWithExt, docxDocument.generateThemeXML(), {
3442
- createFolders: false,
3443
- });
3444
- zip
3445
- .folder(wordFolder)
3446
- .file('document.xml', docxDocument.generateDocumentXML(), { createFolders: false })
3447
- .file('afchunk.mht', getMHTdocument(htmlString), {
3448
- createFolders: false,
3449
- })
3450
- .file('afchunkheader.mht', getMHTdocument(headerHTMLString), {
3451
- createFolders: false,
3452
- })
3453
- .file('afchunkfooter.mht', getMHTdocument(footerHTMLString), {
3454
- createFolders: false,
3455
- })
3456
- .file('fontTable.xml', docxDocument.generateFontTableXML(), { createFolders: false })
3457
- .file('styles.xml', docxDocument.generateStylesXML(), { createFolders: false })
3458
- .file('numbering.xml', docxDocument.generateNumberingXML(), { createFolders: false })
3459
- .file('settings.xml', docxDocument.generateSettingsXML(), { createFolders: false })
3460
- .file('webSettings.xml', docxDocument.generateWebSettingsXML(), { createFolders: false });
3461
- const relationshipXMLs = docxDocument.generateRelsXML();
3462
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
3463
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
3464
- console.log(xmlString);
3465
- zip.folder(wordFolder).folder(relsFolderName).file(`${fileName}.xml.rels`, xmlString, {
3466
- createFolders: false,
3467
- });
3468
- });
3469
- }
3470
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
3471
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
3472
- zip.folder(wordFolder).folder(relsFolderName).file(`header1.xml.rels`, xmlString, {
3473
- createFolders: false,
3474
- });
3475
- });
3476
- }
3477
- if (relationshipXMLs && Array.isArray(relationshipXMLs)) {
3478
- relationshipXMLs.forEach(({ fileName, xmlString }) => {
3479
- zip.folder(wordFolder).folder(relsFolderName).file(`footer1.xml.rels`, xmlString, {
3480
- createFolders: false,
3481
- });
3482
- });
3483
- }
3484
- zip.file('[Content_Types].xml', docxDocument.generateContentTypesXML(), { createFolders: false });
3485
- return zip;
3486
- }
3487
-
3488
- /* eslint-disable no-useless-escape */
3489
- const minifyHTMLString = (htmlString) => {
3490
- try {
3491
- if (typeof htmlString === 'string' || htmlString instanceof String) {
3492
- const minifiedHTMLString = htmlString
3493
- .replace(/\n/g, ' ')
3494
- .replace(/\r/g, ' ')
3495
- .replace(/\r\n/g, ' ')
3496
- .replace(/[\t]+\</g, '<')
3497
- .replace(/\>[\t ]+\</g, '><')
3498
- .replace(/\>[\t ]+$/g, '>');
3499
- return minifiedHTMLString;
3500
- }
3501
- throw new Error('invalid html string');
3502
- }
3503
- catch (error) {
3504
- return null;
3505
- }
3506
- };
3507
- async function generateContainer(htmlString, headerHTMLString, documentOptions = {}, footerHTMLString) {
3508
- const zip = new JSZip();
3509
- let contentHTML = htmlString;
3510
- let headerHTML = headerHTMLString;
3511
- let footerHTML = footerHTMLString;
3512
- if (htmlString) {
3513
- contentHTML = minifyHTMLString(contentHTML);
3514
- }
3515
- if (headerHTMLString) {
3516
- headerHTML = minifyHTMLString(headerHTML);
3517
- }
3518
- if (footerHTMLString) {
3519
- footerHTML = minifyHTMLString(footerHTML);
3520
- }
3521
- await addFilesToContainer(zip, contentHTML, documentOptions, headerHTML, footerHTML);
3522
- const buffer = await zip.generateAsync({ type: 'arraybuffer' });
3523
- if (Object.prototype.hasOwnProperty.call(global, 'Buffer')) {
3524
- return Buffer.from(new Uint8Array(buffer));
3525
- }
3526
- if (Object.prototype.hasOwnProperty.call(global, 'Blob')) {
3527
- // eslint-disable-next-line no-undef
3528
- return new Blob([buffer], {
3529
- type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
3530
- });
3531
- }
3532
- throw new Error('Add blob support using a polyfill eg https://github.com/bjornstar/blob-polyfill');
3533
- }
3534
-
3535
- export { generateContainer };
3536
- //# sourceMappingURL=bnsights-bbsf-utilities-index-C3Twnewr.mjs.map