@e-mc/document 0.10.6 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -8,4 +8,4 @@ Redistribution and use in source and binary forms, with or without modification,
8
8
 
9
9
  3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
10
 
11
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @e-mc/document
2
2
 
3
- * NodeJS 16
4
- * ES2020
3
+ * NodeJS 16 LTS
4
+ * ES2021
5
5
 
6
6
  ## General Usage
7
7
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  ## Interface
11
11
 
12
- * [View Source](https://www.unpkg.com/@e-mc/types@0.10.6/lib/index.d.ts)
12
+ * [View Source](https://www.unpkg.com/@e-mc/types@0.11.1/lib/index.d.ts)
13
13
 
14
14
  ```typescript
15
15
  import type { DataSource, ViewEngine } from "./squared";
@@ -67,6 +67,8 @@ interface IDocument extends IClient<IFileManager, DocumentModule, TransformCallb
67
67
  set imports(value);
68
68
  get imports(): Record<string, string | undefined>;
69
69
  get watching(): boolean;
70
+ set host(value);
71
+ get host(): IFileManager | null;
70
72
  }
71
73
 
72
74
  interface DocumentConstructor extends ModuleConstructor {
@@ -183,15 +185,15 @@ NOTE: **@e-mc/document** is an abstract base class and cannot be instantiated. *
183
185
 
184
186
  ## References
185
187
 
186
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/squared.d.ts
187
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/asset.d.ts
188
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/core.d.ts
189
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/document.d.ts
190
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/filemanager.d.ts
191
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/logger.d.ts
192
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/settings.d.ts
193
- - https://www.unpkg.com/@e-mc/types@0.10.6/lib/watch.d.ts
188
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/squared.d.ts
189
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/asset.d.ts
190
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/core.d.ts
191
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/document.d.ts
192
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/filemanager.d.ts
193
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/logger.d.ts
194
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/settings.d.ts
195
+ - https://www.unpkg.com/@e-mc/types@0.11.1/lib/watch.d.ts
194
196
 
195
197
  ## LICENSE
196
198
 
197
- BSD 3-Clause
199
+ BSD 3-Clause
package/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
- const path = require("path");
3
- const fs = require("fs");
2
+ const path = require("node:path");
3
+ const fs = require("node:fs");
4
4
  const pm = require("picomatch");
5
5
  const yaml = require("js-yaml");
6
6
  const chalk = require("chalk");
7
+ const node_util_1 = require("node:util");
7
8
  const types_1 = require("@e-mc/types");
8
9
  const core_1 = require("@e-mc/core");
9
10
  const db_1 = require("@e-mc/db");
@@ -11,12 +12,11 @@ const transform_1 = require("@e-mc/document/transform");
11
12
  const parse_1 = require("@e-mc/document/parse");
12
13
  const util_1 = require("@e-mc/document/util");
13
14
  const CACHE_PACKAGE = {};
14
- const CACHE_REQUIRE = {};
15
+ const CACHE_TEMPLATE = {};
16
+ const CACHE_EXTERNAL = {};
15
17
  const CACHE_ETAG = {};
16
18
  const CACHE_CODE = {};
17
19
  const CACHE_HASH = {};
18
- const CACHE_TEMPLATE = {};
19
- const CACHE_EXTERNAL = {};
20
20
  const CACHE_PICOMATCH = new Map();
21
21
  let CACHE_TOTAL = 0;
22
22
  function deleteTransform(map, key, timeout) {
@@ -28,7 +28,7 @@ function deleteTransform(map, key, timeout) {
28
28
  }
29
29
  function getSourceMappingURL(value, css) {
30
30
  if (value.includes(' ')) {
31
- value = encodeURIComponent(value);
31
+ value = encodeURIComponent((0, node_util_1.toUSVString)(value));
32
32
  }
33
33
  return css ? `\n/*# sourceMappingURL=${value} */\n` : `\n//# sourceMappingURL=${value}\n`;
34
34
  }
@@ -57,7 +57,6 @@ const toBase64 = (value) => 'data:application/json;base64,' + Buffer.from(value)
57
57
  const toPosix = (value) => value.replace(/(?:^\\|\\+)/g, '/');
58
58
  const joinString = (name, ...values) => (name ? name + ': ' : '') + values.reduce((a, b) => b ? a + (a ? ' -> ' : '') + b : a, '');
59
59
  const truncateString = (value, width) => value.length > width ? value.substring(0, width - 3) + '...' : value.padStart(width);
60
- const spliceSource = (source, startIndex, endIndex, content) => source.substring(0, startIndex) + content + source.substring(endIndex);
61
60
  const isFunction = (value) => typeof value === 'function';
62
61
  class TransformCache {
63
62
  constructor(config, cacheData, cacheDir, encoding, formatKey) {
@@ -163,7 +162,7 @@ class TransformConfig {
163
162
  this.include = {};
164
163
  }
165
164
  init(options) {
166
- let enabled, algorithm, etag, expires, renew, limit, exclude, include;
165
+ let enabled = false, algorithm, etag, expires, renew, limit, include, exclude;
167
166
  if (options === true || options === 'etag') {
168
167
  etag = true;
169
168
  enabled = true;
@@ -173,7 +172,7 @@ class TransformConfig {
173
172
  enabled = true;
174
173
  }
175
174
  else if ((0, types_1.isPlainObject)(options)) {
176
- ({ enabled = true, algorithm, etag, expires, renew, limit, exclude, include } = options);
175
+ ({ enabled = true, algorithm, etag, expires, renew, limit, include, exclude } = options);
177
176
  }
178
177
  if (!enabled) {
179
178
  return false;
@@ -202,25 +201,25 @@ class TransformConfig {
202
201
  if (renew) {
203
202
  this.renew = true;
204
203
  }
205
- if ((0, types_1.isPlainObject)(exclude)) {
206
- for (const type in exclude) {
207
- const item = exclude[type];
204
+ if ((0, types_1.isPlainObject)(include)) {
205
+ for (const type in include) {
206
+ const item = include[type];
208
207
  if (item === '*') {
209
- this.exclude[type] = true;
208
+ this.include[type] = true;
210
209
  }
211
210
  else if ((0, types_1.isArray)(item)) {
212
- this.exclude[type] = item;
211
+ this.include[type] = item;
213
212
  }
214
213
  }
215
214
  }
216
- if ((0, types_1.isPlainObject)(include)) {
217
- for (const type in include) {
218
- const item = include[type];
215
+ if ((0, types_1.isPlainObject)(exclude)) {
216
+ for (const type in exclude) {
217
+ const item = exclude[type];
219
218
  if (item === '*') {
220
- this.include[type] = true;
219
+ this.exclude[type] = true;
221
220
  }
222
221
  else if ((0, types_1.isArray)(item)) {
223
- this.include[type] = item;
222
+ this.exclude[type] = item;
224
223
  }
225
224
  }
226
225
  }
@@ -343,7 +342,7 @@ class Document extends core_1.Client {
343
342
  delete cache[name];
344
343
  }
345
344
  }
346
- for (const cache of [CACHE_PACKAGE, CACHE_REQUIRE, CACHE_EXTERNAL, CACHE_TEMPLATE]) {
345
+ for (const cache of [CACHE_PACKAGE, CACHE_EXTERNAL, CACHE_TEMPLATE]) {
347
346
  for (const name in cache) {
348
347
  delete cache[name];
349
348
  }
@@ -515,7 +514,7 @@ class Document extends core_1.Client {
515
514
  lastIndex = match.index + match[0].length;
516
515
  }
517
516
  }
518
- return spliceSource(source, lastIndex, lastIndex, ident.repeat(length) + replacement + newline);
517
+ return (0, util_1.spliceString)(source, lastIndex, lastIndex, ident.repeat(length) + replacement + newline);
519
518
  }
520
519
  if (updateOnly) {
521
520
  return source;
@@ -530,7 +529,7 @@ class Document extends core_1.Client {
530
529
  trailing += ident.repeat(i) + '}' + newline;
531
530
  }
532
531
  const content = leading + ident.repeat(length) + replacement + newline + trailing;
533
- return lastIndex > 0 ? spliceSource(source, lastIndex, lastIndex, content) : source.trimEnd() + newline + newline + content;
532
+ return lastIndex > 0 ? (0, util_1.spliceString)(source, lastIndex, lastIndex, content) : source.trimEnd() + newline + newline + content;
534
533
  }
535
534
  static generateLintTable(messages, options) {
536
535
  const { leadingText, trailingText, pathname, filename, ruleWidth = 30, messageWidth = 60 } = options;
@@ -566,7 +565,7 @@ class Document extends core_1.Client {
566
565
  if (fatal) {
567
566
  ++fatalErrorCount;
568
567
  }
569
- const [type, errorColor] = typeof error === 'boolean' ? error ? [types_1.STATUS_TYPE.ERROR, 'red'] : [types_1.STATUS_TYPE.WARN, 'yellow'] : [types_1.STATUS_TYPE.INFO, 'white'];
568
+ const [type, errorColor] = error === true ? [types_1.STATUS_TYPE.ERROR, 'red'] : error === false ? [types_1.STATUS_TYPE.WARN, 'yellow'] : [types_1.STATUS_TYPE.INFO, 'white'];
570
569
  maxWidth = Math.max(1 + 0 + 1 + 0 + 1 + 2 + Math.min(Math.max(ruleId.length, ruleWidth), ruleWidth) + 2 + Math.min(Math.max(message.length, messageWidth), messageWidth), maxWidth);
571
570
  result.push({
572
571
  type,
@@ -708,32 +707,30 @@ class Document extends core_1.Client {
708
707
  }
709
708
  this.assets = assets;
710
709
  super.init();
711
- if (ignoreExtensions) {
712
- if (ignoreExtensions === true || ignoreExtensions === this.moduleName || (0, types_1.isArray)(ignoreExtensions) && ignoreExtensions.includes(this.moduleName)) {
713
- this._extensions = [];
714
- }
715
- else {
716
- const extensions = this._extensions;
717
- if ((0, types_1.isArray)(extensions)) {
718
- if (typeof ignoreExtensions === 'string') {
719
- this._extensions = extensions.filter(value => value !== ignoreExtensions);
720
- }
721
- else if ((0, types_1.isArray)(ignoreExtensions)) {
722
- this._extensions = extensions.filter(value => !ignoreExtensions.includes(value));
723
- }
710
+ if (!ignoreExtensions) {
711
+ return this;
712
+ }
713
+ if (ignoreExtensions === true || ignoreExtensions === this.moduleName || (0, types_1.isArray)(ignoreExtensions) && ignoreExtensions.includes(this.moduleName)) {
714
+ this._extensions = [];
715
+ }
716
+ else {
717
+ const extensions = this._extensions;
718
+ if ((0, types_1.isArray)(extensions)) {
719
+ if (typeof ignoreExtensions === 'string') {
720
+ this._extensions = extensions.filter(value => value !== ignoreExtensions);
721
+ }
722
+ else if ((0, types_1.isArray)(ignoreExtensions)) {
723
+ this._extensions = extensions.filter(value => !ignoreExtensions.includes(value));
724
724
  }
725
725
  }
726
726
  }
727
727
  return this;
728
728
  }
729
729
  abort(name, reason) {
730
- if (name instanceof Error) {
731
- reason ||= name;
732
- }
733
730
  if (this.aborted || (0, types_1.isString)(name) && this.settingsOf(name, 'abort') !== true) {
734
731
  return;
735
732
  }
736
- super.abort(reason);
733
+ super.abort(reason || (name instanceof Error ? name : undefined));
737
734
  }
738
735
  customize(options) {
739
736
  const transform = options.transform;
@@ -817,12 +814,12 @@ class Document extends core_1.Client {
817
814
  }
818
815
  }
819
816
  asSourceFile(value, options) {
820
- let encoding, persist, cache;
817
+ let encoding, cache;
821
818
  if (typeof options === 'boolean') {
822
819
  cache = options;
823
820
  }
824
821
  else if ((0, types_1.isObject)(options)) {
825
- ({ encoding, persist, cache } = options);
822
+ ({ encoding, cache } = options);
826
823
  }
827
824
  let result;
828
825
  if ((value = value.trim()).startsWith('npm:')) {
@@ -830,15 +827,9 @@ class Document extends core_1.Client {
830
827
  return null;
831
828
  }
832
829
  const pkgName = value.substring(4);
833
- if (persist) {
834
- result = CACHE_REQUIRE[pkgName];
835
- }
836
830
  if (!result) {
837
831
  try {
838
832
  result = require(pkgName);
839
- if (persist && result) {
840
- CACHE_REQUIRE[pkgName] = result;
841
- }
842
833
  if (typeof result === 'function') {
843
834
  return Object.defineProperty(result, "__cjs__", { value: true });
844
835
  }
@@ -979,7 +970,7 @@ class Document extends core_1.Client {
979
970
  return (imports = this.imports) => {
980
971
  const href = file.uri;
981
972
  const sourceFile = [];
982
- let mainFile, invalid;
973
+ let mainFile, invalid = false;
983
974
  if (Document.isFile(href, 'unc') || path.isAbsolute(href)) {
984
975
  sourceFile.push([href]);
985
976
  }
@@ -1009,7 +1000,7 @@ class Document extends core_1.Client {
1009
1000
  }
1010
1001
  }
1011
1002
  catch (err) {
1012
- this.writeFail(["Unable to read file", localUri && path.basename(localUri)], 32);
1003
+ this.writeFail(["Unable to read file", localUri && path.basename(localUri)], err, 32);
1013
1004
  }
1014
1005
  }
1015
1006
  else if (bundleContent) {
@@ -1083,7 +1074,7 @@ class Document extends core_1.Client {
1083
1074
  }
1084
1075
  }
1085
1076
  async parseTemplate(viewEngine, template, data) {
1086
- let target, stored;
1077
+ let target, stored = false;
1087
1078
  if (typeof viewEngine === 'string') {
1088
1079
  target = this.settings.view_engine?.[viewEngine];
1089
1080
  const userConfig = this.getUserSettings()?.view_engine?.[viewEngine];
@@ -1111,13 +1102,9 @@ class Document extends core_1.Client {
1111
1102
  return '';
1112
1103
  }
1113
1104
  try {
1114
- const name = target.name;
1115
- const context = require(name);
1116
- const { singleRow, options = {} } = target;
1117
- let { compile, output } = options;
1118
- if (!(0, types_1.isPlainObject)(output)) {
1119
- output = undefined;
1120
- }
1105
+ const context = require(target.name);
1106
+ let { singleRow, expires, options = {} } = target;
1107
+ const { compile, output } = options;
1121
1108
  if (this.settingsOf('view_engine', 'coerce') === true) {
1122
1109
  if (compile) {
1123
1110
  (0, types_1.coerceObject)(compile, stored);
@@ -1126,20 +1113,37 @@ class Document extends core_1.Client {
1126
1113
  (0, types_1.coerceObject)(output, stored);
1127
1114
  }
1128
1115
  }
1116
+ if (typeof expires === 'string') {
1117
+ expires = (0, types_1.parseExpires)(expires);
1118
+ }
1129
1119
  const username = this.host?.username || '';
1130
- const cache = CACHE_TEMPLATE[name] ||= {};
1120
+ const cache = CACHE_TEMPLATE[target.name] ||= {};
1131
1121
  const cacheKey = (username ? username + ':' : '') + (0, types_1.hashKey)(template + (compile ? core_1.Client.asString(compile) : ''));
1132
- let result = '', render = cache[cacheKey], valid;
1122
+ let result = '', render, valid = false;
1123
+ if (expires !== 0) {
1124
+ render = cache[cacheKey];
1125
+ }
1126
+ else if (username && cacheKey in cache) {
1127
+ delete cache[cacheKey];
1128
+ }
1133
1129
  if (!render) {
1134
1130
  render = await context.compile(template, compile);
1135
- cache[cacheKey] = render;
1136
- if (!core_1.Client.enabled("memory.settings.users", username)) {
1137
- setTimeout(() => delete cache[cacheKey], 60000);
1131
+ if (expires !== 0) {
1132
+ cache[cacheKey] = render;
1133
+ if (core_1.Client.enabled("memory.settings.users", username)) {
1134
+ expires = typeof expires === 'number' && expires !== Infinity ? expires : 0;
1135
+ }
1136
+ else {
1137
+ expires = 60000;
1138
+ }
1139
+ if (expires > 0) {
1140
+ setTimeout(() => delete cache[cacheKey], expires);
1141
+ }
1138
1142
  }
1139
1143
  }
1140
1144
  const writeRow = async (row) => {
1141
1145
  const content = await render.call(context, row);
1142
- if (content !== undefined && content !== null) {
1146
+ if (content != null) {
1143
1147
  result += content;
1144
1148
  valid = true;
1145
1149
  }
@@ -1153,7 +1157,7 @@ class Document extends core_1.Client {
1153
1157
  }
1154
1158
  }
1155
1159
  else if (!(0, types_1.isObject)(row)) {
1156
- this.addLog(types_1.STATUS_TYPE.WARN, joinString('view engine', name, `row #${i + 1}`, core_1.Client.asString(row) || "Unknown"));
1160
+ this.addLog(types_1.STATUS_TYPE.WARN, joinString('view engine', target.name, `row #${i + 1}`, core_1.Client.asString(row) || "Unknown"));
1157
1161
  continue;
1158
1162
  }
1159
1163
  if (!singleRow) {
@@ -1180,9 +1184,9 @@ class Document extends core_1.Client {
1180
1184
  const username = this.host?.username || '';
1181
1185
  const config = this._transformConfig;
1182
1186
  const cacheData = config && options.cacheData;
1183
- let cache = null, cacheDir = false, excludeKey;
1187
+ let cache = null, excludeKey;
1184
1188
  if (cacheData) {
1185
- cacheDir = username && core_1.Client.enabled("memory.settings.users", username) ? true : this.cacheDir || core_1.Client.enabled("memory.settings.users");
1189
+ const cacheDir = username && core_1.Client.enabled("memory.settings.users", username) ? true : this.cacheDir || core_1.Client.enabled("memory.settings.users");
1186
1190
  if (cacheDir && !CACHE_EXTERNAL[excludeKey = this.moduleName + '_' + type + '_' + format] && config.valid(type, format)) {
1187
1191
  const { uri, etag } = cacheData;
1188
1192
  const encoding = (0, types_1.getEncoding)(cacheData.encoding);
@@ -1213,7 +1217,7 @@ class Document extends core_1.Client {
1213
1217
  const imports = transform.imports ||= {};
1214
1218
  const series = new transform_1.TransformSeries(type, code, options);
1215
1219
  series.init(this, __dirname);
1216
- let valid, excluded, userData, userImports, ignoreCache, storedLog, sourceFiles;
1220
+ let valid = false, excluded = false, userData, userImports, ignoreCache = false, storedLog, sourceFiles;
1217
1221
  if (username && (0, types_1.isObject)(transform = this.getUserSettings()?.transform)) {
1218
1222
  userData = transform[type];
1219
1223
  if (!(0, types_1.isObject)(userData)) {
@@ -1265,7 +1269,7 @@ class Document extends core_1.Client {
1265
1269
  if (plugin && baseConfig) {
1266
1270
  series.outputConfig = outputConfig;
1267
1271
  const source = series.code;
1268
- const startTime = process.hrtime();
1272
+ const startTime = process.hrtime.bigint();
1269
1273
  const hint = plugin + ':' + name;
1270
1274
  const next = (value) => {
1271
1275
  if (this.aborted) {
@@ -1273,7 +1277,7 @@ class Document extends core_1.Client {
1273
1277
  return;
1274
1278
  }
1275
1279
  const out = series.out;
1276
- let bypassLog, failed;
1280
+ let bypassLog = false, failed = false;
1277
1281
  if (typeof value !== 'string' || (0, types_1.isArray)(out.sourceFiles) && this.hasOwnPermission() && out.sourceFiles.some(item => !this.canRead(item, { ownPermissionOnly: true }))) {
1278
1282
  failed = true;
1279
1283
  ignoreCache = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e-mc/document",
3
- "version": "0.10.6",
3
+ "version": "0.11.1",
4
4
  "description": "Document constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -20,9 +20,9 @@
20
20
  "license": "BSD-3-Clause",
21
21
  "homepage": "https://github.com/anpham6/e-mc#readme",
22
22
  "dependencies": {
23
- "@e-mc/core": "0.10.6",
24
- "@e-mc/db": "0.10.6",
25
- "@e-mc/types": "0.10.6",
23
+ "@e-mc/core": "0.11.1",
24
+ "@e-mc/db": "0.11.1",
25
+ "@e-mc/types": "0.11.1",
26
26
  "chalk": "4.1.2",
27
27
  "domhandler": "^5.0.3",
28
28
  "domutils": "^3.1.0",
package/parse/dom.js CHANGED
@@ -14,7 +14,10 @@ const REGEXP_VOID = TAG_VOID.map(tagName => new RegExp(`(\\s*)</${tagName}\\s*>`
14
14
  const REGEXP_TAGNAME = new RegExp(`^${index_1.XmlWriter.PATTERN_TAGNAME}$`);
15
15
  const PARSER_OPTIONS = Object.freeze({ xmlMode: false, decodeEntities: false });
16
16
  class DomWriter extends index_1.XmlWriter {
17
- static hasInnerXml(tagName) {
17
+ static hasInnerXml(tagName, ignoreCase) {
18
+ if (ignoreCase) {
19
+ tagName = tagName.toLowerCase();
20
+ }
18
21
  return !TAG_VOID.includes(tagName);
19
22
  }
20
23
  static normalize(source, newline, ignoreChar = '', escapeEntities) {
@@ -247,7 +250,7 @@ class HtmlElement extends index_1.XmlElement {
247
250
  }
248
251
  get outerXml() {
249
252
  const [tagName, items, innerXml] = this.getOuterContent();
250
- return '<' + tagName + HtmlElement.writeAttributes(items) + '>' + (DomWriter.hasInnerXml(tagName) && tagName !== "html" ? (tagName === 'title' ? index_1.XmlWriter.escapeXmlString(innerXml) : innerXml) + `</${tagName}>` : '');
253
+ return '<' + tagName + HtmlElement.writeAttributes(items) + '>' + (DomWriter.hasInnerXml(tagName, this.ignoreCase) && tagName !== "html" ? (tagName === 'title' ? index_1.XmlWriter.escapeXmlString(innerXml) : innerXml) + `</${tagName}>` : '');
251
254
  }
252
255
  }
253
256
  exports.HtmlElement = HtmlElement;
package/parse/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  exports.XmlElement = exports.XmlWriter = exports.IGNORE_FLAG = void 0;
3
+ const crypto = require("node:crypto");
3
4
  const htmlparser2 = require("htmlparser2");
4
5
  const domhandler = require("domhandler");
5
6
  const domutils = require("domutils");
6
- const crypto = require("crypto");
7
7
  const types_1 = require("@e-mc/types");
8
8
  const module_1 = require("@e-mc/module");
9
9
  const util_1 = require("@e-mc/document/util");
@@ -29,14 +29,13 @@ const PATTERN_TRAILINGSPACE = '[ \\t]*((?:\\r?\\n)*)';
29
29
  const REGEXP_ATTRNAME = new RegExp('\\s+' + PATTERN_ATTRNAME, 'g');
30
30
  const REGEXP_ATTRVALUE = new RegExp(PATTERN_ATTRNAME + '\\s*' + PATTERN_ATTRVALUE, 'g');
31
31
  const REGEXP_TAGATTR = new RegExp(`<${PATTERN_TAGNAME}\\s+(${PATTERN_TAGOPEN}*)>`, 'g');
32
- const REGEXP_ESCAPECHAR = /[-|\\{}()[\]^$+*?.]/g;
33
32
  function applyAttributes(attrs, data, ignoreCase) {
34
33
  for (const key in data) {
35
34
  attrs.set(ignoreCase && typeof key === 'string' ? key.toLowerCase() : key.toString(), data[key]);
36
35
  }
37
36
  }
38
37
  function deletePosition(item, rootName, startIndex) {
39
- if (isIndex(item.startIndex) && (!isIndex(startIndex) || item.startIndex >= startIndex) && item.tagName !== rootName) {
38
+ if (isIndex(item.startIndex) && (startIndex === -1 || item.startIndex >= startIndex) && item.tagName !== rootName) {
40
39
  item.startIndex = undefined;
41
40
  item.endIndex = undefined;
42
41
  }
@@ -52,8 +51,16 @@ function resetTagPosition(item) {
52
51
  }
53
52
  function findCloseIndex(source, tagName, lastIndex, ignoreCase) {
54
53
  const flags = ignoreCase ? 'gi' : 'g';
55
- const pattern = CACHE_TAGNAME[tagName + flags + '0'] ||= new RegExp(`<(?:${escapeTagName(tagName)}\\s*|/${escapeTagName(tagName)}\\s*>)`, flags);
56
- pattern.lastIndex = lastIndex;
54
+ const key = tagName + flags + '0';
55
+ let pattern = CACHE_TAGNAME[key];
56
+ if (pattern) {
57
+ pattern.lastIndex = lastIndex;
58
+ }
59
+ else {
60
+ const tag = escapeTagName(tagName);
61
+ pattern = new RegExp(`<(?:${tag}\\s*|/${tag}\\s*>)`, flags);
62
+ CACHE_TAGNAME[key] = pattern;
63
+ }
57
64
  let openTag = 1, closeTag = 0, match;
58
65
  while (match = pattern.exec(source)) {
59
66
  if (match[0][1] !== '/') {
@@ -98,7 +105,7 @@ function getParserDOM(source, parser) {
98
105
  const isIndex = (value) => typeof value === 'number' && value >= 0 && value !== Infinity;
99
106
  const isCount = (value) => typeof value === 'number' && value > 0 && value !== Infinity;
100
107
  const hasId = (id, source, startIndex, endIndex) => source.substring(startIndex, endIndex).indexOf(id) !== -1;
101
- const escapeTagName = (value) => value.replace(REGEXP_ESCAPECHAR, capture => capture === '-' ? '\\x2d' : '\\' + capture);
108
+ const escapeTagName = (value) => value.replace(/[-.]/g, capture => capture === '-' ? '\\x2d' : '\\' + capture);
102
109
  class XmlWriter {
103
110
  static get PATTERN_ATTRNAME() {
104
111
  return PATTERN_ATTRNAME;
@@ -129,16 +136,15 @@ class XmlWriter {
129
136
  if (options) {
130
137
  let pattern;
131
138
  if ((0, types_1.isPlainObject)(options)) {
132
- let trimLeading, trimTrailing;
133
- ({ pattern, trimLeading, trimTrailing } = options);
134
- if (trimLeading) {
139
+ if (options.trimLeading) {
135
140
  const length = leading.length;
136
141
  leading = leading.trimEnd();
137
142
  index -= length - leading.length;
138
143
  }
139
- if (trimTrailing) {
144
+ if (options.trimTrailing) {
140
145
  trailing = trailing.trimStart();
141
146
  }
147
+ pattern = options.pattern;
142
148
  }
143
149
  else {
144
150
  pattern = options;
@@ -168,7 +174,7 @@ class XmlWriter {
168
174
  static escapeAttributes(source) {
169
175
  let escaped, match, attribute;
170
176
  while (match = REGEXP_TAGATTR.exec(source)) {
171
- let output = match[0], modified;
177
+ let output = match[0], modified = false;
172
178
  while (attribute = REGEXP_ATTRVALUE.exec(match[1])) {
173
179
  const value = attribute[2] || attribute[3] || attribute[4];
174
180
  if (value && (escaped = this.escapeXmlString(value)) !== value) {
@@ -340,7 +346,7 @@ class XmlWriter {
340
346
  }, { xmlMode: true, decodeEntities: false, lowerCaseAttributeNames: false, ...parser }).end(source);
341
347
  if ((0, types_1.isString)(replacement)) {
342
348
  const next = this.getTagOffset(replacement, options);
343
- let modified;
349
+ let modified = false;
344
350
  for (const tagName of new Set([...Object.keys(result), ...Object.keys(next)])) {
345
351
  if (result[tagName] !== next[tagName]) {
346
352
  result[tagName] = (next[tagName] || 0) - (result[tagName] || 0);
@@ -451,6 +457,10 @@ class XmlWriter {
451
457
  this.failCount = 0;
452
458
  this.errors = [];
453
459
  this.newline = '\n';
460
+ this.ignoreTagName = '';
461
+ this.ignoreTagGroup = undefined;
462
+ this.ignoreCaseTagName = false;
463
+ this.rootName = '';
454
464
  this._tagCount = Object.create(null);
455
465
  this._hasInvalidContent = true;
456
466
  this._ignoreFlag = 0;
@@ -473,7 +483,7 @@ class XmlWriter {
473
483
  item.tagCount += offsetMap?.[tagName] || 0;
474
484
  this._tagCount[tagName] = item.tagCount;
475
485
  }
476
- deletePosition(item, rootName);
486
+ deletePosition(item, rootName, -1);
477
487
  }
478
488
  if (appending.length > 0) {
479
489
  this.insertNodes(appending);
@@ -641,7 +651,7 @@ class XmlWriter {
641
651
  }
642
652
  update(node, outerXml, append, offsetMap) {
643
653
  const { elements, documentName, rootName } = this;
644
- const { tagName, startIndex, endIndex } = node;
654
+ const { tagName, startIndex = -1, endIndex } = node;
645
655
  const items = [];
646
656
  const updateMap = offsetMap && Object.keys(offsetMap).length > 0;
647
657
  const index = isIndex(node.index) ? node.index : -1;
@@ -660,7 +670,7 @@ class XmlWriter {
660
670
  item.endIndex = endIndex;
661
671
  }
662
672
  else {
663
- deletePosition(item, rootName);
673
+ deletePosition(item, rootName, -1);
664
674
  }
665
675
  }
666
676
  else {
@@ -935,11 +945,11 @@ class XmlWriter {
935
945
  this.ignoreTagName = tagName + value;
936
946
  this._patternIgnore = null;
937
947
  }
938
- resetPosition(startIndex) {
948
+ resetPosition(startIndex = -1) {
939
949
  const rootName = this.rootName;
940
- this.elements.forEach(item => {
950
+ for (const item of this.elements) {
941
951
  deletePosition(item, rootName, startIndex);
942
- });
952
+ }
943
953
  }
944
954
  close() {
945
955
  const source = this.source;
@@ -1215,7 +1225,7 @@ class XmlElement {
1215
1225
  }
1216
1226
  else {
1217
1227
  if (options.append) {
1218
- let i = startIndex - 1, ch, newline;
1228
+ let i = startIndex - 1, ch, newline = false;
1219
1229
  while (XmlWriter.isSpace(ch = source[i--])) {
1220
1230
  if (ch === '\n') {
1221
1231
  newline = true;
@@ -1298,10 +1308,17 @@ class XmlElement {
1298
1308
  }
1299
1309
  else if (id || isIndex(tagIndex) && isCount(tagCount)) {
1300
1310
  complete: {
1301
- const pattern = CACHE_TAGNAME[tagName + flags + '2'] ||= new RegExp(`<(?:${escapeTagName(tagName)}[\\s|>]|/${escapeTagName(tagName)}\\s*>)`, flags);
1302
1311
  const openTag = [];
1303
- let openCount = 0, found, match;
1304
- pattern.lastIndex = 0;
1312
+ const key = tagName + flags + '2';
1313
+ let pattern = CACHE_TAGNAME[key], openCount = 0, found = false, match;
1314
+ if (pattern) {
1315
+ pattern.lastIndex = 0;
1316
+ }
1317
+ else {
1318
+ const tag = escapeTagName(tagName);
1319
+ pattern = new RegExp(`<(?:${tag}[\\s|>]|/${escapeTagName(tag)}\\s*>)`, flags);
1320
+ CACHE_TAGNAME[key] = pattern;
1321
+ }
1305
1322
  while (match = pattern.exec(source)) {
1306
1323
  const startIndex = match.index;
1307
1324
  if (match[0][1] === '/') {
@@ -1332,7 +1349,7 @@ class XmlElement {
1332
1349
  ++tag[2];
1333
1350
  }
1334
1351
  }
1335
- openCount = openTag.push([startIndex, -1, 1, id && !found && hasId(id, source, startIndex, endIndex) ? (found = true) && 1 : 0]);
1352
+ openCount = openTag.push([startIndex, -1, 1, id && !found && hasId(id, source, startIndex, endIndex) ? (found = true, 1) : 0]);
1336
1353
  }
1337
1354
  pattern.lastIndex = endIndex;
1338
1355
  }
@@ -33,14 +33,14 @@ export interface XmlTagNode extends IXmlTagNode, Partial<SourceIndex> {}
33
33
 
34
34
  export type AttributeMap = Map<string, unknown>;
35
35
  export type AttributeList = [string, unknown][];
36
- export type TagOffsetMap = ObjectMap<Undef<number>>;
37
- export type WriteResult = [string, string, Null<Error>?];
38
- export type SaveResult = [string, Null<Error>?];
36
+ export type TagOffsetMap = ObjectMap<number | undefined>;
37
+ export type WriteResult = [string, string, (Error | null)?];
38
+ export type SaveResult = [string, (Error | null)?];
39
39
  export type XmlWriterOptions = ParserAction;
40
40
 
41
41
  export interface ParserResult extends Partial<TagData>, ParserAction {
42
- element: Null<Element>;
43
- error: Null<Error>;
42
+ element: Element | null;
43
+ error: Error | null;
44
44
  }
45
45
 
46
46
  export interface ReplaceOptions extends SourceIndex {
@@ -106,38 +106,38 @@ export class IXmlWriter extends IXmlBase {
106
106
  failCount: number;
107
107
  elements: XmlTagNode[];
108
108
  errors: Error[];
109
+ ignoreTagName: string;
110
+ ignoreTagGroup: string[] | undefined;
109
111
  parser?: ParserOptions;
110
- ignoreTagName?: string;
111
- ignoreTagGroup?: string[];
112
- readonly rootName?: string;
113
- readonly ignoreCaseTagName?: boolean;
112
+ readonly rootName: string;
113
+ readonly ignoreCaseTagName: boolean;
114
114
  init(offsetMap?: TagOffsetMap): void;
115
- getInvalidArea(): Undef<SourceContent[]>;
115
+ getInvalidArea(): SourceContent[] | undefined;
116
116
  ignoreFlag(...values: number[]): void;
117
117
  insertNodes(nodes?: XmlTagNode[]): void;
118
118
  fromNode(node: XmlTagNode, append?: TagAppend): IXmlElement;
119
119
  newElement(node: XmlTagNode): IXmlElement;
120
- append(node: XmlTagNode): Null<IXmlElement>;
120
+ append(node: XmlTagNode): IXmlElement | null;
121
121
  write(element: IXmlElement): boolean;
122
122
  save(): string;
123
123
  close(): string;
124
- update(node: XmlTagNode, outerXml: string, append?: TagAppend, offsetMap?: Null<TagOffsetMap>): void;
124
+ update(node: XmlTagNode, outerXml: string, append?: TagAppend, offsetMap?: TagOffsetMap | null): void;
125
125
  increment(nodes: XmlTagNode[], offset?: number): void;
126
126
  decrement(node: XmlTagNode, offset?: number, remove?: boolean): XmlTagNode[];
127
127
  renameTag(node: XmlTagNode, tagName: string): void;
128
128
  indexTag(tagName: string, append?: TagAppend, offset?: number): void;
129
129
  resetTag(tagName: string): void;
130
- ignoreTag(value: ArrayOf<string>): void;
130
+ ignoreTag(value: string | string[]): void;
131
131
  resetPosition(startIndex?: number): void;
132
- getElementById(id: string, ignoreCase?: boolean, options?: TagNodeByIdOptions): Undef<SourceTagNode>;
132
+ getElementById(id: string, ignoreCase?: boolean, options?: TagNodeByIdOptions): SourceTagNode | undefined;
133
133
  getElementsByTagName(tagName: string, ignoreCase?: boolean, options?: TagNodeOptions): SourceTagNode[];
134
134
  setRawString(targetXml: string, outerXml: string): string;
135
135
  getRawString(index: SourceIndex): string;
136
136
  spliceRawString(content: SourceContent, reset?: boolean): string;
137
- getComments(): Null<SourceContent[]>;
137
+ getComments(): SourceContent[] | null;
138
138
  hasErrors(): boolean;
139
139
  get newId(): string;
140
- get patternIgnore(): Null<RegExp>;
140
+ get patternIgnore(): RegExp | null;
141
141
  set source(value);
142
142
  get source(): string;
143
143
  }
@@ -150,8 +150,8 @@ export interface XmlWriterConstructor {
150
150
  readonly PATTERN_QUOTEVALUE: string;
151
151
  readonly PATTERN_COMMENT: string;
152
152
  readonly PATTERN_TRAILINGSPACE: string;
153
- replaceMatch(match: RegExpMatchArray, source: string, content: NumString, options: ReplaceMatchOptions): string;
154
- replaceMatch(match: RegExpMatchArray, source: string, content?: NumString, pattern?: RegExp): string;
153
+ replaceMatch(match: RegExpMatchArray, source: string, content: number | string, options: ReplaceMatchOptions): string;
154
+ replaceMatch(match: RegExpMatchArray, source: string, content?: number | string, pattern?: RegExp): string;
155
155
  escapeXmlString(value: string, ampersand?: boolean): string;
156
156
  escapeAttributes(source: string): string;
157
157
  getNewlineString(leading: string, trailing: string, newline?: string): string;
@@ -165,11 +165,11 @@ export interface XmlWriterConstructor {
165
165
  getNameOfId(document: string): string;
166
166
  getPatternId(name: string): RegExp;
167
167
  getCommentsAndCDATA(source: string, tagPattern: unknown, ignoreCase: boolean, stripXml: true): string;
168
- getCommentsAndCDATA(source: string, tagPattern?: ArrayOf<string> | [Undef<string>, Undef<string[]>], ignoreCase?: boolean, stripXml?: boolean): SourceContent[];
168
+ getCommentsAndCDATA(source: string, tagPattern?: string | string[] | [string | undefined, string[] | undefined], ignoreCase?: boolean, stripXml?: boolean): SourceContent[];
169
169
  isEqual(node: XmlTagNode, other: XmlTagNode, ignoreCase: boolean): boolean;
170
170
  isEqual(node: XmlTagNode, other: XmlTagNode, documentName?: string, ignoreCase?: boolean): boolean;
171
- isIndex(value: Undef<number>): value is number;
172
- isCount(value: Undef<number>): value is number;
171
+ isIndex(value: number | undefined): value is number;
172
+ isCount(value: number | undefined): value is number;
173
173
  isSpace(ch: string): boolean;
174
174
  readonly prototype: IXmlWriter;
175
175
  new(documentName: string, source: string, elements: XmlTagNode[], options?: XmlWriterOptions): IXmlWriter;
@@ -180,7 +180,7 @@ export class IXmlElement extends IXmlBase {
180
180
  readonly node: XmlTagNode;
181
181
  setAppend(value?: TagAppend): void;
182
182
  parseOuterXml(value?: string, tagVoid?: boolean): [string, string, boolean];
183
- getTagOffset(replacement?: string, options?: TagOffsetOptions): Undef<TagOffsetMap>;
183
+ getTagOffset(replacement?: string, options?: TagOffsetOptions): TagOffsetMap | undefined;
184
184
  setAttribute(name: string, value: string): void;
185
185
  getAttribute(name: string): string;
186
186
  removeAttribute(...names: string[]): void;
@@ -189,7 +189,7 @@ export class IXmlElement extends IXmlBase {
189
189
  write(source: string, invalid?: SourceIndex[]): WriteResult;
190
190
  save(source: string, invalid?: SourceIndex[]): SaveResult;
191
191
  replace(source: string, options: ReplaceOptions): WriteResult;
192
- findIndexOf(source: string): Undef<SourceIndex>;
192
+ findIndexOf(source: string): SourceIndex | undefined;
193
193
  getOuterContent(): [string, AttributeList, string];
194
194
  getInnerOffset(tagName: string): number;
195
195
  hasPosition(): boolean;
@@ -204,9 +204,9 @@ export class IXmlElement extends IXmlBase {
204
204
  get outerXml(): string;
205
205
  set remove(value);
206
206
  get remove(): boolean;
207
- get append(): Undef<TagAppend>;
208
- set tagOffset(value: Undef<TagOffsetMap>);
209
- get tagOffset(): Undef<TagOffsetMap>;
207
+ get append(): TagAppend | undefined;
208
+ set tagOffset(value: TagOffsetMap | undefined);
209
+ get tagOffset(): TagOffsetMap | undefined;
210
210
  get ignoreCase(): boolean;
211
211
  }
212
212
 
@@ -218,16 +218,16 @@ export interface XmlElementConstructor {
218
218
  }
219
219
 
220
220
  export class IDomWriter extends IXmlWriter {
221
- documentElement: Null<XmlTagNode>;
221
+ documentElement: XmlTagNode | null;
222
222
  readonly initOpts: DomWriterOptions;
223
223
  }
224
224
 
225
225
  export interface DomWriterConstructor extends XmlWriterConstructor {
226
- hasInnerXml(tagName: string): boolean;
226
+ hasInnerXml(tagName: string, ignoreCase?: boolean): boolean;
227
227
  normalize(source: string, options: NormalizeOptions): string;
228
228
  normalize(source: string, newline?: string, ignoreChar?: string, escapeEntities?: boolean): string;
229
229
  getDocumentElement(source: string, parser?: ParserOptions): ParserResult;
230
- getElementsByTagName(tagName: string | ((name: string) => boolean), nodes: ArrayOf<AnyNode>, recurse?: boolean, limit?: number): Element[];
230
+ getElementsByTagName(tagName: string | ((name: string) => boolean), nodes: AnyNode | AnyNode[], recurse?: boolean, limit?: number): Element[];
231
231
  readonly prototype: IDomWriter;
232
232
  new(documentName: string, source: string, elements: XmlTagNode[], options?: DomWriterOptions): IDomWriter;
233
233
  new(documentName: string, source: string, elements: XmlTagNode[], normalize?: boolean | string, escapeEntities?: boolean, parser?: ParserOptions): IDomWriter;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a, _b, _c, _d;
3
3
  exports.SourceMap = exports.TransformSeries = void 0;
4
- const path = require("path");
4
+ const path = require("node:path");
5
5
  const types_1 = require("@e-mc/types");
6
6
  const core_1 = require("@e-mc/core");
7
7
  const kCode = Symbol('code');
package/util.d.ts CHANGED
@@ -2,7 +2,7 @@ declare namespace util {
2
2
  /** @deprecated Types.IMPORT_MAP */
3
3
  const IMPORTS: Record<string, string | undefined>;
4
4
  const PATTERN_PARENTHESIS: string;
5
- function loadPlugins<T = unknown>(name: string | unknown[], plugins?: unknown[]): T[];
5
+ function loadPlugins<T = unknown>(plugins: string | unknown[]): T[];
6
6
  function replaceAll(source: string, valueOf: (name: string) => string, opening?: string, closing?: string): string;
7
7
  function concatString(values: string[] | string | undefined, newline?: string): string;
8
8
  function spliceString(source: string, startIndex: number, endIndex: number, content: string, pattern?: RegExp): string;
package/util.js CHANGED
@@ -13,13 +13,13 @@ exports.getHashData = getHashData;
13
13
  exports.hasValue = hasValue;
14
14
  exports.getModuleName = getModuleName;
15
15
  exports.removeInternalProperties = removeInternalProperties;
16
- const path = require("path");
16
+ const path = require("node:path");
17
17
  const types_1 = require("@e-mc/types");
18
18
  Object.defineProperty(exports, "IMPORTS", { enumerable: true, get: function () { return types_1.IMPORT_MAP; } });
19
19
  Object.defineProperty(exports, "isObject", { enumerable: true, get: function () { return types_1.isObject; } });
20
- function loadPlugins(name, plugins = []) {
21
- if (Array.isArray(name)) {
22
- plugins = name;
20
+ function loadPlugins(plugins) {
21
+ if (!Array.isArray(plugins)) {
22
+ plugins = [plugins];
23
23
  }
24
24
  const result = [];
25
25
  for (const plugin of plugins.map(item => (0, types_1.isString)(item) ? [item, undefined] : Array.isArray(item) && (0, types_1.isString)(item[0]) ? item : null)) {
@@ -207,7 +207,7 @@ function getModuleName(err) {
207
207
  function removeInternalProperties(value, retaining) {
208
208
  if ((0, types_1.isObject)(value)) {
209
209
  for (const prop in value) {
210
- if (Object.prototype.hasOwnProperty.call(value, prop)) {
210
+ if (Object.hasOwn(value, prop)) {
211
211
  if (retaining) {
212
212
  if (!retaining.includes(prop)) {
213
213
  delete value[prop];