als-document 0.5.1 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ class HtmlSelector{constructor(e){"string"==typeof e?(this.html=new HtmlParser(e),this.elements.forEach((e,t)=>{this.makeSelectable(e)})):console.log("Parameter is not string")}get elements(){return this.html.elements}makeSelectable(e){"tag"==e.type&&"close"!==e.status&&(e.$$=t=>this.$$(t,e.index,e.endIndex),e.$=t=>this.$(t,e.index,e.endIndex))}$(e,t=0,s=this.elements.length){return this.$$(e,t,s,!0)}$$(e,t=0,s=this.elements.length,i=!1){let l=[];return(this.selectors=new Query(e).selectors,this.query=e,this.selectors.forEach(e=>{for(let r=t;r<s;r++){let n=this.elements[r];if(this.checkElement(n,e)&&!l.includes(n)&&l.push(n),i&&1==l.length)break}}),i&&1==l.length)?l[0]:i&&0==l.length?null:l}checkElement(e,t){if(void 0==t)return!0;if(null==e)return!1;let{tag:s,classList:i,attribs:l,id:r,prev:n,ancestors:h,parents:a,prevAny:c}=t;return"close"!=e.status&&"text"!=e.type&&(void 0===r||void 0!=e.id)&&(!r||r===e.id)&&(!s||void 0!=e.tag)&&(!s||s===e.tag)&&(void 0===i||void 0!=e.classList)&&(!(void 0!==i&&Array.isArray(e.classList))||!1!=i.every(t=>e.classList.includes(t)))&&!1!=this.checkAttribs(l,e)&&!1!=this.checkElement(e.prev,n)&&!1!=this.checkAncestors(e.ancestors,h)&&!1!=this.checkParents(e.ancestors,a)&&(!e.parent||!1!=this.prevAny(e.parent.children,e.childIndex,c))}prevAny(e=[],t,s){if((0==e.length||0==t)&&s)return!1;for(let i=t;i>=0;i--)if(this.checkElement(e[i],s))return!0;return!1}checkAncestors(e=[],t=[]){let s=0;if(0==t.length)return!0;let i=e.length-1,l=t.length-1;for(;l>=0;){for(let r=i;r>=0;r--)if(i=r-1,!0==this.checkElement(e[r],t[l])){s++;break}l--}return s==t.length}checkParents(e=[],t=[]){if(0==t.length)return!0;if(e.length<t.length)return!1;let s=e.length-1;for(let i=t.length-1;i>=0;i--){if(!1==this.checkElement(e[s],t[i]))return!1;s--}return!0}checkAttribs(e=[],t){let s=t.attribs,i=Object.keys(s),l=0;if(e)for(let r=0;r<e.length;r++){let{name:n,value:h,check:a}=e[r];if("inner"==n&&void 0!==h&&a&&t.innerText&&a(t.innerText)&&l++,i.includes(n)){if(void 0==h)l++;else if(h&&s[n]){if(!1==a(s[n]))continue;l++}}}return l==e.length}}class Query{static get(e){return new Query(e).selectors}constructor(e){this.query=e,this.selectors=[],this.getQueries(e.split(","))}getQueries(e){e.forEach(e=>{let t=e;e=this.removeSpaces(e),this.stringValues=[],e=e.replace(/\[.*?\]/g,e=>(this.stringValues.push(e),`[${this.stringValues.length-1}]`));let[s,i]=this.splitAndCutLast(e," ");s=this.getFamily(s),i.length>0&&(s.ancestors=i.map(e=>this.getFamily(e))),s.group=t,this.selectors.push(s)})}splitAndCutLast(e,t){let s=e.split(t),i;return 1==s.length?(i=s[0],s=[]):i=s.splice(s.length-1,s.length-1)[0],[i,s]}getFamily(e,t,s,i,l){if(null!==e.match(/\~|\+/)){let[r,n]=this.splitAndCutLast(e,/\~|\+/),h=e.replace(r,"");n.forEach(e=>h=h.replace(e,"")),1==(h=h.match(/\~|\+/g)).length?l=h[0]:h.length>1&&(l=h.splice(h.length-1,h.length-1)[0],n[0]=n.map((e,t)=>(t<n.length-1&&(e+=h[t]),e)).join(""),n[0]=this.getFamily(n[0])),"~"==l?i=n[0]:"+"==l&&(s=n[0]),t=r}else t=e;let a;return s||i?(a=this.getParents(t),s&&(a.prev=this.getParents(s)),i&&(a.prevAny=this.getParents(i))):a=this.getParents(t),a.query!==e&&(a.group=e),a}getParents(e){if("string"!=typeof e)return e;{let[t,s]=this.splitAndCutLast(e,">");return t=this.buildElement(t),(s=s.map(e=>this.buildElement(e))).length>0&&(t.parents=s),t}}buildElement(e,t=null,s=null,i=[]){let l=e;e=(e=(e=e.replace(/\#(\w-?)*/,e=>(t=e.replace(/^\#/,""),""))).replace(/\.(\w-?)*/,e=>(i.push(e.replace(/^\./,"")),""))).replace(/(\w-?)*/,e=>(s=""==e?null:e,""));let r=this.getAttributes(e);return e={query:l},t&&(e.id=t),s&&(e.tag=s),i.length>0&&(e.classList=i),r.length>0&&(e.attribs=r),e}getAttributes(e){let t=this.stringValues.filter((t,s)=>{let i=`[${s}]`;return!!e.match(i)});return t.map(e=>{let t=e,[s,i]=(e=e.replace("[","").replace("]","")).split(/[\~\|\^\$\*]?\=/),l=e.replace(s,"").replace(i,"");return e={query:t},s&&(e.name=s),i&&(e.value=i.trim().replace(/^\"/,"").replace(/\"$/,"")),l&&(e.sign=l,e.check=this.getAttribFn(l).bind(e)),e})}getAttribFn(e){return"="==e?function(e){return e==this.value}:"*="==e?function(e){return!!e.includes(this.value)}:"^="==e?function(e){return!!e.startsWith(this.value)}:"$="==e?function(e){return!!e.endsWith(this.value)}:"|="==e?function(e){return!!(1==e.trim().split(" ").length&&(e.startsWith(this.value)||e.startsWith(this.value+"-")))}:"~="==e?function(e){return!!(1==this.value.trim().split(" ").length&&e.includes(this.value))}:void 0}removeSpaces(e){return e=(e=(e=e.replace(/\s{2}/g," ")).replace(/\s?\^?\$?\|?\~?\*?\=\s*/g,e=>e.trim())).replace(/\s?(\+|\~|\>)\s?/g,e=>e.trim())}}class HtmlParser{static parse(e){return new HtmlParser(e).root}constructor(e=""){this.checkHtml(e)&&(this.indexes=[],this.events=[],this.html=this.htmlString=e,this.htmlString=this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,""),this.removeScripts(),this.removeStyles(),this.removeEventStrings(),this.root=this.parse(),this.clean())}clean(){["events","indexes","scripts","styles","htmlString","html"].forEach(e=>{delete this[e]})}checkHtml(e,t=!1){return""==e?console.log("html parameter is empty"):"string"!=typeof e?console.log(`html parameter has to be string. Recieved ${typeof e}`):t=!0,t}removeScripts(e=[]){let t=this.htmlString.match(/\<script(.*?)\>[\S\s]*?\<\/script\>/gm);null!==t&&t.forEach((t,s)=>{let i=t.replace(/^\<script(.*?)\>/,"").replace(/\<\/script\>$/,"");e.push(i),this.htmlString=this.htmlString.replace(i,`{{{{script ${e.length-1}`)}),this.scripts=e}removeStyles(e=[]){let t=this.htmlString.match(/\<style\>[\S\s]*?\<\/style\>/gm);null!==t&&t.forEach((t,s)=>{let i=t.replace(/^\<style\>/,"").replace(/\<\/style\>$/,"");e.push(i),this.htmlString=this.htmlString.replace(i,`{{{{style ${e.length-1}`)}),this.styles=e}removeEventStrings(){let e=this.htmlString.match(/\son\w*\s*?\=\s*?\"(.*?)\"/g);null!==e&&e.forEach(e=>{let t=e.split("=").filter((e,t)=>t>0&&""!==t).join("=");t=t.replace(/^\"/,"").replace(/\"$/,""),this.events.push(t);let s=e.replace(t,`{{{{event ${this.events.length-1}`);this.htmlString=this.htmlString.replace(e,s)})}parse(e=this.htmlString){let t=e.match(/<("[^"]*"|'[^']*'|[^'">])*>/g);t.forEach((s,i)=>{t[i]=this.parseElement(s),e=e.replace(s,`<tag${i}>`)});let s=e.match(/tag[\s\S]*?\</g);for(let i=s.length-1;i>=0;i--){let l=s[i],r=l.match(/(\d*)\>/)[1];(l=l.replace(/tag.*\>/,"").slice(0,-1).trim()).length>0&&t.splice(parseInt(r)+1,0,l)}this.elements=t;let n=this.getPairs();return n.level=0,n.elements=this.elements,this.innerHTML(n),n}lookForPair(e,t,s,i){e.parent=s,e.children=[];let{tag:l}=e,r=0,n;for(let h=t+1;h<this.elements.length;h++){let a=this.elements[h];if(a.tag==l){if("close"==a.status){if(0==r){n=h,a.level=i;break}r--}else"open"==a.status&&r++}}return n||(n=t+1),e.endIndex=n,this.getPairs(e,t+1,n,i+1)}getPairs(e={type:"root",children:[]},t=0,s=this.elements.length,i=0,l=0){for(let r=t;r<s;r++){if(this.indexes.includes(r))continue;let n=this.elements[r],h;"string"==typeof n?h=n:"tag"==n.type&&("single"==n.status?(h=n).parent=e:"open"==n.status?h=this.lookForPair(n,r,e,i):n.index=r),this.addChild(e,h,r,i),l++}return e}addScriptsAndStyles(e,t,s){if("script"==e.tag){let i=t.match(/(?<=\{\{\{\{script\s)(\d*)?/);if(null!==i){let l=parseInt(i[0]);"number"==typeof l&&(t=this.scripts[l])}}if("style"==e.tag){let r=t.match(/(?<=\{\{\{\{style\s)(\d*)?/);if(null!==r){let n=parseInt(r[0]);"number"==typeof n&&(t=this.styles[n])}}return this.elements[s]=t,t}addChild(e,t,s,i){"string"==typeof t&&(t={type:"text",text:t=this.addScriptsAndStyles(e,t,s),parent:e},this.elements[s]=t),t&&(delete t.status,"text"!==t.type&&(this.innerHTML(t),this.outerHTML(t),this.innerText(t)),this.getElements(t),this.getAncestors(t),this.getAttribute(t),this.nextAndPrev(t),t.index=s,t.level=i,e.children.push(t)),this.indexes.push(s)}getAttribute(e){e.getAttribute=function(e){let t=Object.keys(this.attribs).filter(t=>t==e);return t.length>0?this.attribs[t[0]]:null}}getAncestors(e){Object.defineProperty(e,"ancestors",{get(){let e=[],t=this.parent;if(t)for(;t.parent;)e.unshift(t),t=t.parent;return e}})}nextAndPrev(e){Object.defineProperty(e,"childIndex",{get(){return this.parent.children.map(e=>e.index).indexOf(this.index)}}),Object.defineProperty(e,"prev",{get(){let e=this.childIndex,t=this.parent.children;return 0==e?null:t[e-1]}}),Object.defineProperty(e,"next",{get(){let e=this.childIndex,t=this.parent.children;return e==t.length-1?null:t[e+1]}})}getElements(e,t=this){"text"!==e.type&&Object.defineProperty(e,"elements",{configurable:!0,get(){let e=isNaN(this.endIndex)?this.index+1:this.endIndex+1;return t.elements.slice(this.index,e)}}),Object.defineProperty(e,"$elements",{configurable:!0,get:()=>t.elements}),Object.defineProperty(e,"root",{configurable:!0,get:()=>t.root}),Object.defineProperty(e,"html",{configurable:!0,get:()=>t})}outerHTML(e){Object.defineProperty(e,"outerHTML",{get(){let{elements:e}=this;return e[0].text+this.innerHTML+e[e.length-1].text}})}innerText(e){Object.defineProperty(e,"innerText",{get:()=>e.children?e.children.map(e=>"text"==e.type?e.text:"").join(""):""})}innerHTML(e){e.tab=" ",e.n="\n",Object.defineProperty(e,"innerHTML",{get(){let{tab:e,n:t}=this,s="",i,l="",{elements:r}=this,n=r.length,h=n-1,a=1;"root"==this.type&&(h=n,a=0);for(let c=a;c<h;c++){let{level:d,text:o}=r[c];void 0==i&&(i=d),c==h?l="":d&&(l=Array.from(Array(d-i).keys()).map(t=>e).join("")),s+=l+o,n>3&&(s+=t)}return s}})}parseElement(e){if("<!DOCTYPE html>"==e)return{tag:"!DOCTYPE html",status:"single",attribs:{},type:"tag",text:e};let t="close",s=e.match(/(?<=\<\/)(\w*\-?)*/);null==s?(s=e.match(/(?<=\<)(\w*\-?)*/))&&(s=s[0],t=HtmlParser.singleTags.includes(s)?"single":"open"):s=s[0];let{classList:i,attribs:l,style:r,id:n,text:h}=this.parseAttributes(e);return{tag:s,status:t,attribs:l,type:"tag",classList:i,text:h,style:r,id:n}}static singleTags=["comment","area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"];parseAttributes(e,t=[],s={},i={},l=null){let r=e,n=e.match(/(?<=\s)(\w*\-?)*(\s*?\=\s*?\"[\s\S]*?\")?/g);return n&&n.forEach(n=>{let[h,a]=n.split("=");if(void 0!==a&&""!==h){let c=(a=a.trim().replace(/^\"/,"").replace(/\"$/m,"")).match(/(?<=\{\{\{\{event\s)(\d*)?/);null!==c&&(a=this.events[c[0]],r=e.replace(`{{{{event ${c[0]}`,a)),"class"==h?t=a.split(/\s\s?\s?/):"style"==h?i=this.parseInlineCss(a):"id"==h&&(l=a),s[h]=a}else""!==h&&(s[h]=void 0)}),{classList:t,attribs:s,style:i,id:l,text:r}}parseInlineCss(e){let t=e.split(";"),s={};return t.forEach(e=>{let[t,i]=e.trim().split(":");""!==e&&(null!==t.match(/\w*\-\w*(-\w*)?/)&&(t=t.split("-").map((e,t)=>0==t?e:e[0].toUpperCase()+e.slice(1)).join("")),s[t]=i.trim())}),s}}class Document extends HtmlSelector{constructor(e){super(e),this.elements.forEach(e=>{this.addMethods(e)})}addMethods(e){"tag"==e.type&&"close"!==e.status&&(this.insert(e),this.buildAttribs(e),this.classlistMethods(e),this.style(e),this.id(e))}id(e,t=this){(void 0===e.id||!Object.getOwnPropertyDescriptor(e,"id").get)&&(null==e.id||void 0!==e.id)&&("string"==typeof e.id&&delete e.id,Object.defineProperty(e,"id",{get(){return this.attribs.id?this.attribs.id:null},set(e){this.attribs.id=e,t.changeElementText(this)}}))}style(e,t={},s=this){void 0!==e.style&&(t={...e.style});let i=e=>e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`);e.style=new Proxy(t,{get(e,t,s){return"target"===t?e:Reflect.get(...arguments)},set(t,l,r){t[l]=r,e.attribs.style=Object.keys(t).map(e=>`${i(e)}:${t[e]};`).join(""),s.changeElementText(this)},deleteProperty(t,l){l in t&&(delete t[l],e.attribs.style=Object.keys(t).map(e=>`${i(e)}:${t[e]};`).join("")),s.changeElementText(this)}})}classlistMethods(e,t=this){void 0==e.classList&&(e.classList=[]),e.classList.add=function(s){void 0==e.attribs.class&&(e.attribs.class=""),this.push(s),e.attribs.class+=" "+s,t.changeElementText(this)},e.classList.remove=function(s){this.splice(this.indexOf(s),1),e.attribs.class=this.filter(e=>void 0!==e).join(" "),t.changeElementText(this)},e.classList.toggle=function(e){this.includes(e)?this.remove(e):this.add(e),t.changeElementText(this)}}buildAttribs(e,t=this){e.attr||(e.attr=function(e,s){if(e&&void 0===s)return this.attribs[e];e&&null===s&&!["class","style","id"].includes(e)?delete this.attribs[e]:e&&null!=s&&!["style","id"].includes(e)&&(this.attribs[e]=s,"class"==e&&(this.classList=s.split(" ").filter(e=>" "!==e),t.classlistMethods(this))),t.changeElementText(this)})}insert(e){let t=this;e.insert=function(e,s=0){let i,l=this.$elements;if("string"==typeof e)(e=new HtmlParser(e)).elements.forEach(e=>{t.html.getElements(e),t.makeSelectable(e),t.addMethods(e)}),i=e.elements,e=e.root.children[0];else{let{index:r,endIndex:n}=e,h=isNaN(n-r)?1:n-r+1;i=l.splice(r,h);let{parent:a,childIndex:c}=e;a.children.splice(c,1)}t.rebildElements(l),t.addElement(this,l,e,i,s)},e.remove=function(){let{$elements:e,elements:s,parent:i,childIndex:l,index:r}=this;e.splice(r,s.length),i.children.splice(l,1),i.endIndex=i.endIndex-s.length,t.rebildElements(e)},Object.defineProperty(e,"before",{set(e){this.insert(e,0)}}),Object.defineProperty(e,"after",{set(e){this.insert(e,3)}}),Object.defineProperty(e,"last",{set(e){this.insert(e,2)}}),Object.defineProperty(e,"first",{set(e){this.insert(e,1)}})}addElement(e,t,s,i,l){let{parent:r,level:n,index:h,endIndex:a}=e;0==l?(t.splice(h,0,...i),r.children.splice(e.childIndex,0,s)):3==l?(t.splice(a+1,0,...i),r.children.splice(e.childIndex+1,0,s)):(1==l||2==l)&&(n+=1,r=e,1==l?(t.splice(h+1,0,...i),e.children.unshift(s)):2==l&&(t.splice(a-1,0,...i),e.children.push(s)),e.endIndex=e.endIndex+i.length),this.rebildElements(t),this.rebuildChild(i[0],r,e.html,n)}rebildElements(e){for(let t=0;t<e.length;t++){let{endIndex:s,index:i}=e[t];if(s){let l=s-i;e[t].endIndex=t+l}e[t].index=t}}rebuildChild(e,t,s,i){void 0!==e.endIndex&&(e.elements[e.elements.length-1].level=i),s.getElements(e,s),e.parent=t,e.level=i,e.children&&e.children.length>0&&e.children.forEach(t=>{this.rebuildChild(t,e,s,i+1)})}changeElementText(e){let{type:t,status:s,attribs:i,tag:l}=e;if("tag"==t&&"close"!==s){let r=Object.keys(i);r=r.length>0?" "+r.map(e=>`${e}${i[e]?`="${i[e]}"`:""}`).join(" "):"",e.text=`<${l}${r}>`}}}
package/index.js ADDED
@@ -0,0 +1,6 @@
1
+ let HtmlSelector = require('./selector/selector')
2
+ let HtmlParser = require('./parser/parser')
3
+ let Query = require('./query/query')
4
+ let Document = require('./document/document')
5
+
6
+ module.exports = {HtmlSelector,HtmlParser,Query,Document}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "als-document",
3
- "version": "0.5.1",
4
- "description": "",
5
- "main": "document.js",
3
+ "version": "0.6.1",
4
+ "description": "Build virtual dom from string and manage it, similar you do it on browser",
5
+ "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "node test/test.js"
8
8
  },
package/parser/parser.js CHANGED
@@ -8,14 +8,22 @@ class HtmlParser {
8
8
  this.indexes = []
9
9
  this.events = []
10
10
  this.html = this.htmlString = html
11
+ this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
11
12
  this.removeScripts()
12
13
  this.removeStyles()
13
14
  this.removeEventStrings()
14
- this.htmlString = this.htmlString.replace(/\<\!\-\-([\S\s]*?)\-\-\>/gm,'') // remove all comments
15
15
  this.root = this.parse()
16
+ this.clean()
16
17
  }
17
18
  }
18
19
 
20
+ clean() {
21
+ let toDelete = ['events','indexes','scripts','styles','htmlString','html']
22
+ toDelete.forEach(name => {
23
+ delete this[name]
24
+ });
25
+ }
26
+
19
27
  checkHtml(html,isGood=false) {
20
28
  if(html == '') console.log('html parameter is empty')
21
29
  else if(typeof html !== 'string') console.log(`html parameter has to be string. Recieved ${typeof html}`)
@@ -41,9 +49,9 @@ class HtmlParser {
41
49
  });
42
50
  this.styles = styles
43
51
  }
44
-
52
+
45
53
  removeEventStrings() {
46
- let eventsWithHtml = this.htmlString.match(/on\w*\s*?\=\s*?["|'|`](.*?(<[^>]*>)(\'|\`).*?)["|'|`]/g)
54
+ let eventsWithHtml = this.htmlString.match(/\son\w*\s*?\=\s*?\"(.*?)\"/g)
47
55
  if(eventsWithHtml !== null) {
48
56
  eventsWithHtml.forEach(event => {
49
57
  let array = event.split('=')
@@ -58,7 +66,7 @@ class HtmlParser {
58
66
 
59
67
  parse(htmlString=this.htmlString) {
60
68
  // Parse tags
61
- let elements = htmlString.match(/<[^>]*>/g)
69
+ let elements = htmlString.match(/<("[^"]*"|'[^']*'|[^'">])*>/g)
62
70
  elements.forEach((tag,index) => {
63
71
  elements[index] = this.parseElement(tag)
64
72
  htmlString = htmlString.replace(tag,`<tag${index}>`)
@@ -75,6 +83,9 @@ class HtmlParser {
75
83
  }
76
84
  this.elements = elements
77
85
  let root = this.getPairs()
86
+ root.level = 0
87
+ root.elements = this.elements
88
+ this.innerHTML(root)
78
89
  return root
79
90
  }
80
91
 
@@ -105,19 +116,18 @@ class HtmlParser {
105
116
  getPairs(parent={type:'root',children:[]},startIndex = 0,endIndex=this.elements.length,level=0,childIndex=0) {
106
117
  for(let index = startIndex; index < endIndex; index++) {
107
118
  if(this.indexes.includes(index)) continue
108
- const element = this.elements[index];
119
+ let element = this.elements[index];
109
120
  let child
110
121
  if(typeof element == 'string') child = element
111
122
  else if(element.type == 'tag') {
112
123
  if(element.status == 'single') {
113
124
  child = element
114
125
  child.parent = parent
115
- }
116
- else if(element.status == 'open') {
126
+ } else if(element.status == 'open') {
117
127
  child = this.lookForPair(element,index,parent,level)
118
- }
119
- }
120
- this.addChild(parent,child,index,level,childIndex/2)
128
+ } else element.index = index
129
+ }
130
+ this.addChild(parent,child,index,level)
121
131
  childIndex++
122
132
  }
123
133
  return parent
@@ -142,30 +152,25 @@ class HtmlParser {
142
152
  return child
143
153
  }
144
154
 
145
- addChild(parent,child,index,level,childIndex) {
155
+ addChild(parent,child,index,level) {
146
156
  if(typeof child == 'string') {
147
157
  child = this.addScriptsAndStyles(parent,child,index)
148
- child = {type:'text',text:child}
158
+ child = {type:'text',text:child,parent}
149
159
  this.elements[index] = child
150
160
  }
151
161
  if(child) {
152
162
  delete child.status
163
+ if(child.type !== 'text') {
164
+ this.innerHTML(child)
165
+ this.outerHTML(child)
166
+ this.innerText(child)
167
+ }
153
168
  this.getElements(child)
154
- this.innerHTML(child)
155
- this.outerHTML(child)
156
- this.innerText(child)
157
169
  this.getAncestors(child)
158
170
  this.getAttribute(child)
159
- child.childIndex = childIndex
171
+ this.nextAndPrev(child)
160
172
  child.index = index
161
173
  child.level = level
162
- child.prev = null
163
- child.next = null
164
- if(parent.children.length > 0) {
165
- let prevI = parent.children.length-1
166
- parent.children[prevI].next = child
167
- child.prev = parent.children[prevI]
168
- }
169
174
  parent.children.push(child)
170
175
  }
171
176
  this.indexes.push(index)
@@ -190,10 +195,45 @@ class HtmlParser {
190
195
  }});
191
196
  }
192
197
 
193
- getElements(element,elements=this.elements) {
194
- Object.defineProperty(element, 'elements', { get() {
195
- return elements.slice(this.index,this.endIndex+1)
196
- }});
198
+ nextAndPrev(element) {
199
+ Object.defineProperty(element, 'childIndex', {
200
+ get() {return this.parent.children.map(o => o.index).indexOf(this.index)}
201
+ });
202
+ Object.defineProperty(element, 'prev', {
203
+ get() {
204
+ let i = this.childIndex, brothers = this.parent.children
205
+ return i == 0 ? null : brothers[i-1]
206
+ }
207
+ });
208
+ Object.defineProperty(element, 'next', {
209
+ get() {
210
+ let i = this.childIndex, brothers = this.parent.children
211
+ return i == brothers.length-1 ? null : brothers[i+1]
212
+ }
213
+ });
214
+ }
215
+
216
+ getElements(element,self=this) {
217
+ if(element.type !== 'text')
218
+ Object.defineProperty(element, 'elements', {
219
+ configurable:true,
220
+ get() {
221
+ let endIndex = isNaN(this.endIndex) ? this.index + 1 : this.endIndex+1
222
+ return self.elements.slice(this.index,endIndex)
223
+ }
224
+ });
225
+ Object.defineProperty(element, '$elements', {
226
+ configurable:true,
227
+ get() {return self.elements}
228
+ });
229
+ Object.defineProperty(element, 'root', {
230
+ configurable:true,
231
+ get() {return self.root}
232
+ });
233
+ Object.defineProperty(element, 'html', {
234
+ configurable:true,
235
+ get() {return self}
236
+ });
197
237
  }
198
238
 
199
239
  outerHTML(element) {
@@ -210,62 +250,71 @@ class HtmlParser {
210
250
  else return ''
211
251
  }})
212
252
  }
213
-
214
253
  innerHTML(element) {
254
+ element.tab = ' '
255
+ element.n = '\n'
215
256
  Object.defineProperty(element, 'innerHTML', { get() {
216
- let tab = ' ',result = '',firstLevel,space=''
257
+ // let tab = ' ',result = '',firstLevel,space=''
258
+ let {tab,n} = this
259
+ let result = '',firstLevel,space=''
217
260
  let {elements} = this
218
261
  let endIndex = elements.length
219
- for (let i = 1; i < endIndex-1; i++) {
262
+ let end = endIndex-1,start=1
263
+ if(this.type == 'root') {
264
+ end = endIndex
265
+ start = 0
266
+ }
267
+ for(let i = start; i < end; i++) {
220
268
  let element = elements[i]
221
- let {level,tag,text} = element
269
+ let {level,text} = element
222
270
  if(firstLevel == undefined) firstLevel = level
223
- if(i == endIndex-1) space = ''
271
+ if(i == end) space = ''
224
272
  else if(level) space = Array.from(Array(level-firstLevel).keys()).map(n => tab).join('')
225
273
  result += space + text
226
- if(endIndex > 3) result += '\n'
274
+ if(endIndex > 3) result += n
227
275
  }
228
276
  return result
229
277
  }});
230
278
  }
231
279
 
232
280
  parseElement(tagString) {
233
- let text = tagString
234
281
  let type = 'tag'
235
- if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type}
282
+ if(tagString == '<!DOCTYPE html>') return {tag:'!DOCTYPE html',status:'single',attribs:{},type,text:tagString}
236
283
  let status = 'close'
237
284
  let tag = tagString.match(/(?<=\<\/)(\w*\-?)*/)
238
285
  if(tag == null) {
239
286
  tag = tagString.match(/(?<=\<)(\w*\-?)*/)
240
287
  if(tag) {
241
288
  tag = tag[0]
242
- if(this.singleTags.includes(tag)) status='single'
289
+ if(HtmlParser.singleTags.includes(tag)) status='single'
243
290
  else status = 'open'
244
291
  }
245
292
  } else tag = tag[0]
246
- let {classList,attribs,style,id} = this.parseAttributes(tagString)
293
+ let {classList,attribs,style,id,text} = this.parseAttributes(tagString)
247
294
  let obj = {tag,status,attribs,type,classList,text,style,id}
248
295
  return obj
249
296
  }
250
- singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
297
+ static singleTags = ['comment','area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']
251
298
 
252
299
  parseAttributes(tagString,classList=[],attribs={},style={},id=null) {
300
+ let text = tagString
253
301
  let attributes = tagString.match(/(?<=\s)(\w*\-?)*(\s*?\=\s*?\"[\s\S]*?\")?/g)
254
302
  if(attributes) attributes.forEach(attribString => {
255
303
  let [name,value] = attribString.split('=')
256
304
  if(value !== undefined && name !== '') {
257
305
  value = value.trim().replace(/^\"/,'').replace(/\"$/m,'')
258
-
259
306
  let eventIndex = value.match(/(?<=\{\{\{\{event\s)(\d*)?/)
260
- if(eventIndex !== null) value = this.events[eventIndex[0]]
261
-
307
+ if(eventIndex !== null) {
308
+ value = this.events[eventIndex[0]]
309
+ text = tagString.replace(`{{{{event ${eventIndex[0]}`,value)
310
+ }
262
311
  if(name == 'class') classList = value.split(/\s\s?\s?/)
263
312
  else if(name == 'style') style = this.parseInlineCss(value)
264
313
  else if(name == 'id') id = value
265
314
  attribs[name] = value
266
315
  } else if(name !== '') attribs[name] = undefined
267
316
  });
268
- return {classList,attribs,style,id}
317
+ return {classList,attribs,style,id,text}
269
318
  }
270
319
 
271
320
  parseInlineCss(textCss) {
@@ -284,4 +333,4 @@ class HtmlParser {
284
333
  return styles
285
334
  }
286
335
  }
287
- try {module.exports = HtmlParser} catch{}
336
+ try {module.exports = HtmlParser} catch {}
package/parser/test.js CHANGED
@@ -1,7 +1,7 @@
1
1
  let Test = require('als-test')
2
2
  let {equal,greater,smaller,$greater, $smaller,mesureTime} = Test
3
3
  let Parser = require('./parser')
4
- const htmlparser2 = require("htmlparser2");
4
+ // const htmlparser2 = require("htmlparser2");
5
5
 
6
6
  module.exports = new Test('HtmlParser tests',[
7
7
  {
@@ -16,12 +16,12 @@ module.exports = new Test('HtmlParser tests',[
16
16
  }
17
17
  },
18
18
  },
19
- {
20
- title:'Compare to htmlparser2',
21
- expected:mesureTime(function({html2}){htmlparser2.parseDocument(html2);}),
22
- result:mesureTime(function({html2}){Parser.parse(html2)}),
23
- action:greater
24
- },
19
+ // {
20
+ // title:'Compare to htmlparser2',
21
+ // expected:mesureTime(function({html2}){htmlparser2.parseDocument(html2);}),
22
+ // result:mesureTime(function({html2}){Parser.parse(html2)}),
23
+ // action:greater
24
+ // },
25
25
  {
26
26
  title:'Parse html for html2',
27
27
  result:function({html2}){
package/query/query.js CHANGED
@@ -144,4 +144,4 @@ class Query {
144
144
  return selector
145
145
  }
146
146
  }
147
- try {module.exports = Query} catch {}
147
+ module.exports = Query
package/query/readme.md CHANGED
@@ -3,10 +3,13 @@ Query is a class for parsing selectors inside html query. Query not supporting p
3
3
  You can use Query on frontend and on backend.
4
4
 
5
5
  Query can be used on fronten and on backend.
6
+ You can use:
7
+ * node_modules/als-document/document.js - original file
8
+ * node_modules/als-document/document.min.js - minimized file
6
9
 
7
10
  Frontend:
8
11
  ```html
9
- <script src="/node_modules/als-document/query/query.js"></script>
12
+ <script src="node_modules/als-document/document.min.js"></script>
10
13
  ```
11
14
 
12
15
  Backend: