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.
- package/document/document.js +192 -0
- package/document/test.js +678 -0
- package/document.js +375 -145
- package/document.min.js +1 -0
- package/index.js +6 -0
- package/package.json +3 -3
- package/parser/parser.js +92 -43
- package/parser/test.js +7 -7
- package/query/query.js +1 -1
- package/query/readme.md +4 -1
- package/readme.md +253 -59
- package/selector/selector.js +14 -13
- package/test/test.js +3 -1
- package/parser/readme.md +0 -121
- package/selector/readme.md +0 -74
package/document.min.js
ADDED
|
@@ -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
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "als-document",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "
|
|
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(
|
|
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(/<[
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
194
|
-
Object.defineProperty(element, '
|
|
195
|
-
return
|
|
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
|
-
|
|
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,
|
|
269
|
+
let {level,text} = element
|
|
222
270
|
if(firstLevel == undefined) firstLevel = level
|
|
223
|
-
if(i ==
|
|
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 +=
|
|
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(
|
|
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)
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
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="
|
|
12
|
+
<script src="node_modules/als-document/document.min.js"></script>
|
|
10
13
|
```
|
|
11
14
|
|
|
12
15
|
Backend:
|