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