als-document 1.0.2-alpha → 1.0.3-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.
package/index.mjs CHANGED
@@ -1,32 +1,573 @@
1
- class Query{
2
1
  static get(query){
3
2
  let q=new Query(query)
4
3
  return q.selectors
5
4
  }
6
5
  constructor(query){
7
6
  this.query=query
8
7
  this.selectors=[]
9
8
  this.stringValues=[];
10
9
  this.parseSelectors(query.split(','))
11
10
  }
12
11
  parseSelectors(selectors){
13
12
  selectors.forEach(selector=>{
14
13
  let originalSelector=selector.trim()
15
14
  selector=this.removeSpaces(selector)
16
15
  this.stringValues=[]
17
16
  selector=selector.replace(/\[.*?\]/g,(value)=>{
18
17
  this.stringValues.push(value)
19
18
  return `[${this.stringValues.length-1}]`
20
19
  })
21
20
  let [element,ancestors]=this.splitAndCutLast(selector,' ')
22
21
  element=this.getFamily(element)
23
22
  if (ancestors.length>0)
24
23
  element.ancestors=ancestors.map(ancestor=>this.getFamily(ancestor))
25
24
  element.group=originalSelector
26
25
  this.selectors.push(element)
27
26
  });
28
27
  }
29
28
  splitAndCutLast(string,splitBy){
30
29
  const array=string.split(splitBy);
31
30
  const last=array.pop();
32
31
  return [last,array];
33
32
  }
34
33
  getFamily(group,element,prev,prevAny,sign){
35
34
  if (group.match(/\~|\+/)!==null){
36
35
  let [last,prevBrothers]=this.splitAndCutLast(group,/\~|\+/)
37
36
  let signs=group.replace(last,'')
38
37
  prevBrothers.forEach(el=>signs=signs.replace(el,''))
39
38
  signs=signs.match(/\~|\+/g)
40
39
  if (signs.length==1){
41
40
  sign=signs[0]
42
41
  } else if (signs.length>1){
43
42
  sign=signs.splice(signs.length-1,signs.length-1)[0]
44
43
  prevBrothers[0]=prevBrothers.map((b,i)=>{
45
44
  if (i< prevBrothers.length-1) b+=signs[i]
46
45
  return b
47
46
  }).join('')
48
47
  prevBrothers[0]=this.getFamily(prevBrothers[0])
49
48
  }
50
49
  if (sign=='~') prevAny=prevBrothers[0]
51
50
  else if (sign=='+') prev=prevBrothers[0]
52
51
  element=last
53
52
  } else element=group
54
53
  let family
55
54
  if (prev || prevAny){
56
55
  family=this.getParents(element)
57
56
  if (prev) family.prev=this.getParents(prev)
58
57
  if (prevAny) family.prevAny=this.getParents(prevAny)
59
58
  } else family=this.getParents(element)
60
59
  if (family.query!==group) family.group=group
61
60
  return family
62
61
  }
63
62
  getParents(selector){
64
63
  if (typeof selector=='string'){
65
64
  let [element,parents]=this.splitAndCutLast(selector,'>')
66
65
  element=this.buildElement(element)
67
66
  parents=parents.map(parent=>this.buildElement(parent))
68
67
  if (parents.length>0) element.parents=parents
69
68
  return element
70
69
  } else return selector
71
70
  }
72
71
  buildElement(element,id=null,tag=null,classList=[]){
73
72
  let query=element
74
73
  element=element.replace(/\#(\w-?)*/,$id=>{
75
74
  id=$id.replace(/^\#/,''); return ''
76
75
  })
77
76
  element=element.replace(/\.(\w-?)*/,$class=>{
78
77
  classList.push($class.replace(/^\./,'')); return ''
79
78
  })
80
79
  element=element.replace(/(\w\:?-?)*/,$tag=>{
81
80
  tag=$tag=='' ? null : $tag; return ''
82
81
  })
83
82
  let attribs=this.getAttributes(element)
84
83
  element={ query }
85
84
  if (id) element.id=id
86
85
  if (tag) element.tag=tag
87
86
  if (classList.length>0) element.classList=classList
88
87
  if (attribs.length>0) element.attribs=attribs
89
88
  return element
90
89
  }
91
90
  getAttributes(element){
92
91
  let attribs=this.stringValues.filter((value,index)=>{
93
92
  let searchValue=`[${index}]`
94
93
  if (element.match(searchValue)) return true
95
94
  else return false
96
95
  })
97
96
  attribs=attribs.map(attrib=>{
98
97
  let query=attrib
99
98
  attrib=attrib.replace('[','').replace(']','')
100
99
  let [name,value]=attrib.split(/[\~\|\^\$\*]?\=/)
101
100
  let sign=attrib.replace(name,'').replace(value,'')
102
101
  attrib={ query }
103
102
  if (name) attrib.name=name
104
103
  if (value) attrib.value=value.trim().replace(/^\"/,'').replace(/\"$/,'')
105
104
  if (sign){
106
105
  attrib.sign=sign
107
106
  attrib.check=this.getAttribFn(sign).bind(attrib)
108
107
  }
109
108
  return attrib
110
109
  });
111
110
  return attribs
112
111
  }
113
112
  getAttribFn(sign){
114
113
  if (sign=='=') return function (value){ return value===this.value }
115
114
  if (sign=='*=') return function (value){ return value.includes(this.value) }
116
115
  if (sign=='^=') return function (value){ return value.startsWith(this.value) }
117
116
  if (sign=='$=') return function (value){ return value.endsWith(this.value) }
118
117
  if (sign=='|=') return function (value){
119
118
  return value.trim().split(' ').length==1
120
119
  && (value.startsWith(this.value) || value.startsWith(this.value+'-'))
121
120
  ? true : false
122
121
  }
123
122
  if (sign=='~=') return function (value){
124
123
  return this.value.trim().split(' ').length==1 && value.includes(this.value) ? true : false
125
124
  }
126
125
  }
127
126
  removeSpaces(selector){
128
127
  selector=selector.replace(/\s{2}/g,' ')
129
128
  selector=selector.replace(/\s?\^?\$?\|?\~?\*?\=\s*/g,(m)=>m.trim())
130
129
  selector=selector.replace(/\s?(\+|\~|\>)\s?/g,(m)=>m.trim())
131
130
  return selector
132
131
  }
133
- }
134
- function checkElement(el,selector){
135
132
  if(selector==undefined) return true
136
133
  if(el==null) return false
137
134
  let{tag,classList,attributes,id,prev,ancestors,parents,prevAny}=selector
138
135
  if(typeof el==='string') return false
139
136
  if(id!==undefined && el.id===null) return false
140
137
  if(id && id!==el.id) return false
141
138
  if(tag && el.tagName===undefined) return false
142
139
  else if(tag && tag!==el.tagName) return false
143
140
  const clas=el.attributes.class
144
141
  if(classList!==undefined && (clas===undefined || clas==='')) return false
145
142
  else if(classList!==undefined){
146
143
  if(classList.every(e=>el.classList.contains(e))===false) return false
147
144
  }
148
145
  if(checkattributes(attributes,el)===false) return false
149
146
  if(checkElement(el.prev,prev)===false) return false
150
147
  if(checkAncestors(el.ancestors,ancestors)===false) return false
151
148
  if(checkParents(el.ancestors,parents)===false) return false
152
149
  if(el.parent){
153
150
  if(checkPrevAny(el.parent.children,el.childIndex,prevAny)==false) return false
154
151
  }
155
152
  return true
156
- }
157
153
  function checkattributes(attributes=[],el){
158
154
  let elattributes=el.attributes
159
155
  let names=Object.keys(elattributes)
160
156
  let passedTests=0
161
157
  if(attributes) for(let i=0; i<attributes.length; i++){
162
158
  let{name,value,check}=attributes[i]
163
159
  if(name=='inner' && value!==undefined && check && el.inner){
164
160
  if(check(el.inner)) passedTests++
165
161
  }
166
162
  if(!names.includes(name)) continue
167
163
  else if(value==undefined) passedTests++
168
164
  else if(value && elattributes[name]){
169
165
  if(check(elattributes[name])==false) continue
170
166
  else passedTests++
171
167
  }
172
168
  }
173
169
  if(passedTests==attributes.length) return true
174
170
  else return false
175
- }
176
171
  function checkPrevAny(children=[],index,prevAny){
177
172
  let size=children.length
178
173
  if((size==0 || index==0) && prevAny) return false
179
174
  for(let i=index; i>=0; i--){
180
175
  if(checkElement(children[i],prevAny)) return true
181
176
  }
182
177
  return false
183
- }
184
178
  function checkAncestors(ancestors=[],selectorAncestors=[]){
185
179
  let count=0
186
180
  if(selectorAncestors.length==0) return true
187
181
  let endIndex=ancestors.length-1
188
182
  let selectorIndex=selectorAncestors.length-1
189
183
  while(selectorIndex>=0){
190
184
  for(let i=endIndex; i>=0; i--){
191
185
  endIndex=i-1
192
186
  if(checkElement(ancestors[i],selectorAncestors[selectorIndex])==true){
193
187
  count++
194
188
  break
195
189
  }
196
190
  }
197
191
  selectorIndex--
198
192
  }
199
193
  if(count==selectorAncestors.length) return true
200
194
  else return false
201
- }
202
195
  function checkParents(ancestors=[],selectorParents=[]){
203
196
  if(selectorParents.length===0) return true
204
197
  if(ancestors.length< selectorParents.length) return false
205
198
  let index=ancestors.length-1
206
199
  for(let i=selectorParents.length-1; i>=0; i--){
207
200
  if(checkElement(ancestors[index],selectorParents[i])===false) return false
208
201
  index--
209
202
  }
210
203
  return true
211
- }
204
+ class Query{
205
+ static get(query){
206
+ let q=new Query(query)
207
+ return q.selectors
208
+ }
209
+ constructor(query){
210
+ this.query=query
211
+ this.selectors=[]
212
+ this.stringValues=[];
213
+ this.parseSelectors(query.split(','))
214
+ }
215
+ parseSelectors(selectors){
216
+ selectors.forEach(selector=>{
217
+ let originalSelector=selector.trim()
218
+ selector=this.removeSpaces(selector)
219
+ this.stringValues=[]
220
+ selector=selector.replace(/\[.*?\]/g,(value)=>{
221
+ this.stringValues.push(value)
222
+ return `[${this.stringValues.length-1}]`
223
+ })
224
+ let [element,ancestors]=this.splitAndCutLast(selector,' ')
225
+ element=this.getFamily(element)
226
+ if (ancestors.length>0)
227
+ element.ancestors=ancestors.map(ancestor=>this.getFamily(ancestor))
228
+ element.group=originalSelector
229
+ this.selectors.push(element)
230
+ });
231
+ }
232
+ splitAndCutLast(string,splitBy){
233
+ const array=string.split(splitBy);
234
+ const last=array.pop();
235
+ return [last,array];
236
+ }
237
+ getFamily(group,element,prev,prevAny,sign){
238
+ if (group.match(/\~|\+/)!==null){
239
+ let [last,prevBrothers]=this.splitAndCutLast(group,/\~|\+/)
240
+ let signs=group.replace(last,'')
241
+ prevBrothers.forEach(el=>signs=signs.replace(el,''))
242
+ signs=signs.match(/\~|\+/g)
243
+ if (signs.length==1){
244
+ sign=signs[0]
245
+ } else if (signs.length>1){
246
+ sign=signs.splice(signs.length-1,signs.length-1)[0]
247
+ prevBrothers[0]=prevBrothers.map((b,i)=>{
248
+ if (i< prevBrothers.length-1) b+=signs[i]
249
+ return b
250
+ }).join('')
251
+ prevBrothers[0]=this.getFamily(prevBrothers[0])
252
+ }
253
+ if (sign=='~') prevAny=prevBrothers[0]
254
+ else if (sign=='+') prev=prevBrothers[0]
255
+ element=last
256
+ } else element=group
257
+ let family
258
+ if (prev || prevAny){
259
+ family=this.getParents(element)
260
+ if (prev) family.prev=this.getParents(prev)
261
+ if (prevAny) family.prevAny=this.getParents(prevAny)
262
+ } else family=this.getParents(element)
263
+ if (family.query!==group) family.group=group
264
+ return family
265
+ }
266
+ getParents(selector){
267
+ if (typeof selector=='string'){
268
+ let [element,parents]=this.splitAndCutLast(selector,'>')
269
+ element=this.buildElement(element)
270
+ parents=parents.map(parent=>this.buildElement(parent))
271
+ if (parents.length>0) element.parents=parents
272
+ return element
273
+ } else return selector
274
+ }
275
+ buildElement(element,id=null,tag=null,classList=[]){
276
+ let query=element
277
+ element=element.replace(/\#(\w-?)*/,$id=>{
278
+ id=$id.replace(/^\#/,''); return ''
279
+ })
280
+ element=element.replace(/\.(\w-?)*/,$class=>{
281
+ classList.push($class.replace(/^\./,'')); return ''
282
+ })
283
+ element=element.replace(/(\w\:?-?)*/,$tag=>{
284
+ tag=$tag=='' ? null : $tag; return ''
285
+ })
286
+ let attribs=this.getAttributes(element)
287
+ element={ query }
288
+ if (id) element.id=id
289
+ if (tag) element.tag=tag
290
+ if (classList.length>0) element.classList=classList
291
+ if (attribs.length>0) element.attribs=attribs
292
+ return element
293
+ }
294
+ getAttributes(element){
295
+ let attribs=this.stringValues.filter((value,index)=>{
296
+ let searchValue=`[${index}]`
297
+ if (element.match(searchValue)) return true
298
+ else return false
299
+ })
300
+ attribs=attribs.map(attrib=>{
301
+ let query=attrib
302
+ attrib=attrib.replace('[','').replace(']','')
303
+ let [name,value]=attrib.split(/[\~\|\^\$\*]?\=/)
304
+ let sign=attrib.replace(name,'').replace(value,'')
305
+ attrib={ query }
306
+ if (name) attrib.name=name
307
+ if (value) attrib.value=value.trim().replace(/^\"/,'').replace(/\"$/,'')
308
+ if (sign){
309
+ attrib.sign=sign
310
+ attrib.check=this.getAttribFn(sign).bind(attrib)
311
+ }
312
+ return attrib
313
+ });
314
+ return attribs
315
+ }
316
+ getAttribFn(sign){
317
+ if (sign=='=') return function (value){ return value===this.value }
318
+ if (sign=='*=') return function (value){ return value.includes(this.value) }
319
+ if (sign=='^=') return function (value){ return value.startsWith(this.value) }
320
+ if (sign=='$=') return function (value){ return value.endsWith(this.value) }
321
+ if (sign=='|=') return function (value){
322
+ return value.trim().split(' ').length==1
323
+ && (value.startsWith(this.value) || value.startsWith(this.value+'-'))
324
+ ? true : false
325
+ }
326
+ if (sign=='~=') return function (value){
327
+ return this.value.trim().split(' ').length==1 && value.includes(this.value) ? true : false
328
+ }
329
+ }
330
+ removeSpaces(selector){
331
+ selector=selector.replace(/\s{2}/g,' ')
332
+ selector=selector.replace(/\s?\^?\$?\|?\~?\*?\=\s*/g,(m)=>m.trim())
333
+ selector=selector.replace(/\s?(\+|\~|\>)\s?/g,(m)=>m.trim())
334
+ return selector
335
+ }
336
+ }
337
+ function checkElement(el,selector){
338
+ if(selector==undefined) return true
339
+ if(el==null) return false
340
+ let{tag,classList,attributes,id,prev,ancestors,parents,prevAny}=selector
341
+ if(typeof el==='string') return false
342
+ if(id!==undefined && el.id===null) return false
343
+ if(id && id!==el.id) return false
344
+ if(tag && el.tagName===undefined) return false
345
+ else if(tag && tag!==el.tagName) return false
346
+ const clas=el.attributes.class
347
+ if(classList!==undefined && (clas===undefined || clas==='')) return false
348
+ else if(classList!==undefined){
349
+ if(classList.every(e=>el.classList.contains(e))===false) return false
350
+ }
351
+ if(checkattributes(attributes,el)===false) return false
352
+ if(checkElement(el.prev,prev)===false) return false
353
+ if(checkAncestors(el.ancestors,ancestors)===false) return false
354
+ if(checkParents(el.ancestors,parents)===false) return false
355
+ if(el.parent){
356
+ if(checkPrevAny(el.parent.children,el.childIndex,prevAny)==false) return false
357
+ }
358
+ return true
359
+ }
360
+ function checkattributes(attributes=[],el){
361
+ let elattributes=el.attributes
362
+ let names=Object.keys(elattributes)
363
+ let passedTests=0
364
+ if(attributes) for(let i=0; i<attributes.length; i++){
365
+ let{name,value,check}=attributes[i]
366
+ if(name=='inner' && value!==undefined && check && el.inner){
367
+ if(check(el.inner)) passedTests++
368
+ }
369
+ if(!names.includes(name)) continue
370
+ else if(value==undefined) passedTests++
371
+ else if(value && elattributes[name]){
372
+ if(check(elattributes[name])==false) continue
373
+ else passedTests++
374
+ }
375
+ }
376
+ if(passedTests==attributes.length) return true
377
+ else return false
378
+ }
379
+ function checkPrevAny(children=[],index,prevAny){
380
+ let size=children.length
381
+ if((size==0 || index==0) && prevAny) return false
382
+ for(let i=index; i>=0; i--){
383
+ if(checkElement(children[i],prevAny)) return true
384
+ }
385
+ return false
386
+ }
387
+ function checkAncestors(ancestors=[],selectorAncestors=[]){
388
+ let count=0
389
+ if(selectorAncestors.length==0) return true
390
+ let endIndex=ancestors.length-1
391
+ let selectorIndex=selectorAncestors.length-1
392
+ while(selectorIndex>=0){
393
+ for(let i=endIndex; i>=0; i--){
394
+ endIndex=i-1
395
+ if(checkElement(ancestors[i],selectorAncestors[selectorIndex])==true){
396
+ count++
397
+ break
398
+ }
399
+ }
400
+ selectorIndex--
401
+ }
402
+ if(count==selectorAncestors.length) return true
403
+ else return false
404
+ }
405
+ function checkParents(ancestors=[],selectorParents=[]){
406
+ if(selectorParents.length===0) return true
407
+ if(ancestors.length< selectorParents.length) return false
408
+ let index=ancestors.length-1
409
+ for(let i=selectorParents.length-1; i>=0; i--){
410
+ if(checkElement(ancestors[index],selectorParents[i])===false) return false
411
+ index--
412
+ }
413
+ return true
414
+ }
212
415
  const getDataName=prop=>'data-'+prop.toLowerCase()
213
- function getDataset(element){
214
416
  return new Proxy(element.attributes,{
215
417
  get: (target,prop)=>{return target[getDataName(prop)]},set: (target,prop,value)=>{target[getDataName(prop)]=value; return true},deleteProperty: (target,prop)=>{
216
418
  const dataAttr=getDataName(prop)
217
419
  if (dataAttr in target){
218
420
  delete target[dataAttr];
219
421
  return true;
220
422
  }
221
423
  return false;
222
424
  }
223
425
  });
224
- }
225
-
226
- function find(selectors,element,collection,first=false,firstTime=true){
227
426
  for(let selector of selectors){
228
427
  if(checkElement(element,selector)) collection.add(element)
229
428
  }
230
429
  if(element.children)
231
430
  element.children.forEach(child=>{
232
431
  if(first && collection.size>0) return
233
432
  find(selectors,child,collection,first,false)
234
433
  })
235
434
  return firstTime ? [...collection] : collection
236
- }
237
- class TextNode{
238
435
  constructor(data){
239
436
  this.nodeName='#text';
240
437
  this.parent=null;
241
438
  this.textContent=data;
242
439
  }
243
440
  get nodeValue(){return this.textContent}
244
441
  get parentNode(){return this.parent}
245
- }
246
-
247
- function buildStyle(attributes){
248
442
  const styles=attributes.style || "";
249
443
  const camelToKebab=str=>str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,'$1-$2').toLowerCase();
250
444
  const kebabToCamel=str=>str.replace(/-([a-z])/g,g=>g[1].toUpperCase());
251
445
  const baseStyleObj=styles.split(";").reduce((acc,style)=>{
252
446
  const [key,value]=style.split(":").map(s=>s.trim());
253
447
  if (key && value) acc[kebabToCamel(key)]=value;
254
448
  return acc;
255
449
  },{});
256
450
  return new Proxy(baseStyleObj,{
257
451
  get: (obj,prop)=>obj[camelToKebab(prop)] || obj[prop],set: (obj,prop,value)=>{
258
452
  obj[camelToKebab(prop)]=value;
259
453
  attributes.style=Object.entries(obj).map(([k,v])=>`${camelToKebab(k)}: ${v}`).join("; ");
260
454
  return true;
261
455
  },deleteProperty: (obj,prop)=>{
262
456
  delete obj[camelToKebab(prop)];
263
457
  attributes.style=Object.entries(obj).map(([k,v])=>`${camelToKebab(k)}: ${v}`).join("; ");
264
458
  return true;
265
459
  }
266
460
  });
267
- }
268
-
269
- class NodeClassList{
270
461
  constructor(node){ this.node=node }
271
462
  get classes(){ return (this.node.attributes.class || "").split(" ").filter(Boolean) }
272
463
  set classes(val){ this.node.attributes.class=val.join(" ") }
273
464
  contains(className){ return this.classes.includes(className) }
274
465
  add(className){
275
466
  const currentClasses=this.classes;
276
467
  if (!currentClasses.includes(className)) this.classes=[...currentClasses,className];
277
468
  }
278
469
  remove(className){ this.classes=this.classes.filter(cls=>cls!==className); }
279
470
  toggle(className){
280
471
  if (this.classes.includes(className)) this.remove(className);
281
472
  else this.add(className);
282
473
  }
283
474
  replace(oldClass,newClass){
284
475
  if (this.classes.includes(oldClass)){
285
476
  this.remove(oldClass);
286
477
  this.add(newClass);
287
478
  }
288
479
  }
289
- }
290
- class Node{
291
480
  constructor(tagName,attributes={},parent=null){
292
481
  this.isSingle=false;
293
482
  this.tagName=tagName;
294
483
  this.attributes=attributes;
295
484
  this.childNodes=[];
296
485
  if (parent!==null) parent.childNodes.push(this)
297
486
  this.parent=parent;
298
487
  this._classList=null;
299
488
  this.__style=null;
300
489
  this._dataset=null
301
490
  }
302
491
  get id(){ return this.attributes.id || null; }
303
492
  get className(){return this.attributes.class || null}
304
493
  get parentNode(){ return this.parent }
305
494
  get ancestors(){
306
495
  const ancestors=[]
307
496
  let element=this.parent
308
497
  while (element.tagName!=='ROOT'){
309
498
  ancestors.push(element)
310
499
  element=element.parent
311
500
  }
312
501
  return ancestors.reverse()
313
502
  }
314
503
  get childIndex(){ return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null }
315
504
  get previousElementSibling(){ return this.prev }
316
505
  get prev(){
317
506
  if (!this.childIndex) return null
318
507
  return this.parent.childNodes[this.childIndex-1]
319
508
  }
320
509
  get nextElementSibling(){ return this.next }
321
510
  get next(){
322
511
  if (!this.childIndex) return null
323
512
  return this.parent.childNodes[this.childIndex+1] || null
324
513
  }
325
514
  get dataset(){
326
515
  if (!this._dataset) this._dataset=getDataset(this);
327
516
  return this._dataset;
328
517
  }
329
518
  get classList(){
330
519
  if (!this._classList) this._classList=new NodeClassList(this);
331
520
  return this._classList;
332
521
  }
333
522
  get style(){
334
523
  if (!this.__style) this.__style=buildStyle(this.attributes)
335
524
  return this.__style
336
525
  }
337
526
  get outerHTML(){
338
527
  const attrs=Object.entries(this.attributes).map(([key,val])=>`${key}="${val}"`).join(" ");
339
528
  return `<${this.tagName} ${attrs}>${this.innerHTML}</${this.tagName}>`;
340
529
  }
341
530
  getAttribute(attrName){ return this.attributes[attrName] || null }
342
531
  setAttribute(attrName,value){ this.attributes[attrName]=value }
343
532
  removeAttribute(attrName){ delete this.attributes[attrName] }
344
533
  remove(){
345
534
  if (!this.parent) return
346
535
  const index=this.childIndex;
347
536
  if (index!==null) this.parent.childNodes.splice(index,1);
348
537
  }
349
538
  get innerHTML(){
350
539
  return this.childNodes.map(child=>{
351
540
  if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
352
541
  else if (child instanceof TextNode) return child.textContent;
353
542
  else return child
354
543
  }).join("");
355
544
  }
356
545
  $$(query){return this.querySelectorAll(query)}
357
546
  querySelectorAll(query){
358
547
  const selectors=Query.get(query)
359
548
  return find(selectors,this,new Set())
360
549
  }
361
550
  $(query){return this.querySelector(query)}
362
551
  querySelector(query){
363
552
  const selectors=Query.get(query)
364
553
  return find(selectors,this,new Set(),true)[0] || null
365
554
  }
366
555
  getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
367
556
  getElementsByTagName(query){ return this.querySelectorAll(query) }
368
557
  getElementById(query){ return this.querySelector('#'+query) }
369
558
  get children(){
370
559
  return this.childNodes.filter(child=>{
371
560
  if (!(child instanceof Node)) return false
372
561
  if (child.tagName==='#comment') return false
373
562
  return true
374
563
  });
375
564
  }
376
565
  insertAdjacentElement(position,newElement){
377
566
  if(newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
378
567
  const pos=position.toLowerCase();
379
568
  if (pos==="afterbegin") this.childNodes.unshift(newElement);
380
569
  else if (pos==="beforeend") this.childNodes.push(newElement);
381
570
  if (!this.parent) return newElement
382
571
  if (pos==="beforebegin") this.parent.childNodes.unshift(newElement);
383
572
  else if (pos==="afterend") this.parent.childNodes.splice(this.childIndex+1,0,newElement);
384
573
  return newElement
385
574
  }
386
575
  insertAdjacentHTML(position,html){
387
576
  const newNode=parseHTML(html);
388
577
  return this.insertAdjacentElement(position,newNode);
389
578
  }
390
579
  insertAdjacentText(position,text){
391
580
  return this.insertAdjacentElement(position,new TextNode(text));
392
581
  }
393
582
  set innerHTML(html){
394
583
  const parsed=parseHTML(html);
395
584
  this.childNodes=parsed.childNodes;
396
585
  }
397
586
  set outerHTML(html){
398
587
  const parsed=parseHTML(html);
399
588
  if (!this.parent) return console.log('element has no parent node')
400
589
  const index=this.childIndex
401
590
  if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
402
591
  }
403
592
  appendChild(newChild){
404
593
  if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
405
594
  if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
406
595
  } else if(typeof newChild==='string') newChild=new TextNode(newChild)
407
596
  else return newChild
408
597
  this.childNodes.push(newChild);
409
598
  newChild.parent=this;
410
599
  return newChild;
411
600
  }
412
601
  get textContent(){
413
602
  if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
414
603
  return this.childNodes.map(child=>{
415
604
  if(child instanceof SingleNode) return ''
416
605
  if(child instanceof TextNode) return child.nodeValue
417
606
  if(child instanceof Node) return child.textContent;
418
607
  else return child;
419
608
  }).join(" ");
420
609
  }
421
610
  set textContent(value){
422
611
  this.childNodes=[];
423
612
  if (value!==null && value!==undefined){
424
613
  this.childNodes.push(value.toString());
425
614
  }
426
615
  }
427
- }
428
- class SingleNode extends Node{
429
616
  constructor(tagName,attributes={},parent=null){
430
617
  if(attributes['?'] && tagName==='?xml') delete attributes['?']
431
618
  super(tagName,attributes,parent);
432
619
  this.isSingle=true
433
620
  }
434
621
  get outerHTML(){
435
622
  if (this.tagName==="#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
436
623
  const attrs=Object.entries(this.attributes).map(([key,val])=>`${key}="${val}"`).join(" ");
437
624
  return `<${this.tagName} ${attrs}${this.tagName==='?xml' ? '?' : ''}>`;
438
625
  }
439
626
  get innerHTML(){ return ""; }
440
627
  set innerHTML(_){ }
441
628
  $(_){return null}
442
629
  $$(_){return []}
443
630
  querySelectorAll(_){ return []; }
444
631
  querySelector(_){ return null; }
445
632
  getElementsByClassName(_){ return []; }
446
633
  getElementsByTagName(_){ return []; }
447
634
  getElementById(_){ return null; }
448
635
  get children(){ return []; }
449
636
  insertAdjacentElement(_,__){ }
450
637
  insertAdjacentHTML(_,__){ }
451
638
  insertAdjacentText(_,__){ }
452
639
  appendChild(_){ }
453
640
  get textContent(){ return ""; }
454
641
  set textContent(_){ }
455
- }
456
- function parseAttributes(str){
457
642
  const attrs={};
458
643
  let key="";
459
644
  let value="";
460
645
  let isKey=true;
461
646
  let quoteChar=null;
462
647
  for (let i=0; i< str.length; i++){
463
648
  const char=str[i];
464
649
  if (isKey && (char==='=' || char===' ')){
465
650
  if (char==='=') isKey=false;
466
651
  else if (key.trim()){
467
652
  attrs[key.trim()]=true;
468
653
  key="";
469
654
  }
470
655
  continue;
471
656
  }
472
657
  if (!quoteChar && (char==='"' || char==="'")){
473
658
  quoteChar=char;
474
659
  continue;
475
660
  } else if (quoteChar && char===quoteChar){
476
661
  quoteChar=null;
477
662
  attrs[key.trim()]=value.trim();
478
663
  key=""; value=""; isKey=true;
479
664
  continue;
480
665
  }
481
666
  if (isKey) key+=char;
482
667
  else value+=char;
483
668
  }
484
669
  if (key.trim() &&!value) attrs[key.trim()]=true;
485
670
  return attrs;
486
- }
487
- const VOID_TAGS=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr","!doctype",'?xml']);
488
- function parseHTML(html){
489
671
  const root=new Node("ROOT");
490
672
  const stack=[root];
491
673
  let currentText="",i=0;
492
674
  function parseSpecial(startStr,endStr,n1,n2,tag){
493
675
  if (!html.startsWith(startStr,i)) return false
494
676
  const end=html.indexOf(endStr,i+n1);
495
677
  const strNode=new Node(tag,{},stack[stack.length-1]);
496
678
  strNode.childNodes.push(html.substring(i+n1,end));
497
679
  i=end+n2;
498
680
  return true
499
681
  }
500
682
  while (i< html.length){
501
683
  if (parseSpecial("<!--","-->",4,3,'#comment')) continue
502
684
  if (parseSpecial("<script","</script>",8,9,'script')) continue
503
685
  if (parseSpecial("<style","</style>",7,8,'style')) continue
504
686
  if (html.startsWith("<![CDATA[",i)){
505
687
  const end=html.indexOf("]]>",i+9);
506
688
  if (end===-1) break;
507
689
  const content=html.substring(i+9,end);
508
690
  const cdataNode=new SingleNode("#cdata-section",{},stack[stack.length-1]);
509
691
  cdataNode.nodeValue=content;
510
692
  i=end+3;
511
693
  continue;
512
694
  }
513
695
  if (html.startsWith("<",i)){
514
696
  if (currentText.trim()){
515
697
  stack[stack.length-1].childNodes.push(new TextNode(currentText.trim()));
516
698
  currentText="";
517
699
  }
518
700
  let tagEnd=i+1;
519
701
  let insideQuotes=false;
520
702
  let quoteChar=null;
521
703
  while (tagEnd< html.length){
522
704
  const char=html[tagEnd];
523
705
  if (!insideQuotes && (char==='"' || char==="'")){
524
706
  insideQuotes=true;
525
707
  quoteChar=char;
526
708
  } else if (insideQuotes && char===quoteChar){
527
709
  insideQuotes=false;
528
710
  quoteChar=null;
529
711
  }
530
712
  if (!insideQuotes && char==='>') break;
531
713
  tagEnd++;
532
714
  }
533
715
  const tagContent=html.substring(i+1,tagEnd);
534
716
  if (tagContent.startsWith("/")) stack.pop();
535
717
  else{
536
718
  let isSelfClosing=tagContent.endsWith('/');
537
719
  const tagNameEnd=tagContent.search(/\s|>|\//);
538
720
  const tagName=tagContent.substring(0,tagNameEnd>0 ? tagNameEnd : tagEnd-i-1);
539
721
  const attributesString=tagContent.substring(tagName.length,isSelfClosing ? tagContent.length-1 : tagContent.length).trim();
540
722
  const attributes=parseAttributes(attributesString);
541
723
  if (VOID_TAGS.has(tagName.toLowerCase()) || isSelfClosing) new SingleNode(tagName,attributes,stack[stack.length-1])
542
724
  else stack.push(new Node(tagName,attributes,stack[stack.length-1]));
543
725
  }
544
726
  i=tagEnd+1;
545
727
  } else{
546
728
  currentText+=html[i];
547
729
  i++;
548
730
  }
549
731
  }
550
732
  if (currentText.trim()) stack[stack.length-1].childNodes.push(new TextNode(currentText.trim()));
551
733
  return root;
552
- }
734
+ function getDataset(element){
735
+ return new Proxy(element.attributes,{
736
+ get: (target,prop)=>{return target[getDataName(prop)]},set: (target,prop,value)=>{target[getDataName(prop)]=value; return true},deleteProperty: (target,prop)=>{
737
+ const dataAttr=getDataName(prop)
738
+ if (dataAttr in target){
739
+ delete target[dataAttr];
740
+ return true;
741
+ }
742
+ return false;
743
+ }
744
+ });
745
+ }
746
+
747
+ function find(selectors,element,collection,first=false,firstTime=true){
748
+ for(let selector of selectors){
749
+ if(checkElement(element,selector)) collection.add(element)
750
+ }
751
+ if(element.children)
752
+ element.children.forEach(child=>{
753
+ if(first && collection.size>0) return
754
+ find(selectors,child,collection,first,false)
755
+ })
756
+ return firstTime ? [...collection] : collection
757
+ }
758
+ class TextNode{
759
+ constructor(data){
760
+ this.nodeName='#text';
761
+ this.parent=null;
762
+ this.textContent=data;
763
+ }
764
+ get nodeValue(){return this.textContent}
765
+ get parentNode(){return this.parent}
766
+ }
767
+
768
+ function buildStyle(attributes){
769
+ const styles=attributes.style || "";
770
+ const camelToKebab=str=>str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g,'$1-$2').toLowerCase();
771
+ const kebabToCamel=str=>str.replace(/-([a-z])/g,g=>g[1].toUpperCase());
772
+ const baseStyleObj=styles.split(";").reduce((acc,style)=>{
773
+ const [key,value]=style.split(":").map(s=>s.trim());
774
+ if (key && value) acc[kebabToCamel(key)]=value;
775
+ return acc;
776
+ },{});
777
+ return new Proxy(baseStyleObj,{
778
+ get: (obj,prop)=>obj[camelToKebab(prop)] || obj[prop],set: (obj,prop,value)=>{
779
+ obj[camelToKebab(prop)]=value;
780
+ attributes.style=Object.entries(obj).map(([k,v])=>`${camelToKebab(k)}: ${v}`).join("; ");
781
+ return true;
782
+ },deleteProperty: (obj,prop)=>{
783
+ delete obj[camelToKebab(prop)];
784
+ attributes.style=Object.entries(obj).map(([k,v])=>`${camelToKebab(k)}: ${v}`).join("; ");
785
+ return true;
786
+ }
787
+ });
788
+ }
789
+
790
+ class NodeClassList{
791
+ constructor(node){ this.node=node }
792
+ get classes(){ return (this.node.attributes.class || "").split(" ").filter(Boolean) }
793
+ set classes(val){ this.node.attributes.class=val.join(" ") }
794
+ contains(className){ return this.classes.includes(className) }
795
+ add(className){
796
+ const currentClasses=this.classes;
797
+ if (!currentClasses.includes(className)) this.classes=[...currentClasses,className];
798
+ }
799
+ remove(className){ this.classes=this.classes.filter(cls=>cls!==className); }
800
+ toggle(className){
801
+ if (this.classes.includes(className)) this.remove(className);
802
+ else this.add(className);
803
+ }
804
+ replace(oldClass,newClass){
805
+ if (this.classes.includes(oldClass)){
806
+ this.remove(oldClass);
807
+ this.add(newClass);
808
+ }
809
+ }
810
+ }
811
+ class Node{
812
+ constructor(tagName,attributes={},parent=null){
813
+ this.isSingle=false;
814
+ this.tagName=tagName;
815
+ this.attributes=attributes;
816
+ this.childNodes=[];
817
+ if (parent!==null) parent.childNodes.push(this)
818
+ this.parent=parent;
819
+ this._classList=null;
820
+ this.__style=null;
821
+ this._dataset=null
822
+ }
823
+ get id(){ return this.attributes.id || null; }
824
+ get className(){return this.attributes.class || null}
825
+ get parentNode(){ return this.parent }
826
+ get ancestors(){
827
+ const ancestors=[]
828
+ let element=this.parent
829
+ while (element.tagName!=='ROOT'){
830
+ ancestors.push(element)
831
+ element=element.parent
832
+ }
833
+ return ancestors.reverse()
834
+ }
835
+ get childIndex(){ return this.parent.childNodes ? this.parent.childNodes.indexOf(this) : null }
836
+ get previousElementSibling(){ return this.prev }
837
+ get prev(){
838
+ if (!this.childIndex) return null
839
+ return this.parent.childNodes[this.childIndex-1]
840
+ }
841
+ get nextElementSibling(){ return this.next }
842
+ get next(){
843
+ if (!this.childIndex) return null
844
+ return this.parent.childNodes[this.childIndex+1] || null
845
+ }
846
+ get dataset(){
847
+ if (!this._dataset) this._dataset=getDataset(this);
848
+ return this._dataset;
849
+ }
850
+ get classList(){
851
+ if (!this._classList) this._classList=new NodeClassList(this);
852
+ return this._classList;
853
+ }
854
+ get style(){
855
+ if (!this.__style) this.__style=buildStyle(this.attributes)
856
+ return this.__style
857
+ }
858
+ get outerHTML(){
859
+ const attrs=Object.entries(this.attributes).map(([key,val])=>`${key}="${val}"`).join(" ");
860
+ return `<${this.tagName} ${attrs}>${this.innerHTML}</${this.tagName}>`;
861
+ }
862
+ getAttribute(attrName){ return this.attributes[attrName] || null }
863
+ setAttribute(attrName,value){ this.attributes[attrName]=value }
864
+ removeAttribute(attrName){ delete this.attributes[attrName] }
865
+ remove(){
866
+ if (!this.parent) return
867
+ const index=this.childIndex;
868
+ if (index!==null) this.parent.childNodes.splice(index,1);
869
+ }
870
+ get innerHTML(){
871
+ return this.childNodes.map(child=>{
872
+ if (child instanceof Node || child instanceof SingleNode) return child.outerHTML;
873
+ else if (child instanceof TextNode) return child.textContent;
874
+ else return child
875
+ }).join("");
876
+ }
877
+ $$(query){return this.querySelectorAll(query)}
878
+ querySelectorAll(query){
879
+ const selectors=Query.get(query)
880
+ return find(selectors,this,new Set())
881
+ }
882
+ $(query){return this.querySelector(query)}
883
+ querySelector(query){
884
+ const selectors=Query.get(query)
885
+ return find(selectors,this,new Set(),true)[0] || null
886
+ }
887
+ getElementsByClassName(query){ return this.querySelectorAll('.'+query) }
888
+ getElementsByTagName(query){ return this.querySelectorAll(query) }
889
+ getElementById(query){ return this.querySelector('#'+query) }
890
+ get children(){
891
+ return this.childNodes.filter(child=>{
892
+ if (!(child instanceof Node)) return false
893
+ if (child.tagName==='#comment') return false
894
+ return true
895
+ });
896
+ }
897
+ insertAdjacentElement(position,newElement){
898
+ if(newElement.tagName==='ROOT' && newElement.childNodes.length>0) newElement=newElement.childNodes[0]
899
+ const pos=position.toLowerCase();
900
+ if (pos==="afterbegin") this.childNodes.unshift(newElement);
901
+ else if (pos==="beforeend") this.childNodes.push(newElement);
902
+ if (!this.parent) return newElement
903
+ if (pos==="beforebegin") this.parent.childNodes.unshift(newElement);
904
+ else if (pos==="afterend") this.parent.childNodes.splice(this.childIndex+1,0,newElement);
905
+ return newElement
906
+ }
907
+ insertAdjacentHTML(position,html){
908
+ const newNode=parseHTML(html);
909
+ newNode.childNodes.reverse().forEach(node=>{
910
+ this.insertAdjacentElement(position,node);
911
+ });
912
+ return newNode
913
+ }
914
+ insertAdjacentText(position,text){
915
+ return this.insertAdjacentElement(position,new TextNode(text));
916
+ }
917
+ set innerHTML(html){
918
+ const parsed=parseHTML(html);
919
+ this.childNodes=parsed.childNodes;
920
+ }
921
+ set outerHTML(html){
922
+ const parsed=parseHTML(html);
923
+ if (!this.parent) return console.log('element has no parent node')
924
+ const index=this.childIndex
925
+ if (index!==null) this.parent.childNodes.splice(index,1,...parsed.childNodes);
926
+ }
927
+ appendChild(newChild){
928
+ if (newChild instanceof Node || newChild instanceof TextNode || newChild instanceof SingleNode){
929
+ if (newChild.parent) newChild.parent.childNodes=newChild.parent.childNodes.filter(child=>child!==newChild);
930
+ } else if(typeof newChild==='string') newChild=new TextNode(newChild)
931
+ else return newChild
932
+ this.childNodes.push(newChild);
933
+ newChild.parent=this;
934
+ return newChild;
935
+ }
936
+ get textContent(){
937
+ if (this.childNodes.length===0) return this.nodeName==='#text' ? this.nodeValue : '';
938
+ return this.childNodes.map(child=>{
939
+ if(child instanceof SingleNode) return ''
940
+ if(child instanceof TextNode) return child.nodeValue
941
+ if(child instanceof Node) return child.textContent;
942
+ else return child;
943
+ }).join(" ");
944
+ }
945
+ set textContent(value){
946
+ this.childNodes=[];
947
+ if (value!==null && value!==undefined){
948
+ this.childNodes.push(value.toString());
949
+ }
950
+ }
951
+ }
952
+ class SingleNode extends Node{
953
+ constructor(tagName,attributes={},parent=null){
954
+ if(attributes['?'] && tagName==='?xml') delete attributes['?']
955
+ super(tagName,attributes,parent);
956
+ this.isSingle=true
957
+ }
958
+ get outerHTML(){
959
+ if (this.tagName==="#cdata-section") return `<![CDATA[${this.nodeValue}]]>`;
960
+ const attrs=Object.entries(this.attributes).map(([key,val])=>`${key}="${val}"`).join(" ");
961
+ return `<${this.tagName} ${attrs}${this.tagName==='?xml' ? '?' : ''}>`;
962
+ }
963
+ get innerHTML(){ return ""; }
964
+ set innerHTML(_){ }
965
+ $(_){return null}
966
+ $$(_){return []}
967
+ querySelectorAll(_){ return []; }
968
+ querySelector(_){ return null; }
969
+ getElementsByClassName(_){ return []; }
970
+ getElementsByTagName(_){ return []; }
971
+ getElementById(_){ return null; }
972
+ get children(){ return []; }
973
+ insertAdjacentElement(_,__){ }
974
+ insertAdjacentHTML(_,__){ }
975
+ insertAdjacentText(_,__){ }
976
+ appendChild(_){ }
977
+ get textContent(){ return ""; }
978
+ set textContent(_){ }
979
+ }
980
+ function parseAttributes(str){
981
+ const attrs={};
982
+ let key="";
983
+ let value="";
984
+ let isKey=true;
985
+ let quoteChar=null;
986
+ for (let i=0; i< str.length; i++){
987
+ const char=str[i];
988
+ if (isKey && (char==='=' || char===' ')){
989
+ if (char==='=') isKey=false;
990
+ else if (key.trim()){
991
+ attrs[key.trim()]=true;
992
+ key="";
993
+ }
994
+ continue;
995
+ }
996
+ if (!quoteChar && (char==='"' || char==="'")){
997
+ quoteChar=char;
998
+ continue;
999
+ } else if (quoteChar && char===quoteChar){
1000
+ quoteChar=null;
1001
+ attrs[key.trim()]=value.trim();
1002
+ key=""; value=""; isKey=true;
1003
+ continue;
1004
+ }
1005
+ if (isKey) key+=char;
1006
+ else value+=char;
1007
+ }
1008
+ if (key.trim() &&!value) attrs[key.trim()]=true;
1009
+ return attrs;
1010
+ }
1011
+ const VOID_TAGS=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr","!doctype",'?xml']);
1012
+ function parseHTML(html){
1013
+ const root=new Node("ROOT");
1014
+ const stack=[root];
1015
+ let currentText="",i=0;
1016
+ let max=0
1017
+ function parseScript(){
1018
+ if (!html.startsWith("<script",i)) return false;
1019
+ const openTagEnd=html.indexOf(">",i);
1020
+ if (openTagEnd===-1) return false;
1021
+ const attributesString=html.substring(i+7,openTagEnd).trim();
1022
+ const attributes=parseAttributes(attributesString);
1023
+ let closeTagStart=html.indexOf("</script>",openTagEnd);
1024
+ if (closeTagStart===-1) return false;
1025
+ const content=html.substring(openTagEnd+1,closeTagStart);
1026
+ const scriptNode=new Node('script',attributes,stack[stack.length-1]);
1027
+ if(content.length>0) scriptNode.childNodes.push(content);
1028
+ i=closeTagStart+9;
1029
+ return true;
1030
+ }
1031
+ function parseSpecial(startStr,endStr,n1,n2,tag){
1032
+ if (!html.startsWith(startStr,i)) return false
1033
+ const end=html.indexOf(endStr,i+n1);
1034
+ const strNode=new Node(tag,{},stack[stack.length-1]);
1035
+ strNode.childNodes.push(html.substring(i+n1,end));
1036
+ i=end+n2;
1037
+ return true
1038
+ }
1039
+ while (i< html.length){
1040
+ if(i>=max) max=i;
1041
+ else break;
1042
+ if (parseScript()) continue
1043
+ if (parseSpecial("<!--","-->",4,3,'#comment')) continue
1044
+ if (parseSpecial("<style","</style>",7,8,'style')) continue
1045
+ if (html.startsWith("<![CDATA[",i)){
1046
+ const end=html.indexOf("]]>",i+9);
1047
+ if (end===-1) break;
1048
+ const content=html.substring(i+9,end);
1049
+ const cdataNode=new SingleNode("#cdata-section",{},stack[stack.length-1]);
1050
+ cdataNode.nodeValue=content;
1051
+ i=end+3;
1052
+ continue;
1053
+ }
1054
+ if (html.startsWith("<",i)){
1055
+ if (currentText.trim()){
1056
+ stack[stack.length-1].childNodes.push(new TextNode(currentText.trim()));
1057
+ currentText="";
1058
+ }
1059
+ let tagEnd=i+1;
1060
+ let insideQuotes=false;
1061
+ let quoteChar=null;
1062
+ while (tagEnd< html.length){
1063
+ const char=html[tagEnd];
1064
+ if (!insideQuotes && (char==='"' || char==="'")){
1065
+ insideQuotes=true;
1066
+ quoteChar=char;
1067
+ } else if (insideQuotes && char===quoteChar){
1068
+ insideQuotes=false;
1069
+ quoteChar=null;
1070
+ }
1071
+ if (!insideQuotes && char==='>') break;
1072
+ tagEnd++;
1073
+ }
1074
+ const tagContent=html.substring(i+1,tagEnd);
1075
+ if (tagContent.startsWith("/")) stack.pop();
1076
+ else{
1077
+ let isSelfClosing=tagContent.endsWith('/');
1078
+ const tagNameEnd=tagContent.search(/\s|>|\//);
1079
+ const tagName=tagContent.substring(0,tagNameEnd>0 ? tagNameEnd : tagEnd-i-1);
1080
+ const attributesString=tagContent.substring(tagName.length,isSelfClosing ? tagContent.length-1 : tagContent.length).trim();
1081
+ const attributes=parseAttributes(attributesString);
1082
+ if (VOID_TAGS.has(tagName.toLowerCase()) || isSelfClosing) new SingleNode(tagName,attributes,stack[stack.length-1])
1083
+ else stack.push(new Node(tagName,attributes,stack[stack.length-1]));
1084
+ }
1085
+ i=tagEnd+1;
1086
+ } else{
1087
+ currentText+=html[i];
1088
+ i++;
1089
+ }
1090
+ }
1091
+ if (currentText.trim()) stack[stack.length-1].childNodes.push(new TextNode(currentText.trim()));
1092
+ return root;
1093
+ }
553
1094
  export default { parseHTML, Node, Query, TextNode, SingleNode }