@cloudbase/framework-plugin-low-code 0.6.30 → 0.6.33
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/lib/builder/config/index.js +2 -5
- package/lib/builder/core/copy.d.ts.map +1 -1
- package/lib/builder/mp/materials.d.ts.map +1 -1
- package/lib/builder/mp/materials.js +21 -5
- package/package.json +5 -3
- package/template/src/handlers/FieldMiddleware/renderer.jsx +11 -6
- package/template/src/handlers/actionHandler/utils.js +41 -17
- package/template/webpack/web.prod.js +65 -85
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/cookie.js +0 -286
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/history.js +0 -133
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/local-storage.js +0 -103
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/location.js +0 -588
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/miniprogram.js +0 -101
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/navigator.js +0 -80
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/performance.js +0 -28
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/screen.js +0 -31
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/session-storage.js +0 -96
- package/template/dist/mp/miniprogram_npm/miniprogram-render/bom/xml-http-request.js +0 -290
- package/template/dist/mp/miniprogram_npm/miniprogram-render/document.js +0 -396
- package/template/dist/mp/miniprogram_npm/miniprogram-render/event/custom-event.js +0 -12
- package/template/dist/mp/miniprogram_npm/miniprogram-render/event/event-target.js +0 -389
- package/template/dist/mp/miniprogram_npm/miniprogram-render/event/event.js +0 -186
- package/template/dist/mp/miniprogram_npm/miniprogram-render/index.js +0 -41
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/attribute.js +0 -226
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/class-list.js +0 -153
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/comment.js +0 -80
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/a.js +0 -165
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/canvas.js +0 -138
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/image.js +0 -177
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/input.js +0 -181
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/not-support.js +0 -60
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/option.js +0 -126
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/select.js +0 -155
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/textarea.js +0 -178
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/video.js +0 -165
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/wx-component.js +0 -84
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element/wx-custom-component.js +0 -64
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/element.js +0 -970
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/node.js +0 -140
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/style-list.js +0 -28
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/style.js +0 -158
- package/template/dist/mp/miniprogram_npm/miniprogram-render/node/text-node.js +0 -127
- package/template/dist/mp/miniprogram_npm/miniprogram-render/tree/parser.js +0 -269
- package/template/dist/mp/miniprogram_npm/miniprogram-render/tree/query-selector.js +0 -420
- package/template/dist/mp/miniprogram_npm/miniprogram-render/tree/tree.js +0 -130
- package/template/dist/mp/miniprogram_npm/miniprogram-render/util/cache.js +0 -95
- package/template/dist/mp/miniprogram_npm/miniprogram-render/util/pool.js +0 -24
- package/template/dist/mp/miniprogram_npm/miniprogram-render/util/tool.js +0 -131
- package/template/dist/mp/miniprogram_npm/miniprogram-render/window.js +0 -651
- package/template/generator/app/common.js +0 -17
- package/template/generator/app/global-api.js +0 -163
- package/template/generator/app/handlers.js +0 -13
- package/template/generator/datasources/config.js.tpl +0 -21
- package/template/generator/datasources/dataset-profiles.js.tpl +0 -5
- package/template/generator/datasources/datasource-profiles.js.tpl +0 -4
- package/template/generator/datasources/index.js.tpl +0 -14
- package/template/generator/handlers/NodeRenderer.jsx +0 -471
- package/template/generator/handlers/RenderWrapper.jsx +0 -145
- package/template/generator/index.jsx +0 -116
- package/template/generator/index.less +0 -120
- package/template/generator/pages/app.tpl +0 -181
- package/template/generator/pages/composite.tpl +0 -267
- package/template/generator/router/index.tpl +0 -49
- package/template/generator/store/computed.js +0 -11
- package/template/generator/store/index.js +0 -5
- package/template/generator/utils/ScanCodeComponent.js +0 -345
- package/template/generator/utils/actionHandler.js +0 -119
- package/template/generator/utils/common.js +0 -225
- package/template/generator/utils/computed.js +0 -9
- package/template/generator/utils/date.js +0 -324
- package/template/generator/utils/error.jsx +0 -14
- package/template/generator/utils/eventProxy.js +0 -64
- package/template/generator/utils/history.js +0 -35
- package/template/generator/utils/hooks.js +0 -10
- package/template/generator/utils/index.js +0 -41
- package/template/generator/utils/initGlobalVar.js +0 -14
- package/template/generator/utils/lifecycle.js +0 -158
- package/template/generator/utils/monitor-jssdk.min.js +0 -881
- package/template/generator/utils/page.js +0 -10
- package/template/generator/utils/scan-code-action.js +0 -27
- package/template/generator/utils/style.js +0 -81
- package/template/generator/utils/widgets.js +0 -343
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 感谢 John Resig: https://johnresig.com/files/htmlparser.js
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// 正则声明
|
|
6
|
-
const doctypeReg = /^<!\s*doctype((?:\s+[\w:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/i
|
|
7
|
-
const startTagReg = /^<([-A-Za-z0-9_]+)((?:\s+[-A-Za-z0-9_:@.]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/i
|
|
8
|
-
const endTagReg = /^<\/([-A-Za-z0-9_]+)[^>]*>/i
|
|
9
|
-
const attrReg = /([-A-Za-z0-9_:@.]+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g
|
|
10
|
-
|
|
11
|
-
// 空元素 - https://www.w3.org/TR/html/syntax.html#void-elements
|
|
12
|
-
const voidMap = {};
|
|
13
|
-
['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'].forEach(n => voidMap[n] = true)
|
|
14
|
-
|
|
15
|
-
// 块级元素 - https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements#Elements
|
|
16
|
-
const blockMap = {};
|
|
17
|
-
['address', 'article', 'aside', 'blockquote', 'canvas', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'li', 'main', 'nav', 'noscript', 'ol', 'output', 'p', 'pre', 'section', 'table', 'tfoot', 'ul', 'video'].forEach(n => blockMap[n] = true)
|
|
18
|
-
|
|
19
|
-
// 行内元素 - https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements#Elements
|
|
20
|
-
const inlineMap = {};
|
|
21
|
-
['a', 'abbr', 'acronym', 'b', 'bdo', 'big', 'br', 'button', 'cite', 'code', 'dfn', 'em', 'i', 'img', 'input', 'kbd', 'label', 'map', 'object', 'q', 'samp', 'script', 'select', 'small', 'span', 'strong', 'sub', 'sup', 'textarea', 'time', 'tt', 'var'].forEach(n => inlineMap[n] = true)
|
|
22
|
-
|
|
23
|
-
// 可能包含任意内容的元素 - https://www.w3.org/TR/html/syntax.html#raw-text
|
|
24
|
-
const rawTextMap = {};
|
|
25
|
-
['script', 'style'].forEach(n => rawTextMap[n] = true)
|
|
26
|
-
|
|
27
|
-
const longAttributeCache = {}
|
|
28
|
-
let seed = 0
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* 分词
|
|
32
|
-
*/
|
|
33
|
-
function tokenize(content, handler) {
|
|
34
|
-
const stack = []
|
|
35
|
-
let last = content
|
|
36
|
-
|
|
37
|
-
stack.last = function() {
|
|
38
|
-
return this[this.length - 1]
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
while (content) {
|
|
42
|
-
let isText = true
|
|
43
|
-
|
|
44
|
-
if (!stack.last() || !rawTextMap[stack.last()]) {
|
|
45
|
-
if (content.indexOf('<!--') === 0) {
|
|
46
|
-
// comment
|
|
47
|
-
const index = content.indexOf('-->')
|
|
48
|
-
|
|
49
|
-
if (index >= 0) {
|
|
50
|
-
content = content.substring(index + 3)
|
|
51
|
-
if (handler.comment) handler.comment(content)
|
|
52
|
-
isText = false
|
|
53
|
-
}
|
|
54
|
-
} else if (content.indexOf('</') === 0) {
|
|
55
|
-
// end tag
|
|
56
|
-
const match = content.match(endTagReg)
|
|
57
|
-
|
|
58
|
-
if (match) {
|
|
59
|
-
content = content.substring(match[0].length)
|
|
60
|
-
match[0].replace(endTagReg, parseEndTag)
|
|
61
|
-
isText = false
|
|
62
|
-
}
|
|
63
|
-
} else if (content.indexOf('<') === 0) {
|
|
64
|
-
// start tag
|
|
65
|
-
let match = content.match(startTagReg)
|
|
66
|
-
|
|
67
|
-
if (match) {
|
|
68
|
-
content = content.substring(match[0].length)
|
|
69
|
-
match[0].replace(startTagReg, parseStartTag)
|
|
70
|
-
isText = false
|
|
71
|
-
} else {
|
|
72
|
-
// 检测 doctype
|
|
73
|
-
match = content.match(doctypeReg)
|
|
74
|
-
|
|
75
|
-
if (match) {
|
|
76
|
-
content = content.substring(match[0].length)
|
|
77
|
-
isText = false
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (isText) {
|
|
83
|
-
const index = content.indexOf('<')
|
|
84
|
-
|
|
85
|
-
const text = index < 0 ? content : content.substring(0, index)
|
|
86
|
-
content = index < 0 ? '' : content.substring(index)
|
|
87
|
-
|
|
88
|
-
if (handler.text) handler.text(text)
|
|
89
|
-
}
|
|
90
|
-
} else {
|
|
91
|
-
const execRes = (new RegExp(`</${stack.last()}[^>]*>`)).exec(content)
|
|
92
|
-
|
|
93
|
-
if (execRes) {
|
|
94
|
-
const text = content.substring(0, execRes.index)
|
|
95
|
-
content = content.substring(execRes.index + execRes[0].length)
|
|
96
|
-
|
|
97
|
-
text.replace(/<!--(.*?)-->/g, '')
|
|
98
|
-
if (text && handler.text) handler.text(text)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
parseEndTag('', stack.last())
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (content === last) throw new Error(`parse error: ${content}`)
|
|
105
|
-
last = content
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// 关闭栈内的标签
|
|
109
|
-
parseEndTag()
|
|
110
|
-
|
|
111
|
-
function parseStartTag(tag, tagName, rest, unary) {
|
|
112
|
-
tagName = tagName.toLowerCase()
|
|
113
|
-
unary = !!unary
|
|
114
|
-
|
|
115
|
-
// 放宽规则,允许行内元素包含块级元素
|
|
116
|
-
// if (blockMap[tagName]) {
|
|
117
|
-
// while (stack.last() && inlineMap[stack.last()]) {
|
|
118
|
-
// // 自动关闭栈内的行内元素
|
|
119
|
-
// parseEndTag('', stack.last())
|
|
120
|
-
// }
|
|
121
|
-
// }
|
|
122
|
-
|
|
123
|
-
unary = voidMap[tagName] || !!unary
|
|
124
|
-
|
|
125
|
-
if (!unary) stack.push(tagName)
|
|
126
|
-
|
|
127
|
-
if (handler.start) {
|
|
128
|
-
const attrs = []
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
rest.replace(attrReg, (all, $1, $2, $3, $4) => {
|
|
132
|
-
const value = $2 || $3 || $4
|
|
133
|
-
|
|
134
|
-
attrs.push({
|
|
135
|
-
name: $1,
|
|
136
|
-
value,
|
|
137
|
-
})
|
|
138
|
-
})
|
|
139
|
-
} catch (err) {
|
|
140
|
-
// 某些安卓机遇到过长的字符串执行属性正则替换会跪(主要是 base 64),这里就先临时过滤掉这种特殊情况
|
|
141
|
-
rest = rest.replace(/url\([^)]+\)/ig, all => {
|
|
142
|
-
const id = `url(:#|${++seed}|#:)`
|
|
143
|
-
longAttributeCache[id] = all
|
|
144
|
-
return id
|
|
145
|
-
})
|
|
146
|
-
rest.replace(attrReg, (all, $1, $2, $3, $4) => {
|
|
147
|
-
const value = $2 || $3 || $4
|
|
148
|
-
|
|
149
|
-
attrs.push({
|
|
150
|
-
name: $1,
|
|
151
|
-
value: value.replace(/url\(:#\|\d+\|#:\)/ig, all => longAttributeCache[all] || 'url()'),
|
|
152
|
-
})
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
handler.start(tagName, attrs, unary)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function parseEndTag(tag, tagName) {
|
|
161
|
-
let pos
|
|
162
|
-
|
|
163
|
-
if (!tagName) {
|
|
164
|
-
pos = 0
|
|
165
|
-
} else {
|
|
166
|
-
// 找到同名的开始标签
|
|
167
|
-
tagName = tagName.toLowerCase()
|
|
168
|
-
|
|
169
|
-
for (pos = stack.length - 1; pos >= 0; pos--) {
|
|
170
|
-
if (stack[pos] === tagName) break
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (pos >= 0) {
|
|
175
|
-
// 关闭开始标签和结束标签中的所有标签
|
|
176
|
-
for (let i = stack.length - 1; i >= pos; i--) {
|
|
177
|
-
if (handler.end) handler.end(stack[i])
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
stack.length = pos
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* 解析
|
|
187
|
-
*/
|
|
188
|
-
function parse(html) {
|
|
189
|
-
const r = {
|
|
190
|
-
children: [],
|
|
191
|
-
}
|
|
192
|
-
const stack = [r]
|
|
193
|
-
|
|
194
|
-
stack.last = function() {
|
|
195
|
-
return this[this.length - 1]
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
tokenize(html, {
|
|
199
|
-
start(tagName, attrs, unary) {
|
|
200
|
-
const node = {
|
|
201
|
-
type: 'element',
|
|
202
|
-
tagName,
|
|
203
|
-
attrs,
|
|
204
|
-
unary,
|
|
205
|
-
children: [],
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
stack.last().children.push(node)
|
|
209
|
-
|
|
210
|
-
if (!unary) {
|
|
211
|
-
stack.push(node)
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
// eslint-disable-next-line no-unused-vars
|
|
215
|
-
end(tagName) {
|
|
216
|
-
const node = stack.pop()
|
|
217
|
-
|
|
218
|
-
if (node.tagName === 'table') {
|
|
219
|
-
// 补充插入 tbody
|
|
220
|
-
let hasTbody = false
|
|
221
|
-
|
|
222
|
-
for (const child of node.children) {
|
|
223
|
-
if (child.tagName === 'tbody') {
|
|
224
|
-
hasTbody = true
|
|
225
|
-
break
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (!hasTbody) {
|
|
230
|
-
node.children = [{
|
|
231
|
-
type: 'element',
|
|
232
|
-
tagName: 'tbody',
|
|
233
|
-
attrs: [],
|
|
234
|
-
unary: false,
|
|
235
|
-
children: node.children,
|
|
236
|
-
}]
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
text(content) {
|
|
241
|
-
content = content.trim()
|
|
242
|
-
if (!content) return
|
|
243
|
-
|
|
244
|
-
stack.last().children.push({
|
|
245
|
-
type: 'text',
|
|
246
|
-
content,
|
|
247
|
-
})
|
|
248
|
-
},
|
|
249
|
-
comment(content) {
|
|
250
|
-
content = content.trim()
|
|
251
|
-
|
|
252
|
-
stack.last().children.push({
|
|
253
|
-
type: 'comment',
|
|
254
|
-
content,
|
|
255
|
-
})
|
|
256
|
-
},
|
|
257
|
-
})
|
|
258
|
-
|
|
259
|
-
return r.children
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
module.exports = {
|
|
263
|
-
tokenize,
|
|
264
|
-
parse,
|
|
265
|
-
voidMap,
|
|
266
|
-
blockMap,
|
|
267
|
-
inlineMap,
|
|
268
|
-
rawTextMap,
|
|
269
|
-
}
|
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 感谢 sizzle:https://github.com/jquery/sizzle/tree/master
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const PSEUDO_CHECK = {
|
|
6
|
-
checked: node => node.checked || node.selected,
|
|
7
|
-
disabled: node => node.disabled,
|
|
8
|
-
enabled: node => !node.disabled,
|
|
9
|
-
'first-child': node => node.parentNode.children[0] === node,
|
|
10
|
-
'last-child': node => node.parentNode.children[node.parentNode.children.length - 1] === node,
|
|
11
|
-
'nth-child': (node, param) => {
|
|
12
|
-
const children = node.parentNode.children
|
|
13
|
-
const {a, b} = param
|
|
14
|
-
const index = children.indexOf(node) + 1
|
|
15
|
-
|
|
16
|
-
if (a) {
|
|
17
|
-
return (index - b) % a === 0
|
|
18
|
-
} else {
|
|
19
|
-
return index === b
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const ATTR_CHECK = {
|
|
25
|
-
'=': (nodeVal, val) => nodeVal === val,
|
|
26
|
-
'~=': (nodeVal, val) => nodeVal.split(/\s+/).indexOf(val) !== -1,
|
|
27
|
-
'|=': (nodeVal, val) => nodeVal === val || nodeVal.indexOf(val + '-') === 0,
|
|
28
|
-
'^=': (nodeVal, val) => nodeVal.indexOf(val) === 0,
|
|
29
|
-
'$=': (nodeVal, val) => nodeVal.substr(nodeVal.length - val.length) === val,
|
|
30
|
-
'*=': (nodeVal, val) => nodeVal.indexOf(val) !== -1,
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const KINSHIP_CHECK = {
|
|
34
|
-
' ': (node, kinshipRule) => {
|
|
35
|
-
let kinshipNode = node.parentNode
|
|
36
|
-
|
|
37
|
-
while (kinshipNode) {
|
|
38
|
-
if (checkHit(kinshipNode, kinshipRule)) return kinshipNode
|
|
39
|
-
|
|
40
|
-
kinshipNode = kinshipNode.parentNode
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return null
|
|
44
|
-
},
|
|
45
|
-
'>': (node, kinshipRule) => {
|
|
46
|
-
const kinshipNode = node.parentNode
|
|
47
|
-
|
|
48
|
-
return checkHit(kinshipNode, kinshipRule) ? kinshipNode : null
|
|
49
|
-
},
|
|
50
|
-
'+': (node, kinshipRule) => {
|
|
51
|
-
const children = node.parentNode
|
|
52
|
-
|
|
53
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
54
|
-
const child = children[i]
|
|
55
|
-
|
|
56
|
-
if (child === node) {
|
|
57
|
-
const kinshipNode = children[i - 1]
|
|
58
|
-
|
|
59
|
-
return checkHit(kinshipNode, kinshipRule) ? kinshipNode : null
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return null
|
|
64
|
-
},
|
|
65
|
-
'~': (node, kinshipRule) => {
|
|
66
|
-
const children = node.parentNode
|
|
67
|
-
let foundCurrent = false
|
|
68
|
-
|
|
69
|
-
for (let i = children.length - 1; i >= 0; i--) {
|
|
70
|
-
const child = children[i]
|
|
71
|
-
|
|
72
|
-
if (foundCurrent && checkHit(child, kinshipRule)) return child
|
|
73
|
-
if (child === node) foundCurrent = true
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return null
|
|
77
|
-
},
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* 检查节点是否符合规则
|
|
82
|
-
*/
|
|
83
|
-
function checkHit(node, rule) {
|
|
84
|
-
if (!node) return false
|
|
85
|
-
|
|
86
|
-
const {
|
|
87
|
-
id, class: classList, tag, pseudo, attr
|
|
88
|
-
} = rule
|
|
89
|
-
|
|
90
|
-
// id 选择器
|
|
91
|
-
if (id) {
|
|
92
|
-
if (node.id !== id) return false
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// 类选择器
|
|
96
|
-
if (classList && classList.length) {
|
|
97
|
-
for (const className of classList) {
|
|
98
|
-
if (!node.classList || !node.classList.contains(className)) return false
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// 标签选择器
|
|
103
|
-
if (tag && tag !== '*') {
|
|
104
|
-
if (node.tagName !== tag.toUpperCase()) return false
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 伪类选择器
|
|
108
|
-
if (pseudo) {
|
|
109
|
-
for (const {name, param} of pseudo) {
|
|
110
|
-
const checkPseudo = PSEUDO_CHECK[name]
|
|
111
|
-
if (!checkPseudo || !checkPseudo(node, param)) return false
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// 属性选择器
|
|
116
|
-
if (attr) {
|
|
117
|
-
for (const {name, opr, val} of attr) {
|
|
118
|
-
const nodeVal = node[name] || node.getAttribute(name)
|
|
119
|
-
|
|
120
|
-
if (nodeVal === undefined) return false
|
|
121
|
-
if (opr) {
|
|
122
|
-
// 存在操作符
|
|
123
|
-
const checkAttr = ATTR_CHECK[opr]
|
|
124
|
-
if (!checkAttr || !checkAttr(nodeVal, val)) return false
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return true
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 数组去重
|
|
134
|
-
*/
|
|
135
|
-
function unique(list) {
|
|
136
|
-
for (let i = 0; i < list.length; i++) {
|
|
137
|
-
const a = list[i]
|
|
138
|
-
|
|
139
|
-
for (let j = i + 1; j < list.length; j++) {
|
|
140
|
-
const b = list[j]
|
|
141
|
-
if (a === b) list.splice(j, 1)
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return list
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* 将节点按照文档顺序排列
|
|
150
|
-
*/
|
|
151
|
-
function sortNodes(list) {
|
|
152
|
-
list.sort((a, b) => {
|
|
153
|
-
const aList = [a]
|
|
154
|
-
const bList = [b]
|
|
155
|
-
let aParent = a.parentNode
|
|
156
|
-
let bParent = b.parentNode
|
|
157
|
-
|
|
158
|
-
if (aParent === bParent) {
|
|
159
|
-
// 检查顺序
|
|
160
|
-
const children = aParent.children
|
|
161
|
-
return children.indexOf(a) - children.indexOf(b)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// a 到根的列表
|
|
165
|
-
while (aParent) {
|
|
166
|
-
aList.unshift(aParent)
|
|
167
|
-
aParent = aParent.parentNode
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// b 到根的列表
|
|
171
|
-
while (bParent) {
|
|
172
|
-
bList.unshift(bParent)
|
|
173
|
-
bParent = bParent.parentNode
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// 找到最近共同祖先
|
|
177
|
-
let i = 0
|
|
178
|
-
while (aList[i] === bList[i]) i++
|
|
179
|
-
|
|
180
|
-
// 检查顺序
|
|
181
|
-
const children = aList[i - 1].children
|
|
182
|
-
return children.indexOf(aList[i]) - children.indexOf(bList[i])
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
return list
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
class QuerySelector {
|
|
189
|
-
constructor() {
|
|
190
|
-
this.parseCache = {} // 解析查询串缓存
|
|
191
|
-
this.parseCacheKeys = []
|
|
192
|
-
|
|
193
|
-
const idReg = '#([\\\\\\w-]+)' // id 选择器
|
|
194
|
-
const tagReg = '\\*|wx-component|[a-zA-Z-]\\w*' // 标签选择器
|
|
195
|
-
const classReg = '\\.([\\\\\\w-]+)' // 类选择器
|
|
196
|
-
const pseudoReg = ':([\\\\\\w-]+)(?:\\(([^\\(\\)]*|(?:\\([^\\)]+\\)|[^\\(\\)]*)+)\\))?' // 伪类选择器
|
|
197
|
-
const attrReg = '\\[\\s*([\\\\\\w-]+)(?:([*^$|~!]?=)[\'"]?([^\'"\\[]+)[\'"]?)?\\s*\\]' // 属性选择器
|
|
198
|
-
const kinshipReg = '\\s*([>\\s+~](?!=))\\s*' // 亲属选择器
|
|
199
|
-
this.regexp = new RegExp(`^(?:(${idReg})|(${tagReg})|(${classReg})|(${pseudoReg})|(${attrReg})|(${kinshipReg}))`)
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* 存入解析查询串缓存
|
|
204
|
-
*/
|
|
205
|
-
setParseCache(key, value) {
|
|
206
|
-
if (this.parseCacheKeys.length > 50) {
|
|
207
|
-
delete this.parseCache[this.parseCacheKeys.shift()]
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
this.parseCacheKeys.push(key)
|
|
211
|
-
this.parseCache[key] = value
|
|
212
|
-
|
|
213
|
-
return value
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* 获取解析查询串缓存
|
|
218
|
-
*/
|
|
219
|
-
getParseCache(key) {
|
|
220
|
-
return this.parseCache[key]
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* 解析查询串
|
|
225
|
-
*/
|
|
226
|
-
parse(selector) {
|
|
227
|
-
const segment = [{tag: '*'}]
|
|
228
|
-
const regexp = this.regexp
|
|
229
|
-
|
|
230
|
-
const onProcess = (all, idAll, id, tagAll, classAll, className, pseudoAll, pseudoName, pseudoParam, attrAll, attrName, attrOpr, attrVal, kinshipAll, kinship) => {
|
|
231
|
-
if (idAll) {
|
|
232
|
-
// id 选择器
|
|
233
|
-
segment[segment.length - 1].id = id
|
|
234
|
-
} else if (tagAll) {
|
|
235
|
-
// 标签选择器
|
|
236
|
-
segment[segment.length - 1].tag = tagAll.toLowerCase()
|
|
237
|
-
} else if (classAll) {
|
|
238
|
-
// 类选择器
|
|
239
|
-
const currentRule = segment[segment.length - 1]
|
|
240
|
-
currentRule.class = currentRule.class || []
|
|
241
|
-
|
|
242
|
-
currentRule.class.push(className)
|
|
243
|
-
} else if (pseudoAll) {
|
|
244
|
-
// 伪类选择器
|
|
245
|
-
const currentRule = segment[segment.length - 1]
|
|
246
|
-
currentRule.pseudo = currentRule.pseudo || []
|
|
247
|
-
pseudoName = pseudoName.toLowerCase()
|
|
248
|
-
|
|
249
|
-
const pseudo = {name: pseudoName}
|
|
250
|
-
|
|
251
|
-
if (pseudoParam) pseudoParam = pseudoParam.trim()
|
|
252
|
-
if (pseudoName === 'nth-child') {
|
|
253
|
-
// 处理 nth-child 伪类,参数统一处理成 an + b 的格式
|
|
254
|
-
pseudoParam = pseudoParam.replace(/\s+/g, '')
|
|
255
|
-
|
|
256
|
-
if (pseudoParam === 'even') {
|
|
257
|
-
// 偶数个
|
|
258
|
-
pseudoParam = {a: 2, b: 2}
|
|
259
|
-
} else if (pseudoParam === 'odd') {
|
|
260
|
-
// 奇数个
|
|
261
|
-
pseudoParam = {a: 2, b: 1}
|
|
262
|
-
} else if (pseudoParam) {
|
|
263
|
-
// 其他表达式
|
|
264
|
-
const nthParsed = pseudoParam.match(/^(?:(\d+)|(\d*)?n([+-]\d+)?)$/)
|
|
265
|
-
|
|
266
|
-
if (!nthParsed) {
|
|
267
|
-
// 解析失败
|
|
268
|
-
pseudoParam = {a: 0, b: 1}
|
|
269
|
-
} else if (nthParsed[1]) {
|
|
270
|
-
// 纯数字
|
|
271
|
-
pseudoParam = {a: 0, b: +nthParsed[1]}
|
|
272
|
-
} else {
|
|
273
|
-
// 表达式
|
|
274
|
-
pseudoParam = {
|
|
275
|
-
a: nthParsed[2] ? +nthParsed[2] : 1,
|
|
276
|
-
b: nthParsed[3] ? +nthParsed[3] : 0,
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
} else {
|
|
280
|
-
// 默认取第一个
|
|
281
|
-
pseudoParam = {a: 0, b: 1}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (pseudoParam) pseudo.param = pseudoParam
|
|
285
|
-
|
|
286
|
-
currentRule.pseudo.push(pseudo)
|
|
287
|
-
} else if (attrAll) {
|
|
288
|
-
// 属性选择器
|
|
289
|
-
const currentRule = segment[segment.length - 1]
|
|
290
|
-
|
|
291
|
-
currentRule.attr = currentRule.attr || []
|
|
292
|
-
currentRule.attr.push({
|
|
293
|
-
name: attrName,
|
|
294
|
-
opr: attrOpr,
|
|
295
|
-
val: attrVal
|
|
296
|
-
})
|
|
297
|
-
} else if (kinshipAll) {
|
|
298
|
-
// 亲属选择器
|
|
299
|
-
segment[segment.length - 1].kinship = kinship
|
|
300
|
-
segment.push({tag: '*'}) // 插入新规则
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
return ''
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// 逐个选择器解析
|
|
307
|
-
let lastParse
|
|
308
|
-
selector = selector.replace(regexp, onProcess)
|
|
309
|
-
|
|
310
|
-
while (lastParse !== selector) {
|
|
311
|
-
lastParse = selector
|
|
312
|
-
selector = selector.replace(regexp, onProcess)
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return selector ? '' : segment
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* 查询符合条件的节点
|
|
320
|
-
*/
|
|
321
|
-
exec(selector, extra) {
|
|
322
|
-
selector = selector.trim().replace(/\s+/g, ' ').replace(/\s*(,|[>\s+~](?!=)|[*^$|~!]?=)\s*/g, '$1')
|
|
323
|
-
const {idMap, tagMap, classMap} = extra
|
|
324
|
-
|
|
325
|
-
// 查询缓存
|
|
326
|
-
let segment = this.getParseCache(selector)
|
|
327
|
-
|
|
328
|
-
// 无缓存,进行解析
|
|
329
|
-
if (!segment) {
|
|
330
|
-
segment = this.parse(selector)
|
|
331
|
-
|
|
332
|
-
// 无法正常解析
|
|
333
|
-
if (!segment) return []
|
|
334
|
-
|
|
335
|
-
this.setParseCache(selector, segment)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// 无解析结果
|
|
339
|
-
if (!segment[0]) return []
|
|
340
|
-
|
|
341
|
-
// 执行解析结果
|
|
342
|
-
const lastRule = segment[segment.length - 1] // 从右往左
|
|
343
|
-
const {id, class: classList, tag} = lastRule
|
|
344
|
-
let hitNodes = []
|
|
345
|
-
|
|
346
|
-
// 寻找可能符合要求的节点
|
|
347
|
-
if (id) {
|
|
348
|
-
// id 选择器
|
|
349
|
-
const node = idMap[id]
|
|
350
|
-
hitNodes = node ? [node] : []
|
|
351
|
-
} else if (classList && classList.length) {
|
|
352
|
-
// 类选择器
|
|
353
|
-
for (const className of classList) {
|
|
354
|
-
const classNodes = classMap[className]
|
|
355
|
-
if (classNodes) {
|
|
356
|
-
for (const classNode of classNodes) {
|
|
357
|
-
if (hitNodes.indexOf(classNode) === -1) hitNodes.push(classNode)
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
} else if (tag && tag !== '*') {
|
|
362
|
-
// 标签选择器,查询指定标签
|
|
363
|
-
const tagName = tag.toUpperCase()
|
|
364
|
-
const tagNodes = tagMap[tagName]
|
|
365
|
-
if (tagNodes) hitNodes = tagNodes
|
|
366
|
-
} else {
|
|
367
|
-
// 标签选择器,查询全部节点
|
|
368
|
-
Object.keys(tagMap).forEach(key => {
|
|
369
|
-
const tagNodes = tagMap[key]
|
|
370
|
-
if (tagNodes) {
|
|
371
|
-
for (const tagNode of tagNodes) hitNodes.push(tagNode)
|
|
372
|
-
}
|
|
373
|
-
})
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// 从下往上过滤节点列表
|
|
377
|
-
if (hitNodes.length && segment.length) {
|
|
378
|
-
for (let i = hitNodes.length - 1; i >= 0; i--) {
|
|
379
|
-
let checkNode = hitNodes[i]
|
|
380
|
-
let isMatched = false
|
|
381
|
-
|
|
382
|
-
// 从右往左进行规则过滤
|
|
383
|
-
for (let j = segment.length - 1; j >= 0; j--) {
|
|
384
|
-
const prevRule = segment[j - 1]
|
|
385
|
-
|
|
386
|
-
// 检查待选节点,后续的亲属节点不需要再检查
|
|
387
|
-
if (j === segment.length - 1) isMatched = checkHit(checkNode, lastRule)
|
|
388
|
-
|
|
389
|
-
if (isMatched && prevRule) {
|
|
390
|
-
// 检查亲属选择器
|
|
391
|
-
const kinship = prevRule.kinship
|
|
392
|
-
const checkKinship = KINSHIP_CHECK[kinship]
|
|
393
|
-
|
|
394
|
-
if (checkKinship) checkNode = checkKinship(checkNode, prevRule)
|
|
395
|
-
|
|
396
|
-
if (!checkNode) {
|
|
397
|
-
// 亲属检查失败
|
|
398
|
-
isMatched = false
|
|
399
|
-
break
|
|
400
|
-
}
|
|
401
|
-
} else {
|
|
402
|
-
break
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (!isMatched) hitNodes.splice(i, 1) // 不符合,从待选节点列表中删除
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if (hitNodes.length) {
|
|
411
|
-
// 去重、排序
|
|
412
|
-
hitNodes = unique(hitNodes)
|
|
413
|
-
hitNodes = sortNodes(hitNodes)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
return hitNodes
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
module.exports = QuerySelector
|