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