als-document 1.0.7-alpha → 1.0.8-alpha

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.
@@ -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 = 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
  }
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,13 +4,13 @@
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>
7
+ <script src="test.js"></script>
8
8
  <script src="../document.js"></script>
9
- <!-- <script src="./data/html1.js"></script> -->
10
- <script src="./data/html2.js"></script>
9
+ <script src="./data/html1.js"></script>
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 } = alsDocument
14
14
  let {describe,it,beforeEach,runTests,expect,delay,assert,beforeAll} = SimpleTest
15
15
  SimpleTest.showFullError = true
16
16
  </script>
@@ -18,6 +18,7 @@
18
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
24
  <script src="parse-real.js"></script>
package/tests/test.js ADDED
@@ -0,0 +1,169 @@
1
+ class SimpleTest {
2
+ static tests = [];
3
+ static beforeEachCallback;
4
+ static afterEachCallback;
5
+ static nestingLevel = 0;
6
+ static currentParent = [];
7
+ static space = ''
8
+ static results = {}
9
+ static testTitle = ''
10
+ static showFullError = false
11
+ static colors = {
12
+ bold:'\x1b[1m',
13
+ cblue:'\x1b[34m',
14
+ cred:'\x1b[31m',
15
+ cgreen:'\x1b[32m',
16
+ cgray:'\x1b[37m',
17
+ reset:'\x1b[0m'
18
+ }
19
+ static delay = (ms,toResolve) => new Promise((resolve) => {
20
+ setTimeout(() => {resolve(toResolve)}, ms);
21
+ });
22
+
23
+ static describe(title, callback,pause=false) {
24
+ if(pause) return
25
+ let { nestingLevel, currentParent } = SimpleTest
26
+ nestingLevel++;
27
+ currentParent.push(title);
28
+ callback();
29
+
30
+ currentParent.pop();
31
+ nestingLevel--;
32
+ if (nestingLevel === 0) {
33
+ SimpleTest.beforeEachCallback = null; // Clear beforeEachCallback after finishing the outermost describe block
34
+ SimpleTest.afterEachCallback = null; // Clear beforeEachCallback after finishing the outermost describe block
35
+ }
36
+ }
37
+
38
+ static beforeEach(callback) {SimpleTest.beforeEachCallback = callback;}
39
+ static afterEach(callback) {SimpleTest.afterEachCallback = callback;}
40
+ static beforeAll(callback) {SimpleTest.beforAllCallback = callback;}
41
+ static afterAll(callback) {SimpleTest.afterAllCallback = callback;}
42
+
43
+ static it(title, callback) {
44
+ SimpleTest.tests.push({
45
+ titles: [...SimpleTest.currentParent, title],
46
+ before: SimpleTest.beforeEachCallback,
47
+ after:SimpleTest.afterEachCallback,
48
+ test: callback,
49
+ });
50
+ }
51
+
52
+ static async runTests(consoleLog=true) {
53
+ const {bold,cblue,cred,reset} = SimpleTest.colors
54
+ SimpleTest.consoleLog = consoleLog
55
+ let { tests,results,showFullError,beforAllCallback,afterAllCallback } = SimpleTest;
56
+ let previousTitles = [];
57
+ if(typeof beforAllCallback == 'function') await beforAllCallback()
58
+ for(const test of tests) {
59
+ let curentResult = results
60
+ SimpleTest.space = test.titles.map(t => ' ').join('');
61
+ test.titles.forEach((title, index) => {
62
+ if(curentResult[title] == undefined) {
63
+ if(index == test.titles.length-1) curentResult[title] = []
64
+ else curentResult[title] = {}
65
+ }
66
+ curentResult = curentResult[title]
67
+ if(previousTitles[index] !== title) {
68
+ const indentation = ' '.repeat(index);
69
+ console.log(bold+cblue+'%s'+reset,`${indentation} ${title}`);
70
+ previousTitles[index] = title;
71
+ }
72
+ });
73
+ SimpleTest.curentResult = curentResult
74
+ try {
75
+ if (test.before) await test.before();
76
+ await test.test();
77
+ if (test.after) await test.after();
78
+ } catch (error) {
79
+ if(showFullError) console.log(error)
80
+ else console.log(`${SimpleTest.space}${cred}Error:${reset} ${error.message}`);
81
+ curentResult.push({error})
82
+ }
83
+ console.log('\n');
84
+ }
85
+ if(typeof afterAllCallback == 'function') await afterAllCallback()
86
+ }
87
+
88
+ static assert(value,testTitle) {
89
+ if(testTitle) SimpleTest.testTitle = testTitle
90
+ SimpleTest.logResult(value)
91
+ }
92
+
93
+ static expect(value1) {
94
+ let { logResult, isEqual } = SimpleTest
95
+ const methods = {
96
+ is: (text='') => {
97
+ SimpleTest.testTitle = text;
98
+ SimpleTest.not = false
99
+ return methods;
100
+ },
101
+ isNot: (text='') => {
102
+ SimpleTest.testTitle = text;
103
+ SimpleTest.not = true
104
+ return methods;
105
+ },
106
+ equalTo: (value2) => {logResult(value1 === value2);},
107
+ between(value2,value3) {logResult(value1 >= value2 && value1 <= value3);},
108
+ below(value2) {logResult(value1 < value2);},
109
+ above(value2) {logResult(value1 > value2);},
110
+ atLeast(value2) {logResult(value1 >= value2);},
111
+ atMost(value2) {logResult(value1 <= value2);},
112
+ sameAs: (value2) => {logResult(isEqual(value1, value2));},
113
+ defined: () => {logResult(value1 !== undefined);},
114
+ matchTo(pattern) {logResult(pattern.test(new RegExp(value1)));},
115
+ includes(value2) {logResult(value1.includes(value2));},
116
+ error: () => {
117
+ if(typeof value1 !== 'function') return console.log('Expected value has to be function')
118
+ try {
119
+ let result = value1()
120
+ if(result instanceof Error) logResult(true)
121
+ else logResult(false);
122
+ } catch (error) {logResult(true)}
123
+ },
124
+ hasProperty: (property) => {logResult(Object.prototype.hasOwnProperty.call(value1, property));},
125
+ instanceof: (classType) => {logResult(value1.constructor.name == classType.name)},
126
+ closeTo(value2, decimalPlaces = 2) {
127
+ const multiplier = 10 ** decimalPlaces;
128
+ const roundedActual = Math.round(value1 * multiplier);
129
+ const roundedExpected = Math.round(value2 * multiplier);
130
+ const diff = Math.abs(roundedActual - roundedExpected) / multiplier;
131
+ logResult(diff < 1 / multiplier);
132
+ }
133
+ };
134
+ return methods;
135
+ }
136
+
137
+ static logResult(result) {
138
+ let {curentResult,testTitle,not,space,colors} = SimpleTest
139
+ let {cgreen,cred,cgray,reset} = colors
140
+ if(not) result = !result
141
+ curentResult.push({result:result ? true : false,testTitle,error:null})
142
+ const status = result ? 'Success' : 'Failed';
143
+ const color = result ? cgreen : cred;
144
+ if (testTitle == '') console.log(`${color}${space}${status}${reset}`);
145
+ else console.log(`${space}${color}${status}: ${testTitle ? `${cgray}${testTitle}` : ''}`+reset,);
146
+ SimpleTest.not = false
147
+ SimpleTest.testTitle = ''
148
+ }
149
+
150
+ static isEqual(obj1, obj2, visited = new WeakMap()) {
151
+ if (obj1 === obj2) return true;
152
+ if (visited.has(obj1) && visited.get(obj1) === obj2) return true;
153
+ const type1 = typeof obj1;
154
+ const type2 = typeof obj2;
155
+
156
+ if (type1 !== type2 || type1 !== 'object' || obj1 === null || obj2 === null) return false;
157
+ visited.set(obj1, obj2);
158
+
159
+ const keys1 = Object.keys(obj1);
160
+ const keys2 = Object.keys(obj2);
161
+ if(keys1.length !== keys2.length) return false;
162
+
163
+ for (let key of keys1) {
164
+ if (!keys2.includes(key) || !SimpleTest.isEqual(obj1[key], obj2[key], visited)) return false;
165
+ }
166
+ return true;
167
+ };
168
+ }
169
+ try {module.exports = SimpleTest} catch (error) {}