easy-template-x 3.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -2
- package/dist/cjs/easy-template-x.js +184 -98
- package/dist/es/easy-template-x.js +177 -89
- package/dist/types/compilation/delimiterMark.d.ts +6 -6
- package/dist/types/compilation/delimiterSearcher.d.ts +16 -16
- package/dist/types/compilation/index.d.ts +7 -7
- package/dist/types/compilation/scopeData.d.ts +21 -21
- package/dist/types/compilation/tag.d.ts +14 -12
- package/dist/types/compilation/tagParser.d.ts +13 -13
- package/dist/types/compilation/templateCompiler.d.ts +25 -25
- package/dist/types/compilation/templateContext.d.ts +5 -5
- package/dist/types/delimiters.d.ts +10 -8
- package/dist/types/errors/index.d.ts +11 -10
- package/dist/types/errors/malformedFileError.d.ts +4 -4
- package/dist/types/errors/maxXmlDepthError.d.ts +4 -4
- package/dist/types/errors/missingArgumentError.d.ts +4 -4
- package/dist/types/errors/missingCloseDelimiterError.d.ts +4 -4
- package/dist/types/errors/missingStartDelimiterError.d.ts +4 -4
- package/dist/types/errors/tagOptionsParseError.d.ts +5 -0
- package/dist/types/errors/unclosedTagError.d.ts +4 -4
- package/dist/types/errors/unidentifiedFileTypeError.d.ts +3 -3
- package/dist/types/errors/unknownContentTypeError.d.ts +6 -6
- package/dist/types/errors/unopenedTagError.d.ts +4 -4
- package/dist/types/errors/unsupportedFileTypeError.d.ts +4 -4
- package/dist/types/extensions/extensionOptions.d.ts +5 -5
- package/dist/types/extensions/index.d.ts +2 -2
- package/dist/types/extensions/templateExtension.d.ts +14 -14
- package/dist/types/index.d.ts +13 -13
- package/dist/types/mimeType.d.ts +11 -11
- package/dist/types/office/contentPartType.d.ts +9 -9
- package/dist/types/office/contentTypesFile.d.ts +16 -16
- package/dist/types/office/docx.d.ts +28 -28
- package/dist/types/office/docxParser.d.ts +35 -35
- package/dist/types/office/index.d.ts +4 -4
- package/dist/types/office/mediaFiles.d.ts +14 -14
- package/dist/types/office/relationship.d.ts +11 -11
- package/dist/types/office/rels.d.ts +20 -20
- package/dist/types/office/xmlPart.d.ts +14 -14
- package/dist/types/plugins/defaultPlugins.d.ts +2 -2
- package/dist/types/plugins/image/imageContent.d.ts +12 -12
- package/dist/types/plugins/image/imagePlugin.d.ts +10 -10
- package/dist/types/plugins/image/index.d.ts +2 -2
- package/dist/types/plugins/index.d.ts +8 -8
- package/dist/types/plugins/link/index.d.ts +2 -2
- package/dist/types/plugins/link/linkContent.d.ts +7 -7
- package/dist/types/plugins/link/linkPlugin.d.ts +9 -9
- package/dist/types/plugins/loop/index.d.ts +1 -1
- package/dist/types/plugins/loop/loopPlugin.d.ts +13 -13
- package/dist/types/plugins/loop/loopTagOptions.d.ts +7 -0
- package/dist/types/plugins/loop/strategy/iLoopStrategy.d.ts +14 -14
- package/dist/types/plugins/loop/strategy/index.d.ts +4 -4
- package/dist/types/plugins/loop/strategy/loopListStrategy.d.ts +11 -11
- package/dist/types/plugins/loop/strategy/loopParagraphStrategy.d.ts +11 -11
- package/dist/types/plugins/loop/strategy/loopTableStrategy.d.ts +11 -11
- package/dist/types/plugins/pluginContent.d.ts +6 -6
- package/dist/types/plugins/rawXml/index.d.ts +2 -2
- package/dist/types/plugins/rawXml/rawXmlContent.d.ts +6 -6
- package/dist/types/plugins/rawXml/rawXmlPlugin.d.ts +6 -6
- package/dist/types/plugins/templatePlugin.d.ts +15 -15
- package/dist/types/plugins/text/index.d.ts +1 -1
- package/dist/types/plugins/text/textPlugin.d.ts +11 -11
- package/dist/types/templateData.d.ts +6 -6
- package/dist/types/templateHandler.d.ts +20 -20
- package/dist/types/templateHandlerOptions.d.ts +15 -15
- package/dist/types/types.d.ts +4 -6
- package/dist/types/utils/array.d.ts +6 -6
- package/dist/types/utils/base64.d.ts +3 -3
- package/dist/types/utils/binary.d.ts +11 -12
- package/dist/types/utils/index.d.ts +9 -9
- package/dist/types/utils/number.d.ts +1 -1
- package/dist/types/utils/path.d.ts +5 -5
- package/dist/types/utils/regex.d.ts +3 -3
- package/dist/types/utils/sha1.d.ts +1 -1
- package/dist/types/utils/txt.d.ts +2 -1
- package/dist/types/utils/types.d.ts +3 -3
- package/dist/types/xml/index.d.ts +3 -3
- package/dist/types/xml/xmlDepthTracker.d.ts +7 -7
- package/dist/types/xml/xmlNode.d.ts +58 -49
- package/dist/types/xml/xmlParser.d.ts +8 -8
- package/dist/types/zip/index.d.ts +2 -2
- package/dist/types/zip/jsZipHelper.d.ts +7 -7
- package/dist/types/zip/zip.d.ts +13 -13
- package/dist/types/zip/zipObject.d.ts +13 -13
- package/package.json +25 -19
- package/src/compilation/tag.ts +4 -2
- package/src/compilation/tagParser.ts +32 -13
- package/src/delimiters.ts +3 -1
- package/src/errors/index.ts +1 -0
- package/src/errors/malformedFileError.ts +1 -4
- package/src/errors/maxXmlDepthError.ts +1 -4
- package/src/errors/missingArgumentError.ts +1 -4
- package/src/errors/missingCloseDelimiterError.ts +1 -4
- package/src/errors/missingStartDelimiterError.ts +1 -4
- package/src/errors/tagOptionsParseError.ts +12 -0
- package/src/errors/unclosedTagError.ts +1 -4
- package/src/errors/unidentifiedFileTypeError.ts +1 -4
- package/src/errors/unknownContentTypeError.ts +1 -4
- package/src/errors/unopenedTagError.ts +1 -4
- package/src/errors/unsupportedFileTypeError.ts +1 -4
- package/src/office/docx.ts +4 -1
- package/src/office/docxParser.ts +3 -1
- package/src/plugins/loop/loopPlugin.ts +1 -1
- package/src/plugins/loop/loopTagOptions.ts +14 -0
- package/src/plugins/loop/strategy/loopTableStrategy.ts +22 -3
- package/src/plugins/templatePlugin.ts +0 -2
- package/src/types.ts +1 -3
- package/src/utils/txt.ts +29 -1
- package/src/xml/xmlNode.ts +50 -14
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ Generate docx documents from templates, in Node or in the browser.
|
|
|
14
14
|
- [Loop plugin](#loop-plugin)
|
|
15
15
|
- [Conditions](#conditions)
|
|
16
16
|
- [Nested Conditions](#nested-conditions)
|
|
17
|
+
- [Controlling loop behavior](#controlling-loop-behavior)
|
|
17
18
|
- [Image plugin](#image-plugin)
|
|
18
19
|
- [Link plugin](#link-plugin)
|
|
19
20
|
- [Raw xml plugin](#raw-xml-plugin)
|
|
@@ -121,7 +122,7 @@ function saveFile(filename, blob) {
|
|
|
121
122
|
|
|
122
123
|
## Live Demo
|
|
123
124
|
|
|
124
|
-
Checkout this [live demo](https://codesandbox.io/
|
|
125
|
+
Checkout this [live demo](https://codesandbox.io/p/sandbox/easy-template-x-demo-x4ppu?file=%2Findex.ts) on CodeSandbox 😎
|
|
125
126
|
|
|
126
127
|
## Plugins
|
|
127
128
|
|
|
@@ -253,6 +254,39 @@ Output document:
|
|
|
253
254
|
|
|
254
255
|
_If you are looking for a yet more powerful conditional syntax see the [alternative syntax](#advanced-syntax-and-custom-resolvers) section._
|
|
255
256
|
|
|
257
|
+
#### Controlling loop behavior
|
|
258
|
+
|
|
259
|
+
To control the loop (or condition) behavior you can use the `loopOver` option.
|
|
260
|
+
|
|
261
|
+
Given this data:
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
{
|
|
265
|
+
students: [
|
|
266
|
+
{ name: "Alice" },
|
|
267
|
+
{ name: "Bob" }
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
You can use either this template:
|
|
273
|
+
|
|
274
|
+

|
|
275
|
+
|
|
276
|
+
Or this one:
|
|
277
|
+
|
|
278
|
+

|
|
279
|
+
|
|
280
|
+
The first will produce this document:
|
|
281
|
+
|
|
282
|
+

|
|
283
|
+
|
|
284
|
+
And the second will produce this one:
|
|
285
|
+
|
|
286
|
+

|
|
287
|
+
|
|
288
|
+
By default `easy-template-x` will loop over "content" if the opening and closing loop tags are in the same table cell and "row" otherwise.
|
|
289
|
+
|
|
256
290
|
### Image plugin
|
|
257
291
|
|
|
258
292
|
Embed images into the document.
|
|
@@ -480,7 +514,9 @@ const handler = new TemplateHandler({
|
|
|
480
514
|
tagStart: "{",
|
|
481
515
|
tagEnd: "}",
|
|
482
516
|
containerTagOpen: "#",
|
|
483
|
-
containerTagClose: "/"
|
|
517
|
+
containerTagClose: "/",
|
|
518
|
+
tagOptionsStart: "[",
|
|
519
|
+
tagOptionsEnd: "]"
|
|
484
520
|
},
|
|
485
521
|
|
|
486
522
|
maxXmlDepth: 20,
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var xmldom = require('@xmldom/xmldom');
|
|
6
4
|
var getProp = require('lodash.get');
|
|
5
|
+
var JSON5 = require('json5');
|
|
7
6
|
var JSZip = require('jszip');
|
|
8
7
|
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
function _interopNamespace(e) {
|
|
12
|
-
if (e && e.__esModule) return e;
|
|
8
|
+
function _interopNamespaceDefault(e) {
|
|
13
9
|
var n = Object.create(null);
|
|
14
10
|
if (e) {
|
|
15
11
|
Object.keys(e).forEach(function (k) {
|
|
@@ -22,40 +18,34 @@ function _interopNamespace(e) {
|
|
|
22
18
|
}
|
|
23
19
|
});
|
|
24
20
|
}
|
|
25
|
-
n
|
|
21
|
+
n.default = e;
|
|
26
22
|
return Object.freeze(n);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
var
|
|
30
|
-
var JSZip__namespace = /*#__PURE__*/
|
|
25
|
+
var JSON5__namespace = /*#__PURE__*/_interopNamespaceDefault(JSON5);
|
|
26
|
+
var JSZip__namespace = /*#__PURE__*/_interopNamespaceDefault(JSZip);
|
|
31
27
|
|
|
32
|
-
function _defineProperty(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
writable: true
|
|
40
|
-
});
|
|
41
|
-
} else {
|
|
42
|
-
obj[key] = value;
|
|
43
|
-
}
|
|
44
|
-
return obj;
|
|
28
|
+
function _defineProperty(e, r, t) {
|
|
29
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
30
|
+
value: t,
|
|
31
|
+
enumerable: !0,
|
|
32
|
+
configurable: !0,
|
|
33
|
+
writable: !0
|
|
34
|
+
}) : e[r] = t, e;
|
|
45
35
|
}
|
|
46
|
-
function _toPrimitive(
|
|
47
|
-
if (
|
|
48
|
-
var
|
|
49
|
-
if (
|
|
50
|
-
var
|
|
51
|
-
if (
|
|
36
|
+
function _toPrimitive(t, r) {
|
|
37
|
+
if ("object" != typeof t || !t) return t;
|
|
38
|
+
var e = t[Symbol.toPrimitive];
|
|
39
|
+
if (void 0 !== e) {
|
|
40
|
+
var i = e.call(t, r || "default");
|
|
41
|
+
if ("object" != typeof i) return i;
|
|
52
42
|
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
53
43
|
}
|
|
54
|
-
return (
|
|
44
|
+
return ("string" === r ? String : Number)(t);
|
|
55
45
|
}
|
|
56
|
-
function _toPropertyKey(
|
|
57
|
-
var
|
|
58
|
-
return
|
|
46
|
+
function _toPropertyKey(t) {
|
|
47
|
+
var i = _toPrimitive(t, "string");
|
|
48
|
+
return "symbol" == typeof i ? i : i + "";
|
|
59
49
|
}
|
|
60
50
|
|
|
61
51
|
class MalformedFileError extends Error {
|
|
@@ -63,9 +53,6 @@ class MalformedFileError extends Error {
|
|
|
63
53
|
super(`Malformed file detected. Make sure the file is a valid ${expectedFileType} file.`);
|
|
64
54
|
_defineProperty(this, "expectedFileType", void 0);
|
|
65
55
|
this.expectedFileType = expectedFileType;
|
|
66
|
-
|
|
67
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
68
|
-
Object.setPrototypeOf(this, MalformedFileError.prototype);
|
|
69
56
|
}
|
|
70
57
|
}
|
|
71
58
|
|
|
@@ -74,9 +61,6 @@ class MaxXmlDepthError extends Error {
|
|
|
74
61
|
super(`XML maximum depth reached (max depth: ${maxDepth}).`);
|
|
75
62
|
_defineProperty(this, "maxDepth", void 0);
|
|
76
63
|
this.maxDepth = maxDepth;
|
|
77
|
-
|
|
78
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
79
|
-
Object.setPrototypeOf(this, MaxXmlDepthError.prototype);
|
|
80
64
|
}
|
|
81
65
|
}
|
|
82
66
|
|
|
@@ -85,9 +69,6 @@ class MissingArgumentError extends Error {
|
|
|
85
69
|
super(`Argument '${argName}' is missing.`);
|
|
86
70
|
_defineProperty(this, "argName", void 0);
|
|
87
71
|
this.argName = argName;
|
|
88
|
-
|
|
89
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
90
|
-
Object.setPrototypeOf(this, MissingArgumentError.prototype);
|
|
91
72
|
}
|
|
92
73
|
}
|
|
93
74
|
|
|
@@ -96,9 +77,6 @@ class MissingCloseDelimiterError extends Error {
|
|
|
96
77
|
super(`Close delimiter is missing from '${openDelimiterText}'.`);
|
|
97
78
|
_defineProperty(this, "openDelimiterText", void 0);
|
|
98
79
|
this.openDelimiterText = openDelimiterText;
|
|
99
|
-
|
|
100
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
101
|
-
Object.setPrototypeOf(this, MissingCloseDelimiterError.prototype);
|
|
102
80
|
}
|
|
103
81
|
}
|
|
104
82
|
|
|
@@ -107,9 +85,16 @@ class MissingStartDelimiterError extends Error {
|
|
|
107
85
|
super(`Open delimiter is missing from '${closeDelimiterText}'.`);
|
|
108
86
|
_defineProperty(this, "closeDelimiterText", void 0);
|
|
109
87
|
this.closeDelimiterText = closeDelimiterText;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
|
|
91
|
+
class TagOptionsParseError extends Error {
|
|
92
|
+
constructor(tagRawText, parseError) {
|
|
93
|
+
super(`Failed to parse tag options of '${tagRawText}': ${parseError.message}.`);
|
|
94
|
+
_defineProperty(this, "tagRawText", void 0);
|
|
95
|
+
_defineProperty(this, "parseError", void 0);
|
|
96
|
+
this.tagRawText = tagRawText;
|
|
97
|
+
this.parseError = parseError;
|
|
113
98
|
}
|
|
114
99
|
}
|
|
115
100
|
|
|
@@ -118,18 +103,12 @@ class UnclosedTagError extends Error {
|
|
|
118
103
|
super(`Tag '${tagName}' is never closed.`);
|
|
119
104
|
_defineProperty(this, "tagName", void 0);
|
|
120
105
|
this.tagName = tagName;
|
|
121
|
-
|
|
122
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
123
|
-
Object.setPrototypeOf(this, UnclosedTagError.prototype);
|
|
124
106
|
}
|
|
125
107
|
}
|
|
126
108
|
|
|
127
109
|
class UnidentifiedFileTypeError extends Error {
|
|
128
110
|
constructor() {
|
|
129
111
|
super(`The filetype for this file could not be identified, is this file corrupted?`);
|
|
130
|
-
|
|
131
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
132
|
-
Object.setPrototypeOf(this, UnidentifiedFileTypeError.prototype);
|
|
133
112
|
}
|
|
134
113
|
}
|
|
135
114
|
|
|
@@ -142,9 +121,6 @@ class UnknownContentTypeError extends Error {
|
|
|
142
121
|
this.contentType = contentType;
|
|
143
122
|
this.tagRawText = tagRawText;
|
|
144
123
|
this.path = path;
|
|
145
|
-
|
|
146
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
147
|
-
Object.setPrototypeOf(this, UnknownContentTypeError.prototype);
|
|
148
124
|
}
|
|
149
125
|
}
|
|
150
126
|
|
|
@@ -153,9 +129,6 @@ class UnopenedTagError extends Error {
|
|
|
153
129
|
super(`Tag '${tagName}' is closed but was never opened.`);
|
|
154
130
|
_defineProperty(this, "tagName", void 0);
|
|
155
131
|
this.tagName = tagName;
|
|
156
|
-
|
|
157
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
158
|
-
Object.setPrototypeOf(this, UnopenedTagError.prototype);
|
|
159
132
|
}
|
|
160
133
|
}
|
|
161
134
|
|
|
@@ -164,9 +137,6 @@ class UnsupportedFileTypeError extends Error {
|
|
|
164
137
|
super(`Filetype "${fileType}" is not supported.`);
|
|
165
138
|
_defineProperty(this, "fileType", void 0);
|
|
166
139
|
this.fileType = fileType;
|
|
167
|
-
|
|
168
|
-
// typescript hack: https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
169
|
-
Object.setPrototypeOf(this, UnsupportedFileTypeError.prototype);
|
|
170
140
|
}
|
|
171
141
|
}
|
|
172
142
|
|
|
@@ -416,12 +386,48 @@ function utf8Encode(str) {
|
|
|
416
386
|
return utfStr;
|
|
417
387
|
}
|
|
418
388
|
|
|
389
|
+
// Copied from: https://gist.github.com/thanpolas/244d9a13151caf5a12e42208b6111aa6
|
|
390
|
+
// And see: https://unicode-table.com/en/sets/quotation-marks/
|
|
391
|
+
const nonStandardDoubleQuotes = ['“',
|
|
392
|
+
// U+201c
|
|
393
|
+
'”',
|
|
394
|
+
// U+201d
|
|
395
|
+
'«',
|
|
396
|
+
// U+00AB
|
|
397
|
+
'»',
|
|
398
|
+
// U+00BB
|
|
399
|
+
'„',
|
|
400
|
+
// U+201E
|
|
401
|
+
'“',
|
|
402
|
+
// U+201C
|
|
403
|
+
'‟',
|
|
404
|
+
// U+201F
|
|
405
|
+
'”',
|
|
406
|
+
// U+201D
|
|
407
|
+
'❝',
|
|
408
|
+
// U+275D
|
|
409
|
+
'❞',
|
|
410
|
+
// U+275E
|
|
411
|
+
'〝',
|
|
412
|
+
// U+301D
|
|
413
|
+
'〞',
|
|
414
|
+
// U+301E
|
|
415
|
+
'〟',
|
|
416
|
+
// U+301F
|
|
417
|
+
'"' // U+FF02
|
|
418
|
+
];
|
|
419
|
+
const standardDoubleQuotes = '"'; // U+0022
|
|
420
|
+
|
|
421
|
+
const nonStandardDoubleQuotesRegex = new RegExp(nonStandardDoubleQuotes.join('|'), 'g');
|
|
419
422
|
function stringValue(val) {
|
|
420
423
|
if (val === null || val === undefined) {
|
|
421
424
|
return '';
|
|
422
425
|
}
|
|
423
426
|
return val.toString();
|
|
424
427
|
}
|
|
428
|
+
function normalizeDoubleQuotes(text) {
|
|
429
|
+
return text.replace(nonStandardDoubleQuotesRegex, standardDoubleQuotes);
|
|
430
|
+
}
|
|
425
431
|
|
|
426
432
|
class XmlDepthTracker {
|
|
427
433
|
constructor(maxDepth) {
|
|
@@ -442,10 +448,11 @@ class XmlDepthTracker {
|
|
|
442
448
|
let XmlNodeType = /*#__PURE__*/function (XmlNodeType) {
|
|
443
449
|
XmlNodeType["Text"] = "Text";
|
|
444
450
|
XmlNodeType["General"] = "General";
|
|
451
|
+
XmlNodeType["Comment"] = "Comment";
|
|
445
452
|
return XmlNodeType;
|
|
446
453
|
}({});
|
|
447
454
|
const TEXT_NODE_NAME = '#text'; // see: https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName
|
|
448
|
-
|
|
455
|
+
const COMMENT_NODE_NAME = '#comment';
|
|
449
456
|
const XmlNode = {
|
|
450
457
|
//
|
|
451
458
|
// factories
|
|
@@ -464,6 +471,13 @@ const XmlNode = {
|
|
|
464
471
|
nodeName: name
|
|
465
472
|
};
|
|
466
473
|
},
|
|
474
|
+
createCommentNode(text) {
|
|
475
|
+
return {
|
|
476
|
+
nodeType: XmlNodeType.Comment,
|
|
477
|
+
nodeName: COMMENT_NODE_NAME,
|
|
478
|
+
commentContent: text
|
|
479
|
+
};
|
|
480
|
+
},
|
|
467
481
|
//
|
|
468
482
|
// serialization
|
|
469
483
|
//
|
|
@@ -494,6 +508,9 @@ const XmlNode = {
|
|
|
494
508
|
},
|
|
495
509
|
serialize(node) {
|
|
496
510
|
if (this.isTextNode(node)) return this.encodeValue(node.textContent || '');
|
|
511
|
+
if (this.isCommentNode(node)) {
|
|
512
|
+
return `<!-- ${this.encodeValue(node.commentContent || '')} -->`;
|
|
513
|
+
}
|
|
497
514
|
|
|
498
515
|
// attributes
|
|
499
516
|
let attributes = '';
|
|
@@ -528,22 +545,36 @@ const XmlNode = {
|
|
|
528
545
|
let xmlNode;
|
|
529
546
|
|
|
530
547
|
// basic properties
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
xmlNode.
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
548
|
+
switch (domNode.nodeType) {
|
|
549
|
+
case domNode.TEXT_NODE:
|
|
550
|
+
{
|
|
551
|
+
xmlNode = this.createTextNode(domNode.textContent);
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
case domNode.COMMENT_NODE:
|
|
555
|
+
{
|
|
556
|
+
var _domNode$textContent;
|
|
557
|
+
xmlNode = this.createCommentNode((_domNode$textContent = domNode.textContent) === null || _domNode$textContent === void 0 ? void 0 : _domNode$textContent.trim());
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
case domNode.ELEMENT_NODE:
|
|
561
|
+
{
|
|
562
|
+
const generalNode = xmlNode = this.createGeneralNode(domNode.nodeName);
|
|
563
|
+
const attributes = domNode.attributes;
|
|
564
|
+
if (attributes) {
|
|
565
|
+
generalNode.attributes = {};
|
|
566
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
567
|
+
const curAttribute = attributes.item(i);
|
|
568
|
+
generalNode.attributes[curAttribute.name] = curAttribute.value;
|
|
569
|
+
}
|
|
544
570
|
}
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
default:
|
|
574
|
+
{
|
|
575
|
+
xmlNode = this.createGeneralNode(domNode.nodeName);
|
|
576
|
+
break;
|
|
545
577
|
}
|
|
546
|
-
}
|
|
547
578
|
}
|
|
548
579
|
|
|
549
580
|
// children
|
|
@@ -579,6 +610,15 @@ const XmlNode = {
|
|
|
579
610
|
}
|
|
580
611
|
return false;
|
|
581
612
|
},
|
|
613
|
+
isCommentNode(node) {
|
|
614
|
+
if (node.nodeType === XmlNodeType.Comment || node.nodeName === COMMENT_NODE_NAME) {
|
|
615
|
+
if (!(node.nodeType === XmlNodeType.Comment && node.nodeName === COMMENT_NODE_NAME)) {
|
|
616
|
+
throw new Error(`Invalid comment node. Type: '${node.nodeType}', Name: '${node.nodeName}'.`);
|
|
617
|
+
}
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
return false;
|
|
621
|
+
},
|
|
582
622
|
cloneNode(node, deep) {
|
|
583
623
|
if (!node) throw new MissingArgumentError("node");
|
|
584
624
|
if (!deep) {
|
|
@@ -810,9 +850,11 @@ const XmlNode = {
|
|
|
810
850
|
*
|
|
811
851
|
* * **Note:** Prefer calling with explicit index.
|
|
812
852
|
*/
|
|
853
|
+
|
|
813
854
|
/**
|
|
814
855
|
* Remove a child node from it's parent. Returns the removed child.
|
|
815
856
|
*/
|
|
857
|
+
|
|
816
858
|
function removeChild(parent, childOrIndex) {
|
|
817
859
|
if (!parent) throw new MissingArgumentError("parent");
|
|
818
860
|
if (childOrIndex === null || childOrIndex === undefined) throw new MissingArgumentError("childOrIndex");
|
|
@@ -1089,7 +1131,7 @@ class ScopeData {
|
|
|
1089
1131
|
const curPath = args.strPath.slice();
|
|
1090
1132
|
while (result === undefined && curPath.length) {
|
|
1091
1133
|
curPath.pop();
|
|
1092
|
-
result =
|
|
1134
|
+
result = getProp(args.data, curPath.concat(lastKey));
|
|
1093
1135
|
}
|
|
1094
1136
|
return result;
|
|
1095
1137
|
}
|
|
@@ -1139,7 +1181,8 @@ class TagParser {
|
|
|
1139
1181
|
_defineProperty(this, "tagRegex", void 0);
|
|
1140
1182
|
if (!docParser) throw new MissingArgumentError("docParser");
|
|
1141
1183
|
if (!delimiters) throw new MissingArgumentError("delimiters");
|
|
1142
|
-
|
|
1184
|
+
const tagOptionsRegex = `${Regex.escape(delimiters.tagOptionsStart)}(?<tagOptions>.*?)${Regex.escape(delimiters.tagOptionsEnd)}`;
|
|
1185
|
+
this.tagRegex = new RegExp(`^${Regex.escape(delimiters.tagStart)}(?<tagName>.*?)(${tagOptionsRegex})?${Regex.escape(delimiters.tagEnd)}`, 'm');
|
|
1143
1186
|
}
|
|
1144
1187
|
parse(delimiters) {
|
|
1145
1188
|
const tags = [];
|
|
@@ -1238,23 +1281,44 @@ class TagParser {
|
|
|
1238
1281
|
closeDelimiter.xmlTextNode = endTextNode;
|
|
1239
1282
|
}
|
|
1240
1283
|
processTag(tag) {
|
|
1284
|
+
var _tagParts$groups, _tagParts$groups2;
|
|
1241
1285
|
tag.rawText = tag.xmlTextNode.textContent;
|
|
1242
1286
|
const tagParts = this.tagRegex.exec(tag.rawText);
|
|
1243
|
-
const
|
|
1244
|
-
|
|
1287
|
+
const tagName = (((_tagParts$groups = tagParts.groups) === null || _tagParts$groups === void 0 ? void 0 : _tagParts$groups["tagName"]) || '').trim();
|
|
1288
|
+
|
|
1289
|
+
// Ignoring empty tags.
|
|
1290
|
+
if (!(tagName !== null && tagName !== void 0 && tagName.length)) {
|
|
1245
1291
|
tag.disposition = TagDisposition.SelfClosed;
|
|
1246
1292
|
return;
|
|
1247
1293
|
}
|
|
1248
|
-
|
|
1294
|
+
|
|
1295
|
+
// Tag options.
|
|
1296
|
+
const tagOptionsText = (((_tagParts$groups2 = tagParts.groups) === null || _tagParts$groups2 === void 0 ? void 0 : _tagParts$groups2["tagOptions"]) || '').trim();
|
|
1297
|
+
if (tagOptionsText) {
|
|
1298
|
+
try {
|
|
1299
|
+
tag.options = JSON5__namespace.parse("{" + normalizeDoubleQuotes(tagOptionsText) + "}");
|
|
1300
|
+
} catch (e) {
|
|
1301
|
+
throw new TagOptionsParseError(tag.rawText, e);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// Container open tag.
|
|
1306
|
+
if (tagName.startsWith(this.delimiters.containerTagOpen)) {
|
|
1249
1307
|
tag.disposition = TagDisposition.Open;
|
|
1250
|
-
tag.name =
|
|
1251
|
-
|
|
1308
|
+
tag.name = tagName.slice(this.delimiters.containerTagOpen.length).trim();
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// Container close tag.
|
|
1313
|
+
if (tagName.startsWith(this.delimiters.containerTagClose)) {
|
|
1252
1314
|
tag.disposition = TagDisposition.Close;
|
|
1253
|
-
tag.name =
|
|
1254
|
-
|
|
1255
|
-
tag.disposition = TagDisposition.SelfClosed;
|
|
1256
|
-
tag.name = tagContent;
|
|
1315
|
+
tag.name = tagName.slice(this.delimiters.containerTagClose.length).trim();
|
|
1316
|
+
return;
|
|
1257
1317
|
}
|
|
1318
|
+
|
|
1319
|
+
// Self-closed tag.
|
|
1320
|
+
tag.disposition = TagDisposition.SelfClosed;
|
|
1321
|
+
tag.name = tagName;
|
|
1258
1322
|
}
|
|
1259
1323
|
}
|
|
1260
1324
|
|
|
@@ -1297,8 +1361,6 @@ class MimeTypeHelper {
|
|
|
1297
1361
|
}
|
|
1298
1362
|
}
|
|
1299
1363
|
|
|
1300
|
-
/* eslint-disable @typescript-eslint/member-ordering */
|
|
1301
|
-
|
|
1302
1364
|
class TemplatePlugin {
|
|
1303
1365
|
constructor() {
|
|
1304
1366
|
/**
|
|
@@ -1851,6 +1913,7 @@ class Docx {
|
|
|
1851
1913
|
//
|
|
1852
1914
|
// static methods
|
|
1853
1915
|
//
|
|
1916
|
+
|
|
1854
1917
|
static async open(zip, xmlParser) {
|
|
1855
1918
|
const mainDocumentPath = await Docx.getMainDocumentPath(zip, xmlParser);
|
|
1856
1919
|
if (!mainDocumentPath) throw new MalformedFileError('docx');
|
|
@@ -1930,7 +1993,8 @@ class Docx {
|
|
|
1930
1993
|
// find the last section properties
|
|
1931
1994
|
// see: http://officeopenxml.com/WPsection.php
|
|
1932
1995
|
const docRoot = await this.mainDocument.xmlRoot();
|
|
1933
|
-
const body = docRoot.childNodes
|
|
1996
|
+
const body = docRoot.childNodes.find(node => node.nodeName == 'w:body');
|
|
1997
|
+
if (body == null) return null;
|
|
1934
1998
|
const sectionProps = last(body.childNodes.filter(node => node.nodeType === XmlNodeType.General));
|
|
1935
1999
|
if (sectionProps.nodeName != 'w:sectPr') return null;
|
|
1936
2000
|
|
|
@@ -1996,6 +2060,7 @@ class DocxParser {
|
|
|
1996
2060
|
//
|
|
1997
2061
|
// constructor
|
|
1998
2062
|
//
|
|
2063
|
+
|
|
1999
2064
|
constructor(xmlParser) {
|
|
2000
2065
|
this.xmlParser = xmlParser;
|
|
2001
2066
|
}
|
|
@@ -2146,7 +2211,10 @@ class DocxParser {
|
|
|
2146
2211
|
curWordTextNode = this.firstTextNodeChild(curRunNode);
|
|
2147
2212
|
}
|
|
2148
2213
|
while (curWordTextNode) {
|
|
2149
|
-
if (curWordTextNode.nodeName !== DocxParser.TEXT_NODE)
|
|
2214
|
+
if (curWordTextNode.nodeName !== DocxParser.TEXT_NODE) {
|
|
2215
|
+
curWordTextNode = curWordTextNode.nextSibling;
|
|
2216
|
+
continue;
|
|
2217
|
+
}
|
|
2150
2218
|
|
|
2151
2219
|
// move text to first node
|
|
2152
2220
|
const curXmlTextNode = XmlNode.lastTextChild(curWordTextNode);
|
|
@@ -2517,6 +2585,12 @@ class LoopParagraphStrategy {
|
|
|
2517
2585
|
}
|
|
2518
2586
|
}
|
|
2519
2587
|
|
|
2588
|
+
let LoopOver = /*#__PURE__*/function (LoopOver) {
|
|
2589
|
+
LoopOver["Row"] = "row";
|
|
2590
|
+
LoopOver["Content"] = "content";
|
|
2591
|
+
return LoopOver;
|
|
2592
|
+
}({});
|
|
2593
|
+
|
|
2520
2594
|
class LoopTableStrategy {
|
|
2521
2595
|
constructor() {
|
|
2522
2596
|
_defineProperty(this, "utilities", void 0);
|
|
@@ -2525,9 +2599,18 @@ class LoopTableStrategy {
|
|
|
2525
2599
|
this.utilities = utilities;
|
|
2526
2600
|
}
|
|
2527
2601
|
isApplicable(openTag, closeTag) {
|
|
2528
|
-
const
|
|
2529
|
-
if (!
|
|
2530
|
-
|
|
2602
|
+
const openParagraph = this.utilities.docxParser.containingParagraphNode(openTag.xmlTextNode);
|
|
2603
|
+
if (!openParagraph.parentNode) return false;
|
|
2604
|
+
if (!this.utilities.docxParser.isTableCellNode(openParagraph.parentNode)) return false;
|
|
2605
|
+
const closeParagraph = this.utilities.docxParser.containingParagraphNode(closeTag.xmlTextNode);
|
|
2606
|
+
if (!closeParagraph.parentNode) return false;
|
|
2607
|
+
if (!this.utilities.docxParser.isTableCellNode(closeParagraph.parentNode)) return false;
|
|
2608
|
+
const options = openTag.options;
|
|
2609
|
+
const forceRowLoop = (options === null || options === void 0 ? void 0 : options.loopOver) === LoopOver.Row;
|
|
2610
|
+
|
|
2611
|
+
// If both tags are in the same cell, assume it's a paragraph loop (iterate content, not rows).
|
|
2612
|
+
if (!forceRowLoop && openParagraph.parentNode === closeParagraph.parentNode) return false;
|
|
2613
|
+
return true;
|
|
2531
2614
|
}
|
|
2532
2615
|
splitBefore(openTag, closeTag) {
|
|
2533
2616
|
const firstRow = this.utilities.docxParser.containingTableRowNode(openTag.xmlTextNode);
|
|
@@ -2566,7 +2649,6 @@ class LoopPlugin extends TemplatePlugin {
|
|
|
2566
2649
|
_defineProperty(this, "loopStrategies", [new LoopTableStrategy(), new LoopListStrategy(), new LoopParagraphStrategy() // the default strategy
|
|
2567
2650
|
]);
|
|
2568
2651
|
}
|
|
2569
|
-
|
|
2570
2652
|
setUtilities(utilities) {
|
|
2571
2653
|
this.utilities = utilities;
|
|
2572
2654
|
this.loopStrategies.forEach(strategy => strategy.setUtilities(utilities));
|
|
@@ -2577,7 +2659,7 @@ class LoopPlugin extends TemplatePlugin {
|
|
|
2577
2659
|
// Non array value - treat as a boolean condition.
|
|
2578
2660
|
const isCondition = !Array.isArray(value);
|
|
2579
2661
|
if (isCondition) {
|
|
2580
|
-
if (
|
|
2662
|
+
if (value) {
|
|
2581
2663
|
value = [{}];
|
|
2582
2664
|
} else {
|
|
2583
2665
|
value = [];
|
|
@@ -2948,7 +3030,6 @@ class Zip {
|
|
|
2948
3030
|
level: 6 // between 1 (best speed) and 9 (best compression)
|
|
2949
3031
|
}
|
|
2950
3032
|
});
|
|
2951
|
-
|
|
2952
3033
|
return output;
|
|
2953
3034
|
}
|
|
2954
3035
|
}
|
|
@@ -2959,6 +3040,8 @@ class Delimiters {
|
|
|
2959
3040
|
_defineProperty(this, "tagEnd", "}");
|
|
2960
3041
|
_defineProperty(this, "containerTagOpen", "#");
|
|
2961
3042
|
_defineProperty(this, "containerTagClose", "/");
|
|
3043
|
+
_defineProperty(this, "tagOptionsStart", "[");
|
|
3044
|
+
_defineProperty(this, "tagOptionsEnd", "]");
|
|
2962
3045
|
Object.assign(this, initial);
|
|
2963
3046
|
this.encodeAndValidate();
|
|
2964
3047
|
if (this.containerTagOpen === this.containerTagClose) throw new Error(`${"containerTagOpen"} can not be equal to ${"containerTagClose"}`);
|
|
@@ -3006,7 +3089,7 @@ class TemplateHandler {
|
|
|
3006
3089
|
/**
|
|
3007
3090
|
* Version number of the `easy-template-x` library.
|
|
3008
3091
|
*/
|
|
3009
|
-
_defineProperty(this, "version", "3.2.
|
|
3092
|
+
_defineProperty(this, "version", "3.2.1" );
|
|
3010
3093
|
_defineProperty(this, "xmlParser", new XmlParser());
|
|
3011
3094
|
_defineProperty(this, "docxParser", void 0);
|
|
3012
3095
|
_defineProperty(this, "compiler", void 0);
|
|
@@ -3156,6 +3239,7 @@ class TemplateHandler {
|
|
|
3156
3239
|
|
|
3157
3240
|
exports.Base64 = Base64;
|
|
3158
3241
|
exports.Binary = Binary;
|
|
3242
|
+
exports.COMMENT_NODE_NAME = COMMENT_NODE_NAME;
|
|
3159
3243
|
exports.ContentPartType = ContentPartType;
|
|
3160
3244
|
exports.DelimiterSearcher = DelimiterSearcher;
|
|
3161
3245
|
exports.Delimiters = Delimiters;
|
|
@@ -3180,6 +3264,7 @@ exports.ScopeData = ScopeData;
|
|
|
3180
3264
|
exports.TEXT_CONTENT_TYPE = TEXT_CONTENT_TYPE;
|
|
3181
3265
|
exports.TEXT_NODE_NAME = TEXT_NODE_NAME;
|
|
3182
3266
|
exports.TagDisposition = TagDisposition;
|
|
3267
|
+
exports.TagOptionsParseError = TagOptionsParseError;
|
|
3183
3268
|
exports.TagParser = TagParser;
|
|
3184
3269
|
exports.TemplateCompiler = TemplateCompiler;
|
|
3185
3270
|
exports.TemplateExtension = TemplateExtension;
|
|
@@ -3205,6 +3290,7 @@ exports.inheritsFrom = inheritsFrom;
|
|
|
3205
3290
|
exports.isNumber = isNumber;
|
|
3206
3291
|
exports.isPromiseLike = isPromiseLike;
|
|
3207
3292
|
exports.last = last;
|
|
3293
|
+
exports.normalizeDoubleQuotes = normalizeDoubleQuotes;
|
|
3208
3294
|
exports.pushMany = pushMany;
|
|
3209
3295
|
exports.sha1 = sha1;
|
|
3210
3296
|
exports.stringValue = stringValue;
|