als-document 0.6.1 → 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/document.js +25 -11
- package/document.mjs +804 -0
- package/package.json +3 -6
- package/readme.md +12 -4
- package/test/{html1.js → data/html1.js} +1 -2
- package/test/{html2.js → data/html2.js} +1 -1
- package/test/front-test/html.html +5650 -0
- package/test/front-test/html.js +3218 -0
- package/test/front-test/test.html +18 -0
- package/test/front-test/test.js +129 -0
- package/test/test.html +17 -0
- package/test/test.js +15 -19
- package/test/tests/document-test.js +402 -0
- package/test/tests/parser-test.js +99 -0
- package/test/tests/query-test.js +71 -0
- package/test/tests/selector-test.js +169 -0
- package/test/utils/__dirname.js +6 -0
- package/test/utils/als-simple-test/test.mjs +153 -0
- package/test/utils/iframe.js +4 -0
- package/document/document.js +0 -192
- package/document/test.js +0 -678
- package/document.min.js +0 -1
- package/index.js +0 -6
- package/parser/parser.js +0 -336
- package/parser/test.js +0 -233
- package/query/query.js +0 -147
- package/query/readme.md +0 -134
- package/query/test.js +0 -143
- package/selector/selector.js +0 -126
- package/selector/test.js +0 -410
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
|
-
])
|
package/selector/selector.js
DELETED
|
@@ -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
|