easy-template-x 4.1.1 → 4.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,48 +5,6 @@ var getProp = require('lodash.get');
5
5
  var JSON5 = require('json5');
6
6
  var JSZip = require('jszip');
7
7
 
8
- function _interopNamespaceDefault(e) {
9
- var n = Object.create(null);
10
- if (e) {
11
- Object.keys(e).forEach(function (k) {
12
- if (k !== 'default') {
13
- var d = Object.getOwnPropertyDescriptor(e, k);
14
- Object.defineProperty(n, k, d.get ? d : {
15
- enumerable: true,
16
- get: function () { return e[k]; }
17
- });
18
- }
19
- });
20
- }
21
- n.default = e;
22
- return Object.freeze(n);
23
- }
24
-
25
- var JSON5__namespace = /*#__PURE__*/_interopNamespaceDefault(JSON5);
26
-
27
- function _defineProperty(e, r, t) {
28
- return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
29
- value: t,
30
- enumerable: !0,
31
- configurable: !0,
32
- writable: !0
33
- }) : e[r] = t, e;
34
- }
35
- function _toPrimitive(t, r) {
36
- if ("object" != typeof t || !t) return t;
37
- var e = t[Symbol.toPrimitive];
38
- if (void 0 !== e) {
39
- var i = e.call(t, r || "default");
40
- if ("object" != typeof i) return i;
41
- throw new TypeError("@@toPrimitive must return a primitive value.");
42
- }
43
- return ("string" === r ? String : Number)(t);
44
- }
45
- function _toPropertyKey(t) {
46
- var i = _toPrimitive(t, "string");
47
- return "symbol" == typeof i ? i : i + "";
48
- }
49
-
50
8
  class ArgumentError extends Error {
51
9
  constructor(message) {
52
10
  super(message);
@@ -56,7 +14,6 @@ class ArgumentError extends Error {
56
14
  class MalformedFileError extends Error {
57
15
  constructor(expectedFileType) {
58
16
  super(`Malformed file detected. Make sure the file is a valid ${expectedFileType} file.`);
59
- _defineProperty(this, "expectedFileType", void 0);
60
17
  this.expectedFileType = expectedFileType;
61
18
  }
62
19
  }
@@ -64,7 +21,6 @@ class MalformedFileError extends Error {
64
21
  class MaxXmlDepthError extends Error {
65
22
  constructor(maxDepth) {
66
23
  super(`XML maximum depth reached (max depth: ${maxDepth}).`);
67
- _defineProperty(this, "maxDepth", void 0);
68
24
  this.maxDepth = maxDepth;
69
25
  }
70
26
  }
@@ -72,7 +28,6 @@ class MaxXmlDepthError extends Error {
72
28
  class MissingArgumentError extends ArgumentError {
73
29
  constructor(argName) {
74
30
  super(`Argument '${argName}' is missing.`);
75
- _defineProperty(this, "argName", void 0);
76
31
  this.argName = argName;
77
32
  }
78
33
  }
@@ -80,7 +35,6 @@ class MissingArgumentError extends ArgumentError {
80
35
  class MissingCloseDelimiterError extends Error {
81
36
  constructor(openDelimiterText) {
82
37
  super(`Close delimiter is missing from '${openDelimiterText}'.`);
83
- _defineProperty(this, "openDelimiterText", void 0);
84
38
  this.openDelimiterText = openDelimiterText;
85
39
  }
86
40
  }
@@ -88,7 +42,6 @@ class MissingCloseDelimiterError extends Error {
88
42
  class MissingStartDelimiterError extends Error {
89
43
  constructor(closeDelimiterText) {
90
44
  super(`Open delimiter is missing from '${closeDelimiterText}'.`);
91
- _defineProperty(this, "closeDelimiterText", void 0);
92
45
  this.closeDelimiterText = closeDelimiterText;
93
46
  }
94
47
  }
@@ -96,8 +49,6 @@ class MissingStartDelimiterError extends Error {
96
49
  class TagOptionsParseError extends Error {
97
50
  constructor(tagRawText, parseError) {
98
51
  super(`Failed to parse tag options of '${tagRawText}': ${parseError.message}.`);
99
- _defineProperty(this, "tagRawText", void 0);
100
- _defineProperty(this, "parseError", void 0);
101
52
  this.tagRawText = tagRawText;
102
53
  this.parseError = parseError;
103
54
  }
@@ -106,7 +57,6 @@ class TagOptionsParseError extends Error {
106
57
  class UnclosedTagError extends Error {
107
58
  constructor(tagName) {
108
59
  super(`Tag '${tagName}' is never closed.`);
109
- _defineProperty(this, "tagName", void 0);
110
60
  this.tagName = tagName;
111
61
  }
112
62
  }
@@ -120,9 +70,6 @@ class UnidentifiedFileTypeError extends Error {
120
70
  class UnknownContentTypeError extends Error {
121
71
  constructor(contentType, tagRawText, path) {
122
72
  super(`Content type '${contentType}' does not have a registered plugin to handle it.`);
123
- _defineProperty(this, "tagRawText", void 0);
124
- _defineProperty(this, "contentType", void 0);
125
- _defineProperty(this, "path", void 0);
126
73
  this.contentType = contentType;
127
74
  this.tagRawText = tagRawText;
128
75
  this.path = path;
@@ -132,7 +79,6 @@ class UnknownContentTypeError extends Error {
132
79
  class UnopenedTagError extends Error {
133
80
  constructor(tagName) {
134
81
  super(`Tag '${tagName}' is closed but was never opened.`);
135
- _defineProperty(this, "tagName", void 0);
136
82
  this.tagName = tagName;
137
83
  }
138
84
  }
@@ -140,7 +86,6 @@ class UnopenedTagError extends Error {
140
86
  class UnsupportedFileTypeError extends Error {
141
87
  constructor(fileType) {
142
88
  super(`Filetype "${fileType}" is not supported.`);
143
- _defineProperty(this, "fileType", void 0);
144
89
  this.fileType = fileType;
145
90
  }
146
91
  }
@@ -252,7 +197,7 @@ class Path {
252
197
  return path.substring(0, lastSlashIndex);
253
198
  }
254
199
  static combine(...parts) {
255
- return parts.filter(part => part === null || part === void 0 ? void 0 : part.trim()).join('/');
200
+ return parts.filter(part => part?.trim()).join('/');
256
201
  }
257
202
  }
258
203
 
@@ -435,9 +380,9 @@ function normalizeDoubleQuotes(text) {
435
380
  }
436
381
 
437
382
  class XmlDepthTracker {
383
+ depth = 0;
438
384
  constructor(maxDepth) {
439
385
  this.maxDepth = maxDepth;
440
- _defineProperty(this, "depth", 0);
441
386
  }
442
387
  increment() {
443
388
  this.depth++;
@@ -558,8 +503,7 @@ const XmlNode = {
558
503
  }
559
504
  case domNode.COMMENT_NODE:
560
505
  {
561
- var _domNode$textContent;
562
- xmlNode = this.createCommentNode((_domNode$textContent = domNode.textContent) === null || _domNode$textContent === void 0 ? void 0 : _domNode$textContent.trim());
506
+ xmlNode = this.createCommentNode(domNode.textContent?.trim());
563
507
  break;
564
508
  }
565
509
  case domNode.ELEMENT_NODE:
@@ -945,6 +889,13 @@ function recursiveRemoveEmptyTextNodes(node) {
945
889
  }
946
890
 
947
891
  class XmlParser {
892
+ static xmlHeader = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
893
+ /**
894
+ * We always use the DOMParser from 'xmldom', even in the browser since it
895
+ * handles xml namespaces more forgivingly (required mainly by the
896
+ * RawXmlPlugin).
897
+ */
898
+ static parser = new xmldom.DOMParser();
948
899
  parse(str) {
949
900
  const doc = this.domParse(str);
950
901
  return XmlNode.fromDomNode(doc.documentElement);
@@ -957,20 +908,28 @@ class XmlParser {
957
908
  return XmlParser.xmlHeader + XmlNode.serialize(xmlNode);
958
909
  }
959
910
  }
960
- _defineProperty(XmlParser, "xmlHeader", '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
961
- /**
962
- * We always use the DOMParser from 'xmldom', even in the browser since it
963
- * handles xml namespaces more forgivingly (required mainly by the
964
- * RawXmlPlugin).
965
- */
966
- _defineProperty(XmlParser, "parser", new xmldom.DOMParser());
967
911
 
968
912
  class MatchState {
969
- constructor() {
970
- _defineProperty(this, "delimiterIndex", 0);
971
- _defineProperty(this, "openNodes", []);
972
- _defineProperty(this, "firstMatchIndex", -1);
973
- }
913
+ /**
914
+ * The index of the current delimiter character being matched.
915
+ *
916
+ * Example: If the delimiter is `{!` and delimiterIndex is 0, it means we
917
+ * are now looking for the character `{`. If it is 1, then we are looking
918
+ * for `!`.
919
+ */
920
+ delimiterIndex = 0;
921
+ /**
922
+ * The list of text nodes containing the delimiter characters.
923
+ */
924
+ openNodes = [];
925
+ /**
926
+ * The index of the first character of the delimiter, in the text node it
927
+ * was found at.
928
+ *
929
+ * Example: If the delimiter is `{!`, and the text node content is `abc{!xyz`,
930
+ * then the firstMatchIndex is 3.
931
+ */
932
+ firstMatchIndex = -1;
974
933
  reset() {
975
934
  this.delimiterIndex = 0;
976
935
  this.openNodes = [];
@@ -978,11 +937,11 @@ class MatchState {
978
937
  }
979
938
  }
980
939
  class DelimiterSearcher {
940
+ maxXmlDepth = 20;
941
+ startDelimiter = "{";
942
+ endDelimiter = "}";
981
943
  constructor(docxParser) {
982
944
  this.docxParser = docxParser;
983
- _defineProperty(this, "maxXmlDepth", 20);
984
- _defineProperty(this, "startDelimiter", "{");
985
- _defineProperty(this, "endDelimiter", "}");
986
945
  if (!docxParser) throw new MissingArgumentError("docxParser");
987
946
  }
988
947
  findDelimiters(node) {
@@ -992,8 +951,8 @@ class DelimiterSearcher {
992
951
  // The search efficiency is o(m*n) where n is the text size and m is the
993
952
  // delimiter length. We could use a variation of the KMP algorithm here
994
953
  // to reduce it to o(m+n) but since our m is expected to be small
995
- // (delimiters defaults to 2 characters and even on custom inputs are
996
- // not expected to be much longer) it does not worth the extra
954
+ // (delimiters defaults to a single characters and even on custom inputs
955
+ // are not expected to be much longer) it does not worth the extra
997
956
  // complexity and effort.
998
957
  //
999
958
 
@@ -1002,44 +961,44 @@ class DelimiterSearcher {
1002
961
  const depth = new XmlDepthTracker(this.maxXmlDepth);
1003
962
  let lookForOpenDelimiter = true;
1004
963
  while (node) {
1005
- // reset state on paragraph transition
964
+ // Reset state on paragraph transition
1006
965
  if (this.docxParser.isParagraphNode(node)) {
1007
966
  match.reset();
1008
967
  }
1009
968
 
1010
- // skip irrelevant nodes
969
+ // Skip irrelevant nodes
1011
970
  if (!this.shouldSearchNode(node)) {
1012
971
  node = this.findNextNode(node, depth);
1013
972
  continue;
1014
973
  }
1015
974
 
1016
- // search delimiters in text nodes
975
+ // Search delimiters in text nodes
1017
976
  match.openNodes.push(node);
1018
977
  let textIndex = 0;
1019
978
  while (textIndex < node.textContent.length) {
1020
979
  const delimiterPattern = lookForOpenDelimiter ? this.startDelimiter : this.endDelimiter;
1021
980
  const char = node.textContent[textIndex];
1022
981
 
1023
- // no match
982
+ // No match
1024
983
  if (char !== delimiterPattern[match.delimiterIndex]) {
1025
984
  [node, textIndex] = this.noMatch(node, textIndex, match);
1026
985
  textIndex++;
1027
986
  continue;
1028
987
  }
1029
988
 
1030
- // first match
989
+ // First match
1031
990
  if (match.firstMatchIndex === -1) {
1032
991
  match.firstMatchIndex = textIndex;
1033
992
  }
1034
993
 
1035
- // partial match
994
+ // Partial match
1036
995
  if (match.delimiterIndex !== delimiterPattern.length - 1) {
1037
996
  match.delimiterIndex++;
1038
997
  textIndex++;
1039
998
  continue;
1040
999
  }
1041
1000
 
1042
- // full delimiter match
1001
+ // Full delimiter match
1043
1002
  [node, textIndex, lookForOpenDelimiter] = this.fullMatch(node, textIndex, lookForOpenDelimiter, match, delimiters);
1044
1003
  textIndex++;
1045
1004
  }
@@ -1049,7 +1008,7 @@ class DelimiterSearcher {
1049
1008
  }
1050
1009
  noMatch(node, textIndex, match) {
1051
1010
  //
1052
- // go back to first open node
1011
+ // Go back to first open node
1053
1012
  //
1054
1013
  // Required for cases where the text has repeating
1055
1014
  // characters that are the same as a delimiter prefix.
@@ -1061,7 +1020,7 @@ class DelimiterSearcher {
1061
1020
  textIndex = match.firstMatchIndex;
1062
1021
  }
1063
1022
 
1064
- // update state
1023
+ // Update state
1065
1024
  match.reset();
1066
1025
  if (textIndex < node.textContent.length - 1) {
1067
1026
  match.openNodes.push(node);
@@ -1069,7 +1028,7 @@ class DelimiterSearcher {
1069
1028
  return [node, textIndex];
1070
1029
  }
1071
1030
  fullMatch(node, textIndex, lookForOpenDelimiter, match, delimiters) {
1072
- // move all delimiters characters to the same text node
1031
+ // Move all delimiters characters to the same text node
1073
1032
  if (match.openNodes.length > 1) {
1074
1033
  const firstNode = first(match.openNodes);
1075
1034
  const lastNode = last(match.openNodes);
@@ -1078,11 +1037,11 @@ class DelimiterSearcher {
1078
1037
  node = firstNode;
1079
1038
  }
1080
1039
 
1081
- // store delimiter
1040
+ // Store delimiter
1082
1041
  const delimiterMark = this.createDelimiterMark(match, lookForOpenDelimiter);
1083
1042
  delimiters.push(delimiterMark);
1084
1043
 
1085
- // update state
1044
+ // Update state
1086
1045
  lookForOpenDelimiter = !lookForOpenDelimiter;
1087
1046
  match.reset();
1088
1047
  if (textIndex < node.textContent.length - 1) {
@@ -1098,23 +1057,23 @@ class DelimiterSearcher {
1098
1057
  return true;
1099
1058
  }
1100
1059
  findNextNode(node, depth) {
1101
- // children
1060
+ // Children
1102
1061
  if (node.childNodes && node.childNodes.length) {
1103
1062
  depth.increment();
1104
1063
  return node.childNodes[0];
1105
1064
  }
1106
1065
 
1107
- // siblings
1066
+ // Siblings
1108
1067
  if (node.nextSibling) return node.nextSibling;
1109
1068
 
1110
- // parent sibling
1069
+ // Parent sibling
1111
1070
  while (node.parentNode) {
1112
1071
  if (node.parentNode.nextSibling) {
1113
1072
  depth.decrement();
1114
1073
  return node.parentNode.nextSibling;
1115
1074
  }
1116
1075
 
1117
- // go up
1076
+ // Go up
1118
1077
  depth.decrement();
1119
1078
  node = node.parentNode;
1120
1079
  }
@@ -1140,11 +1099,9 @@ class ScopeData {
1140
1099
  }
1141
1100
  return result;
1142
1101
  }
1102
+ path = [];
1103
+ strPath = [];
1143
1104
  constructor(data) {
1144
- _defineProperty(this, "scopeDataResolver", void 0);
1145
- _defineProperty(this, "allData", void 0);
1146
- _defineProperty(this, "path", []);
1147
- _defineProperty(this, "strPath", []);
1148
1105
  this.allData = data;
1149
1106
  }
1150
1107
  pathPush(pathPart) {
@@ -1183,7 +1140,6 @@ class TagParser {
1183
1140
  constructor(docParser, delimiters) {
1184
1141
  this.docParser = docParser;
1185
1142
  this.delimiters = delimiters;
1186
- _defineProperty(this, "tagRegex", void 0);
1187
1143
  if (!docParser) throw new MissingArgumentError("docParser");
1188
1144
  if (!delimiters) throw new MissingArgumentError("delimiters");
1189
1145
  const tagOptionsRegex = `${Regex.escape(delimiters.tagOptionsStart)}(?<tagOptions>.*?)${Regex.escape(delimiters.tagOptionsEnd)}`;
@@ -1286,22 +1242,21 @@ class TagParser {
1286
1242
  closeDelimiter.xmlTextNode = endTextNode;
1287
1243
  }
1288
1244
  processTag(tag) {
1289
- var _tagParts$groups, _tagParts$groups2;
1290
1245
  tag.rawText = tag.xmlTextNode.textContent;
1291
1246
  const tagParts = this.tagRegex.exec(tag.rawText);
1292
- const tagName = (((_tagParts$groups = tagParts.groups) === null || _tagParts$groups === void 0 ? void 0 : _tagParts$groups["tagName"]) || '').trim();
1247
+ const tagName = (tagParts.groups?.["tagName"] || '').trim();
1293
1248
 
1294
1249
  // Ignoring empty tags.
1295
- if (!(tagName !== null && tagName !== void 0 && tagName.length)) {
1250
+ if (!tagName?.length) {
1296
1251
  tag.disposition = TagDisposition.SelfClosed;
1297
1252
  return;
1298
1253
  }
1299
1254
 
1300
1255
  // Tag options.
1301
- const tagOptionsText = (((_tagParts$groups2 = tagParts.groups) === null || _tagParts$groups2 === void 0 ? void 0 : _tagParts$groups2["tagOptions"]) || '').trim();
1256
+ const tagOptionsText = (tagParts.groups?.["tagOptions"] || '').trim();
1302
1257
  if (tagOptionsText) {
1303
1258
  try {
1304
- tag.options = JSON5__namespace.parse("{" + normalizeDoubleQuotes(tagOptionsText) + "}");
1259
+ tag.options = JSON5.parse("{" + normalizeDoubleQuotes(tagOptionsText) + "}");
1305
1260
  } catch (e) {
1306
1261
  throw new TagOptionsParseError(tag.rawText, e);
1307
1262
  }
@@ -1367,13 +1322,10 @@ class MimeTypeHelper {
1367
1322
  }
1368
1323
 
1369
1324
  class TemplatePlugin {
1370
- constructor() {
1371
- /**
1372
- * The content type this plugin handles.
1373
- */
1374
- _defineProperty(this, "contentType", void 0);
1375
- _defineProperty(this, "utilities", void 0);
1376
- }
1325
+ /**
1326
+ * The content type this plugin handles.
1327
+ */
1328
+
1377
1329
  /**
1378
1330
  * Called by the TemplateHandler at runtime.
1379
1331
  */
@@ -1414,10 +1366,7 @@ class TemplatePlugin {
1414
1366
  */
1415
1367
  let nextImageId = 1;
1416
1368
  class ImagePlugin extends TemplatePlugin {
1417
- constructor(...args) {
1418
- super(...args);
1419
- _defineProperty(this, "contentType", 'image');
1420
- }
1369
+ contentType = 'image';
1421
1370
  async simpleTagReplacements(tag, data, context) {
1422
1371
  const wordTextNode = this.utilities.docxParser.containingTextNode(tag.xmlTextNode);
1423
1372
  const content = data.getScopeData();
@@ -1569,12 +1518,11 @@ let ContentPartType = /*#__PURE__*/function (ContentPartType) {
1569
1518
  * http://officeopenxml.com/anatomyofOOXML.php
1570
1519
  */
1571
1520
  class ContentTypesFile {
1521
+ static contentTypesFilePath = '[Content_Types].xml';
1522
+ addedNew = false;
1572
1523
  constructor(zip, xmlParser) {
1573
1524
  this.zip = zip;
1574
1525
  this.xmlParser = xmlParser;
1575
- _defineProperty(this, "addedNew", false);
1576
- _defineProperty(this, "root", void 0);
1577
- _defineProperty(this, "contentTypes", void 0);
1578
1526
  }
1579
1527
  async ensureContentType(mime) {
1580
1528
  // parse the content types file
@@ -1629,17 +1577,16 @@ class ContentTypesFile {
1629
1577
  }
1630
1578
  }
1631
1579
  }
1632
- _defineProperty(ContentTypesFile, "contentTypesFilePath", '[Content_Types].xml');
1633
1580
 
1634
1581
  /**
1635
1582
  * Handles media files of the main document.
1636
1583
  */
1637
1584
  class MediaFiles {
1585
+ static mediaDir = 'word/media';
1586
+ files = new Map();
1587
+ nextFileId = 0;
1638
1588
  constructor(zip) {
1639
1589
  this.zip = zip;
1640
- _defineProperty(this, "hashes", void 0);
1641
- _defineProperty(this, "files", new Map());
1642
- _defineProperty(this, "nextFileId", 0);
1643
1590
  }
1644
1591
 
1645
1592
  /**
@@ -1698,23 +1645,17 @@ class MediaFiles {
1698
1645
  }
1699
1646
  }
1700
1647
  }
1701
- _defineProperty(MediaFiles, "mediaDir", 'word/media');
1702
1648
 
1703
1649
  class Relationship {
1704
1650
  static fromXml(xml) {
1705
- var _xml$attributes, _xml$attributes2, _xml$attributes3, _xml$attributes4;
1706
1651
  return new Relationship({
1707
- id: (_xml$attributes = xml.attributes) === null || _xml$attributes === void 0 ? void 0 : _xml$attributes['Id'],
1708
- type: (_xml$attributes2 = xml.attributes) === null || _xml$attributes2 === void 0 ? void 0 : _xml$attributes2['Type'],
1709
- target: (_xml$attributes3 = xml.attributes) === null || _xml$attributes3 === void 0 ? void 0 : _xml$attributes3['Target'],
1710
- targetMode: (_xml$attributes4 = xml.attributes) === null || _xml$attributes4 === void 0 ? void 0 : _xml$attributes4['TargetMode']
1652
+ id: xml.attributes?.['Id'],
1653
+ type: xml.attributes?.['Type'],
1654
+ target: xml.attributes?.['Target'],
1655
+ targetMode: xml.attributes?.['TargetMode']
1711
1656
  });
1712
1657
  }
1713
1658
  constructor(initial) {
1714
- _defineProperty(this, "id", void 0);
1715
- _defineProperty(this, "type", void 0);
1716
- _defineProperty(this, "target", void 0);
1717
- _defineProperty(this, "targetMode", void 0);
1718
1659
  Object.assign(this, initial);
1719
1660
  }
1720
1661
  toXml() {
@@ -1738,17 +1679,13 @@ class Relationship {
1738
1679
  * http://officeopenxml.com/anatomyofOOXML.php
1739
1680
  */
1740
1681
  class Rels {
1682
+ nextRelId = 0;
1741
1683
  constructor(partPath, zip, xmlParser) {
1742
1684
  this.zip = zip;
1743
1685
  this.xmlParser = xmlParser;
1744
- _defineProperty(this, "rels", void 0);
1745
- _defineProperty(this, "relTargets", void 0);
1746
- _defineProperty(this, "nextRelId", 0);
1747
- _defineProperty(this, "partDir", void 0);
1748
- _defineProperty(this, "relsFilePath", void 0);
1749
1686
  this.partDir = partPath && Path.getDirectory(partPath);
1750
1687
  const partFilename = partPath && Path.getFilename(partPath);
1751
- this.relsFilePath = Path.combine(this.partDir, '_rels', `${partFilename !== null && partFilename !== void 0 ? partFilename : ''}.rels`);
1688
+ this.relsFilePath = Path.combine(this.partDir, '_rels', `${partFilename ?? ''}.rels`);
1752
1689
  }
1753
1690
 
1754
1691
  /**
@@ -1877,8 +1814,6 @@ class XmlPart {
1877
1814
  this.path = path;
1878
1815
  this.zip = zip;
1879
1816
  this.xmlParser = xmlParser;
1880
- _defineProperty(this, "rels", void 0);
1881
- _defineProperty(this, "root", void 0);
1882
1817
  this.rels = new Rels(this.path, zip, xmlParser);
1883
1818
  }
1884
1819
 
@@ -1926,6 +1861,8 @@ class XmlPart {
1926
1861
  * Represents a single docx file.
1927
1862
  */
1928
1863
  class Docx {
1864
+ static mainDocumentRelType = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument';
1865
+
1929
1866
  //
1930
1867
  // static methods
1931
1868
  //
@@ -1936,17 +1873,18 @@ class Docx {
1936
1873
  return new Docx(mainDocumentPath, zip, xmlParser);
1937
1874
  }
1938
1875
  static async getMainDocumentPath(zip, xmlParser) {
1939
- var _relations$find;
1940
1876
  const rootPart = '';
1941
1877
  const rootRels = new Rels(rootPart, zip, xmlParser);
1942
1878
  const relations = await rootRels.list();
1943
- return (_relations$find = relations.find(rel => rel.type == Docx.mainDocumentRelType)) === null || _relations$find === void 0 ? void 0 : _relations$find.target;
1879
+ return relations.find(rel => rel.type == Docx.mainDocumentRelType)?.target;
1944
1880
  }
1945
1881
 
1946
1882
  //
1947
1883
  // fields
1948
1884
  //
1949
1885
 
1886
+ _parts = {};
1887
+
1950
1888
  /**
1951
1889
  * **Notice:** You should only use this property if there is no other way to
1952
1890
  * do what you need. Use with caution.
@@ -1962,10 +1900,6 @@ class Docx {
1962
1900
  constructor(mainDocumentPath, zip, xmlParser) {
1963
1901
  this.zip = zip;
1964
1902
  this.xmlParser = xmlParser;
1965
- _defineProperty(this, "mainDocument", void 0);
1966
- _defineProperty(this, "mediaFiles", void 0);
1967
- _defineProperty(this, "contentTypes", void 0);
1968
- _defineProperty(this, "_parts", {});
1969
1903
  this.mainDocument = new XmlPart(mainDocumentPath, zip, xmlParser);
1970
1904
  this.mediaFiles = new MediaFiles(zip);
1971
1905
  this.contentTypes = new ContentTypesFile(zip, xmlParser);
@@ -2002,7 +1936,6 @@ class Docx {
2002
1936
  //
2003
1937
 
2004
1938
  async getHeaderOrFooter(type) {
2005
- var _sectionProps$childNo, _attributes;
2006
1939
  const nodeName = this.headerFooterNodeName(type);
2007
1940
  const nodeTypeAttribute = this.headerFooterType(type);
2008
1941
 
@@ -2015,11 +1948,10 @@ class Docx {
2015
1948
  if (sectionProps.nodeName != 'w:sectPr') return null;
2016
1949
 
2017
1950
  // find the header or footer reference
2018
- const reference = (_sectionProps$childNo = sectionProps.childNodes) === null || _sectionProps$childNo === void 0 ? void 0 : _sectionProps$childNo.find(node => {
2019
- var _node$attributes;
2020
- return node.nodeType === XmlNodeType.General && node.nodeName === nodeName && ((_node$attributes = node.attributes) === null || _node$attributes === void 0 ? void 0 : _node$attributes['w:type']) === nodeTypeAttribute;
1951
+ const reference = sectionProps.childNodes?.find(node => {
1952
+ return node.nodeType === XmlNodeType.General && node.nodeName === nodeName && node.attributes?.['w:type'] === nodeTypeAttribute;
2021
1953
  });
2022
- const relId = reference === null || reference === void 0 ? void 0 : (_attributes = reference.attributes) === null || _attributes === void 0 ? void 0 : _attributes['r:id'];
1954
+ const relId = reference?.attributes?.['r:id'];
2023
1955
  if (!relId) return null;
2024
1956
 
2025
1957
  // return the XmlPart
@@ -2070,9 +2002,38 @@ class Docx {
2070
2002
  await this.contentTypes.save();
2071
2003
  }
2072
2004
  }
2073
- _defineProperty(Docx, "mainDocumentRelType", 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument');
2074
2005
 
2075
2006
  class DocxParser {
2007
+ /*
2008
+ * Word markup intro:
2009
+ *
2010
+ * In Word text nodes are contained in "run" nodes (which specifies text
2011
+ * properties such as font and color). The "run" nodes in turn are
2012
+ * contained in paragraph nodes which is the core unit of content.
2013
+ *
2014
+ * Example:
2015
+ *
2016
+ * <w:p> <-- paragraph
2017
+ * <w:r> <-- run
2018
+ * <w:rPr> <-- run properties
2019
+ * <w:b/> <-- bold
2020
+ * </w:rPr>
2021
+ * <w:t>This is text.</w:t> <-- actual text
2022
+ * </w:r>
2023
+ * </w:p>
2024
+ *
2025
+ * see: http://officeopenxml.com/WPcontentOverview.php
2026
+ */
2027
+
2028
+ static PARAGRAPH_NODE = 'w:p';
2029
+ static PARAGRAPH_PROPERTIES_NODE = 'w:pPr';
2030
+ static RUN_NODE = 'w:r';
2031
+ static RUN_PROPERTIES_NODE = 'w:rPr';
2032
+ static TEXT_NODE = 'w:t';
2033
+ static TABLE_ROW_NODE = 'w:tr';
2034
+ static TABLE_CELL_NODE = 'w:tc';
2035
+ static NUMBER_PROPERTIES_NODE = 'w:numPr';
2036
+
2076
2037
  //
2077
2038
  // constructor
2078
2039
  //
@@ -2371,9 +2332,8 @@ class DocxParser {
2371
2332
  //
2372
2333
 
2373
2334
  isEmptyTextNode(node) {
2374
- var _node$childNodes;
2375
2335
  if (!this.isTextNode(node)) throw new Error(`Text node expected but '${node.nodeName}' received.`);
2376
- if (!((_node$childNodes = node.childNodes) !== null && _node$childNodes !== void 0 && _node$childNodes.length)) return true;
2336
+ if (!node.childNodes?.length) return true;
2377
2337
  const xmlTextNode = node.childNodes[0];
2378
2338
  if (!XmlNode.isTextNode(xmlTextNode)) throw new Error("Invalid XML structure. 'w:t' node should contain a single text node only.");
2379
2339
  if (!xmlTextNode.textContent) return true;
@@ -2381,8 +2341,7 @@ class DocxParser {
2381
2341
  }
2382
2342
  isEmptyRun(node) {
2383
2343
  if (!this.isRunNode(node)) throw new Error(`Run node expected but '${node.nodeName}' received.`);
2384
- for (const child of (_node$childNodes2 = node.childNodes) !== null && _node$childNodes2 !== void 0 ? _node$childNodes2 : []) {
2385
- var _node$childNodes2;
2344
+ for (const child of node.childNodes ?? []) {
2386
2345
  if (this.isRunPropertiesNode(child)) continue;
2387
2346
  if (this.isTextNode(child) && this.isEmptyTextNode(child)) continue;
2388
2347
  return false;
@@ -2390,40 +2349,10 @@ class DocxParser {
2390
2349
  return true;
2391
2350
  }
2392
2351
  }
2393
- /*
2394
- * Word markup intro:
2395
- *
2396
- * In Word text nodes are contained in "run" nodes (which specifies text
2397
- * properties such as font and color). The "run" nodes in turn are
2398
- * contained in paragraph nodes which is the core unit of content.
2399
- *
2400
- * Example:
2401
- *
2402
- * <w:p> <-- paragraph
2403
- * <w:r> <-- run
2404
- * <w:rPr> <-- run properties
2405
- * <w:b/> <-- bold
2406
- * </w:rPr>
2407
- * <w:t>This is text.</w:t> <-- actual text
2408
- * </w:r>
2409
- * </w:p>
2410
- *
2411
- * see: http://officeopenxml.com/WPcontentOverview.php
2412
- */
2413
- _defineProperty(DocxParser, "PARAGRAPH_NODE", 'w:p');
2414
- _defineProperty(DocxParser, "PARAGRAPH_PROPERTIES_NODE", 'w:pPr');
2415
- _defineProperty(DocxParser, "RUN_NODE", 'w:r');
2416
- _defineProperty(DocxParser, "RUN_PROPERTIES_NODE", 'w:rPr');
2417
- _defineProperty(DocxParser, "TEXT_NODE", 'w:t');
2418
- _defineProperty(DocxParser, "TABLE_ROW_NODE", 'w:tr');
2419
- _defineProperty(DocxParser, "TABLE_CELL_NODE", 'w:tc');
2420
- _defineProperty(DocxParser, "NUMBER_PROPERTIES_NODE", 'w:numPr');
2421
2352
 
2422
2353
  class LinkPlugin extends TemplatePlugin {
2423
- constructor(...args) {
2424
- super(...args);
2425
- _defineProperty(this, "contentType", 'link');
2426
- }
2354
+ static linkRelType = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink';
2355
+ contentType = 'link';
2427
2356
  async simpleTagReplacements(tag, data, context) {
2428
2357
  const wordTextNode = this.utilities.docxParser.containingTextNode(tag.xmlTextNode);
2429
2358
  const content = data.getScopeData();
@@ -2492,12 +2421,8 @@ class LinkPlugin extends TemplatePlugin {
2492
2421
  }
2493
2422
  }
2494
2423
  }
2495
- _defineProperty(LinkPlugin, "linkRelType", 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink');
2496
2424
 
2497
2425
  class LoopListStrategy {
2498
- constructor() {
2499
- _defineProperty(this, "utilities", void 0);
2500
- }
2501
2426
  setUtilities(utilities) {
2502
2427
  this.utilities = utilities;
2503
2428
  }
@@ -2535,9 +2460,6 @@ class LoopListStrategy {
2535
2460
  }
2536
2461
 
2537
2462
  class LoopParagraphStrategy {
2538
- constructor() {
2539
- _defineProperty(this, "utilities", void 0);
2540
- }
2541
2463
  setUtilities(utilities) {
2542
2464
  this.utilities = utilities;
2543
2465
  }
@@ -2608,9 +2530,6 @@ let LoopOver = /*#__PURE__*/function (LoopOver) {
2608
2530
  }({});
2609
2531
 
2610
2532
  class LoopTableStrategy {
2611
- constructor() {
2612
- _defineProperty(this, "utilities", void 0);
2613
- }
2614
2533
  setUtilities(utilities) {
2615
2534
  this.utilities = utilities;
2616
2535
  }
@@ -2622,7 +2541,7 @@ class LoopTableStrategy {
2622
2541
  if (!closeParagraph.parentNode) return false;
2623
2542
  if (!this.utilities.docxParser.isTableCellNode(closeParagraph.parentNode)) return false;
2624
2543
  const options = openTag.options;
2625
- const forceRowLoop = (options === null || options === void 0 ? void 0 : options.loopOver) === LoopOver.Row;
2544
+ const forceRowLoop = options?.loopOver === LoopOver.Row;
2626
2545
 
2627
2546
  // If both tags are in the same cell, assume it's a paragraph loop (iterate content, not rows).
2628
2547
  if (!forceRowLoop && openParagraph.parentNode === closeParagraph.parentNode) return false;
@@ -2659,12 +2578,9 @@ class LoopTableStrategy {
2659
2578
 
2660
2579
  const LOOP_CONTENT_TYPE = 'loop';
2661
2580
  class LoopPlugin extends TemplatePlugin {
2662
- constructor(...args) {
2663
- super(...args);
2664
- _defineProperty(this, "contentType", LOOP_CONTENT_TYPE);
2665
- _defineProperty(this, "loopStrategies", [new LoopTableStrategy(), new LoopListStrategy(), new LoopParagraphStrategy() // the default strategy
2666
- ]);
2667
- }
2581
+ contentType = LOOP_CONTENT_TYPE;
2582
+ loopStrategies = [new LoopTableStrategy(), new LoopListStrategy(), new LoopParagraphStrategy() // the default strategy
2583
+ ];
2668
2584
  setUtilities(utilities) {
2669
2585
  this.utilities = utilities;
2670
2586
  this.loopStrategies.forEach(strategy => strategy.setUtilities(utilities));
@@ -2769,14 +2685,11 @@ class LoopPlugin extends TemplatePlugin {
2769
2685
  }
2770
2686
 
2771
2687
  class RawXmlPlugin extends TemplatePlugin {
2772
- constructor(...args) {
2773
- super(...args);
2774
- _defineProperty(this, "contentType", 'rawXml');
2775
- }
2688
+ contentType = 'rawXml';
2776
2689
  simpleTagReplacements(tag, data) {
2777
2690
  const value = data.getScopeData();
2778
- const replaceNode = value !== null && value !== void 0 && value.replaceParagraph ? this.utilities.docxParser.containingParagraphNode(tag.xmlTextNode) : this.utilities.docxParser.containingTextNode(tag.xmlTextNode);
2779
- if (typeof (value === null || value === void 0 ? void 0 : value.xml) === 'string') {
2691
+ const replaceNode = value?.replaceParagraph ? this.utilities.docxParser.containingParagraphNode(tag.xmlTextNode) : this.utilities.docxParser.containingTextNode(tag.xmlTextNode);
2692
+ if (typeof value?.xml === 'string') {
2780
2693
  const newNode = this.utilities.xmlParser.parse(value.xml);
2781
2694
  XmlNode.insertBefore(newNode, replaceNode);
2782
2695
  }
@@ -2786,10 +2699,8 @@ class RawXmlPlugin extends TemplatePlugin {
2786
2699
 
2787
2700
  const TEXT_CONTENT_TYPE = 'text';
2788
2701
  class TextPlugin extends TemplatePlugin {
2789
- constructor(...args) {
2790
- super(...args);
2791
- _defineProperty(this, "contentType", TEXT_CONTENT_TYPE);
2792
- }
2702
+ contentType = TEXT_CONTENT_TYPE;
2703
+
2793
2704
  /**
2794
2705
  * Replace the node text content with the specified value.
2795
2706
  */
@@ -2864,7 +2775,6 @@ class TemplateCompiler {
2864
2775
  this.delimiterSearcher = delimiterSearcher;
2865
2776
  this.tagParser = tagParser;
2866
2777
  this.options = options;
2867
- _defineProperty(this, "pluginsLookup", void 0);
2868
2778
  this.pluginsLookup = toDictionary(plugins, p => p.contentType);
2869
2779
  }
2870
2780
 
@@ -2963,9 +2873,6 @@ class TemplateCompiler {
2963
2873
  }
2964
2874
 
2965
2875
  class TemplateExtension {
2966
- constructor() {
2967
- _defineProperty(this, "utilities", void 0);
2968
- }
2969
2876
  /**
2970
2877
  * Called by the TemplateHandler at runtime.
2971
2878
  */
@@ -3051,13 +2958,13 @@ class Zip {
3051
2958
  }
3052
2959
 
3053
2960
  class Delimiters {
2961
+ tagStart = "{";
2962
+ tagEnd = "}";
2963
+ containerTagOpen = "#";
2964
+ containerTagClose = "/";
2965
+ tagOptionsStart = "[";
2966
+ tagOptionsEnd = "]";
3054
2967
  constructor(initial) {
3055
- _defineProperty(this, "tagStart", "{");
3056
- _defineProperty(this, "tagEnd", "}");
3057
- _defineProperty(this, "containerTagOpen", "#");
3058
- _defineProperty(this, "containerTagClose", "/");
3059
- _defineProperty(this, "tagOptionsStart", "[");
3060
- _defineProperty(this, "tagOptionsEnd", "]");
3061
2968
  Object.assign(this, initial);
3062
2969
  this.encodeAndValidate();
3063
2970
  if (this.containerTagOpen === this.containerTagClose) throw new Error(`${"containerTagOpen"} can not be equal to ${"containerTagClose"}`);
@@ -3073,22 +2980,22 @@ class Delimiters {
3073
2980
  }
3074
2981
 
3075
2982
  class TemplateHandlerOptions {
2983
+ plugins = createDefaultPlugins();
2984
+
2985
+ /**
2986
+ * Determines the behavior in case of an empty input data. If set to true
2987
+ * the tag will be left untouched, if set to false the tag will be replaced
2988
+ * by an empty string.
2989
+ *
2990
+ * Default: false
2991
+ */
2992
+ skipEmptyTags = false;
2993
+ defaultContentType = TEXT_CONTENT_TYPE;
2994
+ containerContentType = LOOP_CONTENT_TYPE;
2995
+ delimiters = new Delimiters();
2996
+ maxXmlDepth = 20;
2997
+ extensions = {};
3076
2998
  constructor(initial) {
3077
- _defineProperty(this, "plugins", createDefaultPlugins());
3078
- /**
3079
- * Determines the behavior in case of an empty input data. If set to true
3080
- * the tag will be left untouched, if set to false the tag will be replaced
3081
- * by an empty string.
3082
- *
3083
- * Default: false
3084
- */
3085
- _defineProperty(this, "skipEmptyTags", false);
3086
- _defineProperty(this, "defaultContentType", TEXT_CONTENT_TYPE);
3087
- _defineProperty(this, "containerContentType", LOOP_CONTENT_TYPE);
3088
- _defineProperty(this, "delimiters", new Delimiters());
3089
- _defineProperty(this, "maxXmlDepth", 20);
3090
- _defineProperty(this, "extensions", {});
3091
- _defineProperty(this, "scopeDataResolver", void 0);
3092
2999
  Object.assign(this, initial);
3093
3000
  if (initial) {
3094
3001
  this.delimiters = new Delimiters(initial.delimiters);
@@ -3100,16 +3007,12 @@ class TemplateHandlerOptions {
3100
3007
  }
3101
3008
 
3102
3009
  class TemplateHandler {
3010
+ /**
3011
+ * Version number of the `easy-template-x` library.
3012
+ */
3013
+ version = "4.1.3" ;
3014
+ xmlParser = new XmlParser();
3103
3015
  constructor(options) {
3104
- var _this$options$extensi, _this$options$extensi2, _this$options$extensi3, _this$options$extensi4;
3105
- /**
3106
- * Version number of the `easy-template-x` library.
3107
- */
3108
- _defineProperty(this, "version", "4.1.0" );
3109
- _defineProperty(this, "xmlParser", new XmlParser());
3110
- _defineProperty(this, "docxParser", void 0);
3111
- _defineProperty(this, "compiler", void 0);
3112
- _defineProperty(this, "options", void 0);
3113
3016
  this.options = new TemplateHandlerOptions(options);
3114
3017
 
3115
3018
  //
@@ -3140,10 +3043,10 @@ class TemplateHandler {
3140
3043
  tagParser,
3141
3044
  compiler: this.compiler
3142
3045
  };
3143
- (_this$options$extensi = this.options.extensions) === null || _this$options$extensi === void 0 ? void 0 : (_this$options$extensi2 = _this$options$extensi.beforeCompilation) === null || _this$options$extensi2 === void 0 ? void 0 : _this$options$extensi2.forEach(extension => {
3046
+ this.options.extensions?.beforeCompilation?.forEach(extension => {
3144
3047
  extension.setUtilities(extensionUtilities);
3145
3048
  });
3146
- (_this$options$extensi3 = this.options.extensions) === null || _this$options$extensi3 === void 0 ? void 0 : (_this$options$extensi4 = _this$options$extensi3.afterCompilation) === null || _this$options$extensi4 === void 0 ? void 0 : _this$options$extensi4.forEach(extension => {
3049
+ this.options.extensions?.afterCompilation?.forEach(extension => {
3147
3050
  extension.setUtilities(extensionUtilities);
3148
3051
  });
3149
3052
  }
@@ -3165,18 +3068,17 @@ class TemplateHandler {
3165
3068
  };
3166
3069
  const contentParts = await docx.getContentParts();
3167
3070
  for (const part of contentParts) {
3168
- var _this$options$extensi5, _this$options$extensi6;
3169
3071
  context.currentPart = part;
3170
3072
 
3171
3073
  // extensions - before compilation
3172
- await this.callExtensions((_this$options$extensi5 = this.options.extensions) === null || _this$options$extensi5 === void 0 ? void 0 : _this$options$extensi5.beforeCompilation, scopeData, context);
3074
+ await this.callExtensions(this.options.extensions?.beforeCompilation, scopeData, context);
3173
3075
 
3174
3076
  // compilation (do replacements)
3175
3077
  const xmlRoot = await part.xmlRoot();
3176
3078
  await this.compiler.compile(xmlRoot, scopeData, context);
3177
3079
 
3178
3080
  // extensions - after compilation
3179
- await this.callExtensions((_this$options$extensi6 = this.options.extensions) === null || _this$options$extensi6 === void 0 ? void 0 : _this$options$extensi6.afterCompilation, scopeData, context);
3081
+ await this.callExtensions(this.options.extensions?.afterCompilation, scopeData, context);
3180
3082
  }
3181
3083
 
3182
3084
  // export the result
@@ -3243,7 +3145,7 @@ class TemplateHandler {
3243
3145
  let zip;
3244
3146
  try {
3245
3147
  zip = await Zip.load(file);
3246
- } catch (_unused) {
3148
+ } catch {
3247
3149
  throw new MalformedFileError('docx');
3248
3150
  }
3249
3151