xml-twig 1.6.1 → 1.7.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/twig.js +62 -61
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "name": "xml-twig",
7
7
  "description": "Node module for processing huge XML documents in tree mode",
8
- "version": "1.6.1",
8
+ "version": "1.7.0",
9
9
  "main": "twig.js",
10
10
  "directories": {
11
11
  "doc": "doc"
package/twig.js CHANGED
@@ -1,9 +1,6 @@
1
1
  const SAX = 'sax';
2
2
  const EXPAT = ['expat', 'node-expat'];
3
3
 
4
- let tree;
5
- let current;
6
-
7
4
  /**
8
5
  * @external XMLWriter
9
6
  * @see {@link https://www.npmjs.com/package/xml-writer|xml-writer}
@@ -160,7 +157,7 @@ function createParser(handler, options = {}) {
160
157
  });
161
158
 
162
159
  parser.on("closetag", onClose.bind(null, handler, parser, options));
163
- parser.on("opentagstart", onStart.bind(null, {
160
+ parser.on("opentagstart", onStart.bind(null, parser, {
164
161
  handler: Array.isArray(handler) ? handler : [handler],
165
162
  options: options,
166
163
  namespaces: namespaces
@@ -174,14 +171,14 @@ function createParser(handler, options = {}) {
174
171
  let [k, v] = item.split('=');
175
172
  declaration[k] = v.replaceAll('"', '').replaceAll("'", '');
176
173
  }
177
- tree = new Twig(null);
178
- Object.defineProperty(tree, 'declaration', {
174
+ parser.twig.tree = new Twig(parser, null);
175
+ Object.defineProperty(parser.twig.tree, 'declaration', {
179
176
  value: declaration,
180
177
  writable: false,
181
178
  enumerable: true
182
179
  });
183
- } else if (tree.PI === undefined) {
184
- Object.defineProperty(tree, 'PI', {
180
+ } else if (parser.twig.tree.PI === undefined) {
181
+ Object.defineProperty(parser.twig.tree, 'PI', {
185
182
  value: { target: pi.name, data: pi.body },
186
183
  writable: false,
187
184
  enumerable: true
@@ -192,26 +189,25 @@ function createParser(handler, options = {}) {
192
189
  parser.on("attribute", function (attr) {
193
190
  if (options.xmlns && (attr.uri ?? '') !== '' && attr.local !== undefined) {
194
191
  namespaces[attr.local] = attr.uri;
195
- if (current.name.includes(':')) {
196
- Object.defineProperty(current, 'namespace', {
192
+ if (parser.twig.current.name.includes(':')) {
193
+ Object.defineProperty(parser.twig.current, 'namespace', {
197
194
  value: { local: attr.local, uri: attr.uri },
198
195
  writable: false,
199
196
  enumerable: true
200
197
  });
201
198
  } else {
202
- current.attribute(attr.name, attr.value);
199
+ parser.twig.current.attribute(attr.name, attr.value);
203
200
  }
204
201
  } else {
205
- current.attribute(attr.name, attr.value);
202
+ parser.twig.current.attribute(attr.name, attr.value);
206
203
  }
207
204
  });
208
205
  parser.on("cdata", function (str) {
209
- current.text = options.trim ? str.trim() : str;
206
+ parser.twig.current.text = options.trim ? str.trim() : str;
210
207
  });
211
208
 
212
209
  parser.on('end', function () {
213
- tree = undefined;
214
- current = undefined;
210
+ parser.twig = { current: null, tree: null };
215
211
  parser.emit("finish");
216
212
  parser.emit("close");
217
213
  });
@@ -228,19 +224,19 @@ function createParser(handler, options = {}) {
228
224
  });
229
225
 
230
226
  parser.on("endElement", onClose.bind(null, handler, parser, options));
231
- parser.on("startElement", onStart.bind(null, {
227
+ parser.on("startElement", onStart.bind(null, parser, {
232
228
  handler: Array.isArray(handler) ? handler : [handler],
233
229
  options: options,
234
230
  namespaces: namespaces
235
231
  }));
236
232
 
237
233
  parser.on('xmlDecl', function (version, encoding, standalone) {
238
- tree = new Twig(null);
234
+ parser.twig.tree = new Twig(parser, null);
239
235
  let dec = {};
240
236
  if (version !== undefined) dec.version = version;
241
237
  if (encoding !== undefined) dec.encoding = encoding;
242
238
  if (standalone !== undefined) dec.standalone = standalone;
243
- Object.defineProperty(tree, 'declaration', {
239
+ Object.defineProperty(parser.twig.tree, 'declaration', {
244
240
  value: dec,
245
241
  writable: false,
246
242
  enumerable: true
@@ -248,12 +244,11 @@ function createParser(handler, options = {}) {
248
244
  });
249
245
 
250
246
  parser.on('processingInstruction', function (target, data) {
251
- tree.PI = { target: target, data: data };
247
+ parser.twig.tree.PI = { target: target, data: data };
252
248
  });
253
249
 
254
250
  parser.on('end', function () {
255
- tree = undefined;
256
- current = undefined;
251
+ parser.twig = { current: null, tree: null };
257
252
  parser.emit("finish");
258
253
  });
259
254
 
@@ -261,6 +256,12 @@ function createParser(handler, options = {}) {
261
256
  throw new UnsupportedParser(options.method);
262
257
  }
263
258
 
259
+ Object.defineProperty(parser, 'twig', {
260
+ enumerable: true,
261
+ value: { current: null, tree: null },
262
+ writable: true
263
+ });
264
+
264
265
  Object.defineProperty(parser, 'method', {
265
266
  value: options.method,
266
267
  writable: false,
@@ -277,19 +278,19 @@ function createParser(handler, options = {}) {
277
278
 
278
279
  // Common events
279
280
  parser.on('text', function (str) {
280
- if (current === undefined || current === null) return;
281
- current.text = options.trim ? str.trim() : str;
281
+ if (parser.twig.current === null) return;
282
+ parser.twig.current.text = options.trim ? str.trim() : str;
282
283
  });
283
284
 
284
285
  parser.on("comment", function (str) {
285
- if (current.hasOwnProperty('comment')) {
286
- if (typeof current.comment === 'string') {
287
- current.comment = [current.comment, str.trim()];
286
+ if (parser.twig.current.hasOwnProperty('comment')) {
287
+ if (typeof parser.twig.current.comment === 'string') {
288
+ parser.twig.current.comment = [parser.twig.current.comment, str.trim()];
288
289
  } else {
289
- current.comment.push(str.trim());
290
+ parser.twig.current.comment.push(str.trim());
290
291
  }
291
292
  } else {
292
- Object.defineProperty(current, 'comment', {
293
+ Object.defineProperty(parser.twig.current, 'comment', {
293
294
  value: str.trim(),
294
295
  writable: true,
295
296
  enumerable: true,
@@ -316,7 +317,7 @@ function createParser(handler, options = {}) {
316
317
  * @param {object|string} node - Node or Node name
317
318
  * @param {object} attrs - Node Attributes
318
319
  */
319
- function onStart(binds, node, attrs) {
320
+ function onStart(parser, binds, node, attrs) {
320
321
 
321
322
  const name = typeof node === 'string' ? node : node.name;
322
323
  const handler = binds.handler;
@@ -329,17 +330,17 @@ function onStart(binds, node, attrs) {
329
330
  attrNS[key] = attrs[key];
330
331
  }
331
332
 
332
- if (tree === undefined) {
333
- tree = new Twig(name, current, options.xmlns ? attrNS : attrs);
333
+ if (parser.twig.tree === null) {
334
+ parser.twig.tree = new Twig(parser, name, parser.twig.current, options.xmlns ? attrNS : attrs);
334
335
  } else {
335
- if (current.isRoot && current.name === undefined) {
336
- current.setRoot(name);
336
+ if (parser.twig.current.isRoot && parser.twig.current.name === undefined) {
337
+ parser.twig.current.setRoot(name);
337
338
  if (attrs !== undefined) {
338
339
  for (let [key, val] of Object.entries(options.xmlns ? attrNS : attrs))
339
- current.attribute(key, val);
340
+ parser.twig.current.attribute(key, val);
340
341
  }
341
342
  } else {
342
- let elt = new Twig(name, current, options.xmlns ? attrNS : attrs);
343
+ let elt = new Twig(parser, name, parser.twig.current, options.xmlns ? attrNS : attrs);
343
344
  if (options.partial) {
344
345
  for (let hndl of handler) {
345
346
  if (typeof hndl.tag === 'string' && name === hndl.tag) {
@@ -351,7 +352,7 @@ function onStart(binds, node, attrs) {
351
352
  } else if (hndl.tag instanceof RegExp && hndl.tag.test(name)) {
352
353
  elt.pin();
353
354
  break;
354
- } else if (typeof hndl.tag === 'function' && hndl.tag(name, current ?? tree)) {
355
+ } else if (typeof hndl.tag === 'function' && hndl.tag(name, parser.twig.current ?? parser.twig.tree)) {
355
356
  elt.pin();
356
357
  break;
357
358
  }
@@ -368,7 +369,7 @@ function onStart(binds, node, attrs) {
368
369
  if (name.includes(':')) {
369
370
  let prefix = name.split(':')[0];
370
371
  if (namespaces[prefix] !== undefined) {
371
- Object.defineProperty(current, 'namespace', {
372
+ Object.defineProperty(parser.twig.current, 'namespace', {
372
373
  value: { local: prefix, uri: namespaces[prefix] },
373
374
  writable: false,
374
375
  enumerable: true
@@ -386,40 +387,40 @@ function onStart(binds, node, attrs) {
386
387
  * @param {string} name - Event handler parameter
387
388
  */
388
389
  function onClose(handler, parser, options, name) {
389
- current.close();
390
+ parser.twig.current.close();
390
391
  let purge = true;
391
392
 
392
393
  for (let hndl of Array.isArray(handler) ? handler : [handler]) {
393
394
  if (hndl.tag instanceof AnyHandler) {
394
- if (typeof hndl.function === 'function') hndl.function(current ?? tree, parser);
395
- if (typeof hndl.event === 'string') parser.emit(hndl.event, current ?? tree);
395
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.current ?? parser.twig.tree, parser);
396
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.current ?? parser.twig.tree);
396
397
  purge = false;
397
- } else if (hndl.tag instanceof RootHandler && current.isRoot) {
398
- if (typeof hndl.function === 'function') hndl.function(tree, parser);
399
- if (typeof hndl.event === 'string') parser.emit(hndl.event, tree);
398
+ } else if (hndl.tag instanceof RootHandler && parser.twig.current.isRoot) {
399
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.tree, parser);
400
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.tree);
400
401
  purge = false;
401
402
  } else if (Array.isArray(hndl.tag) && hndl.tag.includes(name)) {
402
- if (typeof hndl.function === 'function') hndl.function(current ?? tree, parser);
403
- if (typeof hndl.event === 'string') parser.emit(hndl.event, current ?? tree);
403
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.current ?? parser.twig.tree, parser);
404
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.current ?? parser.twig.tree);
404
405
  purge = false;
405
406
  } else if (typeof hndl.tag === 'string' && name === hndl.tag) {
406
- if (typeof hndl.function === 'function') hndl.function(current ?? tree, parser);
407
- if (typeof hndl.event === 'string') parser.emit(hndl.event, current ?? tree);
407
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.current ?? parser.twig.tree, parser);
408
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.current ?? parser.twig.tree);
408
409
  purge = false;
409
410
  } else if (hndl.tag instanceof RegExp && hndl.tag.test(name)) {
410
- if (typeof hndl.function === 'function') hndl.function(current ?? tree, parser);
411
- if (typeof hndl.event === 'string') parser.emit(hndl.event, current ?? tree);
411
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.current ?? parser.twig.tree, parser);
412
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.current ?? parser.twig.tree);
412
413
  purge = false;
413
- } else if (typeof hndl.tag === 'function' && hndl.tag(name, current ?? tree)) {
414
- if (typeof hndl.function === 'function') hndl.function(current ?? tree, parser);
415
- if (typeof hndl.event === 'string') parser.emit(hndl.event, current ?? tree);
414
+ } else if (typeof hndl.tag === 'function' && hndl.tag(name, parser.twig.current ?? parser.twig.tree)) {
415
+ if (typeof hndl.function === 'function') hndl.function(parser.twig.current ?? parser.twig.tree, parser);
416
+ if (typeof hndl.event === 'string') parser.emit(hndl.event, parser.twig.current ?? parser.twig.tree);
416
417
  purge = false;
417
418
  }
418
419
  }
419
420
 
420
- if (options.partial && purge && !current.pinned && !current.isRoot)
421
- current.purge();
422
- current = current.parent();
421
+ if (options.partial && purge && !parser.twig.current.pinned && !parser.twig.current.isRoot)
422
+ parser.twig.parser.twig.current.purge();
423
+ parser.twig.current = parser.twig.current.parent();
423
424
 
424
425
  }
425
426
 
@@ -507,20 +508,20 @@ class Twig {
507
508
  * @param {object} [attributes] - Attribute object
508
509
  * @param {string|number} [index] - Position name 'first', 'last' or the position in the current `children` array.<br>Defaults to 'last'
509
510
  */
510
- constructor(name, parent, attributes, index) {
511
+ constructor(parser, name, parent, attributes, index) {
511
512
  if (index === undefined)
512
- current = this;
513
+ parser.twig.current = this;
513
514
 
514
515
  if (name === null) {
515
516
  // Root element not available yet
516
- tree = this;
517
+ parser.twig.tree = this;
517
518
  } else {
518
519
  this.#name = name;
519
520
  if (attributes !== undefined)
520
521
  this.#attributes = attributes;
521
522
  if (parent === undefined) {
522
523
  // Root element
523
- tree = this;
524
+ parser.twig.tree = this;
524
525
  } else {
525
526
  this.#parent = parent;
526
527
  if (this.#parent.#pinned)
@@ -1216,8 +1217,8 @@ class Twig {
1216
1217
  * @param {name|number} [position] - Position name 'first', 'last' or the position in the `children`
1217
1218
  * @returns {Twig} - The appended element
1218
1219
  */
1219
- addElement = function (name, text, attributes, position) {
1220
- let twig = new Twig(name, this, attributes ?? {}, position ?? 'last');
1220
+ addElement = function (parser, name, text, attributes, position) {
1221
+ let twig = new Twig(parser, name, this, attributes ?? {}, position ?? 'last');
1221
1222
  twig.#text = text ?? null;
1222
1223
  twig.close();
1223
1224
  return twig;