@bnsights/bbsf-utilities 1.0.36 → 1.0.37

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 (171) hide show
  1. package/README.md +4 -0
  2. package/bnsights-bbsf-utilities.d.ts +4 -0
  3. package/bnsights-bbsf-utilities.metadata.json +1 -0
  4. package/bundles/bnsights-bbsf-utilities.umd.js +4870 -0
  5. package/bundles/bnsights-bbsf-utilities.umd.js.map +1 -0
  6. package/esm2015/bnsights-bbsf-utilities.js +5 -0
  7. package/esm2015/lib/bbsf-utilities.module.js +52 -0
  8. package/esm2015/lib/shared/authentication/auth.service.js +234 -0
  9. package/esm2015/lib/shared/config/environment.js +12 -0
  10. package/esm2015/lib/shared/config/word/constants.js +105 -0
  11. package/esm2015/lib/shared/config/word/docx-document.js +351 -0
  12. package/esm2015/lib/shared/config/word/helpers/index.js +4 -0
  13. package/esm2015/lib/shared/config/word/helpers/render-document-file.js +278 -0
  14. package/esm2015/lib/shared/config/word/helpers/xml-builder.js +1765 -0
  15. package/esm2015/lib/shared/config/word/html-to-docx.js +195 -0
  16. package/esm2015/lib/shared/config/word/index.js +55 -0
  17. package/esm2015/lib/shared/config/word/namespaces.js +37 -0
  18. package/esm2015/lib/shared/config/word/schemas/content-types.js +26 -0
  19. package/esm2015/lib/shared/config/word/schemas/core.js +29 -0
  20. package/esm2015/lib/shared/config/word/schemas/document-rels.js +16 -0
  21. package/esm2015/lib/shared/config/word/schemas/document.template.js +109 -0
  22. package/esm2015/lib/shared/config/word/schemas/font-table.js +40 -0
  23. package/esm2015/lib/shared/config/word/schemas/generic-rels.js +11 -0
  24. package/esm2015/lib/shared/config/word/schemas/index.js +13 -0
  25. package/esm2015/lib/shared/config/word/schemas/numbering.js +19 -0
  26. package/esm2015/lib/shared/config/word/schemas/rels.js +11 -0
  27. package/esm2015/lib/shared/config/word/schemas/settings.js +13 -0
  28. package/esm2015/lib/shared/config/word/schemas/styles.js +149 -0
  29. package/esm2015/lib/shared/config/word/schemas/theme.js +200 -0
  30. package/esm2015/lib/shared/config/word/schemas/web-settings.js +9 -0
  31. package/esm2015/lib/shared/config/word/utils/color-conversion.js +60 -0
  32. package/esm2015/lib/shared/config/word/utils/list.js +51 -0
  33. package/esm2015/lib/shared/config/word/utils/unit-conversion.js +30 -0
  34. package/esm2015/lib/shared/config/word/utils/url.js +9 -0
  35. package/esm2015/lib/shared/config/word/utils/vnode.js +3 -0
  36. package/esm2015/lib/shared/config/word/word-work/templates/documentTemplate.js +54 -0
  37. package/esm2015/lib/shared/config/word/word-work/templates/index.js +4 -0
  38. package/esm2015/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.js +22 -0
  39. package/esm2015/lib/shared/config/word/word-work/templates/mhtPartTemplate.js +10 -0
  40. package/esm2015/lib/shared/config/word/word-work/utils.js +26 -0
  41. package/esm2015/lib/shared/models/AreaModel.js +3 -0
  42. package/esm2015/lib/shared/models/ErrorModel.js +3 -0
  43. package/esm2015/lib/shared/models/RequestOptionsModel.js +11 -0
  44. package/esm2015/lib/shared/models/WordDocumentModel.js +8 -0
  45. package/esm2015/lib/shared/services/AppearanceConfiguration.service.js +37 -0
  46. package/esm2015/lib/shared/services/configuration.service.js +26 -0
  47. package/esm2015/lib/shared/services/controlvalidation.service.js +175 -0
  48. package/esm2015/lib/shared/services/environment.service.js +48 -0
  49. package/esm2015/lib/shared/services/masterlayout.service.js +96 -0
  50. package/esm2015/lib/shared/services/requesthandler.service.js +206 -0
  51. package/esm2015/lib/shared/services/stylesbundle.service.js +56 -0
  52. package/esm2015/lib/shared/services/translate.service.js +13 -0
  53. package/esm2015/lib/shared/services/translationresolver.service.js +20 -0
  54. package/esm2015/lib/shared/services/utility.service.js +96 -0
  55. package/esm2015/lib/shared/services/word-document.service.js +39 -0
  56. package/esm2015/public-api.js +20 -0
  57. package/fesm2015/bnsights-bbsf-utilities.js +4639 -0
  58. package/fesm2015/bnsights-bbsf-utilities.js.map +1 -0
  59. package/lib/bbsf-utilities.module.d.ts +6 -0
  60. package/lib/shared/authentication/auth.service.d.ts +41 -0
  61. package/lib/shared/config/environment.d.ts +1 -0
  62. package/lib/shared/config/word/constants.d.ts +124 -0
  63. package/lib/shared/config/word/docx-document.d.ts +73 -0
  64. package/lib/shared/config/word/helpers/index.d.ts +1 -0
  65. package/lib/shared/config/word/helpers/render-document-file.d.ts +4 -0
  66. package/lib/shared/config/word/helpers/xml-builder.d.ts +14 -0
  67. package/lib/shared/config/word/html-to-docx.d.ts +1 -0
  68. package/lib/shared/config/word/index.d.ts +1 -0
  69. package/lib/shared/config/word/namespaces.d.ts +36 -0
  70. package/lib/shared/config/word/schemas/content-types.d.ts +1 -0
  71. package/lib/shared/config/word/schemas/core.d.ts +1 -0
  72. package/lib/shared/config/word/schemas/document-rels.d.ts +1 -0
  73. package/lib/shared/config/word/schemas/document.template.d.ts +4 -0
  74. package/lib/shared/config/word/schemas/font-table.d.ts +1 -0
  75. package/lib/shared/config/word/schemas/generic-rels.d.ts +1 -0
  76. package/lib/shared/config/word/schemas/index.d.ts +12 -0
  77. package/lib/shared/config/word/schemas/numbering.d.ts +1 -0
  78. package/lib/shared/config/word/schemas/rels.d.ts +1 -0
  79. package/lib/shared/config/word/schemas/settings.d.ts +1 -0
  80. package/lib/shared/config/word/schemas/styles.d.ts +1 -0
  81. package/lib/shared/config/word/schemas/theme.d.ts +1 -0
  82. package/lib/shared/config/word/schemas/web-settings.d.ts +1 -0
  83. package/lib/shared/config/word/utils/color-conversion.d.ts +7 -0
  84. package/lib/shared/config/word/utils/list.d.ts +6 -0
  85. package/lib/shared/config/word/utils/unit-conversion.d.ts +29 -0
  86. package/lib/shared/config/word/utils/url.d.ts +1 -0
  87. package/lib/shared/config/word/utils/vnode.d.ts +1 -0
  88. package/lib/shared/config/word/word-work/templates/documentTemplate.d.ts +12 -0
  89. package/lib/shared/config/word/word-work/templates/index.d.ts +3 -0
  90. package/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.d.ts +1 -0
  91. package/lib/shared/config/word/word-work/templates/mhtPartTemplate.d.ts +1 -0
  92. package/lib/shared/config/word/word-work/utils.d.ts +1 -0
  93. package/lib/shared/models/AreaModel.d.ts +4 -0
  94. package/{src/lib/shared/models/ErrorModel.ts → lib/shared/models/ErrorModel.d.ts} +2 -5
  95. package/lib/shared/models/RequestOptionsModel.d.ts +11 -0
  96. package/lib/shared/models/WordDocumentModel.d.ts +16 -0
  97. package/lib/shared/services/AppearanceConfiguration.service.d.ts +11 -0
  98. package/lib/shared/services/configuration.service.d.ts +7 -0
  99. package/lib/shared/services/controlvalidation.service.d.ts +20 -0
  100. package/lib/shared/services/environment.service.d.ts +13 -0
  101. package/lib/shared/services/masterlayout.service.d.ts +24 -0
  102. package/lib/shared/services/requesthandler.service.d.ts +32 -0
  103. package/lib/shared/services/stylesbundle.service.d.ts +9 -0
  104. package/lib/shared/services/translate.service.d.ts +3 -0
  105. package/lib/shared/services/translationresolver.service.d.ts +8 -0
  106. package/lib/shared/services/utility.service.d.ts +21 -0
  107. package/lib/shared/services/word-document.service.d.ts +5 -0
  108. package/package.json +28 -20
  109. package/public-api.d.ts +16 -0
  110. package/karma.conf.js +0 -44
  111. package/ng-package.json +0 -10
  112. package/src/lib/bbsf-utilities.module.ts +0 -52
  113. package/src/lib/shared/authentication/auth.service.ts +0 -242
  114. package/src/lib/shared/config/environment.ts +0 -16
  115. package/src/lib/shared/config/word/constants.js +0 -133
  116. package/src/lib/shared/config/word/docx-document.js +0 -482
  117. package/src/lib/shared/config/word/helpers/index.js +0 -3
  118. package/src/lib/shared/config/word/helpers/render-document-file.js +0 -334
  119. package/src/lib/shared/config/word/helpers/xml-builder.js +0 -2165
  120. package/src/lib/shared/config/word/html-to-docx.js +0 -259
  121. package/src/lib/shared/config/word/index.js +0 -63
  122. package/src/lib/shared/config/word/namespaces.js +0 -40
  123. package/src/lib/shared/config/word/schemas/content-types.js +0 -26
  124. package/src/lib/shared/config/word/schemas/core.js +0 -44
  125. package/src/lib/shared/config/word/schemas/document-rels.js +0 -17
  126. package/src/lib/shared/config/word/schemas/document.template.js +0 -119
  127. package/src/lib/shared/config/word/schemas/font-table.js +0 -41
  128. package/src/lib/shared/config/word/schemas/generic-rels.js +0 -11
  129. package/src/lib/shared/config/word/schemas/index.js +0 -12
  130. package/src/lib/shared/config/word/schemas/numbering.js +0 -18
  131. package/src/lib/shared/config/word/schemas/rels.js +0 -12
  132. package/src/lib/shared/config/word/schemas/settings.js +0 -14
  133. package/src/lib/shared/config/word/schemas/styles.js +0 -152
  134. package/src/lib/shared/config/word/schemas/theme.js +0 -199
  135. package/src/lib/shared/config/word/schemas/web-settings.js +0 -10
  136. package/src/lib/shared/config/word/utils/color-conversion.js +0 -60
  137. package/src/lib/shared/config/word/utils/list.js +0 -55
  138. package/src/lib/shared/config/word/utils/unit-conversion.js +0 -53
  139. package/src/lib/shared/config/word/utils/url.js +0 -8
  140. package/src/lib/shared/config/word/utils/vnode.js +0 -3
  141. package/src/lib/shared/config/word/word-work/assets/contentTypesXml.ts +0 -1
  142. package/src/lib/shared/config/word/word-work/assets/documentXmlRels.ts +0 -1
  143. package/src/lib/shared/config/word/word-work/assets/index.ts +0 -3
  144. package/src/lib/shared/config/word/word-work/assets/relsXml.ts +0 -1
  145. package/src/lib/shared/config/word/word-work/index.ts +0 -8
  146. package/src/lib/shared/config/word/word-work/internal.ts +0 -69
  147. package/src/lib/shared/config/word/word-work/templates/documentTemplate.ts +0 -58
  148. package/src/lib/shared/config/word/word-work/templates/index.ts +0 -3
  149. package/src/lib/shared/config/word/word-work/templates/mhtDocumentTemplate.ts +0 -21
  150. package/src/lib/shared/config/word/word-work/templates/mhtPartTemplate.ts +0 -14
  151. package/src/lib/shared/config/word/word-work/utils.ts +0 -27
  152. package/src/lib/shared/models/AreaModel.ts +0 -5
  153. package/src/lib/shared/models/RequestOptionsModel.ts +0 -13
  154. package/src/lib/shared/models/WordDocumentModel.ts +0 -19
  155. package/src/lib/shared/services/AppearanceConfiguration.service.ts +0 -30
  156. package/src/lib/shared/services/configuration.service.ts +0 -18
  157. package/src/lib/shared/services/controlvalidation.service.ts +0 -194
  158. package/src/lib/shared/services/environment.service.ts +0 -56
  159. package/src/lib/shared/services/masterlayout.service.ts +0 -89
  160. package/src/lib/shared/services/requesthandler.service.ts +0 -241
  161. package/src/lib/shared/services/stylesbundle.service.ts +0 -52
  162. package/src/lib/shared/services/translate.service.ts +0 -8
  163. package/src/lib/shared/services/translationresolver.service.ts +0 -16
  164. package/src/lib/shared/services/utility.service.ts +0 -94
  165. package/src/lib/shared/services/word-document.service.ts +0 -36
  166. package/src/public-api.ts +0 -27
  167. package/src/test.ts +0 -26
  168. package/tsconfig.lib.json +0 -39
  169. package/tsconfig.lib.prod.json +0 -11
  170. package/tsconfig.spec.json +0 -17
  171. package/tslint.json +0 -17
@@ -1,2165 +0,0 @@
1
- /* eslint-disable no-await-in-loop */
2
- /* eslint-disable radix */
3
- /* eslint-disable no-param-reassign */
4
- /* eslint-disable no-case-declarations */
5
- /* eslint-disable no-plusplus */
6
- /* eslint-disable no-else-return */
7
- import { fragment } from 'xmlbuilder2';
8
- import isVNode from 'virtual-dom/vnode/is-vnode';
9
- import isVText from 'virtual-dom/vnode/is-vtext';
10
- import colorNames from 'color-name';
11
- import { cloneDeep } from 'lodash';
12
- import imageToBase64 from 'image-to-base64';
13
- import mimeTypes from 'mime-types';
14
- import sizeOf from 'image-size';
15
-
16
- import namespaces from '../namespaces';
17
- import {
18
- rgbToHex,
19
- hslToHex,
20
- hslRegex,
21
- rgbRegex,
22
- hexRegex,
23
- hex3Regex,
24
- hex3ToHex,
25
- } from '../utils/color-conversion';
26
- import {
27
- pixelToEMU,
28
- pixelRegex,
29
- TWIPToEMU,
30
- percentageRegex,
31
- pointRegex,
32
- pointToHIP,
33
- HIPToTWIP,
34
- pointToTWIP,
35
- pixelToHIP,
36
- pixelToTWIP,
37
- pixelToEIP,
38
- pointToEIP,
39
- cmToTWIP,
40
- cmRegex,
41
- inchRegex,
42
- inchToTWIP,
43
- } from '../utils/unit-conversion';
44
- // FIXME: remove the cyclic dependency
45
- // eslint-disable-next-line import/no-cycle
46
- import { buildImage, buildList } from './render-document-file';
47
- import {
48
- defaultFont,
49
- hyperlinkType,
50
- paragraphBordersObject,
51
- colorlessColors,
52
- verticalAlignValues,
53
- imageType,
54
- internalRelationship,
55
- } from '../constants';
56
- import { vNodeHasChildren } from '../utils/vnode';
57
- import { isValidUrl } from '../utils/url';
58
-
59
- // eslint-disable-next-line consistent-return
60
- const fixupColorCode = (colorCodeString) => {
61
- if (Object.prototype.hasOwnProperty.call(colorNames, colorCodeString.toLowerCase())) {
62
- const [red, green, blue] = colorNames[colorCodeString.toLowerCase()];
63
-
64
- return rgbToHex(red, green, blue);
65
- } else if (rgbRegex.test(colorCodeString)) {
66
- const matchedParts = colorCodeString.match(rgbRegex);
67
- const red = matchedParts[1];
68
- const green = matchedParts[2];
69
- const blue = matchedParts[3];
70
-
71
- return rgbToHex(red, green, blue);
72
- } else if (hslRegex.test(colorCodeString)) {
73
- const matchedParts = colorCodeString.match(hslRegex);
74
- const hue = matchedParts[1];
75
- const saturation = matchedParts[2];
76
- const luminosity = matchedParts[3];
77
-
78
- return hslToHex(hue, saturation, luminosity);
79
- } else if (hexRegex.test(colorCodeString)) {
80
- const matchedParts = colorCodeString.match(hexRegex);
81
-
82
- return matchedParts[1];
83
- } else if (hex3Regex.test(colorCodeString)) {
84
- const matchedParts = colorCodeString.match(hex3Regex);
85
- const red = matchedParts[1];
86
- const green = matchedParts[2];
87
- const blue = matchedParts[3];
88
-
89
- return hex3ToHex(red, green, blue);
90
- } else {
91
- return '000000';
92
- }
93
- };
94
-
95
- const buildRunFontFragment = (fontName = defaultFont) =>
96
- fragment({ namespaceAlias: { w: namespaces.w } })
97
- .ele('@w', 'rFonts')
98
- .att('@w', 'ascii', fontName)
99
- .att('@w', 'hAnsi', fontName)
100
- .up();
101
-
102
- const buildRunStyleFragment = (type = 'Hyperlink') =>
103
- fragment({ namespaceAlias: { w: namespaces.w } })
104
- .ele('@w', 'rStyle')
105
- .att('@w', 'val', type)
106
- .up();
107
-
108
- const buildTableRowHeight = (tableRowHeight) =>
109
- fragment({ namespaceAlias: { w: namespaces.w } })
110
- .ele('@w', 'trHeight')
111
- .att('@w', 'val', tableRowHeight)
112
- .att('@w', 'hRule', 'atLeast')
113
- .up();
114
-
115
- const buildVerticalAlignment = (verticalAlignment) => {
116
- if (verticalAlignment.toLowerCase() === 'middle') {
117
- verticalAlignment = 'center';
118
- }
119
-
120
- return fragment({ namespaceAlias: { w: namespaces.w } })
121
- .ele('@w', 'vAlign')
122
- .att('@w', 'val', verticalAlignment)
123
- .up();
124
- };
125
-
126
- const buildVerticalMerge = (verticalMerge = 'continue') =>
127
- fragment({ namespaceAlias: { w: namespaces.w } })
128
- .ele('@w', 'vMerge')
129
- .att('@w', 'val', verticalMerge)
130
- .up();
131
-
132
- const buildColor = (colorCode) =>
133
- fragment({ namespaceAlias: { w: namespaces.w } })
134
- .ele('@w', 'color')
135
- .att('@w', 'val', colorCode)
136
- .up();
137
-
138
- const buildFontSize = (fontSize) =>
139
- fragment({ namespaceAlias: { w: namespaces.w } })
140
- .ele('@w', 'sz')
141
- .att('@w', 'val', fontSize)
142
- .up();
143
-
144
- const buildShading = (colorCode) =>
145
- fragment({ namespaceAlias: { w: namespaces.w } })
146
- .ele('@w', 'shd')
147
- .att('@w', 'val', 'clear')
148
- .att('@w', 'fill', colorCode)
149
- .up();
150
-
151
- const buildHighlight = (color = 'yellow') =>
152
- fragment({ namespaceAlias: { w: namespaces.w } })
153
- .ele('@w', 'highlight')
154
- .att('@w', 'val', color)
155
- .up();
156
-
157
- const buildVertAlign = (type = 'baseline') =>
158
- fragment({ namespaceAlias: { w: namespaces.w } })
159
- .ele('@w', 'vertAlign')
160
- .att('@w', 'val', type)
161
- .up();
162
-
163
- const buildStrike = () =>
164
- fragment({ namespaceAlias: { w: namespaces.w } })
165
- .ele('@w', 'strike')
166
- .att('@w', 'val', true)
167
- .up();
168
-
169
- const buildBold = () =>
170
- fragment({ namespaceAlias: { w: namespaces.w } })
171
- .ele('@w', 'b')
172
- .up();
173
-
174
- const buildItalics = () =>
175
- fragment({ namespaceAlias: { w: namespaces.w } })
176
- .ele('@w', 'i')
177
- .up();
178
-
179
- const buildUnderline = (type = 'single') =>
180
- fragment({ namespaceAlias: { w: namespaces.w } })
181
- .ele('@w', 'u')
182
- .att('@w', 'val', type)
183
- .up();
184
-
185
- const buildLineBreak = (type = 'textWrapping') =>
186
- fragment({ namespaceAlias: { w: namespaces.w } })
187
- .ele('@w', 'br')
188
- .att('@w', 'type', type)
189
- .up();
190
-
191
- const buildBorder = (
192
- borderSide = 'top',
193
- borderSize = 0,
194
- borderSpacing = 0,
195
- borderColor = fixupColorCode('black'),
196
- borderStroke = 'single'
197
- ) =>
198
- fragment({ namespaceAlias: { w: namespaces.w } })
199
- .ele('@w', borderSide)
200
- .att('@w', 'val', borderStroke)
201
- .att('@w', 'sz', borderSize)
202
- .att('@w', 'space', borderSpacing)
203
- .att('@w', 'color', borderColor)
204
- .up();
205
-
206
- const buildTextElement = (text) =>
207
- fragment({ namespaceAlias: { w: namespaces.w } })
208
- .ele('@w', 't')
209
- .att('@xml', 'space', 'preserve')
210
- .txt(text)
211
- .up();
212
-
213
- // eslint-disable-next-line consistent-return
214
- const fixupLineHeight = (lineHeight, fontSize) => {
215
- // FIXME: If line height is anything other than a number
216
- // eslint-disable-next-line no-restricted-globals
217
- if (!isNaN(lineHeight)) {
218
- if (fontSize) {
219
- const actualLineHeight = +lineHeight * fontSize;
220
-
221
- return HIPToTWIP(actualLineHeight);
222
- } else {
223
- // 240 TWIP or 12 point is default line height
224
- return +lineHeight * 240;
225
- }
226
- } else {
227
- // 240 TWIP or 12 point is default line height
228
- return 240;
229
- }
230
- };
231
-
232
- // eslint-disable-next-line consistent-return
233
- const fixupFontSize = (fontSizeString) => {
234
- if (pointRegex.test(fontSizeString)) {
235
- const matchedParts = fontSizeString.match(pointRegex);
236
- // convert point to half point
237
- return pointToHIP(matchedParts[1]);
238
- } else if (pixelRegex.test(fontSizeString)) {
239
- const matchedParts = fontSizeString.match(pixelRegex);
240
- // convert pixels to half point
241
- return pixelToHIP(matchedParts[1]);
242
- }
243
- };
244
-
245
- // eslint-disable-next-line consistent-return
246
- const fixupRowHeight = (rowHeightString) => {
247
- if (pointRegex.test(rowHeightString)) {
248
- const matchedParts = rowHeightString.match(pointRegex);
249
- // convert point to half point
250
- return pointToTWIP(matchedParts[1]);
251
- } else if (pixelRegex.test(rowHeightString)) {
252
- const matchedParts = rowHeightString.match(pixelRegex);
253
- // convert pixels to half point
254
- return pixelToTWIP(matchedParts[1]);
255
- } else if (cmRegex.test(rowHeightString)) {
256
- const matchedParts = rowHeightString.match(cmRegex);
257
- return cmToTWIP(matchedParts[1]);
258
- } else if (inchRegex.test(rowHeightString)) {
259
- const matchedParts = rowHeightString.match(inchRegex);
260
- return inchToTWIP(matchedParts[1]);
261
- }
262
- };
263
-
264
- // eslint-disable-next-line consistent-return
265
- const fixupColumnWidth = (columnWidthString) => {
266
- if (pointRegex.test(columnWidthString)) {
267
- const matchedParts = columnWidthString.match(pointRegex);
268
- return pointToTWIP(matchedParts[1]);
269
- } else if (pixelRegex.test(columnWidthString)) {
270
- const matchedParts = columnWidthString.match(pixelRegex);
271
- return pixelToTWIP(matchedParts[1]);
272
- } else if (cmRegex.test(columnWidthString)) {
273
- const matchedParts = columnWidthString.match(cmRegex);
274
- return cmToTWIP(matchedParts[1]);
275
- } else if (inchRegex.test(columnWidthString)) {
276
- const matchedParts = columnWidthString.match(inchRegex);
277
- return inchToTWIP(matchedParts[1]);
278
- }
279
- };
280
-
281
- // eslint-disable-next-line consistent-return
282
- const fixupMargin = (marginString) => {
283
- if (pointRegex.test(marginString)) {
284
- const matchedParts = marginString.match(pointRegex);
285
- // convert point to half point
286
- return pointToTWIP(matchedParts[1]);
287
- } else if (pixelRegex.test(marginString)) {
288
- const matchedParts = marginString.match(pixelRegex);
289
- // convert pixels to half point
290
- return pixelToTWIP(matchedParts[1]);
291
- }
292
- };
293
-
294
- const modifiedStyleAttributesBuilder = (vNode, attributes, options) => {
295
- const modifiedAttributes = { ...attributes };
296
-
297
- // styles
298
- if (isVNode(vNode) && vNode.properties && vNode.properties.style) {
299
- if (vNode.properties.style.color && !colorlessColors.includes(vNode.properties.style.color)) {
300
- modifiedAttributes.color = fixupColorCode(vNode.properties.style.color);
301
- }
302
-
303
- if (
304
- vNode.properties.style['background-color'] &&
305
- !colorlessColors.includes(vNode.properties.style['background-color'])
306
- ) {
307
- modifiedAttributes.backgroundColor = fixupColorCode(
308
- vNode.properties.style['background-color']
309
- );
310
- }
311
-
312
- if (
313
- vNode.properties.style['vertical-align'] &&
314
- verticalAlignValues.includes(vNode.properties.style['vertical-align'])
315
- ) {
316
- modifiedAttributes.verticalAlign = vNode.properties.style['vertical-align'];
317
- }
318
-
319
- if (
320
- vNode.properties.style['text-align'] &&
321
- ['left', 'right', 'center', 'justify'].includes(vNode.properties.style['text-align'])
322
- ) {
323
- modifiedAttributes.textAlign = vNode.properties.style['text-align'];
324
- }
325
-
326
- // FIXME: remove bold check when other font weights are handled.
327
- if (vNode.properties.style['font-weight'] && vNode.properties.style['font-weight'] === 'bold') {
328
- modifiedAttributes.strong = vNode.properties.style['font-weight'];
329
- }
330
- if (vNode.properties.style['font-size']) {
331
- modifiedAttributes.fontSize = fixupFontSize(vNode.properties.style['font-size']);
332
- }
333
- if (vNode.properties.style['line-height']) {
334
- modifiedAttributes.lineHeight = fixupLineHeight(
335
- vNode.properties.style['line-height'],
336
- vNode.properties.style['font-size']
337
- ? fixupFontSize(vNode.properties.style['font-size'])
338
- : null
339
- );
340
- }
341
- if (vNode.properties.style['margin-left'] || vNode.properties.style['margin-right']) {
342
- const leftMargin = fixupMargin(vNode.properties.style['margin-left']);
343
- const rightMargin = fixupMargin(vNode.properties.style['margin-right']);
344
- const indentation = {};
345
- if (leftMargin) {
346
- indentation.left = leftMargin;
347
- }
348
- if (rightMargin) {
349
- indentation.right = rightMargin;
350
- }
351
- if (leftMargin || rightMargin) {
352
- modifiedAttributes.indentation = indentation;
353
- }
354
- }
355
- if (vNode.properties.style.display) {
356
- modifiedAttributes.display = vNode.properties.style.display;
357
- }
358
-
359
- if (vNode.properties.style.width) {
360
- modifiedAttributes.width = vNode.properties.style.width;
361
- }
362
- }
363
-
364
- // paragraph only
365
- if (options && options.isParagraph) {
366
- if (isVNode(vNode) && vNode.tagName === 'blockquote') {
367
- modifiedAttributes.indentation = { left: 284 };
368
- modifiedAttributes.textAlign = 'justify';
369
- } else if (isVNode(vNode) && vNode.tagName === 'code') {
370
- modifiedAttributes.highlightColor = 'lightGray';
371
- } else if (isVNode(vNode) && vNode.tagName === 'pre') {
372
- modifiedAttributes.font = 'Courier';
373
- }
374
- }
375
-
376
- return modifiedAttributes;
377
- };
378
-
379
- // html tag to formatting function
380
- // options are passed to the formatting function if needed
381
- const buildFormatting = (htmlTag, options) => {
382
- switch (htmlTag) {
383
- case 'strong':
384
- case 'b':
385
- return buildBold();
386
- case 'em':
387
- case 'i':
388
- return buildItalics();
389
- case 'ins':
390
- case 'u':
391
- return buildUnderline();
392
- case 'strike':
393
- case 'del':
394
- case 's':
395
- return buildStrike();
396
- case 'sub':
397
- return buildVertAlign('subscript');
398
- case 'sup':
399
- return buildVertAlign('superscript');
400
- case 'mark':
401
- return buildHighlight();
402
- case 'code':
403
- return buildHighlight('lightGray');
404
- case 'highlightColor':
405
- return buildHighlight(options && options.color ? options.color : 'lightGray');
406
- case 'font':
407
- case 'pre':
408
- return buildRunFontFragment('Courier');
409
- case 'color':
410
- return buildColor(options && options.color ? options.color : 'black');
411
- case 'backgroundColor':
412
- return buildShading(options && options.color ? options.color : 'black');
413
- case 'fontSize':
414
- // does this need a unit of measure?
415
- return buildFontSize(options && options.fontSize ? options.fontSize : 10);
416
- case 'hyperlink':
417
- return buildRunStyleFragment('Hyperlink');
418
- }
419
-
420
- return null;
421
- };
422
-
423
- const buildRunProperties = (attributes) => {
424
- const runPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'rPr');
425
- if (attributes && attributes.constructor === Object) {
426
- Object.keys(attributes).forEach((key) => {
427
- const options = {};
428
- if (key === 'color' || key === 'backgroundColor' || key === 'highlightColor') {
429
- options.color = attributes[key];
430
- }
431
-
432
- if (key === 'fontSize') {
433
- options.fontSize = attributes[key];
434
- }
435
-
436
- const formattingFragment = buildFormatting(key, options);
437
- if (formattingFragment) {
438
- runPropertiesFragment.import(formattingFragment);
439
- }
440
- });
441
- }
442
- runPropertiesFragment.up();
443
-
444
- return runPropertiesFragment;
445
- };
446
-
447
- const buildRun = async (vNode, attributes, docxDocumentInstance) => {
448
- const runFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
449
- const runPropertiesFragment = buildRunProperties(cloneDeep(attributes));
450
-
451
- // case where we have recursive spans representing font changes
452
- if (isVNode(vNode) && vNode.tagName === 'span') {
453
- // eslint-disable-next-line no-use-before-define
454
- return buildRunOrRuns(vNode, attributes, docxDocumentInstance);
455
- }
456
-
457
- if (
458
- isVNode(vNode) &&
459
- [
460
- 'strong',
461
- 'b',
462
- 'em',
463
- 'i',
464
- 'u',
465
- 'ins',
466
- 'strike',
467
- 'del',
468
- 's',
469
- 'sub',
470
- 'sup',
471
- 'mark',
472
- 'blockquote',
473
- 'code',
474
- 'pre',
475
- ].includes(vNode.tagName)
476
- ) {
477
- const runFragmentsArray = [];
478
-
479
- let vNodes = [vNode];
480
- // create temp run fragments to split the paragraph into different runs
481
- let tempAttributes = cloneDeep(attributes);
482
- let tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
483
- while (vNodes.length) {
484
- const tempVNode = vNodes.shift();
485
- if (isVText(tempVNode)) {
486
- const textFragment = buildTextElement(tempVNode.text);
487
- const tempRunPropertiesFragment = buildRunProperties({ ...attributes, ...tempAttributes });
488
- tempRunFragment.import(tempRunPropertiesFragment);
489
- tempRunFragment.import(textFragment);
490
- runFragmentsArray.push(tempRunFragment);
491
-
492
- // re initialize temp run fragments with new fragment
493
- tempAttributes = cloneDeep(attributes);
494
- tempRunFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'r');
495
- } else if (isVNode(tempVNode)) {
496
- if (
497
- [
498
- 'strong',
499
- 'b',
500
- 'em',
501
- 'i',
502
- 'u',
503
- 'ins',
504
- 'strike',
505
- 'del',
506
- 's',
507
- 'sub',
508
- 'sup',
509
- 'mark',
510
- 'code',
511
- 'pre',
512
- ].includes(tempVNode.tagName)
513
- ) {
514
- tempAttributes = {};
515
- switch (tempVNode.tagName) {
516
- case 'strong':
517
- case 'b':
518
- tempAttributes.strong = true;
519
- break;
520
- case 'i':
521
- tempAttributes.i = true;
522
- break;
523
- case 'u':
524
- tempAttributes.u = true;
525
- break;
526
- case 'sub':
527
- tempAttributes.sub = true;
528
- break;
529
- case 'sup':
530
- tempAttributes.sup = true;
531
- break;
532
- }
533
- const formattingFragment = buildFormatting(tempVNode);
534
-
535
- if (formattingFragment) {
536
- runPropertiesFragment.import(formattingFragment);
537
- }
538
- // go a layer deeper if there is a span somewhere in the children
539
- } else if (tempVNode.tagName === 'span') {
540
- // eslint-disable-next-line no-use-before-define
541
- const spanFragment = await buildRunOrRuns(
542
- tempVNode,
543
- { ...attributes, ...tempAttributes },
544
- docxDocumentInstance
545
- );
546
-
547
- // 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
548
- if (Array.isArray(spanFragment)) {
549
- spanFragment.flat(Infinity);
550
- runFragmentsArray.push(...spanFragment);
551
- } else {
552
- runFragmentsArray.push(spanFragment);
553
- }
554
-
555
- // do not slice and concat children since this is already accounted for in the buildRunOrRuns function
556
- // eslint-disable-next-line no-continue
557
- continue;
558
- }
559
- }
560
-
561
- if (tempVNode.children && tempVNode.children.length) {
562
- if (tempVNode.children.length > 1) {
563
- attributes = { ...attributes, ...tempAttributes };
564
- }
565
-
566
- vNodes = tempVNode.children.slice().concat(vNodes);
567
- }
568
- }
569
- if (runFragmentsArray.length) {
570
- return runFragmentsArray;
571
- }
572
- }
573
-
574
- runFragment.import(runPropertiesFragment);
575
- if (isVText(vNode)) {
576
- const textFragment = buildTextElement(vNode.text);
577
- runFragment.import(textFragment);
578
- } else if (attributes && attributes.type === 'picture') {
579
- let response = null;
580
-
581
- const base64Uri = decodeURIComponent(vNode.properties.src);
582
- if (base64Uri) {
583
- response = docxDocumentInstance.createMediaFile(base64Uri);
584
- }
585
-
586
- if (response) {
587
- docxDocumentInstance.zip
588
- .folder('word')
589
- .folder('media')
590
- .file(response.fileNameWithExtension, Buffer.from(response.fileContent, 'base64'), {
591
- createFolders: false,
592
- });
593
-
594
- const documentRelsId = docxDocumentInstance.createDocumentRelationships(
595
- docxDocumentInstance.relationshipFilename,
596
- imageType,
597
- `media/${response.fileNameWithExtension}`,
598
- internalRelationship
599
- );
600
-
601
- attributes.inlineOrAnchored = true;
602
- attributes.relationshipId = documentRelsId;
603
- attributes.id = response.id;
604
- attributes.fileContent = response.fileContent;
605
- attributes.fileNameWithExtension = response.fileNameWithExtension;
606
- }
607
-
608
- const { type, inlineOrAnchored, ...otherAttributes } = attributes;
609
- // eslint-disable-next-line no-use-before-define
610
- const imageFragment = buildDrawing(inlineOrAnchored, type, otherAttributes);
611
- runFragment.import(imageFragment);
612
- } else if (isVNode(vNode) && vNode.tagName === 'br') {
613
- const lineBreakFragment = buildLineBreak();
614
- runFragment.import(lineBreakFragment);
615
- }
616
- runFragment.up();
617
-
618
- return runFragment;
619
- };
620
-
621
- const buildRunOrRuns = async (vNode, attributes, docxDocumentInstance) => {
622
- if (isVNode(vNode) && vNode.tagName === 'span') {
623
- let runFragments = [];
624
-
625
- for (let index = 0; index < vNode.children.length; index++) {
626
- const childVNode = vNode.children[index];
627
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes);
628
- const tempRunFragments = await buildRun(childVNode, modifiedAttributes, docxDocumentInstance);
629
- runFragments = runFragments.concat(
630
- Array.isArray(tempRunFragments) ? tempRunFragments : [tempRunFragments]
631
- );
632
- }
633
-
634
- return runFragments;
635
- } else {
636
- const tempRunFragments = await buildRun(vNode, attributes, docxDocumentInstance);
637
- return tempRunFragments;
638
- }
639
- };
640
-
641
- const buildRunOrHyperLink = async (vNode, attributes, docxDocumentInstance) => {
642
- if (isVNode(vNode) && vNode.tagName === 'a') {
643
- const relationshipId = docxDocumentInstance.createDocumentRelationships(
644
- docxDocumentInstance.relationshipFilename,
645
- hyperlinkType,
646
- vNode.properties && vNode.properties.href ? vNode.properties.href : ''
647
- );
648
- const hyperlinkFragment = fragment({ namespaceAlias: { w: namespaces.w, r: namespaces.r } })
649
- .ele('@w', 'hyperlink')
650
- .att('@r', 'id', `rId${relationshipId}`);
651
-
652
- const modifiedAttributes = { ...attributes };
653
- modifiedAttributes.hyperlink = true;
654
-
655
- const runFragments = await buildRunOrRuns(
656
- vNode.children[0],
657
- modifiedAttributes,
658
- docxDocumentInstance
659
- );
660
- if (Array.isArray(runFragments)) {
661
- for (let index = 0; index < runFragments.length; index++) {
662
- const runFragment = runFragments[index];
663
-
664
- hyperlinkFragment.import(runFragment);
665
- }
666
- } else {
667
- hyperlinkFragment.import(runFragments);
668
- }
669
- hyperlinkFragment.up();
670
-
671
- return hyperlinkFragment;
672
- }
673
-
674
- const runFragments = await buildRunOrRuns(vNode, attributes, docxDocumentInstance);
675
-
676
- return runFragments;
677
- };
678
-
679
- const buildNumberingProperties = (levelId, numberingId) =>
680
- fragment({ namespaceAlias: { w: namespaces.w } })
681
- .ele('@w', 'numPr')
682
- .ele('@w', 'ilvl')
683
- .att('@w', 'val', String(levelId))
684
- .up()
685
- .ele('@w', 'numId')
686
- .att('@w', 'val', String(numberingId))
687
- .up()
688
- .up();
689
-
690
- const buildNumberingInstances = () =>
691
- fragment({ namespaceAlias: { w: namespaces.w } })
692
- .ele('@w', 'num')
693
- .ele('@w', 'abstractNumId')
694
- .up()
695
- .up();
696
-
697
- const buildSpacing = (lineSpacing, beforeSpacing, afterSpacing) => {
698
- const spacingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'spacing');
699
-
700
- if (lineSpacing) {
701
- spacingFragment.att('@w', 'line', lineSpacing);
702
- }
703
- if (beforeSpacing) {
704
- spacingFragment.att('@w', 'before', beforeSpacing);
705
- }
706
- if (afterSpacing) {
707
- spacingFragment.att('@w', 'after', afterSpacing);
708
- }
709
-
710
- spacingFragment.att('@w', 'lineRule', 'auto').up();
711
-
712
- return spacingFragment;
713
- };
714
-
715
- const buildIndentation = ({ left, right }) => {
716
- const indentationFragment = fragment({
717
- namespaceAlias: { w: namespaces.w },
718
- }).ele('@w', 'ind');
719
-
720
- if (left) {
721
- indentationFragment.att('@w', 'left', left);
722
- }
723
- if (right) {
724
- indentationFragment.att('@w', 'right', right);
725
- }
726
-
727
- indentationFragment.up();
728
-
729
- return indentationFragment;
730
- };
731
-
732
- const buildPStyle = (style = 'Normal') =>
733
- fragment({ namespaceAlias: { w: namespaces.w } })
734
- .ele('@w', 'pStyle')
735
- .att('@w', 'val', style)
736
- .up();
737
-
738
- const buildHorizontalAlignment = (horizontalAlignment) => {
739
- if (horizontalAlignment === 'justify') {
740
- horizontalAlignment = 'both';
741
- }
742
- return fragment({ namespaceAlias: { w: namespaces.w } })
743
- .ele('@w', 'jc')
744
- .att('@w', 'val', horizontalAlignment)
745
- .up();
746
- };
747
-
748
- const buildParagraphBorder = () => {
749
- const paragraphBorderFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
750
- '@w',
751
- 'pBdr'
752
- );
753
- const bordersObject = cloneDeep(paragraphBordersObject);
754
-
755
- Object.keys(bordersObject).forEach((borderName) => {
756
- if (bordersObject[borderName]) {
757
- const { size, spacing, color } = bordersObject[borderName];
758
-
759
- const borderFragment = buildBorder(borderName, size, spacing, color);
760
- paragraphBorderFragment.import(borderFragment);
761
- }
762
- });
763
-
764
- paragraphBorderFragment.up();
765
-
766
- return paragraphBorderFragment;
767
- };
768
-
769
- const buildParagraphProperties = (attributes) => {
770
- const paragraphPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
771
- '@w',
772
- 'pPr'
773
- );
774
- if (attributes && attributes.constructor === Object) {
775
- Object.keys(attributes).forEach((key) => {
776
- switch (key) {
777
- case 'numbering':
778
- const { levelId, numberingId } = attributes[key];
779
- const numberingPropertiesFragment = buildNumberingProperties(levelId, numberingId);
780
- paragraphPropertiesFragment.import(numberingPropertiesFragment);
781
- // eslint-disable-next-line no-param-reassign
782
- delete attributes.numbering;
783
- break;
784
- case 'textAlign':
785
- const horizontalAlignmentFragment = buildHorizontalAlignment(attributes[key]);
786
- paragraphPropertiesFragment.import(horizontalAlignmentFragment);
787
- // eslint-disable-next-line no-param-reassign
788
- delete attributes.textAlign;
789
- break;
790
- case 'backgroundColor':
791
- // Add shading to Paragraph Properties only if display is block
792
- // Essentially if background color needs to be across the row
793
- if (attributes.display === 'block') {
794
- const shadingFragment = buildShading(attributes[key]);
795
- paragraphPropertiesFragment.import(shadingFragment);
796
- // FIXME: Inner padding in case of shaded paragraphs.
797
- const paragraphBorderFragment = buildParagraphBorder();
798
- paragraphPropertiesFragment.import(paragraphBorderFragment);
799
- // eslint-disable-next-line no-param-reassign
800
- delete attributes.backgroundColor;
801
- }
802
- break;
803
- case 'paragraphStyle':
804
- const pStyleFragment = buildPStyle(attributes.paragraphStyle);
805
- paragraphPropertiesFragment.import(pStyleFragment);
806
- delete attributes.paragraphStyle;
807
- break;
808
- case 'indentation':
809
- const indentationFragment = buildIndentation(attributes[key]);
810
- paragraphPropertiesFragment.import(indentationFragment);
811
- // eslint-disable-next-line no-param-reassign
812
- delete attributes.indentation;
813
- break;
814
- }
815
- });
816
-
817
- const spacingFragment = buildSpacing(
818
- attributes.lineHeight,
819
- attributes.beforeSpacing,
820
- attributes.afterSpacing
821
- );
822
- // eslint-disable-next-line no-param-reassign
823
- delete attributes.lineHeight;
824
- // eslint-disable-next-line no-param-reassign
825
- delete attributes.beforeSpacing;
826
- // eslint-disable-next-line no-param-reassign
827
- delete attributes.afterSpacing;
828
-
829
- paragraphPropertiesFragment.import(spacingFragment);
830
- }
831
- paragraphPropertiesFragment.up();
832
-
833
- return paragraphPropertiesFragment;
834
- };
835
-
836
- const computeImageDimensions = (vNode, attributes) => {
837
- const { maximumWidth, originalWidth, originalHeight } = attributes;
838
- const aspectRatio = originalWidth / originalHeight;
839
- const maximumWidthInEMU = TWIPToEMU(maximumWidth);
840
- let originalWidthInEMU = pixelToEMU(originalWidth);
841
- let originalHeightInEMU = pixelToEMU(originalHeight);
842
- if (originalWidthInEMU > maximumWidthInEMU) {
843
- originalWidthInEMU = maximumWidthInEMU;
844
- originalHeightInEMU = Math.round(originalWidthInEMU / aspectRatio);
845
- }
846
- let modifiedHeight;
847
- let modifiedWidth;
848
-
849
- if (vNode.properties && vNode.properties.style) {
850
- if (vNode.properties.style.width) {
851
- if (vNode.properties.style.width !== 'auto') {
852
- if (pixelRegex.test(vNode.properties.style.width)) {
853
- modifiedWidth = pixelToEMU(vNode.properties.style.width.match(pixelRegex)[1]);
854
- } else if (percentageRegex.test(vNode.properties.style.width)) {
855
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
856
-
857
- modifiedWidth = Math.round((percentageValue / 100) * originalWidthInEMU);
858
- }
859
- } else {
860
- // eslint-disable-next-line no-lonely-if
861
- if (vNode.properties.style.height && vNode.properties.style.height === 'auto') {
862
- modifiedWidth = originalWidthInEMU;
863
- modifiedHeight = originalHeightInEMU;
864
- }
865
- }
866
- }
867
- if (vNode.properties.style.height) {
868
- if (vNode.properties.style.height !== 'auto') {
869
- if (pixelRegex.test(vNode.properties.style.height)) {
870
- modifiedHeight = pixelToEMU(vNode.properties.style.height.match(pixelRegex)[1]);
871
- } else if (percentageRegex.test(vNode.properties.style.height)) {
872
- const percentageValue = vNode.properties.style.width.match(percentageRegex)[1];
873
-
874
- modifiedHeight = Math.round((percentageValue / 100) * originalHeightInEMU);
875
- if (!modifiedWidth) {
876
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
877
- }
878
- }
879
- } else {
880
- // eslint-disable-next-line no-lonely-if
881
- if (modifiedWidth) {
882
- if (!modifiedHeight) {
883
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
884
- }
885
- } else {
886
- modifiedHeight = originalHeightInEMU;
887
- modifiedWidth = originalWidthInEMU;
888
- }
889
- }
890
- }
891
- if (modifiedWidth && !modifiedHeight) {
892
- modifiedHeight = Math.round(modifiedWidth / aspectRatio);
893
- } else if (modifiedHeight && !modifiedWidth) {
894
- modifiedWidth = Math.round(modifiedHeight * aspectRatio);
895
- }
896
- } else {
897
- modifiedWidth = originalWidthInEMU;
898
- modifiedHeight = originalHeightInEMU;
899
- }
900
-
901
- // eslint-disable-next-line no-param-reassign
902
- attributes.width = modifiedWidth;
903
- // eslint-disable-next-line no-param-reassign
904
- attributes.height = modifiedHeight;
905
- };
906
-
907
- const buildParagraph = async (vNode, attributes, docxDocumentInstance) => {
908
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p');
909
- const modifiedAttributes = modifiedStyleAttributesBuilder(vNode, attributes, {
910
- isParagraph: true,
911
- });
912
- const paragraphPropertiesFragment = buildParagraphProperties(modifiedAttributes);
913
- paragraphFragment.import(paragraphPropertiesFragment);
914
- if (isVNode(vNode) && vNodeHasChildren(vNode)) {
915
- if (
916
- [
917
- 'span',
918
- 'strong',
919
- 'b',
920
- 'em',
921
- 'i',
922
- 'u',
923
- 'ins',
924
- 'strike',
925
- 'del',
926
- 's',
927
- 'sub',
928
- 'sup',
929
- 'mark',
930
- 'a',
931
- 'code',
932
- 'pre',
933
- ].includes(vNode.tagName)
934
- ) {
935
- const runOrHyperlinkFragments = await buildRunOrHyperLink(
936
- vNode,
937
- modifiedAttributes,
938
- docxDocumentInstance
939
- );
940
- if (Array.isArray(runOrHyperlinkFragments)) {
941
- for (
942
- let iteratorIndex = 0;
943
- iteratorIndex < runOrHyperlinkFragments.length;
944
- iteratorIndex++
945
- ) {
946
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
947
-
948
- paragraphFragment.import(runOrHyperlinkFragment);
949
- }
950
- } else {
951
- paragraphFragment.import(runOrHyperlinkFragments);
952
- }
953
- } else if (vNode.tagName === 'blockquote') {
954
- const runFragmentOrFragments = await buildRun(vNode, attributes);
955
- if (Array.isArray(runFragmentOrFragments)) {
956
- for (let index = 0; index < runFragmentOrFragments.length; index++) {
957
- paragraphFragment.import(runFragmentOrFragments[index]);
958
- }
959
- } else {
960
- paragraphFragment.import(runFragmentOrFragments);
961
- }
962
- } else {
963
- for (let index = 0; index < vNode.children.length; index++) {
964
- const childVNode = vNode.children[index];
965
- if (childVNode.tagName === 'img') {
966
- let base64String;
967
- const imageSource = childVNode.properties.src;
968
- if (isValidUrl(imageSource)) {
969
- base64String = await imageToBase64(imageSource).catch((error) => {
970
- // eslint-disable-next-line no-console
971
- console.warning(`skipping image download and conversion due to ${error}`);
972
- });
973
-
974
- if (base64String && mimeTypes.lookup(imageSource)) {
975
- childVNode.properties.src = `data:${mimeTypes.lookup(
976
- imageSource
977
- )};base64, ${base64String}`;
978
- } else {
979
- break;
980
- }
981
- } else {
982
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
983
- base64String = imageSource.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
984
- }
985
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
986
- const imageProperties = sizeOf(imageBuffer);
987
-
988
- modifiedAttributes.maximumWidth =
989
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
990
- modifiedAttributes.originalWidth = imageProperties.width;
991
- modifiedAttributes.originalHeight = imageProperties.height;
992
-
993
- computeImageDimensions(childVNode, modifiedAttributes);
994
- }
995
- const runOrHyperlinkFragments = await buildRunOrHyperLink(
996
- childVNode,
997
- isVNode(childVNode) && childVNode.tagName === 'img'
998
- ? { ...modifiedAttributes, type: 'picture' }
999
- : modifiedAttributes,
1000
- docxDocumentInstance
1001
- );
1002
- if (Array.isArray(runOrHyperlinkFragments)) {
1003
- for (
1004
- let iteratorIndex = 0;
1005
- iteratorIndex < runOrHyperlinkFragments.length;
1006
- iteratorIndex++
1007
- ) {
1008
- const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex];
1009
-
1010
- paragraphFragment.import(runOrHyperlinkFragment);
1011
- }
1012
- } else {
1013
- paragraphFragment.import(runOrHyperlinkFragments);
1014
- }
1015
- }
1016
- }
1017
- } else {
1018
- // In case paragraphs has to be rendered where vText is present. Eg. table-cell
1019
- // Or in case the vNode is something like img
1020
- if (isVNode(vNode) && vNode.tagName === 'img') {
1021
- const imageSource = vNode.properties.src;
1022
- let base64String = imageSource;
1023
- if (isValidUrl(imageSource)) {
1024
- base64String = await imageToBase64(imageSource).catch((error) => {
1025
- // eslint-disable-next-line no-console
1026
- console.warning(`skipping image download and conversion due to ${error}`);
1027
- });
1028
-
1029
- if (base64String && mimeTypes.lookup(imageSource)) {
1030
- vNode.properties.src = `data:${mimeTypes.lookup(imageSource)};base64, ${base64String}`;
1031
- } else {
1032
- paragraphFragment.up();
1033
-
1034
- return paragraphFragment;
1035
- }
1036
- } else {
1037
- // eslint-disable-next-line no-useless-escape, prefer-destructuring
1038
- base64String = base64String.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/)[2];
1039
- }
1040
-
1041
- const imageBuffer = Buffer.from(decodeURIComponent(base64String), 'base64');
1042
- const imageProperties = sizeOf(imageBuffer);
1043
-
1044
- modifiedAttributes.maximumWidth =
1045
- modifiedAttributes.maximumWidth || docxDocumentInstance.availableDocumentSpace;
1046
- modifiedAttributes.originalWidth = imageProperties.width;
1047
- modifiedAttributes.originalHeight = imageProperties.height;
1048
-
1049
- computeImageDimensions(vNode, modifiedAttributes);
1050
- }
1051
- const runFragments = await buildRunOrRuns(vNode, modifiedAttributes, docxDocumentInstance);
1052
- if (Array.isArray(runFragments)) {
1053
- for (let index = 0; index < runFragments.length; index++) {
1054
- const runFragment = runFragments[index];
1055
-
1056
- paragraphFragment.import(runFragment);
1057
- }
1058
- } else {
1059
- paragraphFragment.import(runFragments);
1060
- }
1061
- }
1062
- paragraphFragment.up();
1063
-
1064
- return paragraphFragment;
1065
- };
1066
-
1067
- const buildGridSpanFragment = (spanValue) =>
1068
- fragment({ namespaceAlias: { w: namespaces.w } })
1069
- .ele('@w', 'gridSpan')
1070
- .att('@w', 'val', spanValue)
1071
- .up();
1072
-
1073
- const buildTableCellSpacing = (cellSpacing = 0) =>
1074
- fragment({ namespaceAlias: { w: namespaces.w } })
1075
- .ele('@w', 'tblCellSpacing')
1076
- .att('@w', 'w', cellSpacing)
1077
- .att('@w', 'type', 'dxa')
1078
- .up();
1079
-
1080
- const buildTableCellBorders = (tableCellBorder) => {
1081
- const tableCellBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1082
- '@w',
1083
- 'tcBorders'
1084
- );
1085
-
1086
- const { color, stroke, ...borders } = tableCellBorder;
1087
- Object.keys(borders).forEach((border) => {
1088
- if (tableCellBorder[border]) {
1089
- const borderFragment = buildBorder(border, tableCellBorder[border], 0, color, stroke);
1090
- tableCellBordersFragment.import(borderFragment);
1091
- }
1092
- });
1093
-
1094
- tableCellBordersFragment.up();
1095
-
1096
- return tableCellBordersFragment;
1097
- };
1098
-
1099
- const buildTableCellWidth = (tableCellWidth) =>
1100
- fragment({ namespaceAlias: { w: namespaces.w } })
1101
- .ele('@w', 'tcW')
1102
- .att('@w', 'w', fixupColumnWidth(tableCellWidth))
1103
- .att('@w', 'type', 'dxa')
1104
- .up();
1105
-
1106
- const buildTableCellProperties = (attributes) => {
1107
- const tableCellPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1108
- '@w',
1109
- 'tcPr'
1110
- );
1111
- if (attributes && attributes.constructor === Object) {
1112
- Object.keys(attributes).forEach((key) => {
1113
- switch (key) {
1114
- case 'backgroundColor':
1115
- const shadingFragment = buildShading(attributes[key]);
1116
- tableCellPropertiesFragment.import(shadingFragment);
1117
- // eslint-disable-next-line no-param-reassign
1118
- delete attributes.backgroundColor;
1119
- break;
1120
- case 'verticalAlign':
1121
- const verticalAlignmentFragment = buildVerticalAlignment(attributes[key]);
1122
- tableCellPropertiesFragment.import(verticalAlignmentFragment);
1123
- // eslint-disable-next-line no-param-reassign
1124
- delete attributes.verticalAlign;
1125
- break;
1126
- case 'colSpan':
1127
- const gridSpanFragment = buildGridSpanFragment(attributes[key]);
1128
- tableCellPropertiesFragment.import(gridSpanFragment);
1129
- // eslint-disable-next-line no-param-reassign
1130
- delete attributes.colSpan;
1131
- break;
1132
- case 'tableCellBorder':
1133
- const tableCellBorderFragment = buildTableCellBorders(attributes[key]);
1134
- tableCellPropertiesFragment.import(tableCellBorderFragment);
1135
- // eslint-disable-next-line no-param-reassign
1136
- delete attributes.tableCellBorder;
1137
- break;
1138
- case 'rowSpan':
1139
- const verticalMergeFragment = buildVerticalMerge(attributes[key]);
1140
- tableCellPropertiesFragment.import(verticalMergeFragment);
1141
-
1142
- delete attributes.rowSpan;
1143
- break;
1144
- case 'width':
1145
- const widthFragment = buildTableCellWidth(attributes[key]);
1146
- tableCellPropertiesFragment.import(widthFragment);
1147
- delete attributes.width;
1148
- break;
1149
- }
1150
- });
1151
- }
1152
- tableCellPropertiesFragment.up();
1153
-
1154
- return tableCellPropertiesFragment;
1155
- };
1156
-
1157
- const fixupTableCellBorder = (vNode, attributes) => {
1158
- if (Object.prototype.hasOwnProperty.call(vNode.properties.style, 'border')) {
1159
- if (vNode.properties.style.border === 'none' || vNode.properties.style.border === 0) {
1160
- attributes.tableCellBorder = {};
1161
- } else {
1162
- // eslint-disable-next-line no-use-before-define
1163
- const [borderSize, borderStroke, borderColor] = cssBorderParser(
1164
- vNode.properties.style.border
1165
- );
1166
-
1167
- attributes.tableCellBorder = {
1168
- top: borderSize,
1169
- left: borderSize,
1170
- bottom: borderSize,
1171
- right: borderSize,
1172
- color: borderColor,
1173
- stroke: borderStroke,
1174
- };
1175
- }
1176
- }
1177
- if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] === '0') {
1178
- attributes.tableCellBorder = {
1179
- ...attributes.tableCellBorder,
1180
- top: 0,
1181
- };
1182
- } else if (vNode.properties.style['border-top'] && vNode.properties.style['border-top'] !== '0') {
1183
- // eslint-disable-next-line no-use-before-define
1184
- const [borderSize, borderStroke, borderColor] = cssBorderParser(
1185
- vNode.properties.style['border-top']
1186
- );
1187
- attributes.tableCellBorder = {
1188
- ...attributes.tableCellBorder,
1189
- top: borderSize,
1190
- color: borderColor,
1191
- stroke: borderStroke,
1192
- };
1193
- }
1194
- if (vNode.properties.style['border-left'] && vNode.properties.style['border-left'] === '0') {
1195
- attributes.tableCellBorder = {
1196
- ...attributes.tableCellBorder,
1197
- left: 0,
1198
- };
1199
- } else if (
1200
- vNode.properties.style['border-left'] &&
1201
- vNode.properties.style['border-left'] !== '0'
1202
- ) {
1203
- // eslint-disable-next-line no-use-before-define
1204
- const [borderSize, borderStroke, borderColor] = cssBorderParser(
1205
- vNode.properties.style['border-left']
1206
- );
1207
- attributes.tableCellBorder = {
1208
- ...attributes.tableCellBorder,
1209
- left: borderSize,
1210
- color: borderColor,
1211
- stroke: borderStroke,
1212
- };
1213
- }
1214
- if (vNode.properties.style['border-bottom'] && vNode.properties.style['border-bottom'] === '0') {
1215
- attributes.tableCellBorder = {
1216
- ...attributes.tableCellBorder,
1217
- bottom: 0,
1218
- };
1219
- } else if (
1220
- vNode.properties.style['border-bottom'] &&
1221
- vNode.properties.style['border-bottom'] !== '0'
1222
- ) {
1223
- // eslint-disable-next-line no-use-before-define
1224
- const [borderSize, borderStroke, borderColor] = cssBorderParser(
1225
- vNode.properties.style['border-bottom']
1226
- );
1227
- attributes.tableCellBorder = {
1228
- ...attributes.tableCellBorder,
1229
- bottom: borderSize,
1230
- color: borderColor,
1231
- stroke: borderStroke,
1232
- };
1233
- }
1234
- if (vNode.properties.style['border-right'] && vNode.properties.style['border-right'] === '0') {
1235
- attributes.tableCellBorder = {
1236
- ...attributes.tableCellBorder,
1237
- right: 0,
1238
- };
1239
- } else if (
1240
- vNode.properties.style['border-right'] &&
1241
- vNode.properties.style['border-right'] !== '0'
1242
- ) {
1243
- // eslint-disable-next-line no-use-before-define
1244
- const [borderSize, borderStroke, borderColor] = cssBorderParser(
1245
- vNode.properties.style['border-right']
1246
- );
1247
- attributes.tableCellBorder = {
1248
- ...attributes.tableCellBorder,
1249
- right: borderSize,
1250
- color: borderColor,
1251
- stroke: borderStroke,
1252
- };
1253
- }
1254
- };
1255
-
1256
- const buildTableCell = async (vNode, attributes, rowSpanMap, columnIndex, docxDocumentInstance) => {
1257
- const tableCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
1258
-
1259
- let modifiedAttributes = { ...attributes };
1260
- if (isVNode(vNode) && vNode.properties) {
1261
- if (vNode.properties.rowSpan) {
1262
- rowSpanMap.set(columnIndex.index, { rowSpan: vNode.properties.rowSpan - 1, colSpan: 0 });
1263
- modifiedAttributes.rowSpan = 'restart';
1264
- } else {
1265
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
1266
- rowSpanMap.set(
1267
- columnIndex.index,
1268
- // eslint-disable-next-line prefer-object-spread
1269
- Object.assign({}, previousSpanObject, {
1270
- rowSpan: 0,
1271
- colSpan: (previousSpanObject && previousSpanObject.colSpan) || 0,
1272
- })
1273
- );
1274
- }
1275
- if (
1276
- vNode.properties.colSpan ||
1277
- (vNode.properties.style && vNode.properties.style['column-span'])
1278
- ) {
1279
- modifiedAttributes.colSpan =
1280
- vNode.properties.colSpan ||
1281
- (vNode.properties.style && vNode.properties.style['column-span']);
1282
- const previousSpanObject = rowSpanMap.get(columnIndex.index);
1283
- rowSpanMap.set(
1284
- columnIndex.index,
1285
- // eslint-disable-next-line prefer-object-spread
1286
- Object.assign({}, previousSpanObject, {
1287
- colSpan: parseInt(modifiedAttributes.colSpan) || 0,
1288
- })
1289
- );
1290
- columnIndex.index += parseInt(modifiedAttributes.colSpan) - 1;
1291
- }
1292
- if (vNode.properties.style) {
1293
- modifiedAttributes = {
1294
- ...modifiedAttributes,
1295
- ...modifiedStyleAttributesBuilder(vNode, attributes),
1296
- };
1297
-
1298
- fixupTableCellBorder(vNode, modifiedAttributes);
1299
- }
1300
- }
1301
- const tableCellPropertiesFragment = buildTableCellProperties(modifiedAttributes);
1302
- tableCellFragment.import(tableCellPropertiesFragment);
1303
- if (vNodeHasChildren(vNode)) {
1304
- for (let index = 0; index < vNode.children.length; index++) {
1305
- const childVNode = vNode.children[index];
1306
- if (isVNode(childVNode) && childVNode.tagName === 'img') {
1307
- const imageFragment = await buildImage(
1308
- docxDocumentInstance,
1309
- childVNode,
1310
- modifiedAttributes.maximumWidth
1311
- );
1312
- if (imageFragment) {
1313
- tableCellFragment.import(imageFragment);
1314
- }
1315
- } else if (isVNode(childVNode) && childVNode.tagName === 'figure') {
1316
- if (vNodeHasChildren(childVNode)) {
1317
- // eslint-disable-next-line no-plusplus
1318
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
1319
- const grandChildVNode = childVNode.children[iteratorIndex];
1320
- if (grandChildVNode.tagName === 'img') {
1321
- const imageFragment = await buildImage(
1322
- docxDocumentInstance,
1323
- grandChildVNode,
1324
- modifiedAttributes.maximumWidth
1325
- );
1326
- if (imageFragment) {
1327
- tableCellFragment.import(imageFragment);
1328
- }
1329
- }
1330
- }
1331
- }
1332
- } else if (isVNode(childVNode) && ['ul', 'ol'].includes(childVNode.tagName)) {
1333
- // render list in table
1334
- if (vNodeHasChildren(childVNode)) {
1335
- await buildList(childVNode, docxDocumentInstance, tableCellFragment);
1336
- }
1337
- } else {
1338
- const paragraphFragment = await buildParagraph(
1339
- childVNode,
1340
- modifiedAttributes,
1341
- docxDocumentInstance
1342
- );
1343
-
1344
- tableCellFragment.import(paragraphFragment);
1345
- }
1346
- }
1347
- } else {
1348
- // TODO: Figure out why building with buildParagraph() isn't working
1349
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1350
- .ele('@w', 'p')
1351
- .up();
1352
- tableCellFragment.import(paragraphFragment);
1353
- }
1354
- tableCellFragment.up();
1355
-
1356
- return tableCellFragment;
1357
- };
1358
-
1359
- const buildRowSpanCell = (rowSpanMap, columnIndex, attributes) => {
1360
- const rowSpanCellFragments = [];
1361
- let spanObject = rowSpanMap.get(columnIndex.index);
1362
- while (spanObject && spanObject.rowSpan) {
1363
- const rowSpanCellFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tc');
1364
-
1365
- const tableCellPropertiesFragment = buildTableCellProperties({
1366
- ...attributes,
1367
- rowSpan: 'continue',
1368
- colSpan: spanObject.colSpan ? spanObject.colSpan : 0,
1369
- });
1370
- rowSpanCellFragment.import(tableCellPropertiesFragment);
1371
-
1372
- const paragraphFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1373
- .ele('@w', 'p')
1374
- .up();
1375
- rowSpanCellFragment.import(paragraphFragment);
1376
- rowSpanCellFragment.up();
1377
-
1378
- rowSpanCellFragments.push(rowSpanCellFragment);
1379
-
1380
- if (spanObject.rowSpan - 1 === 0) {
1381
- rowSpanMap.delete(columnIndex.index);
1382
- } else {
1383
- rowSpanMap.set(columnIndex.index, {
1384
- rowSpan: spanObject.rowSpan - 1,
1385
- colSpan: spanObject.colSpan || 0,
1386
- });
1387
- }
1388
- columnIndex.index += spanObject.colSpan || 1;
1389
- spanObject = rowSpanMap.get(columnIndex.index);
1390
- }
1391
-
1392
- return rowSpanCellFragments;
1393
- };
1394
-
1395
- const buildTableRowProperties = (attributes) => {
1396
- const tableRowPropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1397
- '@w',
1398
- 'trPr'
1399
- );
1400
- if (attributes && attributes.constructor === Object) {
1401
- Object.keys(attributes).forEach((key) => {
1402
- switch (key) {
1403
- case 'tableRowHeight':
1404
- const tableRowHeightFragment = buildTableRowHeight(attributes[key]);
1405
- tableRowPropertiesFragment.import(tableRowHeightFragment);
1406
- // eslint-disable-next-line no-param-reassign
1407
- delete attributes.tableRowHeight;
1408
- break;
1409
- case 'rowCantSplit':
1410
- if (attributes.rowCantSplit) {
1411
- const cantSplitFragment = fragment({ namespaceAlias: { w: namespaces.w } })
1412
- .ele('@w', 'cantSplit')
1413
- .up();
1414
- tableRowPropertiesFragment.import(cantSplitFragment);
1415
- // eslint-disable-next-line no-param-reassign
1416
- delete attributes.rowCantSplit;
1417
- }
1418
- break;
1419
- }
1420
- });
1421
- }
1422
- tableRowPropertiesFragment.up();
1423
- return tableRowPropertiesFragment;
1424
- };
1425
-
1426
- const buildTableRow = async (vNode, attributes, rowSpanMap, docxDocumentInstance) => {
1427
- const tableRowFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tr');
1428
- const modifiedAttributes = { ...attributes };
1429
- if (isVNode(vNode) && vNode.properties) {
1430
- // FIXME: find a better way to get row height from cell style
1431
- if (
1432
- (vNode.properties.style && vNode.properties.style.height) ||
1433
- (vNode.children[0] &&
1434
- isVNode(vNode.children[0]) &&
1435
- vNode.children[0].properties.style &&
1436
- vNode.children[0].properties.style.height)
1437
- ) {
1438
- modifiedAttributes.tableRowHeight = fixupRowHeight(
1439
- (vNode.properties.style && vNode.properties.style.height) ||
1440
- (vNode.children[0] &&
1441
- isVNode(vNode.children[0]) &&
1442
- vNode.children[0].properties.style &&
1443
- vNode.children[0].properties.style.height
1444
- ? vNode.children[0].properties.style.height
1445
- : undefined)
1446
- );
1447
- }
1448
- if (vNode.properties.style) {
1449
- fixupTableCellBorder(vNode, modifiedAttributes);
1450
- }
1451
- }
1452
-
1453
- const tableRowPropertiesFragment = buildTableRowProperties(modifiedAttributes);
1454
- tableRowFragment.import(tableRowPropertiesFragment);
1455
-
1456
- const columnIndex = { index: 0 };
1457
-
1458
- if (vNodeHasChildren(vNode)) {
1459
- const tableColumns = vNode.children.filter((childVNode) =>
1460
- ['td', 'th'].includes(childVNode.tagName)
1461
- );
1462
- const maximumColumnWidth = docxDocumentInstance.availableDocumentSpace / tableColumns.length;
1463
-
1464
- // eslint-disable-next-line no-restricted-syntax
1465
- for (const column of tableColumns) {
1466
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
1467
- if (Array.isArray(rowSpanCellFragments)) {
1468
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
1469
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
1470
-
1471
- tableRowFragment.import(rowSpanCellFragment);
1472
- }
1473
- }
1474
- const tableCellFragment = await buildTableCell(
1475
- column,
1476
- { ...modifiedAttributes, maximumWidth: maximumColumnWidth },
1477
- rowSpanMap,
1478
- columnIndex,
1479
- docxDocumentInstance
1480
- );
1481
- columnIndex.index++;
1482
-
1483
- tableRowFragment.import(tableCellFragment);
1484
- }
1485
- }
1486
-
1487
- if (columnIndex.index < rowSpanMap.size) {
1488
- const rowSpanCellFragments = buildRowSpanCell(rowSpanMap, columnIndex, modifiedAttributes);
1489
- if (Array.isArray(rowSpanCellFragments)) {
1490
- for (let iteratorIndex = 0; iteratorIndex < rowSpanCellFragments.length; iteratorIndex++) {
1491
- const rowSpanCellFragment = rowSpanCellFragments[iteratorIndex];
1492
-
1493
- tableRowFragment.import(rowSpanCellFragment);
1494
- }
1495
- }
1496
- }
1497
-
1498
- tableRowFragment.up();
1499
-
1500
- return tableRowFragment;
1501
- };
1502
-
1503
- const buildTableGridCol = (gridWidth) =>
1504
- fragment({ namespaceAlias: { w: namespaces.w } })
1505
- .ele('@w', 'gridCol')
1506
- .att('@w', 'w', String(gridWidth));
1507
-
1508
- const buildTableGrid = (vNode, attributes) => {
1509
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
1510
- if (vNodeHasChildren(vNode)) {
1511
- const gridColumns = vNode.children.filter((childVNode) => childVNode.tagName === 'col');
1512
- const gridWidth = attributes.maximumWidth / gridColumns.length;
1513
-
1514
- for (let index = 0; index < gridColumns.length; index++) {
1515
- const tableGridColFragment = buildTableGridCol(gridWidth);
1516
- tableGridFragment.import(tableGridColFragment);
1517
- }
1518
- }
1519
- tableGridFragment.up();
1520
-
1521
- return tableGridFragment;
1522
- };
1523
-
1524
- const buildTableGridFromTableRow = (vNode, attributes) => {
1525
- const tableGridFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tblGrid');
1526
- if (vNodeHasChildren(vNode)) {
1527
- const numberOfGridColumns = vNode.children.reduce((accumulator, childVNode) => {
1528
- const colSpan =
1529
- childVNode.properties.colSpan ||
1530
- (childVNode.properties.style && childVNode.properties.style['column-span']);
1531
-
1532
- return accumulator + (colSpan ? parseInt(colSpan) : 1);
1533
- }, 0);
1534
- const gridWidth = attributes.maximumWidth / numberOfGridColumns;
1535
-
1536
- for (let index = 0; index < numberOfGridColumns; index++) {
1537
- const tableGridColFragment = buildTableGridCol(gridWidth);
1538
- tableGridFragment.import(tableGridColFragment);
1539
- }
1540
- }
1541
- tableGridFragment.up();
1542
-
1543
- return tableGridFragment;
1544
- };
1545
-
1546
- const buildTableBorders = (tableBorder) => {
1547
- const tableBordersFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1548
- '@w',
1549
- 'tblBorders'
1550
- );
1551
-
1552
- const { color, stroke, ...borders } = tableBorder;
1553
-
1554
- Object.keys(borders).forEach((border) => {
1555
- if (borders[border]) {
1556
- const borderFragment = buildBorder(border, borders[border], 0, color, stroke);
1557
- tableBordersFragment.import(borderFragment);
1558
- }
1559
- });
1560
-
1561
- tableBordersFragment.up();
1562
-
1563
- return tableBordersFragment;
1564
- };
1565
-
1566
- const buildTableWidth = (tableWidth) =>
1567
- fragment({ namespaceAlias: { w: namespaces.w } })
1568
- .ele('@w', 'tblW')
1569
- .att('@w', 'type', 'dxa')
1570
- .att('@w', 'w', String(tableWidth))
1571
- .up();
1572
-
1573
- const buildCellMargin = (side, margin) =>
1574
- fragment({ namespaceAlias: { w: namespaces.w } })
1575
- .ele('@w', side)
1576
- .att('@w', 'type', 'dxa')
1577
- .att('@w', 'w', String(margin))
1578
- .up();
1579
-
1580
- const buildTableCellMargins = (margin) => {
1581
- const tableCellMarFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1582
- '@w',
1583
- 'tblCellMar'
1584
- );
1585
-
1586
- ['top', 'bottom'].forEach((side) => {
1587
- const marginFragment = buildCellMargin(side, margin / 2);
1588
- tableCellMarFragment.import(marginFragment);
1589
- });
1590
- ['left', 'right'].forEach((side) => {
1591
- const marginFragment = buildCellMargin(side, margin);
1592
- tableCellMarFragment.import(marginFragment);
1593
- });
1594
-
1595
- return tableCellMarFragment;
1596
- };
1597
-
1598
- const buildTableProperties = (attributes) => {
1599
- const tablePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele(
1600
- '@w',
1601
- 'tblPr'
1602
- );
1603
-
1604
- if (attributes && attributes.constructor === Object) {
1605
- Object.keys(attributes).forEach((key) => {
1606
- switch (key) {
1607
- case 'tableBorder':
1608
- const tableBordersFragment = buildTableBorders(attributes[key]);
1609
- tablePropertiesFragment.import(tableBordersFragment);
1610
- // eslint-disable-next-line no-param-reassign
1611
- delete attributes.tableBorder;
1612
- break;
1613
- case 'tableCellSpacing':
1614
- const tableCellSpacingFragment = buildTableCellSpacing(attributes[key]);
1615
- tablePropertiesFragment.import(tableCellSpacingFragment);
1616
- // eslint-disable-next-line no-param-reassign
1617
- delete attributes.tableCellSpacing;
1618
- break;
1619
- case 'width':
1620
- if (attributes[key]) {
1621
- const tableWidthFragment = buildTableWidth(attributes[key]);
1622
- tablePropertiesFragment.import(tableWidthFragment);
1623
- }
1624
- // eslint-disable-next-line no-param-reassign
1625
- delete attributes.width;
1626
- break;
1627
- }
1628
- });
1629
- }
1630
- const tableCellMarginFragment = buildTableCellMargins(160);
1631
- tablePropertiesFragment.import(tableCellMarginFragment);
1632
-
1633
- // by default, all tables are center aligned.
1634
- const alignmentFragment = buildHorizontalAlignment('center');
1635
- tablePropertiesFragment.import(alignmentFragment);
1636
-
1637
- tablePropertiesFragment.up();
1638
-
1639
- return tablePropertiesFragment;
1640
- };
1641
-
1642
- const cssBorderParser = (borderString) => {
1643
- let [size, stroke, color] = borderString.split(' ');
1644
-
1645
- if (pointRegex.test(size)) {
1646
- const matchedParts = size.match(pointRegex);
1647
- // convert point to eighth of a point
1648
- size = pointToEIP(matchedParts[1]);
1649
- } else if (pixelRegex.test(size)) {
1650
- const matchedParts = size.match(pixelRegex);
1651
- // convert pixels to eighth of a point
1652
- size = pixelToEIP(matchedParts[1]);
1653
- }
1654
- stroke = stroke && ['dashed', 'dotted', 'double'].includes(stroke) ? stroke : 'single';
1655
-
1656
- color = color && fixupColorCode(color).toUpperCase();
1657
-
1658
- return [size, stroke, color];
1659
- };
1660
-
1661
- const buildTable = async (vNode, attributes, docxDocumentInstance) => {
1662
- const tableFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'tbl');
1663
- const modifiedAttributes = { ...attributes };
1664
- if (isVNode(vNode) && vNode.properties) {
1665
- const tableAttributes = vNode.properties.attributes || {};
1666
- const tableStyles = vNode.properties.style || {};
1667
- const tableBorders = {};
1668
- const tableCellBorders = {};
1669
- let [borderSize, borderStrike, borderColor] = [2, 'single', '000000'];
1670
-
1671
- // eslint-disable-next-line no-restricted-globals
1672
- if (!isNaN(tableAttributes.border)) {
1673
- borderSize = parseInt(tableAttributes.border, 10);
1674
- }
1675
-
1676
- // css style overrides table border properties
1677
- if (tableStyles.border) {
1678
- const [cssSize, cssStroke, cssColor] = cssBorderParser(tableStyles.border);
1679
- borderSize = cssSize || borderSize;
1680
- borderColor = cssColor || borderColor;
1681
- borderStrike = cssStroke || borderStrike;
1682
- }
1683
-
1684
- tableBorders.top = borderSize;
1685
- tableBorders.bottom = borderSize;
1686
- tableBorders.left = borderSize;
1687
- tableBorders.right = borderSize;
1688
- tableBorders.stroke = borderStrike;
1689
- tableBorders.color = borderColor;
1690
-
1691
- if (tableStyles['border-collapse'] === 'collapse') {
1692
- tableBorders.insideV = borderSize;
1693
- tableBorders.insideH = borderSize;
1694
- } else {
1695
- tableBorders.insideV = 0;
1696
- tableBorders.insideH = 0;
1697
- tableCellBorders.top = 1;
1698
- tableCellBorders.bottom = 1;
1699
- tableCellBorders.left = 1;
1700
- tableCellBorders.right = 1;
1701
- }
1702
-
1703
- modifiedAttributes.tableBorder = tableBorders;
1704
- modifiedAttributes.tableCellSpacing = 0;
1705
-
1706
- if (Object.keys(tableCellBorders).length) {
1707
- modifiedAttributes.tableCellBorder = tableCellBorders;
1708
- }
1709
-
1710
- let minimumWidth;
1711
- let maximumWidth;
1712
- let width;
1713
- // Calculate minimum width of table
1714
- if (pixelRegex.test(tableStyles['min-width'])) {
1715
- minimumWidth = pixelToTWIP(tableStyles['min-width'].match(pixelRegex)[1]);
1716
- } else if (percentageRegex.test(tableStyles['min-width'])) {
1717
- const percentageValue = tableStyles['min-width'].match(percentageRegex)[1];
1718
- minimumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
1719
- }
1720
-
1721
- // Calculate maximum width of table
1722
- if (pixelRegex.test(tableStyles['max-width'])) {
1723
- pixelRegex.lastIndex = 0;
1724
- maximumWidth = pixelToTWIP(tableStyles['max-width'].match(pixelRegex)[1]);
1725
- } else if (percentageRegex.test(tableStyles['max-width'])) {
1726
- percentageRegex.lastIndex = 0;
1727
- const percentageValue = tableStyles['max-width'].match(percentageRegex)[1];
1728
- maximumWidth = Math.round((percentageValue / 100) * attributes.maximumWidth);
1729
- }
1730
-
1731
- // Calculate specified width of table
1732
- if (pixelRegex.test(tableStyles.width)) {
1733
- pixelRegex.lastIndex = 0;
1734
- width = pixelToTWIP(tableStyles.width.match(pixelRegex)[1]);
1735
- } else if (percentageRegex.test(tableStyles.width)) {
1736
- percentageRegex.lastIndex = 0;
1737
- const percentageValue = tableStyles.width.match(percentageRegex)[1];
1738
- width = Math.round((percentageValue / 100) * attributes.maximumWidth);
1739
- }
1740
-
1741
- // If width isn't supplied, we should have min-width as the width.
1742
- if (width) {
1743
- modifiedAttributes.width = width;
1744
- if (maximumWidth) {
1745
- modifiedAttributes.width = Math.min(modifiedAttributes.width, maximumWidth);
1746
- }
1747
- if (minimumWidth) {
1748
- modifiedAttributes.width = Math.max(modifiedAttributes.width, minimumWidth);
1749
- }
1750
- } else if (minimumWidth) {
1751
- modifiedAttributes.width = minimumWidth;
1752
- }
1753
- if (modifiedAttributes.width) {
1754
- modifiedAttributes.width = Math.min(modifiedAttributes.width, attributes.maximumWidth);
1755
- }
1756
- }
1757
- const tablePropertiesFragment = buildTableProperties(modifiedAttributes);
1758
- tableFragment.import(tablePropertiesFragment);
1759
-
1760
- const rowSpanMap = new Map();
1761
-
1762
- if (vNodeHasChildren(vNode)) {
1763
- for (let index = 0; index < vNode.children.length; index++) {
1764
- const childVNode = vNode.children[index];
1765
- if (childVNode.tagName === 'colgroup') {
1766
- const tableGridFragment = buildTableGrid(childVNode, modifiedAttributes);
1767
- tableFragment.import(tableGridFragment);
1768
- } else if (childVNode.tagName === 'thead') {
1769
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
1770
- const grandChildVNode = childVNode.children[iteratorIndex];
1771
- if (grandChildVNode.tagName === 'tr') {
1772
- if (iteratorIndex === 0) {
1773
- const tableGridFragment = buildTableGridFromTableRow(
1774
- grandChildVNode,
1775
- modifiedAttributes
1776
- );
1777
- tableFragment.import(tableGridFragment);
1778
- }
1779
- const tableRowFragment = await buildTableRow(
1780
- grandChildVNode,
1781
- modifiedAttributes,
1782
- rowSpanMap,
1783
- docxDocumentInstance
1784
- );
1785
- tableFragment.import(tableRowFragment);
1786
- }
1787
- }
1788
- } else if (childVNode.tagName === 'tbody') {
1789
- for (let iteratorIndex = 0; iteratorIndex < childVNode.children.length; iteratorIndex++) {
1790
- const grandChildVNode = childVNode.children[iteratorIndex];
1791
- if (grandChildVNode.tagName === 'tr') {
1792
- if (iteratorIndex === 0) {
1793
- const tableGridFragment = buildTableGridFromTableRow(
1794
- grandChildVNode,
1795
- modifiedAttributes
1796
- );
1797
- tableFragment.import(tableGridFragment);
1798
- }
1799
- const tableRowFragment = await buildTableRow(
1800
- grandChildVNode,
1801
- modifiedAttributes,
1802
- rowSpanMap,
1803
- docxDocumentInstance
1804
- );
1805
- tableFragment.import(tableRowFragment);
1806
- }
1807
- }
1808
- } else if (childVNode.tagName === 'tr') {
1809
- if (index === 0) {
1810
- const tableGridFragment = buildTableGridFromTableRow(childVNode, modifiedAttributes);
1811
- tableFragment.import(tableGridFragment);
1812
- }
1813
- const tableRowFragment = await buildTableRow(
1814
- childVNode,
1815
- modifiedAttributes,
1816
- rowSpanMap,
1817
- docxDocumentInstance
1818
- );
1819
- tableFragment.import(tableRowFragment);
1820
- }
1821
- }
1822
- }
1823
- tableFragment.up();
1824
-
1825
- return tableFragment;
1826
- };
1827
-
1828
- const buildPresetGeometry = () =>
1829
- fragment({ namespaceAlias: { a: namespaces.a } })
1830
- .ele('@a', 'prstGeom')
1831
- .att('prst', 'rect')
1832
- .up();
1833
-
1834
- const buildExtents = ({ width, height }) =>
1835
- fragment({ namespaceAlias: { a: namespaces.a } })
1836
- .ele('@a', 'ext')
1837
- .att('cx', width)
1838
- .att('cy', height)
1839
- .up();
1840
-
1841
- const buildOffset = () =>
1842
- fragment({ namespaceAlias: { a: namespaces.a } })
1843
- .ele('@a', 'off')
1844
- .att('x', '0')
1845
- .att('y', '0')
1846
- .up();
1847
-
1848
- const buildGraphicFrameTransform = (attributes) => {
1849
- const graphicFrameTransformFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele(
1850
- '@a',
1851
- 'xfrm'
1852
- );
1853
-
1854
- const offsetFragment = buildOffset();
1855
- graphicFrameTransformFragment.import(offsetFragment);
1856
- const extentsFragment = buildExtents(attributes);
1857
- graphicFrameTransformFragment.import(extentsFragment);
1858
-
1859
- graphicFrameTransformFragment.up();
1860
-
1861
- return graphicFrameTransformFragment;
1862
- };
1863
-
1864
- const buildShapeProperties = (attributes) => {
1865
- const shapeProperties = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'spPr');
1866
-
1867
- const graphicFrameTransformFragment = buildGraphicFrameTransform(attributes);
1868
- shapeProperties.import(graphicFrameTransformFragment);
1869
- const presetGeometryFragment = buildPresetGeometry();
1870
- shapeProperties.import(presetGeometryFragment);
1871
-
1872
- shapeProperties.up();
1873
-
1874
- return shapeProperties;
1875
- };
1876
-
1877
- const buildFillRect = () =>
1878
- fragment({ namespaceAlias: { a: namespaces.a } })
1879
- .ele('@a', 'fillRect')
1880
- .up();
1881
-
1882
- const buildStretch = () => {
1883
- const stretchFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'stretch');
1884
-
1885
- const fillRectFragment = buildFillRect();
1886
- stretchFragment.import(fillRectFragment);
1887
-
1888
- stretchFragment.up();
1889
-
1890
- return stretchFragment;
1891
- };
1892
-
1893
- const buildSrcRectFragment = () =>
1894
- fragment({ namespaceAlias: { a: namespaces.a } })
1895
- .ele('@a', 'srcRect')
1896
- .att('b', '0')
1897
- .att('l', '0')
1898
- .att('r', '0')
1899
- .att('t', '0')
1900
- .up();
1901
-
1902
- const buildBinaryLargeImageOrPicture = (relationshipId) =>
1903
- fragment({
1904
- namespaceAlias: { a: namespaces.a, r: namespaces.r },
1905
- })
1906
- .ele('@a', 'blip')
1907
- .att('@r', 'embed', `rId${relationshipId}`)
1908
- // FIXME: possible values 'email', 'none', 'print', 'hqprint', 'screen'
1909
- .att('cstate', 'print')
1910
- .up();
1911
-
1912
- const buildBinaryLargeImageOrPictureFill = (relationshipId) => {
1913
- const binaryLargeImageOrPictureFillFragment = fragment({
1914
- namespaceAlias: { pic: namespaces.pic },
1915
- }).ele('@pic', 'blipFill');
1916
- const binaryLargeImageOrPictureFragment = buildBinaryLargeImageOrPicture(relationshipId);
1917
- binaryLargeImageOrPictureFillFragment.import(binaryLargeImageOrPictureFragment);
1918
- const srcRectFragment = buildSrcRectFragment();
1919
- binaryLargeImageOrPictureFillFragment.import(srcRectFragment);
1920
- const stretchFragment = buildStretch();
1921
- binaryLargeImageOrPictureFillFragment.import(stretchFragment);
1922
-
1923
- binaryLargeImageOrPictureFillFragment.up();
1924
-
1925
- return binaryLargeImageOrPictureFillFragment;
1926
- };
1927
-
1928
- const buildNonVisualPictureDrawingProperties = () =>
1929
- fragment({ namespaceAlias: { pic: namespaces.pic } })
1930
- .ele('@pic', 'cNvPicPr')
1931
- .up();
1932
-
1933
- const buildNonVisualDrawingProperties = (
1934
- pictureId,
1935
- pictureNameWithExtension,
1936
- pictureDescription = ''
1937
- ) =>
1938
- fragment({ namespaceAlias: { pic: namespaces.pic } })
1939
- .ele('@pic', 'cNvPr')
1940
- .att('id', pictureId)
1941
- .att('name', pictureNameWithExtension)
1942
- .att('descr', pictureDescription)
1943
- .up();
1944
-
1945
- const buildNonVisualPictureProperties = (
1946
- pictureId,
1947
- pictureNameWithExtension,
1948
- pictureDescription
1949
- ) => {
1950
- const nonVisualPicturePropertiesFragment = fragment({
1951
- namespaceAlias: { pic: namespaces.pic },
1952
- }).ele('@pic', 'nvPicPr');
1953
- // TODO: Handle picture attributes
1954
- const nonVisualDrawingPropertiesFragment = buildNonVisualDrawingProperties(
1955
- pictureId,
1956
- pictureNameWithExtension,
1957
- pictureDescription
1958
- );
1959
- nonVisualPicturePropertiesFragment.import(nonVisualDrawingPropertiesFragment);
1960
- const nonVisualPictureDrawingPropertiesFragment = buildNonVisualPictureDrawingProperties();
1961
- nonVisualPicturePropertiesFragment.import(nonVisualPictureDrawingPropertiesFragment);
1962
- nonVisualPicturePropertiesFragment.up();
1963
-
1964
- return nonVisualPicturePropertiesFragment;
1965
- };
1966
-
1967
- const buildPicture = ({
1968
- id,
1969
- fileNameWithExtension,
1970
- description,
1971
- relationshipId,
1972
- width,
1973
- height,
1974
- }) => {
1975
- const pictureFragment = fragment({ namespaceAlias: { pic: namespaces.pic } }).ele('@pic', 'pic');
1976
- const nonVisualPicturePropertiesFragment = buildNonVisualPictureProperties(
1977
- id,
1978
- fileNameWithExtension,
1979
- description
1980
- );
1981
- pictureFragment.import(nonVisualPicturePropertiesFragment);
1982
- const binaryLargeImageOrPictureFill = buildBinaryLargeImageOrPictureFill(relationshipId);
1983
- pictureFragment.import(binaryLargeImageOrPictureFill);
1984
- const shapeProperties = buildShapeProperties({ width, height });
1985
- pictureFragment.import(shapeProperties);
1986
- pictureFragment.up();
1987
-
1988
- return pictureFragment;
1989
- };
1990
-
1991
- const buildGraphicData = (graphicType, attributes) => {
1992
- const graphicDataFragment = fragment({ namespaceAlias: { a: namespaces.a } })
1993
- .ele('@a', 'graphicData')
1994
- .att('uri', 'http://schemas.openxmlformats.org/drawingml/2006/picture');
1995
- if (graphicType === 'picture') {
1996
- const pictureFragment = buildPicture(attributes);
1997
- graphicDataFragment.import(pictureFragment);
1998
- }
1999
- graphicDataFragment.up();
2000
-
2001
- return graphicDataFragment;
2002
- };
2003
-
2004
- const buildGraphic = (graphicType, attributes) => {
2005
- const graphicFragment = fragment({ namespaceAlias: { a: namespaces.a } }).ele('@a', 'graphic');
2006
- // TODO: Handle drawing type
2007
- const graphicDataFragment = buildGraphicData(graphicType, attributes);
2008
- graphicFragment.import(graphicDataFragment);
2009
- graphicFragment.up();
2010
-
2011
- return graphicFragment;
2012
- };
2013
-
2014
- const buildDrawingObjectNonVisualProperties = (pictureId, pictureName) =>
2015
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2016
- .ele('@wp', 'docPr')
2017
- .att('id', pictureId)
2018
- .att('name', pictureName)
2019
- .up();
2020
-
2021
- const buildWrapSquare = () =>
2022
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2023
- .ele('@wp', 'wrapSquare')
2024
- .att('wrapText', 'bothSides')
2025
- .att('distB', '228600')
2026
- .att('distT', '228600')
2027
- .att('distL', '228600')
2028
- .att('distR', '228600')
2029
- .up();
2030
-
2031
- // eslint-disable-next-line no-unused-vars
2032
- const buildWrapNone = () =>
2033
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2034
- .ele('@wp', 'wrapNone')
2035
- .up();
2036
-
2037
- const buildEffectExtentFragment = () =>
2038
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2039
- .ele('@wp', 'effectExtent')
2040
- .att('b', '0')
2041
- .att('l', '0')
2042
- .att('r', '0')
2043
- .att('t', '0')
2044
- .up();
2045
-
2046
- const buildExtent = ({ width, height }) =>
2047
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2048
- .ele('@wp', 'extent')
2049
- .att('cx', width)
2050
- .att('cy', height)
2051
- .up();
2052
-
2053
- const buildPositionV = () =>
2054
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2055
- .ele('@wp', 'positionV')
2056
- .att('relativeFrom', 'paragraph')
2057
- .ele('@wp', 'posOffset')
2058
- .txt('19050')
2059
- .up()
2060
- .up();
2061
-
2062
- const buildPositionH = () =>
2063
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2064
- .ele('@wp', 'positionH')
2065
- .att('relativeFrom', 'column')
2066
- .ele('@wp', 'posOffset')
2067
- .txt('19050')
2068
- .up()
2069
- .up();
2070
-
2071
- const buildSimplePos = () =>
2072
- fragment({ namespaceAlias: { wp: namespaces.wp } })
2073
- .ele('@wp', 'simplePos')
2074
- .att('x', '0')
2075
- .att('y', '0')
2076
- .up();
2077
-
2078
- const buildAnchoredDrawing = (graphicType, attributes) => {
2079
- const anchoredDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
2080
- .ele('@wp', 'anchor')
2081
- .att('distB', '0')
2082
- .att('distL', '0')
2083
- .att('distR', '0')
2084
- .att('distT', '0')
2085
- .att('relativeHeight', '0')
2086
- .att('behindDoc', 'false')
2087
- .att('locked', 'true')
2088
- .att('layoutInCell', 'true')
2089
- .att('allowOverlap', 'false')
2090
- .att('simplePos', 'false');
2091
- // Even though simplePos isnt supported by Word 2007 simplePos is required.
2092
- const simplePosFragment = buildSimplePos();
2093
- anchoredDrawingFragment.import(simplePosFragment);
2094
- const positionHFragment = buildPositionH();
2095
- anchoredDrawingFragment.import(positionHFragment);
2096
- const positionVFragment = buildPositionV();
2097
- anchoredDrawingFragment.import(positionVFragment);
2098
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
2099
- anchoredDrawingFragment.import(extentFragment);
2100
- const effectExtentFragment = buildEffectExtentFragment();
2101
- anchoredDrawingFragment.import(effectExtentFragment);
2102
- const wrapSquareFragment = buildWrapSquare();
2103
- anchoredDrawingFragment.import(wrapSquareFragment);
2104
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(
2105
- attributes.id,
2106
- attributes.fileNameWithExtension
2107
- );
2108
- anchoredDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
2109
- const graphicFragment = buildGraphic(graphicType, attributes);
2110
- anchoredDrawingFragment.import(graphicFragment);
2111
-
2112
- anchoredDrawingFragment.up();
2113
-
2114
- return anchoredDrawingFragment;
2115
- };
2116
-
2117
- const buildInlineDrawing = (graphicType, attributes) => {
2118
- const inlineDrawingFragment = fragment({ namespaceAlias: { wp: namespaces.wp } })
2119
- .ele('@wp', 'inline')
2120
- .att('distB', '0')
2121
- .att('distL', '0')
2122
- .att('distR', '0')
2123
- .att('distT', '0');
2124
-
2125
- const extentFragment = buildExtent({ width: attributes.width, height: attributes.height });
2126
- inlineDrawingFragment.import(extentFragment);
2127
- const effectExtentFragment = buildEffectExtentFragment();
2128
- inlineDrawingFragment.import(effectExtentFragment);
2129
- const drawingObjectNonVisualPropertiesFragment = buildDrawingObjectNonVisualProperties(
2130
- attributes.id,
2131
- attributes.fileNameWithExtension
2132
- );
2133
- inlineDrawingFragment.import(drawingObjectNonVisualPropertiesFragment);
2134
- const graphicFragment = buildGraphic(graphicType, attributes);
2135
- inlineDrawingFragment.import(graphicFragment);
2136
-
2137
- inlineDrawingFragment.up();
2138
-
2139
- return inlineDrawingFragment;
2140
- };
2141
-
2142
- const buildDrawing = (inlineOrAnchored = false, graphicType, attributes) => {
2143
- const drawingFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'drawing');
2144
- const inlineOrAnchoredDrawingFragment = inlineOrAnchored
2145
- ? buildInlineDrawing(graphicType, attributes)
2146
- : buildAnchoredDrawing(graphicType, attributes);
2147
- drawingFragment.import(inlineOrAnchoredDrawingFragment);
2148
- drawingFragment.up();
2149
-
2150
- return drawingFragment;
2151
- };
2152
-
2153
- export {
2154
- buildParagraph,
2155
- buildTable,
2156
- buildNumberingInstances,
2157
- buildLineBreak,
2158
- buildIndentation,
2159
- buildTextElement,
2160
- buildBold,
2161
- buildItalics,
2162
- buildUnderline,
2163
- buildDrawing,
2164
- fixupLineHeight,
2165
- };