node-html-parser 1.4.5 → 1.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -62,7 +62,7 @@ var HTMLParser = require('node-html-parser');
62
62
  var root = HTMLParser.parse('<ul id="list"><li>Hello World</li></ul>');
63
63
  ```
64
64
 
65
- ## HTMLElement Methods
65
+ ## Global Methods
66
66
 
67
67
  ### parse(data[, options])
68
68
 
@@ -84,6 +84,8 @@ Parse given data, and return root of the generated DOM.
84
84
  }
85
85
  ```
86
86
 
87
+ ## HTMLElement Methods
88
+
87
89
  ### HTMLElement#trimRight()
88
90
 
89
91
  Trim element from right (in block) after seeing pattern in a TextNode.
@@ -140,6 +142,10 @@ Same as [outerHTML](#htmlelementouterhtml)
140
142
 
141
143
  Set content. **Notice**: Do not set content of the **root** node.
142
144
 
145
+ ### HTMLElement#remove()
146
+
147
+ Remove current element.
148
+
143
149
  ## HTMLElement Properties
144
150
 
145
151
  ### HTMLElement#text
@@ -175,3 +181,11 @@ Get innerHTML.
175
181
  ### HTMLElement#outerHTML
176
182
 
177
183
  Get outerHTML.
184
+
185
+ ### HTMLElement#nextSibling
186
+
187
+ Returns a reference to the next child node of the current element's parent.
188
+
189
+ ### HTMLElement#nextElementSibling
190
+
191
+ Returns a reference to the next child element of the current element's parent.
@@ -161,31 +161,21 @@ export default class Matcher {
161
161
  let attr_key = '';
162
162
  let value = '';
163
163
  if (tagName && tagName !== '*') {
164
- let reg;
165
164
  if (tagName.startsWith('#')) {
166
165
  // source += 'if (el.id != ' + JSON.stringify(tagName.substr(1)) + ') return false;';// 1
167
166
  function_name += '1';
168
167
  }
169
168
  else {
170
- reg = /^\[\s*(\S+)\s*(=|!=)\s*((((["'])([^\6]*)\6))|(\S*?))\]\s*/.exec(tagName);
169
+ // https://github.com/taoqf/node-html-parser/issues/86
170
+ // const reg = /\[\s*([\w-]+)(\s*=\s*(((?<quote>'|")\s*(.*)(\k<quote>))|(\S*)))?\s*\]/.exec(tagName);
171
+ // `[a-b]`,`[ a-b ]`,`[a-b=c]`, `[a-b=c'd]`,`[a-b='c\' d"e ']`,`[ a-b = 'c\' d"e ' ]`,`[a-b="c' d\"e " ]`,`[ a-b = "c' d\"e " ]`
172
+ const reg = /\[\s*([\w-]+)(\s*=\s*(('\s*(.*)'|"\s*(.*)")|(\S*)))?\s*\]/.exec(tagName);
171
173
  if (reg) {
172
174
  attr_key = reg[1];
173
- let method = reg[2];
174
- if (method !== '=' && method !== '!=') {
175
- // eslint-disable-next-line no-template-curly-in-string
176
- throw new Error('Selector not supported, Expect [key${op}value].op must be =,!=');
177
- }
178
- if (method === '=') {
179
- method = '==';
180
- }
181
- value = reg[7] || reg[8];
175
+ value = reg[5] || reg[6] || reg[7];
182
176
  // source += `let attrs = el.attributes;for (let key in attrs){const val = attrs[key]; if (key == "${attr_key}" && val == "${value}"){return true;}} return false;`;// 2
183
177
  function_name += '2';
184
178
  }
185
- else if ((reg = /^\[(.*?)\]/.exec(tagName))) {
186
- attr_key = reg[1];
187
- function_name += '5';
188
- }
189
179
  else {
190
180
  // source += 'if (el.tagName != ' + JSON.stringify(tagName) + ') return false;';// 3
191
181
  function_name += '3';
@@ -71,6 +71,17 @@ export default class HTMLElement extends Node {
71
71
  }
72
72
  }
73
73
  }
74
+ /**
75
+ * Remove current element
76
+ */
77
+ remove() {
78
+ if (this.parentNode) {
79
+ const children = this.parentNode.childNodes;
80
+ this.parentNode.childNodes = children.filter((child) => {
81
+ return this !== child;
82
+ });
83
+ }
84
+ }
74
85
  /**
75
86
  * Remove Child element from childNodes array
76
87
  * @param {HTMLElement} node node to remove
@@ -86,14 +97,13 @@ export default class HTMLElement extends Node {
86
97
  * @param {HTMLElement} newNode new node
87
98
  */
88
99
  exchangeChild(oldNode, newNode) {
89
- let idx = -1;
90
- for (let i = 0; i < this.childNodes.length; i++) {
91
- if (this.childNodes[i] === oldNode) {
92
- idx = i;
93
- break;
100
+ const children = this.childNodes;
101
+ this.childNodes = children.map((child) => {
102
+ if (child === oldNode) {
103
+ return newNode;
94
104
  }
95
- }
96
- this.childNodes[idx] = newNode;
105
+ return child;
106
+ });
97
107
  }
98
108
  get tagName() {
99
109
  return this.rawTagName ? this.rawTagName.toUpperCase() : this.rawTagName;
@@ -545,6 +555,38 @@ export default class HTMLElement extends Node {
545
555
  // return;
546
556
  // }
547
557
  }
558
+ get nextSibling() {
559
+ if (this.parentNode) {
560
+ const children = this.parentNode.childNodes;
561
+ let i = 0;
562
+ while (i < children.length) {
563
+ const child = children[i++];
564
+ if (this === child) {
565
+ return children[i] || null;
566
+ }
567
+ }
568
+ return null;
569
+ }
570
+ }
571
+ get nextElementSibling() {
572
+ if (this.parentNode) {
573
+ const children = this.parentNode.childNodes;
574
+ let i = 0;
575
+ let find = false;
576
+ while (i < children.length) {
577
+ const child = children[i++];
578
+ if (find) {
579
+ if (child instanceof HTMLElement) {
580
+ return child || null;
581
+ }
582
+ }
583
+ else if (this === child) {
584
+ find = true;
585
+ }
586
+ }
587
+ return null;
588
+ }
589
+ }
548
590
  }
549
591
  // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
550
592
  const kMarkupPattern = /<!--[^]*?(?=-->)-->|<(\/?)([a-z][-.:0-9_a-z]*)\s*([^>]*?)(\/?)>/ig;
package/dist/main.js CHANGED
@@ -312,31 +312,21 @@ define("matcher", ["require", "exports"], function (require, exports) {
312
312
  var attr_key = '';
313
313
  var value = '';
314
314
  if (tagName && tagName !== '*') {
315
- var reg = void 0;
316
315
  if (tagName.startsWith('#')) {
317
316
  // source += 'if (el.id != ' + JSON.stringify(tagName.substr(1)) + ') return false;';// 1
318
317
  function_name += '1';
319
318
  }
320
319
  else {
321
- reg = /^\[\s*(\S+)\s*(=|!=)\s*((((["'])([^\6]*)\6))|(\S*?))\]\s*/.exec(tagName);
320
+ // https://github.com/taoqf/node-html-parser/issues/86
321
+ // const reg = /\[\s*([\w-]+)(\s*=\s*(((?<quote>'|")\s*(.*)(\k<quote>))|(\S*)))?\s*\]/.exec(tagName);
322
+ // `[a-b]`,`[ a-b ]`,`[a-b=c]`, `[a-b=c'd]`,`[a-b='c\' d"e ']`,`[ a-b = 'c\' d"e ' ]`,`[a-b="c' d\"e " ]`,`[ a-b = "c' d\"e " ]`
323
+ var reg = /\[\s*([\w-]+)(\s*=\s*(('\s*(.*)'|"\s*(.*)")|(\S*)))?\s*\]/.exec(tagName);
322
324
  if (reg) {
323
325
  attr_key = reg[1];
324
- var method = reg[2];
325
- if (method !== '=' && method !== '!=') {
326
- // eslint-disable-next-line no-template-curly-in-string
327
- throw new Error('Selector not supported, Expect [key${op}value].op must be =,!=');
328
- }
329
- if (method === '=') {
330
- method = '==';
331
- }
332
- value = reg[7] || reg[8];
326
+ value = reg[5] || reg[6] || reg[7];
333
327
  // source += `let attrs = el.attributes;for (let key in attrs){const val = attrs[key]; if (key == "${attr_key}" && val == "${value}"){return true;}} return false;`;// 2
334
328
  function_name += '2';
335
329
  }
336
- else if ((reg = /^\[(.*?)\]/.exec(tagName))) {
337
- attr_key = reg[1];
338
- function_name += '5';
339
- }
340
330
  else {
341
331
  // source += 'if (el.tagName != ' + JSON.stringify(tagName) + ') return false;';// 3
342
332
  function_name += '3';
@@ -487,6 +477,18 @@ define("nodes/html", ["require", "exports", "he", "nodes/node", "nodes/type", "n
487
477
  }
488
478
  return _this;
489
479
  }
480
+ /**
481
+ * Remove current element
482
+ */
483
+ HTMLElement.prototype.remove = function () {
484
+ var _this = this;
485
+ if (this.parentNode) {
486
+ var children = this.parentNode.childNodes;
487
+ this.parentNode.childNodes = children.filter(function (child) {
488
+ return _this !== child;
489
+ });
490
+ }
491
+ };
490
492
  /**
491
493
  * Remove Child element from childNodes array
492
494
  * @param {HTMLElement} node node to remove
@@ -502,14 +504,13 @@ define("nodes/html", ["require", "exports", "he", "nodes/node", "nodes/type", "n
502
504
  * @param {HTMLElement} newNode new node
503
505
  */
504
506
  HTMLElement.prototype.exchangeChild = function (oldNode, newNode) {
505
- var idx = -1;
506
- for (var i = 0; i < this.childNodes.length; i++) {
507
- if (this.childNodes[i] === oldNode) {
508
- idx = i;
509
- break;
507
+ var children = this.childNodes;
508
+ this.childNodes = children.map(function (child) {
509
+ if (child === oldNode) {
510
+ return newNode;
510
511
  }
511
- }
512
- this.childNodes[idx] = newNode;
512
+ return child;
513
+ });
513
514
  };
514
515
  Object.defineProperty(HTMLElement.prototype, "tagName", {
515
516
  get: function () {
@@ -1011,6 +1012,46 @@ define("nodes/html", ["require", "exports", "he", "nodes/node", "nodes/type", "n
1011
1012
  // return;
1012
1013
  // }
1013
1014
  };
1015
+ Object.defineProperty(HTMLElement.prototype, "nextSibling", {
1016
+ get: function () {
1017
+ if (this.parentNode) {
1018
+ var children = this.parentNode.childNodes;
1019
+ var i = 0;
1020
+ while (i < children.length) {
1021
+ var child = children[i++];
1022
+ if (this === child) {
1023
+ return children[i] || null;
1024
+ }
1025
+ }
1026
+ return null;
1027
+ }
1028
+ },
1029
+ enumerable: false,
1030
+ configurable: true
1031
+ });
1032
+ Object.defineProperty(HTMLElement.prototype, "nextElementSibling", {
1033
+ get: function () {
1034
+ if (this.parentNode) {
1035
+ var children = this.parentNode.childNodes;
1036
+ var i = 0;
1037
+ var find = false;
1038
+ while (i < children.length) {
1039
+ var child = children[i++];
1040
+ if (find) {
1041
+ if (child instanceof HTMLElement) {
1042
+ return child || null;
1043
+ }
1044
+ }
1045
+ else if (this === child) {
1046
+ find = true;
1047
+ }
1048
+ }
1049
+ return null;
1050
+ }
1051
+ },
1052
+ enumerable: false,
1053
+ configurable: true
1054
+ });
1014
1055
  return HTMLElement;
1015
1056
  }(node_3.default));
1016
1057
  exports.default = HTMLElement;
package/dist/matcher.js CHANGED
@@ -163,31 +163,21 @@ var Matcher = /** @class */ (function () {
163
163
  var attr_key = '';
164
164
  var value = '';
165
165
  if (tagName && tagName !== '*') {
166
- var reg = void 0;
167
166
  if (tagName.startsWith('#')) {
168
167
  // source += 'if (el.id != ' + JSON.stringify(tagName.substr(1)) + ') return false;';// 1
169
168
  function_name += '1';
170
169
  }
171
170
  else {
172
- reg = /^\[\s*(\S+)\s*(=|!=)\s*((((["'])([^\6]*)\6))|(\S*?))\]\s*/.exec(tagName);
171
+ // https://github.com/taoqf/node-html-parser/issues/86
172
+ // const reg = /\[\s*([\w-]+)(\s*=\s*(((?<quote>'|")\s*(.*)(\k<quote>))|(\S*)))?\s*\]/.exec(tagName);
173
+ // `[a-b]`,`[ a-b ]`,`[a-b=c]`, `[a-b=c'd]`,`[a-b='c\' d"e ']`,`[ a-b = 'c\' d"e ' ]`,`[a-b="c' d\"e " ]`,`[ a-b = "c' d\"e " ]`
174
+ var reg = /\[\s*([\w-]+)(\s*=\s*(('\s*(.*)'|"\s*(.*)")|(\S*)))?\s*\]/.exec(tagName);
173
175
  if (reg) {
174
176
  attr_key = reg[1];
175
- var method = reg[2];
176
- if (method !== '=' && method !== '!=') {
177
- // eslint-disable-next-line no-template-curly-in-string
178
- throw new Error('Selector not supported, Expect [key${op}value].op must be =,!=');
179
- }
180
- if (method === '=') {
181
- method = '==';
182
- }
183
- value = reg[7] || reg[8];
177
+ value = reg[5] || reg[6] || reg[7];
184
178
  // source += `let attrs = el.attributes;for (let key in attrs){const val = attrs[key]; if (key == "${attr_key}" && val == "${value}"){return true;}} return false;`;// 2
185
179
  function_name += '2';
186
180
  }
187
- else if ((reg = /^\[(.*?)\]/.exec(tagName))) {
188
- attr_key = reg[1];
189
- function_name += '5';
190
- }
191
181
  else {
192
182
  // source += 'if (el.tagName != ' + JSON.stringify(tagName) + ') return false;';// 3
193
183
  function_name += '3';
@@ -42,6 +42,10 @@ export default class HTMLElement extends Node {
42
42
  * @memberof HTMLElement
43
43
  */
44
44
  constructor(tagName: string, keyAttrs: KeyAttributes, rawAttrs?: string, parentNode?: Node);
45
+ /**
46
+ * Remove current element
47
+ */
48
+ remove(): void;
45
49
  /**
46
50
  * Remove Child element from childNodes array
47
51
  * @param {HTMLElement} node node to remove
@@ -148,6 +152,8 @@ export default class HTMLElement extends Node {
148
152
  */
149
153
  setAttributes(attributes: Attributes): void;
150
154
  insertAdjacentHTML(where: InsertPosition, html: string): void;
155
+ get nextSibling(): Node;
156
+ get nextElementSibling(): HTMLElement;
151
157
  }
152
158
  export interface Options {
153
159
  lowerCaseTagName: boolean;
@@ -101,6 +101,18 @@ var HTMLElement = /** @class */ (function (_super) {
101
101
  }
102
102
  return _this;
103
103
  }
104
+ /**
105
+ * Remove current element
106
+ */
107
+ HTMLElement.prototype.remove = function () {
108
+ var _this = this;
109
+ if (this.parentNode) {
110
+ var children = this.parentNode.childNodes;
111
+ this.parentNode.childNodes = children.filter(function (child) {
112
+ return _this !== child;
113
+ });
114
+ }
115
+ };
104
116
  /**
105
117
  * Remove Child element from childNodes array
106
118
  * @param {HTMLElement} node node to remove
@@ -116,14 +128,13 @@ var HTMLElement = /** @class */ (function (_super) {
116
128
  * @param {HTMLElement} newNode new node
117
129
  */
118
130
  HTMLElement.prototype.exchangeChild = function (oldNode, newNode) {
119
- var idx = -1;
120
- for (var i = 0; i < this.childNodes.length; i++) {
121
- if (this.childNodes[i] === oldNode) {
122
- idx = i;
123
- break;
131
+ var children = this.childNodes;
132
+ this.childNodes = children.map(function (child) {
133
+ if (child === oldNode) {
134
+ return newNode;
124
135
  }
125
- }
126
- this.childNodes[idx] = newNode;
136
+ return child;
137
+ });
127
138
  };
128
139
  Object.defineProperty(HTMLElement.prototype, "tagName", {
129
140
  get: function () {
@@ -625,6 +636,46 @@ var HTMLElement = /** @class */ (function (_super) {
625
636
  // return;
626
637
  // }
627
638
  };
639
+ Object.defineProperty(HTMLElement.prototype, "nextSibling", {
640
+ get: function () {
641
+ if (this.parentNode) {
642
+ var children = this.parentNode.childNodes;
643
+ var i = 0;
644
+ while (i < children.length) {
645
+ var child = children[i++];
646
+ if (this === child) {
647
+ return children[i] || null;
648
+ }
649
+ }
650
+ return null;
651
+ }
652
+ },
653
+ enumerable: false,
654
+ configurable: true
655
+ });
656
+ Object.defineProperty(HTMLElement.prototype, "nextElementSibling", {
657
+ get: function () {
658
+ if (this.parentNode) {
659
+ var children = this.parentNode.childNodes;
660
+ var i = 0;
661
+ var find = false;
662
+ while (i < children.length) {
663
+ var child = children[i++];
664
+ if (find) {
665
+ if (child instanceof HTMLElement) {
666
+ return child || null;
667
+ }
668
+ }
669
+ else if (this === child) {
670
+ find = true;
671
+ }
672
+ }
673
+ return null;
674
+ }
675
+ },
676
+ enumerable: false,
677
+ configurable: true
678
+ });
628
679
  return HTMLElement;
629
680
  }(node_1.default));
630
681
  exports.default = HTMLElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-html-parser",
3
- "version": "1.4.5",
3
+ "version": "1.4.9",
4
4
  "description": "A very fast HTML parser, generating a simplified DOM, with basic element query support.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -13,11 +13,14 @@
13
13
  "ts:amd": "tsc -t es5 -m amd -d false --outFile ./dist/main.js",
14
14
  "ts:esm": "tsc -t esnext -m esnext -d false --outDir ./dist/esm/",
15
15
  "build": "npm run lint && npm run clean && npm run ts:cjs && npm run ts:amd && npm run ts:esm",
16
- "dev": "tsc -w",
16
+ "dev": "tsc -w & mocha -w ./test/*.js",
17
17
  "pretest": "tsc -m commonjs"
18
18
  },
19
19
  "keywords": [
20
- "fast html parser nodejs typescript"
20
+ "parser",
21
+ "html",
22
+ "nodejs",
23
+ "typescript"
21
24
  ],
22
25
  "author": "Xiaoyi Shi <ashi009@gmail.com>",
23
26
  "contributors": [