als-document 0.6.11 → 0.7.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/query/query.js DELETED
@@ -1,147 +0,0 @@
1
- class Query {
2
- static get(query) {
3
- let q = new Query(query)
4
- return q.selectors
5
- }
6
-
7
- constructor(query) {
8
- this.query = query
9
- this.selectors = []
10
- this.getQueries(query.split(','))
11
- }
12
-
13
- getQueries(selectors) {
14
- selectors.forEach(selector => {
15
- let originalSelector = selector
16
- selector = this.removeSpaces(selector)
17
- this.stringValues = []
18
- selector = selector.replace(/\[.*?\]/g,(value) => {
19
- this.stringValues.push(value)
20
- return `[${this.stringValues.length-1}]`
21
- })
22
- let [element,ancestors] = this.splitAndCutLast(selector,' ') // \s - ancestor
23
- element = this.getFamily(element)
24
- if(ancestors.length > 0)
25
- element.ancestors = ancestors.map(ancestor => this.getFamily(ancestor))
26
- element.group = originalSelector
27
- this.selectors.push(element)
28
- });
29
- }
30
-
31
- splitAndCutLast(string,splitBy) {
32
- let array = string.split(splitBy)
33
- let last
34
- if(array.length == 1) {
35
- last = array[0]
36
- array = []
37
- } else last = array.splice(array.length-1,array.length-1)[0]
38
- return [last,array]
39
- }
40
-
41
- getFamily(group,element,prev,prevAny,sign) {
42
- if(group.match(/\~|\+/) !== null) {
43
- let [last,prevBrothers] = this.splitAndCutLast(group,/\~|\+/)
44
- let signs = group.replace(last,'')
45
- prevBrothers.forEach(el => signs = signs.replace(el,''))
46
- signs = signs.match(/\~|\+/g)
47
- if(signs.length == 1) {
48
- sign = signs[0]
49
- } else if(signs.length > 1){
50
- sign = signs.splice(signs.length-1,signs.length-1)[0]
51
- prevBrothers[0] = prevBrothers.map((b,i) => {
52
- if(i<prevBrothers.length-1) b += signs[i]
53
- return b
54
- }).join('')
55
- prevBrothers[0] = this.getFamily(prevBrothers[0])
56
- }
57
- if(sign == '~') prevAny = prevBrothers[0] // ~ - any prev brother
58
- else if(sign == '+') prev = prevBrothers[0] // + - prev brother
59
- element = last
60
- } else element = group
61
- let family
62
- if(prev || prevAny) {
63
- family = this.getParents(element)
64
- if(prev) family.prev = this.getParents(prev)
65
- if(prevAny) family.prevAny = this.getParents(prevAny)
66
- } else family = this.getParents(element)
67
- if(family.query !== group) family.group = group
68
- return family
69
- }
70
-
71
- getParents(selector) {
72
- if(typeof selector == 'string') {
73
- let [element,parents] = this.splitAndCutLast(selector,'>')
74
- element = this.buildElement(element)
75
- parents = parents.map(parent => this.buildElement(parent))
76
- if(parents.length > 0) element.parents = parents
77
- return element
78
- } else return selector
79
- }
80
-
81
-
82
- buildElement(element,id=null,tag=null,classList=[]) {
83
- let query = element
84
- element = element.replace(/\#(\w-?)*/,$id => {
85
- id = $id.replace(/^\#/,''); return ''
86
- })
87
- element = element.replace(/\.(\w-?)*/,$class => {
88
- classList.push($class.replace(/^\./,'')); return ''
89
- })
90
- element = element.replace(/(\w-?)*/,$tag => {
91
- tag = $tag == '' ? null : $tag; return ''
92
- })
93
- let attribs = this.getAttributes(element)
94
- element = {query}
95
- if(id) element.id = id
96
- if(tag) element.tag = tag
97
- if(classList.length > 0) element.classList = classList
98
- if(attribs.length > 0) element.attribs = attribs
99
- return element
100
- }
101
-
102
- getAttributes(element) {
103
- let attribs = this.stringValues.filter((value,index) => {
104
- let searchValue = `[${index}]`
105
- if(element.match(searchValue)) return true
106
- else return false
107
- })
108
- attribs = attribs.map(attrib => {
109
- let query = attrib
110
- attrib = attrib.replace('[','').replace(']','')
111
- let [name,value] = attrib.split(/[\~\|\^\$\*]?\=/)
112
- let sign = attrib.replace(name,'').replace(value,'')
113
- attrib = {query}
114
- if(name) attrib.name = name
115
- if(value) attrib.value = value.trim().replace(/^\"/,'').replace(/\"$/,'')
116
- if(sign) {
117
- attrib.sign = sign
118
- attrib.check = this.getAttribFn(sign).bind(attrib)
119
- }
120
- return attrib
121
- });
122
- return attribs
123
- }
124
-
125
- getAttribFn(sign) {
126
- if(sign == '=') return function(value) {return value == this.value ? true : false}
127
- if(sign == '*=') return function(value) {return value.includes(this.value) ? true : false}
128
- if(sign == '^=') return function(value) {return value.startsWith(this.value) ? true : false}
129
- if(sign == '$=') return function(value) {return value.endsWith(this.value) ? true : false}
130
- if(sign == '|=') return function(value) {
131
- return value.trim().split(' ').length == 1
132
- && (value.startsWith(this.value) || value.startsWith(this.value+'-'))
133
- ? true : false
134
- }
135
- if(sign == '~=') return function(value) { // includes whole word only
136
- return this.value.trim().split(' ').length == 1 && value.includes(this.value) ? true : false
137
- }
138
- }
139
-
140
- removeSpaces(selector) {
141
- selector = selector.replace(/\s{2}/g,' ') // remove double spaces
142
- selector = selector.replace(/\s?\^?\$?\|?\~?\*?\=\s*/g,(m) => m.trim()) // remove spaces inside []
143
- selector = selector.replace(/\s?(\+|\~|\>)\s?/g,(m) => m.trim()) // remove spaces around +|~|>
144
- return selector
145
- }
146
- }
147
- module.exports = Query
package/query/readme.md DELETED
@@ -1,134 +0,0 @@
1
- ## Query
2
- Query is a class for parsing selectors inside html query. Query not supporting pseudo selectors so far.
3
- You can use Query on frontend and on backend.
4
-
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
9
-
10
- Frontend:
11
- ```html
12
- <script src="node_modules/als-document/document.min.js"></script>
13
- ```
14
-
15
- Backend:
16
- ```javascript
17
- let {Query} = require('als-document')
18
- ```
19
-
20
- ### Syntax
21
-
22
- ```javascript
23
- let queryObj = new Query(qeury:string): instanceof Query
24
- let selectors = queryObj.selectors:string
25
- // or
26
- let selectors = Query.get(q1:string):string
27
- ```
28
-
29
- ``query`` - html/css query
30
-
31
-
32
- ### Example
33
-
34
- ```javascript
35
- let q1 = 'html>body>div.tabs~.some[type $= "radio and some"]>p+div>.some-id .tab-content~input[disabled] div.some'
36
- let result = new Query(q1).selectors
37
- let result1 = Query.get(q1)
38
- // result and result1 has to be same
39
- console.log(result)
40
- ```
41
-
42
- Result:
43
- ```javascript
44
- [
45
- {
46
- "query": "div.some",
47
- "tag": "div",
48
- "classList": [
49
- "some"
50
- ],
51
- "ancestors": [
52
- {
53
- "query": ".some-id",
54
- "classList": [
55
- "some-id"
56
- ],
57
- "parents": [
58
- {
59
- "query": "div",
60
- "tag": "div"
61
- }
62
- ],
63
- "prev": {
64
- "query": "p",
65
- "tag": "p",
66
- "parents": [
67
- {
68
- "query": ".some[0]",
69
- "classList": [
70
- "some"
71
- ],
72
- "attribs": [
73
- {
74
- check:(f),
75
- "query": "[type$=\"radio and some\"]",
76
- "name": "type",
77
- "value": "radio and some",
78
- "sign": "$="
79
- }
80
- ]
81
- }
82
- ],
83
- "prevAny": {
84
- "query": "div.tabs",
85
- "tag": "div",
86
- "classList": [
87
- "tabs"
88
- ],
89
- "parents": [
90
- {
91
- "query": "html",
92
- "tag": "html"
93
- },
94
- {
95
- "query": "body",
96
- "tag": "body"
97
- }
98
- ]
99
- },
100
- "group": "html>body>div.tabs~.some[0]>p"
101
- },
102
- "group": "html>body>div.tabs~.some[0]>p+div>.some-id"
103
- },
104
- {
105
- "query": "input[1]",
106
- "tag": "input",
107
- "attribs": [
108
- {
109
- "query": "[disabled]",
110
- "name": "disabled"
111
- }
112
- ],
113
- "prevAny": {
114
- "query": ".tab-content",
115
- "classList": [
116
- "tab-content"
117
- ]
118
- },
119
- "group": ".tab-content~input[1]"
120
- }
121
- ],
122
- "group": "html>body>div.tabs~.some[type $= \"radio and some\"]>p+div>.some-id .tab-content~input[disabled] div.some"
123
- }
124
- ]
125
- ```
126
-
127
- ### Attribs and check function
128
- if attribute has value, attrib object will contain check function with one parameter for value to check.
129
-
130
- ```javascript
131
- let s = Query.get('[test^="some"]')[0]
132
- console.log(s.attribs[0].check('some value test')) // true
133
- ```
134
-
package/query/test.js DELETED
@@ -1,143 +0,0 @@
1
- let Test = require('als-test')
2
- let {equal,greater,smaller,$greater, $smaller} = Test
3
- let Query = require('./query')
4
-
5
- module.exports = new Test('Query tests',[
6
- {
7
- title:'Build query',
8
- result:function(){
9
- this.vars.q1 = 'html>body>div.tabs~.some[type $= "some"][test]>p+div>.some-id .tab-content~input[disabled] div.some'
10
- this.vars.s1 = Query.get(this.vars.q1)[0]
11
- },
12
- },
13
- {
14
- title:'Check target',
15
- expected:'div.some',
16
- result:function({s1}){
17
- let {tag,classList} = s1
18
- return `${tag}.${classList[0]}`
19
- },
20
- action:equal
21
- },
22
- {
23
- title:'Check ancestors length',
24
- expected:2,
25
- result:function({s1}){
26
- return s1.ancestors.length
27
- },
28
- action:equal
29
- },
30
- {
31
- title:'Check prev group',
32
- expected:function({s1}) {
33
- return s1.ancestors[0].group.split('+')[0]
34
- },
35
- result:function({s1}){
36
- return s1.ancestors[0].prev.group
37
- },
38
- action:equal
39
- },
40
- {
41
- title:'Check parents length',
42
- expected:1,
43
- result:async function({s1}){
44
- return s1.ancestors[0].parents.length
45
- },
46
- action:equal
47
- },
48
- {
49
- title:'Check prev any, prev and classList',
50
- expected:'tabs',
51
- result:async function({s1}){
52
- return s1.ancestors[0].prev.prevAny.classList[0]
53
- },
54
- action:equal
55
- },
56
- {
57
- title:'Check attributes length',
58
- expected:2,
59
- result:async function({s1}){
60
- return s1.ancestors[0].prev.parents[0].attribs.length
61
- },
62
- action:equal
63
- },
64
- {
65
- title:'Check attributes fn $',
66
- expected:true,
67
- result:async function({s1}){
68
- return s1.ancestors[0].prev.parents[0].attribs[0].check('test and some')
69
- },
70
- action:equal
71
- },
72
- {
73
- title:'Check attributes fn *=',
74
- expected:true,
75
- result:async function({s1}){
76
- return s1.ancestors[0].prev.parents[0].attribs[0].check('some')
77
- },
78
- action:equal
79
- },
80
- {
81
- title:'Check attributes fn *=',
82
- expected:true,
83
- result:async function(){
84
- let s = Query.get('[test*="some value"]')[0]
85
- return s.attribs[0].check('some value test')
86
- },
87
- action:equal
88
- },
89
- {
90
- title:'Check attributes fn ~= prase instead single word',
91
- expected:false,
92
- result:async function(){
93
- let s = Query.get('[test~="some value"]')[0]
94
- return s.attribs[0].check('some value test')
95
- },
96
- action:equal
97
- },
98
- {
99
- title:'Check attributes fn ~=',
100
- expected:true,
101
- result:async function(){
102
- let s = Query.get('[test~="value"]')[0]
103
- return s.attribs[0].check('some value test')
104
- },
105
- action:equal
106
- },
107
- {
108
- title:'Check attributes fn ^=',
109
- expected:true,
110
- result:async function(){
111
- let s = Query.get('[test^="some"]')[0]
112
- return s.attribs[0].check('some value test')
113
- },
114
- action:equal
115
- },
116
- {
117
- title:'Check attributes fn |= with few words',
118
- expected:false,
119
- result:async function(){
120
- let s = Query.get('[test|="some value test"]')[0]
121
- return s.attribs[0].check('some')
122
- },
123
- action:equal
124
- },
125
- {
126
- title:'Check attributes fn |=word',
127
- expected:true,
128
- result:async function(){
129
- let s = Query.get('[test|="some"]')[0]
130
- return s.attribs[0].check('some')
131
- },
132
- action:equal
133
- },
134
- {
135
- title:'Check attributes fn |=word-word',
136
- expected:true,
137
- result:async function(){
138
- let s = Query.get('[test|="some"]')[0]
139
- return s.attribs[0].check('some-value')
140
- },
141
- action:equal
142
- },
143
- ])
@@ -1,126 +0,0 @@
1
- let Query = require('../query/query')
2
- let HtmlParser = require("../parser/parser")
3
-
4
- class HtmlSelector {
5
- constructor(html) {
6
- if(typeof html == 'string') {
7
- this.html = new HtmlParser(html)
8
- this.elements.forEach((element,i) => {this.makeSelectable(element)});
9
- } else console.log('Parameter is not string')
10
- }
11
- get elements() {return this.html.elements}
12
-
13
- makeSelectable(element) {
14
- if(element.type == 'tag' && element.status !== 'close') {
15
- element.$$ = (query) => this.$$(query,element.index,element.endIndex)
16
- element.$ = (query) => this.$(query,element.index,element.endIndex)
17
- }
18
- }
19
-
20
- $(query,start=0,end=this.elements.length) {
21
- return this.$$(query,start,end,true)
22
- }
23
-
24
- $$(query,start=0,end=this.elements.length,single=false) {
25
- let result = []
26
- this.selectors = new Query(query).selectors
27
- this.query = query
28
- this.selectors.forEach(selector => {
29
- for(let i=start; i<end; i++) {
30
- let el = this.elements[i]
31
- if(this.checkElement(el,selector) && !result.includes(el)) result.push(el)
32
- if(single && result.length == 1) break
33
- }
34
- });
35
- if(single && result.length == 1) return result[0]
36
- else if(single && result.length == 0) return null
37
- else return result
38
- }
39
-
40
- checkElement(el,selector) {
41
- if(selector == undefined) return true
42
- if(el == null) return false
43
- let {tag,classList,attribs,id,prev,ancestors,parents,prevAny} = selector
44
-
45
- if(el.status == 'close' || el.type == 'text') return false
46
- if(id !== undefined && el.id == undefined) return false
47
- if(id && id !== el.id) return false
48
- if(tag && el.tag == undefined) return false
49
- else if(tag && tag !== el.tag) return false
50
- if(classList !== undefined && el.classList == undefined) return false
51
- else if(classList !== undefined && Array.isArray(el.classList)) {
52
- if(classList.every(e => el.classList.includes(e)) == false) return false
53
- }
54
- if(this.checkAttribs(attribs,el) == false) return false
55
- if(this.checkElement(el.prev,prev) == false) return false
56
- if(this.checkAncestors(el.ancestors,ancestors) == false) return false
57
- if(this.checkParents(el.ancestors,parents) == false) return false
58
- if(el.parent) {
59
- if(this.prevAny(el.parent.children,el.childIndex,prevAny) == false) return false
60
- }
61
- return true
62
- }
63
-
64
- prevAny(children=[],index,prevAny) {
65
- let size = children.length
66
- if((size == 0 || index == 0) && prevAny) return false
67
- for(let i=index; i>=0; i--) {
68
- if(this.checkElement(children[i],prevAny)) return true
69
- }
70
- return false
71
- }
72
-
73
- checkAncestors(ancestors=[],selectorAncestors=[]) {
74
- let count = 0
75
- if(selectorAncestors.length == 0) return true
76
- let endIndex = ancestors.length-1
77
- let selectorIndex = selectorAncestors.length-1
78
- while(selectorIndex>=0) {
79
- for(let i=endIndex; i>=0; i--) {
80
- endIndex=i-1
81
- if(this.checkElement(ancestors[i],selectorAncestors[selectorIndex]) == true) {
82
- count++
83
- break
84
- }
85
- }
86
- selectorIndex--
87
- }
88
- if(count == selectorAncestors.length) return true
89
- else return false
90
- }
91
-
92
- checkParents(ancestors=[],selectorParents=[]) {
93
- if(selectorParents.length == 0) return true
94
- if(ancestors.length < selectorParents.length) return false
95
- let index = ancestors.length-1
96
- for(let i=selectorParents.length-1; i>=0; i--) {
97
- if(this.checkElement(ancestors[index],selectorParents[i]) == false) return false
98
- index--
99
- }
100
- return true
101
- }
102
-
103
- checkAttribs(attribs=[],el) {
104
- let elAttribs = el.attribs
105
- let names = Object.keys(elAttribs)
106
- let passedTests = 0
107
- if(attribs) for(let i=0; i<attribs.length; i++) {
108
- let {name,value,check} = attribs[i]
109
- if(name == 'inner' && value !== undefined && check && el.innerText) {
110
- if(check(el.innerText)) passedTests++
111
- }
112
-
113
- if(!names.includes(name)) continue
114
- else if(value == undefined) passedTests++
115
- else if(value && elAttribs[name]) {
116
- if(check(elAttribs[name]) == false) continue
117
- else passedTests++
118
- }
119
- }
120
- if(passedTests == attribs.length) return true
121
- else return false
122
- }
123
-
124
- }
125
-
126
- module.exports = HtmlSelector