als-document 1.0.2-alpha → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "als-document",
3
- "version": "1.0.2-alpha",
3
+ "version": "1.0.2",
4
4
  "description": "A powerful HTML parser & DOM manipulation library for both backend and frontend.",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -10,8 +10,5 @@
10
10
  },
11
11
  "keywords": ["HTML", "DOM", "parser", "manipulation", "backend", "frontend", "als-document"],
12
12
  "author": "Alex Sorkin <alexsorkin1980@gmail.com>",
13
- "license": "ISC",
14
- "devDependencies": {
15
- "als-simple-test": "^0.3.5"
16
- }
13
+ "license": "ISC"
17
14
  }
package/readme.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  `als-document` is a powerful library for parsing HTML and manipulating the DOM structure on backend and frontend. It provides a robust and intuitive API for querying and interacting with DOM elements using selectors, making it a valuable tool for web developers.
6
6
 
7
+ ## Release notes
8
+ * als-document is still on alpha testing. All tested features works fine, but through the use, discovering some bugs or things that should work different. For example in this release, changed the way for storing attributes with empty value.
9
+ * Also, this release, has additional very powefull feature which is building cache for storing DOM tree as json and building back DOM from cache.
10
+
7
11
 
8
12
  ## Installation
9
13
 
@@ -21,13 +25,13 @@ The library provides three different files to cater to different module systems:
21
25
  1. **index.js**: This file uses the CommonJS module system. It's suitable for projects using Node.js or bundlers like Browserify or Webpack. The entry point in `package.json` for this file is "main".
22
26
 
23
27
  ```javascript
24
- const { parseHTML, Node, Query, TextNode, SingleNode } = require('als-document');
28
+ const { parseHTML, Node, Query, TextNode, SingleNode,Root } = require('als-document');
25
29
  ```
26
30
 
27
31
  2. **index.mjs**: This file uses the ES Modules (ESM) system. It's suitable for modern JavaScript environments that support ESM. The entry point in `package.json` for this file is "module".
28
32
 
29
33
  ```js
30
- import { parseHTML, Node, Query, TextNode, SingleNode } from 'als-document';
34
+ import { parseHTML, Node, Query, TextNode, SingleNode, Root } from 'als-document';
31
35
  ```
32
36
 
33
37
  3. **document.js**: By including this file, a constant variable named `alsDocument` is created, which wraps all the exports.
@@ -35,7 +39,7 @@ import { parseHTML, Node, Query, TextNode, SingleNode } from 'als-document';
35
39
  ```html
36
40
  <script src="/node_modules/als-document/document.js"></script>
37
41
  <script>
38
- const { parseHTML, Node, Query, TextNode, SingleNode } = alsDocument
42
+ const { parseHTML, Node, Query, TextNode, SingleNode, buildFromCache, cacheDoc, Root } = alsDocument
39
43
  </script>
40
44
  ```
41
45
 
@@ -101,6 +105,7 @@ Remember, the actual tree structure will be more complex and detailed, but the p
101
105
  - **getElementsByClassName, getElementsByTagName, getElementById**: Get elements by class, tag, or id respectively.
102
106
  - **insertAdjacentElement, insertAdjacentHTML, insertAdjacentText**: Insert content relative to the element.
103
107
  - **appendChild**: Add a child node to the element.
108
+ - **insert(place,element)**: place (0-3) or beforebegin,afterbegin,... eleemnt - raw html or element
104
109
 
105
110
 
106
111
  ### SingleNode
@@ -112,6 +117,15 @@ Remember, the actual tree structure will be more complex and detailed, but the p
112
117
  `TextNode` is a class that represents text content within the DOM. A TextNode holds raw text data and does not have child nodes.
113
118
 
114
119
 
120
+ ### Root node (extends Node)
121
+
122
+ Has additional getters and setters:
123
+ * getter root.title
124
+ * setter root.title
125
+ * getter root.body
126
+ * getter root.head
127
+
128
+
115
129
 
116
130
  ### Examples:
117
131
 
@@ -242,3 +256,18 @@ if attribute has value, attrib object will contain check function with one param
242
256
  let s = Query.get('[test^="some"]')[0]
243
257
  console.log(s.attribs[0].check('some value test')) // true
244
258
  ```
259
+
260
+ ## buildFromCache and cacheDoc
261
+
262
+ Building DOM from raw html, usually takes tens of milliseconds. But now, you can build DOM once and save it's cache as regular stringified JSON.
263
+ The caching process and building from cache takes less then 5ms for each and require realy low resources.
264
+
265
+
266
+ How it works?
267
+ ```js
268
+ const html = `` // some real html 255KB
269
+ const root = parseHTML(html); // 31.9ms
270
+ const cache = cacheDoc(root); // 2.4ms
271
+ const root1 = buildFromCache(cache); // 1.2ms
272
+ console.log(root.inneHTML === root1.innerHTML) // true
273
+ ```
package/src/build.js CHANGED
@@ -2,7 +2,9 @@ const { readFileSync, writeFileSync, watchFile, watch } = require('fs')
2
2
  const { join,basename } = require('path')
3
3
 
4
4
  function optimizeCode(content) {
5
+ // content = content.replace(/(?<!\\)\/\/.*$/gm, '') // remove comments
5
6
  content = content.replace(/^(?<!\\)\/\/.*$|(?<=\s)(?<!\\)\/\/.*$/gm, '') // remove comments
7
+ // content = content.replace(/\;\s*?$/gm,'') // remove ; at end of line
6
8
  content = content.replace(/\[\s*?\n\s*/gm, '[') //
7
9
  content = content.replace(/\s*?\]/gm, ']') //
8
10
  content = content.replace(/\s*?$/gm, '') // remove space at end of line
@@ -20,9 +22,9 @@ const files = {
20
22
  'query': ['query','check-element'],
21
23
  'node':[
22
24
  'dataset','find','text-node',
23
- 'style','class-list','node','single-node'
25
+ 'style','class-list','node','single-node','root'
24
26
  ],
25
- 'parse':['parse-atts','void-tags','parser'],
27
+ 'parse':['parse-atts','void-tags','parser','cache'],
26
28
  }
27
29
  const fileList = []
28
30
  function buildFileList() {
@@ -38,7 +40,7 @@ buildFileList()
38
40
  function build() {
39
41
  let content = fileList.map(filePath => readFileSync(filePath, 'utf-8')).join('\n');
40
42
 
41
- const toReturn = '{ parseHTML, Node, Query, TextNode, SingleNode }'
43
+ const toReturn = '{ parseHTML, Node, Query, TextNode, SingleNode, buildFromCache, cacheDoc, Root }'
42
44
  content = optimizeCode(content)
43
45
  writeFileSync(join(root, 'document.js'), `const alsDocument = (function(){\n${content}\nreturn ${toReturn}\n})()`)
44
46
  writeFileSync(join(root, 'index.js'), content + '\n' + `module.exports = ${toReturn}`)
package/src/node/node.js CHANGED
@@ -1,3 +1,9 @@
1
+ function insertBefore(arr, index, newItem) {
2
+ const existingIndex = arr.indexOf(newItem);
3
+ if (existingIndex !== -1) arr.splice(existingIndex, 1);
4
+ arr.splice(index, 0, newItem);
5
+ }
6
+
1
7
  class Node {
2
8
  constructor(tagName, attributes = {}, parent = null) {
3
9
  this.isSingle = false;
@@ -11,10 +17,12 @@ class Node {
11
17
  this._dataset = null
12
18
  }
13
19
 
14
- get id() { return this.attributes.id || null; }
20
+ get id() { return this.attributes.id ? this.attributes.id : null; }
21
+ set id(newValue) { this.attributes.id = newValue; }
15
22
  get className() {return this.attributes.class || null}
16
23
  get parentNode() { return this.parent }
17
24
  get ancestors() {
25
+ if(!this.parent) return []
18
26
  const ancestors = []
19
27
  let element = this.parent
20
28
  while (element.tagName !== 'ROOT') {
@@ -24,17 +32,25 @@ class Node {
24
32
  return ancestors.reverse()
25
33
  }
26
34
 
27
- get childIndex() { return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null }
35
+ get childNodeIndex() {
36
+ if(!this.parent) return null
37
+ return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null
38
+ }
39
+
40
+ get childIndex() {
41
+ if(!this.parent) return null
42
+ return this.parent.children ? this.parent.children.indexOf(this) : null
43
+ }
28
44
  get previousElementSibling() { return this.prev }
29
45
  get prev() {
30
46
  if (!this.childIndex) return null // if no index or index == 0
31
- return this.parent.childNodes[this.childIndex - 1]
47
+ return this.parent.children[this.childIndex - 1]
32
48
  }
33
49
 
34
50
  get nextElementSibling() { return this.next }
35
51
  get next() {
36
52
  if (!this.childIndex) return null
37
- return this.parent.childNodes[this.childIndex + 1] || null
53
+ return this.parent.children[this.childIndex + 1] || null
38
54
  }
39
55
 
40
56
  get dataset() {
@@ -53,8 +69,8 @@ class Node {
53
69
  }
54
70
 
55
71
  get outerHTML() {
56
- const attrs = Object.entries(this.attributes).map(([key, val]) => `${key}="${val}"`).join(" ");
57
- return `<${this.tagName} ${attrs}>${this.innerHTML}</${this.tagName}>`;
72
+ const attrs = Object.entries(this.attributes).map(([key, val]) => val.length ? `${key}="${val}"` : key).join(" ");
73
+ return `<${this.tagName}${attrs ? ' '+attrs : ''}>${this.innerHTML}</${this.tagName}>`;
58
74
  }
59
75
 
60
76
  getAttribute(attrName) { return this.attributes[attrName] || null }
@@ -63,7 +79,7 @@ class Node {
63
79
 
64
80
  remove() {
65
81
  if (!this.parent) return
66
- const index = this.childIndex;
82
+ const index = this.childNodeIndex;
67
83
  if (index !== null) this.parent.childNodes.splice(index, 1);
68
84
  }
69
85
 
@@ -101,23 +117,44 @@ class Node {
101
117
  insertAdjacentElement(position, newElement) {
102
118
  if(newElement.tagName === 'ROOT' && newElement.childNodes.length > 0) newElement = newElement.childNodes[0]
103
119
  const pos = position.toLowerCase();
104
- if (pos === "afterbegin") this.childNodes.unshift(newElement);
105
- else if (pos === "beforeend") this.childNodes.push(newElement);
106
- if (!this.parent) return newElement
107
- if (pos === "beforebegin") this.parent.childNodes.unshift(newElement);
108
- else if (pos === "afterend") this.parent.childNodes.splice(this.childIndex + 1, 0, newElement);
120
+ if(pos === 'afterbegin' || pos === 'beforeend') {
121
+ if (pos === "afterbegin") this.childNodes.unshift(newElement);
122
+ else if (pos === "beforeend") this.childNodes.push(newElement);
123
+ newElement.parent = this
124
+ return newElement
125
+ }
126
+ if (!this.parent) throw new Error("Can't insert element to element without parent")
127
+ if (pos === "beforebegin") insertBefore(this.parent.childNodes, this.childNodeIndex, newElement)
128
+ else if (pos === "afterend") this.parent.childNodes.splice(this.childNodeIndex + 1, 0, newElement);
129
+ newElement.parent = this.parent
109
130
  return newElement
110
131
  }
111
132
 
112
133
  insertAdjacentHTML(position, html) {
113
134
  const newNode = parseHTML(html);
114
- return this.insertAdjacentElement(position, newNode);
135
+ newNode.childNodes.reverse().forEach(node => {
136
+ this.insertAdjacentElement(position, node);
137
+ });
138
+ return newNode
115
139
  }
116
140
 
117
141
  insertAdjacentText(position, text) {
118
142
  return this.insertAdjacentElement(position, new TextNode(text));
119
143
  }
120
144
 
145
+ insert(position,element) {
146
+ const positions = ['beforebegin','afterbegin','beforeend','afterend']
147
+ if(positions[position]) position = positions[position]
148
+ if(typeof element === 'string') {
149
+ element = element.trim()
150
+ if(element.startsWith('<') && element.endsWith('>')) {
151
+ return this.insertAdjacentHTML(position,element)
152
+ }
153
+ return this.insertAdjacentText(position,element)
154
+ }
155
+ return this.insertAdjacentElement(position,element)
156
+ }
157
+
121
158
  set innerHTML(html) {
122
159
  const parsed = parseHTML(html);
123
160
  this.childNodes = parsed.childNodes;
@@ -0,0 +1,11 @@
1
+ class Root extends Node {
2
+ constructor() {
3
+ super('ROOT',{},null);
4
+ this.isSingle = false
5
+ }
6
+
7
+ get body() {return this.$('body')}
8
+ get head() {return this.$('head')}
9
+ get title() {return this.$('title')}
10
+ set title(title) {return this.$('title').innerHTML = title}
11
+ }
@@ -5,12 +5,12 @@ class SingleNode extends Node {
5
5
  this.isSingle = true
6
6
  }
7
7
 
8
- get outerHTML() { // Переопределение outerHTML для одиночного узла
8
+ get outerHTML() { // outerHTML for single node
9
9
  if (this.tagName === "#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
10
- const attrs = Object.entries(this.attributes).map(([key, val]) => `${key}="${val}"`).join(" ");
10
+ const attrs = Object.entries(this.attributes).map(([key, val]) => val.length ? `${key}="${val}"` : key).join(" ");
11
11
  return `<${this.tagName} ${attrs}${this.tagName === '?xml' ? '?' : ''}>`;
12
12
  }
13
- // Удаляем методы и свойства, которые не имеют смысла для одиночных узлов
13
+ // Remove getters,setters and methods which no make sence in single node
14
14
  get innerHTML() { return ""; }
15
15
  set innerHTML(_) { }
16
16
  $(_) {return null}
@@ -25,6 +25,7 @@ class SingleNode extends Node {
25
25
  insertAdjacentHTML(_, __) { }
26
26
  insertAdjacentText(_, __) { }
27
27
  appendChild(_) { }
28
+ insert(_,__) { }
28
29
  get textContent() { return ""; }
29
30
  set textContent(_) { }
30
- }
31
+ }
@@ -0,0 +1,33 @@
1
+ function buildFromCache(cached) {
2
+ function buildNode(cache,parent=null) {
3
+ if(typeof cache === 'string') return parent.childNodes.push(cache)
4
+ const {isSingle,tagName,attributes,childNodes,textContent} = cache
5
+ if(textContent) return parent.childNodes.push(new TextNode(textContent))
6
+ if(isSingle) return parent.childNodes.push(new SingleNode(tagName,attributes))
7
+ const newDoc = tagName === 'ROOT' ? new Root() : new Node(tagName,attributes,parent)
8
+ childNodes.forEach(childNode => {
9
+ buildNode(childNode,newDoc)
10
+ });
11
+ return newDoc
12
+ }
13
+ return buildNode(cached)
14
+ }
15
+
16
+
17
+ function cacheDoc(doc) {
18
+ const props = ['isSingle','tagName','attributes']
19
+ function addToCache(element,cache={}) {
20
+ if(typeof element === 'string') return element
21
+ if(element.nodeName === '#text') return {textContent:element.textContent}
22
+ props.forEach(prop => {
23
+ if(element[prop]) cache[prop] = element[prop]
24
+ });
25
+ if(!element.childNodes) return cache
26
+ cache.childNodes = []
27
+ element.childNodes.forEach(childNode => {
28
+ cache.childNodes.push(addToCache(childNode))
29
+ });
30
+ return cache
31
+ }
32
+ return addToCache(doc)
33
+ }
@@ -31,6 +31,6 @@ function parseAttributes(str) {
31
31
  else value += char;
32
32
  }
33
33
 
34
- if (key.trim() && !value) attrs[key.trim()] = true; // After the loop, check if there's a leftover key, which would be an attribute without a value
34
+ if (key.trim() && !value) attrs[key.trim()] = ''; // After the loop, check if there's a leftover key, which would be an attribute without a value
35
35
  return attrs;
36
36
  }
@@ -1,7 +1,28 @@
1
1
  function parseHTML(html) {
2
- const root = new Node("ROOT");
2
+ const root = new Root();
3
3
  const stack = [root];
4
4
  let currentText = "", i = 0;
5
+ let max = 0
6
+
7
+ function parseScript() {
8
+ if (!html.startsWith("<script", i)) return false;
9
+ const openTagEnd = html.indexOf(">", i);
10
+ if (openTagEnd === -1) return false;
11
+
12
+ const attributesString = html.substring(i + 7, openTagEnd).trim(); // +7 чтобы пропустить "<script"
13
+ const attributes = parseAttributes(attributesString); // Извлечь атрибуты
14
+
15
+ let closeTagStart = html.indexOf("</script>", openTagEnd); // Находим закрывающий тег
16
+ if (closeTagStart === -1) return false; // Если нет закрывающего тега, возвращаем ошибку
17
+ const content = html.substring(openTagEnd + 1, closeTagStart); // Получить содержимое тега
18
+
19
+ const scriptNode = new Node('script', attributes, stack[stack.length - 1]); // Создаем узел
20
+ if(content.length > 0) scriptNode.childNodes.push(content);
21
+
22
+ // Переместить указатель i к концу закрывающего тега
23
+ i = closeTagStart + 9; // +9 чтобы пропустить "</script>"
24
+ return true;
25
+ }
5
26
 
6
27
  function parseSpecial(startStr, endStr, n1, n2, tag) {
7
28
  if (!html.startsWith(startStr, i)) return false
@@ -13,8 +34,10 @@ function parseHTML(html) {
13
34
  }
14
35
 
15
36
  while (i < html.length) {
37
+ if(i >= max) max = i;
38
+ else break;
39
+ if (parseScript()) continue
16
40
  if (parseSpecial("<!--", "-->", 4, 3, '#comment')) continue
17
- if (parseSpecial("<script", "</script>", 8, 9, 'script')) continue
18
41
  if (parseSpecial("<style", "</style>", 7, 8, 'style')) continue
19
42
 
20
43
  if (html.startsWith("<![CDATA[", i)) {
@@ -28,8 +51,10 @@ function parseHTML(html) {
28
51
  }
29
52
 
30
53
  if (html.startsWith("<", i)) {
31
- if (currentText.trim()) {
32
- stack[stack.length - 1].childNodes.push(new TextNode(currentText.trim()));
54
+ if (currentText && stack[stack.length - 1]) {
55
+ const textNode = new TextNode(currentText)
56
+ stack[stack.length - 1].childNodes.push(textNode);
57
+ textNode.parent = stack[stack.length - 1]
33
58
  currentText = "";
34
59
  }
35
60
 
@@ -52,7 +77,6 @@ function parseHTML(html) {
52
77
  }
53
78
 
54
79
  const tagContent = html.substring(i + 1, tagEnd);
55
-
56
80
  if (tagContent.startsWith("/")) stack.pop(); // It is close tag
57
81
  else { // It is open tag
58
82
  let isSelfClosing = tagContent.endsWith('/');
@@ -69,6 +93,6 @@ function parseHTML(html) {
69
93
  i++;
70
94
  }
71
95
  }
72
- if (currentText.trim()) stack[stack.length - 1].childNodes.push(new TextNode(currentText.trim()));
96
+ if (currentText.trim() && stack[stack.length - 1]) stack[stack.length - 1].childNodes.push(new TextNode(currentText));
73
97
  return root;
74
98
  }
@@ -1,7 +1,7 @@
1
1
  function checkElement(el,selector) {
2
2
  if(selector == undefined) return true
3
3
  if(el == null) return false
4
- let {tag,classList,attributes,id,prev,ancestors,parents,prevAny} = selector
4
+ let {tag,classList,attribs:attributes,id,prev,ancestors,parents,prevAny} = selector
5
5
  if(typeof el === 'string') return false
6
6
  if(id !== undefined && el.id === null) return false
7
7
  if(id && id !== el.id) return false
@@ -31,7 +31,7 @@ class Query {
31
31
 
32
32
  splitAndCutLast(string, splitBy) {
33
33
  const array = string.split(splitBy);
34
- const last = array.pop(); // pop() удаляет и возвращает последний элемент массива
34
+ const last = array.pop();
35
35
  return [last, array];
36
36
  }
37
37
 
@@ -104,11 +104,18 @@ class Query {
104
104
  attribs = attribs.map(attrib => {
105
105
  let query = attrib
106
106
  attrib = attrib.replace('[', '').replace(']', '')
107
- let [name, value] = attrib.split(/[\~\|\^\$\*]?\=/)
108
- let sign = attrib.replace(name, '').replace(value, '')
109
- attrib = { query }
110
- if (name) attrib.name = name
111
- if (value) attrib.value = value.trim().replace(/^\"/, '').replace(/\"$/, '')
107
+ let [name,...values] = attrib.split('=')
108
+ const value = values.join('=').trim().replace(/^\"/,'').replace(/\"$/,'')
109
+ let sign
110
+ attrib = {query,name}
111
+ if(value) {
112
+ sign = '='
113
+ attrib.name = attrib.name.replace(/[\~\|\^\$\*]$/,(match => {
114
+ sign = match+sign
115
+ return ''
116
+ }))
117
+ attrib.value = value
118
+ }
112
119
  if (sign) {
113
120
  attrib.sign = sign
114
121
  attrib.check = this.getAttribFn(sign).bind(attrib)
package/tests/cache.js ADDED
@@ -0,0 +1,19 @@
1
+ function mesureTime(fn) {
2
+ let time = performance.now()
3
+ const result = fn()
4
+ time = performance.now() - time
5
+ return {result,time}
6
+ }
7
+
8
+ describe('Cache and build from cache', () => {
9
+ const {result:root,time:rootTime} = mesureTime(() => parseHTML(html1))
10
+ const {result:cache,time:cacheTime} = mesureTime(() => cacheDoc(root))
11
+ const {result:root1,time:root1Time} = mesureTime(() => buildFromCache(cache))
12
+
13
+ it('HTML from cache and HTML from not cached same',() => {
14
+ console.log({rootTime,cacheTime,root1Time})
15
+ assert(cacheTime < 5,'Build cache takes less then 5ms')
16
+ assert(root1Time < 5,'Build DOM from cache takes less then 5ms')
17
+ assert(root.innerHTML === root1.innerHTML)
18
+ })
19
+ })
package/tests/index.html CHANGED
@@ -4,23 +4,24 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>Document</title>
7
- <script src="/node_modules/als-simple-test/test.js"></script>
8
- <script src="/document.js"></script>
7
+ <script src="test.js"></script>
8
+ <script src="../document.js"></script>
9
9
  <script src="./data/html1.js"></script>
10
10
  <!-- <script src="./data/html2.js"></script> -->
11
11
  <script src="./data/svg.js"></script>
12
12
  <script>
13
- const { parseHTML, Node, Query, TextNode, SingleNode } = alsDocument
13
+ const { parseHTML, Node, Query, TextNode, SingleNode, buildFromCache, cacheDoc,Root } = alsDocument
14
14
  let {describe,it,beforeEach,runTests,expect,delay,assert,beforeAll} = SimpleTest
15
15
  SimpleTest.showFullError = true
16
16
  </script>
17
- <script src="./query.js"></script>
18
17
  <script src="utils.js"></script>
18
+ <script src="./query.js"></script>
19
19
  <script src="parser.js"></script>
20
20
  <script src="node.js"></script>
21
+ <script src="./cache.js"></script>
21
22
  </head>
22
23
  <body>
23
- <script src="parse-real.js"></script>
24
+ <!-- <script src="parse-real.js"></script> -->
24
25
  <script>
25
26
  runTests();
26
27
 
package/tests/node.js CHANGED
@@ -130,7 +130,7 @@ describe('Content Manipulation', () => {
130
130
  expect(rootNode.childNodes[2].tagName).equalTo('a');
131
131
 
132
132
  childNode.insertAdjacentHTML('beforebegin', '<strong></strong>');
133
- expect(rootNode.childNodes[0].tagName).equalTo('strong');
133
+ expect(rootNode.childNodes[1].tagName).equalTo('strong');
134
134
 
135
135
  childNode.insertAdjacentText('afterend', 'Some text');
136
136
  expect(typeof rootNode.childNodes[3].nodeValue).equalTo('string');
@@ -32,8 +32,9 @@ describe('Real data html1', async () => {
32
32
  it('Text nodes check', () => {
33
33
  const realParagraph = iframe.querySelector('p');
34
34
  const parsedParagraph = parsedHTML.querySelector('p');
35
- const real = realParagraph.textContent.trim().replace(/\n\s*/gm,'')
36
- const parsed = parsedParagraph.textContent.trim()
35
+ const real = realParagraph.textContent.trim().replace(/\n|\s/gm,'')
36
+ const parsed = parsedParagraph.textContent.trim().replace(/\n|\s/gm,'')
37
+ console.log({parsed,real})
37
38
  assert(real === parsed, 'Text contents are the same');
38
39
  });
39
40
 
package/tests/parser.js CHANGED
@@ -70,7 +70,7 @@ describe('Advanced tests', () => {
70
70
  let time = Date.now() - now
71
71
  // console.log(memoryAfter - memoryBefore)
72
72
  assert(time < 20, `Big html (${(deepHTML.length / 1024).toFixed(2)}KB) in less then 20ms (${time}ms)`)
73
- expect(result).instanceof(Node); // or any other validation you see fit
73
+ expect(result).instanceof(Root); // or any other validation you see fit
74
74
  });
75
75
 
76
76
  it('handles incorrectly closed tags', () => {
@@ -225,11 +225,11 @@ describe('signle tags, script and style', () => {
225
225
  <link rel="stylesheet" href="styles.css">
226
226
  `;
227
227
  const rootMetaLink = parseHTML(testMetaLink);
228
- assert(rootMetaLink.childNodes[0].tagName === "meta", "Test Meta/Link 1: Meta tag not created");
229
- assert(rootMetaLink.childNodes[0].getAttribute("charset") === "UTF-8", "Test Meta/Link 1: Meta content not correct");
230
- assert(rootMetaLink.childNodes[1].tagName === "link", "Test Meta/Link 2: Link tag not created");
231
- assert(rootMetaLink.childNodes[1].getAttribute("rel") === "stylesheet", "Test Meta/Link 2: Link rel attribute not correct");
232
- assert(rootMetaLink.childNodes[1].getAttribute("href") === "styles.css", "Test Meta/Link 2: Link href attribute not correct");
228
+ assert(rootMetaLink.children[0].tagName === "meta", "Test Meta/Link 1: Meta tag not created");
229
+ assert(rootMetaLink.children[0].getAttribute("charset") === "UTF-8", "Test Meta/Link 1: Meta content not correct");
230
+ assert(rootMetaLink.children[1].tagName === "link", "Test Meta/Link 2: Link tag not created");
231
+ assert(rootMetaLink.children[1].getAttribute("rel") === "stylesheet", "Test Meta/Link 2: Link rel attribute not correct");
232
+ assert(rootMetaLink.children[1].getAttribute("href") === "styles.css", "Test Meta/Link 2: Link href attribute not correct");
233
233
  })
234
234
 
235
235
  it('broken html structure', () => {