als-document 0.5.0 → 0.6.0

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,3 +1,124 @@
1
+ class HtmlSelector {
2
+ constructor(html) {
3
+ if(typeof html == 'string') {
4
+ this.html = new HtmlParser(html)
5
+ this.elements.forEach((element,i) => {this.makeSelectable(element)});
6
+ } else console.log('Parameter is not string')
7
+ }
8
+ get elements() {return this.html.elements}
9
+
10
+ makeSelectable(element) {
11
+ if(element.type == 'tag' && element.status !== 'close') {
12
+ element.$$ = (query) => this.$$(query,element.index,element.endIndex)
13
+ element.$ = (query) => this.$(query,element.index,element.endIndex)
14
+ }
15
+ }
16
+
17
+ $(query,start=0,end=this.elements.length) {
18
+ return this.$$(query,start,end,true)
19
+ }
20
+
21
+ $$(query,start=0,end=this.elements.length,single=false) {
22
+ let result = []
23
+ this.selectors = new Query(query).selectors
24
+ this.query = query
25
+ this.selectors.forEach(selector => {
26
+ for(let i=start; i<end; i++) {
27
+ let el = this.elements[i]
28
+ if(this.checkElement(el,selector) && !result.includes(el)) result.push(el)
29
+ if(single && result.length == 1) break
30
+ }
31
+ });
32
+ if(single && result.length == 1) return result[0]
33
+ else if(single && result.length == 0) return null
34
+ else return result
35
+ }
36
+
37
+ checkElement(el,selector) {
38
+ if(selector == undefined) return true
39
+ if(el == null) return false
40
+ let {tag,classList,attribs,id,prev,ancestors,parents,prevAny} = selector
41
+
42
+ if(el.status == 'close' || el.type == 'text') return false
43
+ if(id !== undefined && el.id == undefined) return false
44
+ if(id && id !== el.id) return false
45
+ if(tag && el.tag == undefined) return false
46
+ else if(tag && tag !== el.tag) return false
47
+ if(classList !== undefined && el.classList == undefined) return false
48
+ else if(classList !== undefined && Array.isArray(el.classList)) {
49
+ if(classList.every(e => el.classList.includes(e)) == false) return false
50
+ }
51
+ if(this.checkAttribs(attribs,el) == false) return false
52
+ if(this.checkElement(el.prev,prev) == false) return false
53
+ if(this.checkAncestors(el.ancestors,ancestors) == false) return false
54
+ if(this.checkParents(el.ancestors,parents) == false) return false
55
+ if(el.parent) {
56
+ if(this.prevAny(el.parent.children,el.childIndex,prevAny) == false) return false
57
+ }
58
+ return true
59
+ }
60
+
61
+ prevAny(children=[],index,prevAny) {
62
+ let size = children.length
63
+ if((size == 0 || index == 0) && prevAny) return false
64
+ for(let i=index; i>=0; i--) {
65
+ if(this.checkElement(children[i],prevAny)) return true
66
+ }
67
+ return false
68
+ }
69
+
70
+ checkAncestors(ancestors=[],selectorAncestors=[]) {
71
+ let count = 0
72
+ if(selectorAncestors.length == 0) return true
73
+ let endIndex = ancestors.length-1
74
+ let selectorIndex = selectorAncestors.length-1
75
+ while(selectorIndex>=0) {
76
+ for(let i=endIndex; i>=0; i--) {
77
+ endIndex=i-1
78
+ if(this.checkElement(ancestors[i],selectorAncestors[selectorIndex]) == true) {
79
+ count++
80
+ break
81
+ }
82
+ }
83
+ selectorIndex--
84
+ }
85
+ if(count == selectorAncestors.length) return true
86
+ else return false
87
+ }
88
+
89
+ checkParents(ancestors=[],selectorParents=[]) {
90
+ if(selectorParents.length == 0) return true
91
+ if(ancestors.length < selectorParents.length) return false
92
+ let index = ancestors.length-1
93
+ for(let i=selectorParents.length-1; i>=0; i--) {
94
+ if(this.checkElement(ancestors[index],selectorParents[i]) == false) return false
95
+ index--
96
+ }
97
+ return true
98
+ }
99
+
100
+ checkAttribs(attribs=[],el) {
101
+ let elAttribs = el.attribs
102
+ let names = Object.keys(elAttribs)
103
+ let passedTests = 0
104
+ if(attribs) for(let i=0; i<attribs.length; i++) {
105
+ let {name,value,check} = attribs[i]
106
+ if(name == 'inner' && value !== undefined && check && el.innerText) {
107
+ if(check(el.innerText)) passedTests++
108
+ }
109
+
110
+ if(!names.includes(name)) continue
111
+ else if(value == undefined) passedTests++
112
+ else if(value && elAttribs[name]) {
113
+ if(check(elAttribs[name]) == false) continue
114
+ else passedTests++
115
+ }
116
+ }
117
+ if(passedTests == attribs.length) return true
118
+ else return false
119
+ }
120
+ }
121
+
1
122
  class Query {
2
123
  static get(query) {
3
124
  let q = new Query(query)
@@ -144,7 +265,7 @@ class Query {
144
265
  return selector
145
266
  }
146
267
  }
147
-
268
+
148
269
  class HtmlParser {
149
270
  static parse(html) {
150
271
  let result = new HtmlParser(html)
@@ -155,14 +276,22 @@ class HtmlParser {
155
276
  this.indexes = []
156
277
  this.events = []
157
278
  this.html = this.htmlString = html
279
+ this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
158
280
  this.removeScripts()
159
281
  this.removeStyles()
160
282
  this.removeEventStrings()
161
- this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
162
283
  this.root = this.parse()
284
+ this.clean()
163
285
  }
164
286
  }
165
287
 
288
+ clean() {
289
+ let toDelete = ['events','indexes','scripts','styles','htmlString','html']
290
+ toDelete.forEach(name => {
291
+ delete this[name]
292
+ });
293
+ }
294
+
166
295
  checkHtml(html,isGood=false) {
167
296
  if(html == '') console.log('html parameter is empty')
168
297
  else if(typeof html !== 'string') console.log(`html parameter has to be string. Recieved ${typeof html}`)
@@ -222,6 +351,9 @@ class HtmlParser {
222
351
  }
223
352
  this.elements = elements
224
353
  let root = this.getPairs()
354
+ root.level = 0
355
+ root.elements = this.elements
356
+ this.innerHTML(root)
225
357
  return root
226
358
  }
227
359
 
@@ -252,19 +384,18 @@ class HtmlParser {
252
384
  getPairs(parent={type:'root',children:[]},startIndex = 0,endIndex=this.elements.length,level=0,childIndex=0) {
253
385
  for(let index = startIndex; index < endIndex; index++) {
254
386
  if(this.indexes.includes(index)) continue
255
- const element = this.elements[index];
387
+ let element = this.elements[index];
256
388
  let child
257
389
  if(typeof element == 'string') child = element
258
390
  else if(element.type == 'tag') {
259
391
  if(element.status == 'single') {
260
392
  child = element
261
393
  child.parent = parent
262
- }
263
- else if(element.status == 'open') {
394
+ } else if(element.status == 'open') {
264
395
  child = this.lookForPair(element,index,parent,level)
265
- }
266
- }
267
- this.addChild(parent,child,index,level,childIndex/2)
396
+ } else element.index = index
397
+ }
398
+ this.addChild(parent,child,index,level)
268
399
  childIndex++
269
400
  }
270
401
  return parent
@@ -289,30 +420,25 @@ class HtmlParser {
289
420
  return child
290
421
  }
291
422
 
292
- addChild(parent,child,index,level,childIndex) {
423
+ addChild(parent,child,index,level) {
293
424
  if(typeof child == 'string') {
294
425
  child = this.addScriptsAndStyles(parent,child,index)
295
- child = {type:'text',text:child}
426
+ child = {type:'text',text:child,parent}
296
427
  this.elements[index] = child
297
428
  }
298
429
  if(child) {
299
430
  delete child.status
431
+ if(child.type !== 'text') {
432
+ this.innerHTML(child)
433
+ this.outerHTML(child)
434
+ this.innerText(child)
435
+ }
300
436
  this.getElements(child)
301
- this.innerHTML(child)
302
- this.outerHTML(child)
303
- this.innerText(child)
304
437
  this.getAncestors(child)
305
438
  this.getAttribute(child)
306
- child.childIndex = childIndex
439
+ this.nextAndPrev(child)
307
440
  child.index = index
308
441
  child.level = level
309
- child.prev = null
310
- child.next = null
311
- if(parent.children.length > 0) {
312
- let prevI = parent.children.length-1
313
- parent.children[prevI].next = child
314
- child.prev = parent.children[prevI]
315
- }
316
442
  parent.children.push(child)
317
443
  }
318
444
  this.indexes.push(index)
@@ -337,10 +463,45 @@ class HtmlParser {
337
463
  }});
338
464
  }
339
465
 
340
- getElements(element,elements=this.elements) {
341
- Object.defineProperty(element, 'elements', { get() {
342
- return elements.slice(this.index,this.endIndex+1)
343
- }});
466
+ nextAndPrev(element) {
467
+ Object.defineProperty(element, 'childIndex', {
468
+ get() {return this.parent.children.map(o => o.index).indexOf(this.index)}
469
+ });
470
+ Object.defineProperty(element, 'prev', {
471
+ get() {
472
+ let i = this.childIndex, brothers = this.parent.children
473
+ return i == 0 ? null : brothers[i-1]
474
+ }
475
+ });
476
+ Object.defineProperty(element, 'next', {
477
+ get() {
478
+ let i = this.childIndex, brothers = this.parent.children
479
+ return i == brothers.length-1 ? null : brothers[i+1]
480
+ }
481
+ });
482
+ }
483
+
484
+ getElements(element,self=this) {
485
+ if(element.type !== 'text')
486
+ Object.defineProperty(element, 'elements', {
487
+ configurable:true,
488
+ get() {
489
+ let endIndex = isNaN(this.endIndex) ? this.index + 1 : this.endIndex+1
490
+ return self.elements.slice(this.index,endIndex)
491
+ }
492
+ });
493
+ Object.defineProperty(element, '$elements', {
494
+ configurable:true,
495
+ get() {return self.elements}
496
+ });
497
+ Object.defineProperty(element, 'root', {
498
+ configurable:true,
499
+ get() {return self.root}
500
+ });
501
+ Object.defineProperty(element, 'html', {
502
+ configurable:true,
503
+ get() {return self}
504
+ });
344
505
  }
345
506
 
346
507
  outerHTML(element) {
@@ -357,62 +518,71 @@ class HtmlParser {
357
518
  else return ''
358
519
  }})
359
520
  }
360
-
361
521
  innerHTML(element) {
522
+ element.tab = ' '
523
+ element.n = '\n'
362
524
  Object.defineProperty(element, 'innerHTML', { get() {
363
- let tab = ' ',result = '',firstLevel,space=''
525
+ // let tab = ' ',result = '',firstLevel,space=''
526
+ let {tab,n} = this
527
+ let result = '',firstLevel,space=''
364
528
  let {elements} = this
365
529
  let endIndex = elements.length
366
- for (let i = 1; i < endIndex-1; i++) {
530
+ let end = endIndex-1,start=1
531
+ if(this.type == 'root') {
532
+ end = endIndex
533
+ start = 0
534
+ }
535
+ for(let i = start; i < end; i++) {
367
536
  let element = elements[i]
368
- let {level,tag,text} = element
537
+ let {level,text} = element
369
538
  if(firstLevel == undefined) firstLevel = level
370
- if(i == endIndex-1) space = ''
539
+ if(i == end) space = ''
371
540
  else if(level) space = Array.from(Array(level-firstLevel).keys()).map(n => tab).join('')
372
541
  result += space + text
373
- if(endIndex > 3) result += '\n'
542
+ if(endIndex > 3) result += n
374
543
  }
375
544
  return result
376
545
  }});
377
546
  }
378
547
 
379
548
  parseElement(tagString) {
380
- let text = tagString
381
549
  let type = 'tag'
382
- if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type}
550
+ if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type,text:tagString}
383
551
  let status = 'close'
384
552
  let tag = tagString.match(/(?<=\<\/)(\w*\-?)*/)
385
553
  if(tag == null) {
386
554
  tag = tagString.match(/(?<=\<)(\w*\-?)*/)
387
555
  if(tag) {
388
556
  tag = tag[0]
389
- if(this.singleTags.includes(tag)) status='single'
557
+ if(HtmlParser.singleTags.includes(tag)) status='single'
390
558
  else status = 'open'
391
559
  }
392
560
  } else tag = tag[0]
393
- let {classList,attribs,style,id} = this.parseAttributes(tagString)
561
+ let {classList,attribs,style,id,text} = this.parseAttributes(tagString)
394
562
  let obj = {tag,status,attribs,type,classList,text,style,id}
395
563
  return obj
396
564
  }
397
- singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
565
+ static singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
398
566
 
399
567
  parseAttributes(tagString,classList=[],attribs={},style={},id=null) {
568
+ let text = tagString
400
569
  let attributes = tagString.match(/(?<=\s)(\w*\-?)*(\s*?\=\s*?\"[\s\S]*?\")?/g)
401
570
  if(attributes) attributes.forEach(attribString => {
402
571
  let [name,value] = attribString.split('=')
403
572
  if(value !== undefined && name !== '') {
404
573
  value = value.trim().replace(/^\"/,'').replace(/\"$/m,'')
405
-
406
574
  let eventIndex = value.match(/(?<=\{\{\{\{event\s)(\d*)?/)
407
- if(eventIndex !== null) value = this.events[eventIndex[0]]
408
-
575
+ if(eventIndex !== null) {
576
+ value = this.events[eventIndex[0]]
577
+ text = tagString.replace(`{{{{event ${eventIndex[0]}`,value)
578
+ }
409
579
  if(name == 'class') classList = value.split(/\s\s?\s?/)
410
580
  else if(name == 'style') style = this.parseInlineCss(value)
411
581
  else if(name == 'id') id = value
412
582
  attribs[name] = value
413
583
  } else if(name !== '') attribs[name] = undefined
414
584
  });
415
- return {classList,attribs,style,id}
585
+ return {classList,attribs,style,id,text}
416
586
  }
417
587
 
418
588
  parseInlineCss(textCss) {
@@ -432,131 +602,191 @@ class HtmlParser {
432
602
  }
433
603
  }
434
604
 
435
-
436
- class HtmlSelector {
605
+ class Document extends HtmlSelector {
437
606
  constructor(html) {
438
- if(typeof html == 'string') {
439
- html = new HtmlParser(html)
440
- this.html = html
441
- this.elements = html.elements
442
- this.makeSelectable()
443
- } else console.log('Parameter is not string')
607
+ super(html)
608
+ this.elements.forEach((element) => {this.addMethods(element)});
444
609
  }
445
-
446
- makeSelectable() {
447
- this.elements.forEach(element => {
448
- if(element.type == 'tag' && element.status !== 'close') {
449
- element.$$ = (query) => this.$$(query,element.index,element.endIndex)
450
- element.$ = (query) => this.$(query,element.index,element.endIndex)
451
- }
452
- })
610
+
611
+ addMethods(element) {
612
+ if(element.type == 'tag' && element.status !== 'close') {
613
+ this.insert(element)
614
+ this.buildAttribs(element)
615
+ this.classlistMethods(element)
616
+ this.style(element)
617
+ this.id(element)
618
+ }
453
619
  }
454
620
 
455
- $(query,start=0,end=this.elements.length) {
456
- return this.$$(query,start,end,true)
621
+ id(element,self=this) {
622
+ if(element.id !== undefined)
623
+ if(!!Object.getOwnPropertyDescriptor(element, 'id')['get']) return
624
+ if(element.id == null || element.id !== undefined) {
625
+ if(typeof element.id == 'string') delete element.id
626
+ Object.defineProperty(element, 'id', {
627
+ get() {return this.attribs.id ? this.attribs.id : null},
628
+ set(value) {
629
+ this.attribs.id = value
630
+ self.changeElementText(this)
631
+ }
632
+ })
633
+ }
457
634
  }
458
635
 
459
- $$(query,start=0,end=this.elements.length,single=false) {
460
- let result = []
461
- this.selectors = new Query(query).selectors
462
- this.query = query
463
- this.selectors.forEach(selector => {
464
- for(let i=start; i<end; i++) {
465
- let el = this.elements[i]
466
- if(this.checkElement(el,selector) && !result.includes(el)) result.push(el)
467
- if(single && result.length == 1) break
636
+ style(element,obj={},self=this) {
637
+ if(element.style !== undefined) obj = {...element.style}
638
+ const convertProp = str => str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);
639
+ const handler = {
640
+ get(target,prop,receiver) {
641
+ if(prop === 'target') return target
642
+ return Reflect.get(...arguments);
643
+ },
644
+ set(obj, prop, value) {
645
+ obj[prop] = value
646
+ element.attribs.style = Object.keys(obj).map(key => `${convertProp(key)}:${obj[key]};`).join('')
647
+ self.changeElementText(this)
648
+ },
649
+ deleteProperty(obj, prop) {
650
+ if (prop in obj) {
651
+ delete obj[prop];
652
+ element.attribs.style = Object.keys(obj).map(key => `${convertProp(key)}:${obj[key]};`).join('')
653
+ }
654
+ self.changeElementText(this)
468
655
  }
469
- });
470
- if(single && result.length == 1) return result[0]
471
- else if(single && result.length == 0) return null
472
- else return result
656
+ };
657
+ element.style = new Proxy(obj, handler);
473
658
  }
474
659
 
475
- checkElement(el,selector) {
476
- if(selector == undefined) return true
477
- if(el == null) return false
478
- let {tag,classList,attribs,id,prev,ancestors,parents,prevAny} = selector
479
-
480
- if(el.status == 'close' || el.type == 'text') return false
481
- if(id !== undefined && el.id == undefined) return false
482
- if(id && id !== el.id) return false
483
- if(tag && el.tag == undefined) return false
484
- else if(tag && tag !== el.tag) return false
485
- if(classList !== undefined && el.classList == undefined) return false
486
- else if(classList !== undefined && Array.isArray(el.classList)) {
487
- if(classList.every(e => el.classList.includes(e)) == false) return false
660
+ classlistMethods(element,self=this) {
661
+ if(element.classList == undefined) element.classList = []
662
+ element.classList.add = function(newClass) {
663
+ if(element.attribs.class == undefined) element.attribs.class = ''
664
+ this.push(newClass)
665
+ element.attribs.class += ' '+newClass
666
+ self.changeElementText(this)
488
667
  }
489
- if(this.checkAttribs(attribs,el) == false) return false
490
- if(this.checkElement(el.prev,prev) == false) return false
491
- if(this.checkAncestors(el.ancestors,ancestors) == false) return false
492
- if(this.checkParents(el.ancestors,parents) == false) return false
493
- if(el.parent) {
494
- if(this.prevAny(el.parent.children,el.childIndex,prevAny) == false) return false
668
+ element.classList.remove = function(clsToRemove) {
669
+ this.splice(this.indexOf(clsToRemove),1)
670
+ element.attribs.class = this.filter(c => c !== undefined).join(' ')
671
+ self.changeElementText(this)
495
672
  }
496
- return true
497
- }
498
-
499
- prevAny(children=[],index,prevAny) {
500
- let size = children.length
501
- if((size == 0 || index == 0) && prevAny) return false
502
- for(let i=index; i>=0; i--) {
503
- if(this.checkElement(children[i],prevAny)) return true
673
+ element.classList.toggle = function(clsToToggle) {
674
+ if(this.includes(clsToToggle)) this.remove(clsToToggle)
675
+ else this.add(clsToToggle)
676
+ self.changeElementText(this)
504
677
  }
505
- return false
506
678
  }
507
679
 
508
- checkAncestors(ancestors=[],selectorAncestors=[]) {
509
- let count = 0
510
- if(selectorAncestors.length == 0) return true
511
- let endIndex = ancestors.length-1
512
- let selectorIndex = selectorAncestors.length-1
513
- while(selectorIndex>=0) {
514
- for(let i=endIndex; i>=0; i--) {
515
- endIndex=i-1
516
- if(this.checkElement(ancestors[i],selectorAncestors[selectorIndex]) == true) {
517
- count++
518
- break
680
+ buildAttribs(element,self=this) {
681
+ if(!element.attr) element.attr = function(name,value) {
682
+ let notForRemove = ['class','style','id']
683
+ let notForChange = ['style','id']
684
+ if(name && value === undefined) return this.attribs[name]
685
+ else if(name && value === null && !notForRemove.includes(name)) {
686
+ delete this.attribs[name]
687
+ } else if(name && value !== undefined && value !== null && !notForChange.includes(name)) {
688
+ this.attribs[name] = value
689
+ if(name == 'class') {
690
+ this.classList = value.split(' ').filter(c => c !== ' ')
691
+ self.classlistMethods(this)
519
692
  }
520
693
  }
521
- selectorIndex--
694
+ self.changeElementText(this)
522
695
  }
523
- if(count == selectorAncestors.length) return true
524
- else return false
525
696
  }
526
697
 
527
- checkParents(ancestors=[],selectorParents=[]) {
528
- if(selectorParents.length == 0) return true
529
- if(ancestors.length < selectorParents.length) return false
530
- let index = ancestors.length-1
531
- for(let i=selectorParents.length-1; i>=0; i--) {
532
- if(this.checkElement(ancestors[index],selectorParents[i]) == false) return false
533
- index--
698
+ insert(element) {
699
+ let self = this
700
+ element.insert = function(newElement,pos=0) {
701
+ let elements
702
+ let $elements = this.$elements
703
+ if(typeof newElement == 'string') {
704
+ newElement = new HtmlParser(newElement)
705
+ newElement.elements.forEach(el => {
706
+ self.html.getElements(el)
707
+ self.makeSelectable(el);
708
+ self.addMethods(el);
709
+ });
710
+ elements = newElement.elements
711
+ newElement = newElement.root.children[0]
712
+ } else {
713
+ let {index,endIndex} = newElement
714
+ let count = isNaN(endIndex - index) ? 1 : endIndex - index+1
715
+ elements = $elements.splice(index,count)
716
+ let {parent,childIndex} = newElement
717
+ parent.children.splice(childIndex,1)
718
+ }
719
+ self.rebildElements($elements)
720
+ self.addElement(this,$elements,newElement,elements,pos)
534
721
  }
535
- return true
722
+ element.remove = function() {
723
+ let {$elements,elements,parent,childIndex,index} = this
724
+ $elements.splice(index,elements.length)
725
+ parent.children.splice(childIndex,1)
726
+ parent.endIndex = parent.endIndex-elements.length
727
+ self.rebildElements($elements)
728
+ }
729
+ Object.defineProperty(element, 'before', { set(newEl) {this.insert(newEl,0)}})
730
+ Object.defineProperty(element, 'after', { set(newEl) {this.insert(newEl,3)}})
731
+ Object.defineProperty(element, 'last', { set(newEl) {this.insert(newEl,2)}})
732
+ Object.defineProperty(element, 'first', { set(newEl) {this.insert(newEl,1)}})
733
+ }
734
+
735
+ addElement(element,$elements,newElement,elements,pos) {
736
+ let {parent,level,index,endIndex} = element
737
+ if(pos == 0) { // beforebegin
738
+ $elements.splice(index,0,...elements) // add elements to $elements
739
+ parent.children.splice(element.childIndex,0,newElement) // add as child before
740
+ } else if(pos == 3) { // afterend
741
+ $elements.splice(endIndex+1,0,...elements) // add elements to $elements
742
+ parent.children.splice(element.childIndex+1,0,newElement) // add element as child after
743
+ } else if(pos == 1 || pos == 2) {
744
+ level = level+1
745
+ parent = element
746
+ if(pos == 1) { // afterbegin
747
+ $elements.splice(index+1,0,...elements) // add elements to $elements
748
+ element.children.unshift(newElement) // add element as first child
749
+ } else if(pos == 2) { // beforeend
750
+ $elements.splice(endIndex-1,0,...elements) // add elements to $elements
751
+ element.children.push(newElement) // add element as last child
752
+ }
753
+ element.endIndex = element.endIndex + elements.length
754
+ }
755
+ this.rebildElements($elements)
756
+ this.rebuildChild(elements[0],parent,element.html,level)
536
757
  }
537
758
 
538
- checkAttribs(attribs=[],el) {
539
- let elAttribs = el.attribs
540
- let names = Object.keys(elAttribs)
541
- let passedTests = 0
542
- if(attribs) for(let i=0; i<attribs.length; i++) {
543
- let {name,value,check} = attribs[i]
544
- if(name == 'inner' && value !== undefined && check && el.innerText) {
545
- if(check(el.innerText)) passedTests++
759
+ rebildElements($elements) {
760
+ for(let i=0; i<$elements.length; i++) {
761
+ let {endIndex,index} = $elements[i]
762
+ if(endIndex) {
763
+ let gap = endIndex - index
764
+ $elements[i].endIndex = i + gap
546
765
  }
547
-
548
- if(!names.includes(name)) continue
549
- else if(value == undefined) passedTests++
550
- else if(value && elAttribs[name]) {
551
- if(check(elAttribs[name]) == false) continue
552
- else passedTests++
553
- }
766
+ $elements[i].index = i
554
767
  }
555
- if(passedTests == attribs.length) return true
556
- else return false
557
768
  }
558
- }
559
769
 
560
-
561
-
562
- try {module.exports = {HtmlSelector,Query,HtmlParser}} catch{}
770
+ rebuildChild(child,parent,html,level) {
771
+ if(child.endIndex !== undefined) { // add level to close tag
772
+ child.elements[child.elements.length-1].level = level
773
+ }
774
+ html.getElements(child,html) // bind element to this.$elements
775
+ child.parent = parent
776
+ child.level = level
777
+ if(child.children)
778
+ if(child.children.length > 0)
779
+ child.children.forEach(grandChild => {
780
+ this.rebuildChild(grandChild,child,html,level+1)
781
+ });
782
+ }
783
+
784
+ changeElementText(element) {
785
+ let {type,status,attribs,tag} = element
786
+ if(type == 'tag' && status !== 'close') {
787
+ let atts = Object.keys(attribs)
788
+ atts = atts.length>0 ? ' '+atts.map(name => `${name}${attribs[name] ? `="${attribs[name]}"`: ''}`).join(' ') : ''
789
+ element.text = `<${tag}${atts}>`
790
+ }
791
+ }
792
+ }