@litejs/dom 25.5.0 → 25.9.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/css.js +6 -30
- package/dom.js +16 -14
- package/package.json +2 -2
- package/selector.js +102 -97
package/css.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
"use strict"
|
|
5
5
|
|
|
6
|
-
exports.selectorSplit = selectorSplit
|
|
7
6
|
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
8
7
|
exports.CSSStyleSheet = CSSStyleSheet
|
|
9
8
|
|
|
@@ -15,7 +14,7 @@ var fs = require("fs")
|
|
|
15
14
|
var { DOMParser } = require("./dom.js")
|
|
16
15
|
return v.replace(urlRe, function(_, q1, q2, url) {
|
|
17
16
|
if (q1) return _
|
|
18
|
-
var frag = url.split("#")
|
|
17
|
+
var frag = url.split("#")[1]
|
|
19
18
|
, ext = url.split(/[?#]/)[0].split(".").pop()
|
|
20
19
|
, enc = ext === "svg" ? "utf8" : "base64"
|
|
21
20
|
url = read(sheet, url, enc)
|
|
@@ -45,17 +44,15 @@ var fs = require("fs")
|
|
|
45
44
|
, clear = s => s
|
|
46
45
|
.replace(/("|')((?:\\\1|[^\1])*?)\1|\s*(\/)\*(?:[^*]|\*(?!\/))*\*\/\s*|(?:[^"'\/]|\/(?!\*))+/g, clearFn)
|
|
47
46
|
.replace(/(["']).*?\1|url\(("|')([^'"()\s]+)\2\)/g, (m,q1,q2,u) => q1 ? m : "url(" + u + ")")
|
|
47
|
+
, hex = n => (0 | +n + 256.5).toString(16).slice(1)
|
|
48
48
|
, toRgb = {
|
|
49
|
-
rgb(r, g, b)
|
|
50
|
-
var f = n => ((n | 0) + 256).toString(16).slice(1)
|
|
51
|
-
return f(r) + f(g) + f(b)
|
|
52
|
-
},
|
|
49
|
+
rgb: (r, g, b) => hex(r) + hex(g) + hex(b),
|
|
53
50
|
hsl(h, s, l) {
|
|
54
51
|
l /= 100
|
|
55
52
|
s /= 100 / (l < 0.5 ? l : 1 - l)
|
|
56
53
|
function f(n) {
|
|
57
54
|
n = (n + h / 30) % 12
|
|
58
|
-
return (
|
|
55
|
+
return hex(255 * (l - s * (n < 2 || n > 10 ? -1 : n < 4 ? n - 3 : n > 8 ? 9 - n : 1)))
|
|
59
56
|
}
|
|
60
57
|
return f(0) + f(8) + f(4)
|
|
61
58
|
}
|
|
@@ -89,7 +86,6 @@ var fs = require("fs")
|
|
|
89
86
|
for (; (m = re.exec(val)); ) {
|
|
90
87
|
if (m[4]) {
|
|
91
88
|
if (min && len && plugins[m[4] = m[4].trim()]) style[k = style[len - 1]] = clear(plugins[m[4]](sheet, style[k]))
|
|
92
|
-
continue
|
|
93
89
|
} else {
|
|
94
90
|
k = m[1]
|
|
95
91
|
if (lastIdx[k] >= 0) style.__[lastIdx[k]] = style[k]
|
|
@@ -235,10 +231,11 @@ CSSStyleSheet.prototype = {
|
|
|
235
231
|
} else if (char === "{") {
|
|
236
232
|
depth++
|
|
237
233
|
} else if (char === "}" && --depth < 1 || char === ";" && depth < 1) {
|
|
238
|
-
if (depth < 0) throw "
|
|
234
|
+
if (depth < 0) throw Error("Unexpected '}'")
|
|
239
235
|
sheet.rules.push(CSSRule(text.slice(start, start = pos + 1), sheet, char))
|
|
240
236
|
}
|
|
241
237
|
}
|
|
238
|
+
if (depth > 0) throw Error("Unclosed block")
|
|
242
239
|
},
|
|
243
240
|
toString(min) {
|
|
244
241
|
if (min) this.min = min
|
|
@@ -246,25 +243,4 @@ CSSStyleSheet.prototype = {
|
|
|
246
243
|
}
|
|
247
244
|
}
|
|
248
245
|
|
|
249
|
-
function selectorSplit(text) {
|
|
250
|
-
for (var char, inQuote, depth = 0, start = 0, pos = 0, len = text.length, out = []; pos < len; ) {
|
|
251
|
-
char = text[pos++]
|
|
252
|
-
if (char === "\\") {
|
|
253
|
-
pos++
|
|
254
|
-
} else if (inQuote) {
|
|
255
|
-
if (char === inQuote) inQuote = ""
|
|
256
|
-
} else if (char === "'" || char === "\"") {
|
|
257
|
-
inQuote = char
|
|
258
|
-
} else if (char === "(" || char === "[") {
|
|
259
|
-
depth++
|
|
260
|
-
} else if (char === ")" || char === "]") {
|
|
261
|
-
depth--
|
|
262
|
-
} else if (char === "," && depth === 0) {
|
|
263
|
-
out.push(text.slice(start, (start = pos) - 1).trim())
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
out.push(text.slice(start).trim())
|
|
267
|
-
return out
|
|
268
|
-
}
|
|
269
|
-
|
|
270
246
|
|
package/dom.js
CHANGED
|
@@ -21,8 +21,9 @@ var boolAttrs = {
|
|
|
21
21
|
, rawTextElements = { SCRIPT: /<(?=\/script)/i, STYLE: /<(?=\/style)/i }
|
|
22
22
|
, rawTextEscape = { SCRIPT: /<(?=\/script|!--)/ig, STYLE: /<(?=\/style|!--)/ig }
|
|
23
23
|
, hasOwn = voidElements.hasOwnProperty
|
|
24
|
-
, {
|
|
24
|
+
, { CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
|
|
25
25
|
, selector = require("./selector.js")
|
|
26
|
+
, cssEscape = sel => ("" + sel).replace(/[^a-zA-Z0-9_\u00A0-\uFFFF-]/g, "\\$&").replace(/^(-?)([0-9])/, "$1\\3$2 ")
|
|
26
27
|
, Node = {
|
|
27
28
|
ELEMENT_NODE: 1,
|
|
28
29
|
TEXT_NODE: 3,
|
|
@@ -108,17 +109,6 @@ var boolAttrs = {
|
|
|
108
109
|
child.setAttribute(name, (q ? qvalue : value || "").replace(unescRe, unescFn))
|
|
109
110
|
}
|
|
110
111
|
},
|
|
111
|
-
get outerHTML() {
|
|
112
|
-
return this.toString()
|
|
113
|
-
},
|
|
114
|
-
set outerHTML(html) {
|
|
115
|
-
var frag = this.ownerDocument.createDocumentFragment()
|
|
116
|
-
frag.innerHTML = html
|
|
117
|
-
this.parentNode.replaceChild(frag, this)
|
|
118
|
-
},
|
|
119
|
-
get sheet() {
|
|
120
|
-
return makeSheet(this)
|
|
121
|
-
},
|
|
122
112
|
get style() {
|
|
123
113
|
return this._style || (this._style = CSSStyleDeclaration(this.getAttribute("style") || ""))
|
|
124
114
|
},
|
|
@@ -205,6 +195,14 @@ var boolAttrs = {
|
|
|
205
195
|
get previousElementSibling() {
|
|
206
196
|
return getSibling(this, -1, 1)
|
|
207
197
|
},
|
|
198
|
+
get outerHTML() {
|
|
199
|
+
return this.toString()
|
|
200
|
+
},
|
|
201
|
+
set outerHTML(html) {
|
|
202
|
+
var frag = this.ownerDocument.createDocumentFragment()
|
|
203
|
+
frag.innerHTML = html
|
|
204
|
+
this.parentNode.replaceChild(frag, this)
|
|
205
|
+
},
|
|
208
206
|
replaceChildren() {
|
|
209
207
|
removeChilds(this)
|
|
210
208
|
for (var i = 0, l = arguments.length; i < l; ) this.insertBefore(arguments[i++])
|
|
@@ -261,7 +259,7 @@ function addGetter(key, opts) {
|
|
|
261
259
|
})
|
|
262
260
|
}
|
|
263
261
|
|
|
264
|
-
;["hasAttribute", "getAttribute", "setAttribute", "removeAttribute"].forEach(
|
|
262
|
+
;["hasAttribute", "getAttribute", "setAttribute", "removeAttribute"].forEach(name => {
|
|
265
263
|
Element[name + "NS"] = function(ns, a, b) {
|
|
266
264
|
return this[name].call(this, a, b)
|
|
267
265
|
}
|
|
@@ -350,6 +348,9 @@ extendNode(HTMLElement, Element, {
|
|
|
350
348
|
namespaceURI: "http://www.w3.org/1999/xhtml",
|
|
351
349
|
nodeType: 1,
|
|
352
350
|
tagName: null,
|
|
351
|
+
get sheet() {
|
|
352
|
+
return makeSheet(this)
|
|
353
|
+
},
|
|
353
354
|
blur() {
|
|
354
355
|
this.ownerDocument.activeElement = null
|
|
355
356
|
},
|
|
@@ -521,7 +522,8 @@ function mergeAttributes(source, target) {
|
|
|
521
522
|
exports.document = new Document()
|
|
522
523
|
exports.entities = entities
|
|
523
524
|
exports.mergeAttributes = mergeAttributes
|
|
524
|
-
exports.selectorSplit = selectorSplit
|
|
525
|
+
exports.selectorSplit = selector.selectorSplit
|
|
526
|
+
exports.cssEscape = cssEscape
|
|
525
527
|
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
526
528
|
exports.CSSStyleSheet = CSSStyleSheet
|
|
527
529
|
exports.DOMParser = DOMParser
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litejs/dom",
|
|
3
|
-
"version": "25.
|
|
3
|
+
"version": "25.9.0",
|
|
4
4
|
"description": "A small DOM library for server-side testing, rendering, and handling of HTML files",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lauri Rooden <lauri@rooden.ee>",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"test": "lj t"
|
|
24
24
|
},
|
|
25
|
-
"repository": "github
|
|
25
|
+
"repository": "https://github.com/litejs/dom.git",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@litejs/cli": "25.1.0"
|
|
28
28
|
}
|
package/selector.js
CHANGED
|
@@ -3,112 +3,117 @@
|
|
|
3
3
|
|
|
4
4
|
"use strict"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"": function() {}
|
|
9
|
-
}
|
|
10
|
-
, selectorRe = /([.#:[])([-\w]+)(?:\(((?:[^()]|\([^)]+\))+?)\)|([~^$*|]?)=(("|')(?:\\.|[^\\])*?\6|[-\w]+))?]?/g
|
|
11
|
-
, selectorLastRe = /([\s>+~]*)(?:("|')(?:\\.|[^\\])*?\2|\((?:[^()]|\([^()]+\))+?\)|~=|[^'"()\s>+~])+$/
|
|
12
|
-
, selectorSplitRe = /\s*,\s*(?=(?:[^'"()]|"(?:\\.|[^\\"])*?"|'(?:\\.|[^\\'])*?'|\((?:[^()]|\([^()]+\))+?\))+$)/
|
|
13
|
-
, selectorMap = {
|
|
14
|
-
"contains": "_.textContent.indexOf(v)>-1",
|
|
15
|
-
"empty": "!_.lastChild",
|
|
16
|
-
"enabled": "!m(_,':disabled')",
|
|
17
|
-
"first-child": "(a=_.parentNode)&&a.firstChild==_",
|
|
18
|
-
"first-of-type": "!p(_,_.tagName)",
|
|
19
|
-
"is": "m(_,v)",
|
|
20
|
-
"lang": "m(c(_,'[lang]'),'[lang|='+v+']')",
|
|
21
|
-
"last-child": "(a=_.parentNode)&&a.lastChild==_",
|
|
22
|
-
"last-of-type": "!n(_,_.tagName)",
|
|
23
|
-
"link": "m(_,'a[href]')",
|
|
24
|
-
"not": "!m(_,v)",
|
|
25
|
-
"nth-child": "(a=2,'odd'==v?b=1:'even'==v?b=0:a=1 in(v=v.split('n'))?(b=v[1],v[0]):(b=v[0],0),v=_.parentNode.childNodes,v=1+v.indexOf(_),0==a?v==b:('-'==a||0==(v-b)%a)&&(0<a||v<=b))",
|
|
26
|
-
"only-child": "(a=_.parentNode)&&a.firstChild==a.lastChild",
|
|
27
|
-
"only-of-type": "!p(_,_.tagName)&&!n(_,_.tagName)",
|
|
28
|
-
"optional": "!m(_,':required')",
|
|
29
|
-
"root": "(a=_.parentNode)&&!a.tagName",
|
|
30
|
-
".": "~_.className.split(/\\s+/).indexOf(a)",
|
|
31
|
-
"#": "_.id==a",
|
|
32
|
-
"^": "!a.indexOf(v)",
|
|
33
|
-
"|": "a.split('-')[0]==v",
|
|
34
|
-
"$": "a.slice(-v.length)==v",
|
|
35
|
-
"~": "~a.split(/\\s+/).indexOf(v)",
|
|
36
|
-
"*": "~a.indexOf(v)",
|
|
37
|
-
">>": "m(_.parentNode,v)",
|
|
38
|
-
"++": "m(_.previousSibling,v)",
|
|
39
|
-
"~~": "p(_,v)",
|
|
40
|
-
"": "c(_.parentNode,v)"
|
|
41
|
-
}
|
|
42
|
-
, closest = exports.closest = walk.bind(exports, "parentNode", 1)
|
|
6
|
+
exports.find = find
|
|
7
|
+
exports.selectorSplit = selectorSplit
|
|
43
8
|
|
|
9
|
+
var selectorCache = {
|
|
10
|
+
"": () => {}
|
|
11
|
+
}
|
|
12
|
+
, selectorRe = /([.#:[])([-\w]+)(?:\(((?:[^()]|\([^)]+\))+?)\)|([~^$*|]?)=(("|')(?:\\.|[^\\])*?\6|[-\w]+))?]?/g
|
|
13
|
+
, selectorLastRe = /([\s>+~]*)(?:("|')(?:\\.|[^\\])*?\2|\((?:[^()]|\([^()]+\))+?\)|~=|[^'"()\s>+~])+$/
|
|
14
|
+
, selectorMap = exports.selectorMap = {
|
|
15
|
+
"contains": "_.textContent.indexOf(v)>-1",
|
|
16
|
+
"empty": "!_.lastChild",
|
|
17
|
+
"enabled": "!m(_,':disabled')",
|
|
18
|
+
"first-child": "(a=_.parentNode)&&a.firstChild==_",
|
|
19
|
+
"first-of-type": "!p(_,_.tagName)",
|
|
20
|
+
"is": "m(_,v)",
|
|
21
|
+
"lang": "m(c(_,'[lang]'),'[lang|='+v+']')",
|
|
22
|
+
"last-child": "(a=_.parentNode)&&a.lastChild==_",
|
|
23
|
+
"last-of-type": "!n(_,_.tagName)",
|
|
24
|
+
"link": "m(_,'a[href]')",
|
|
25
|
+
"not": "!m(_,v)",
|
|
26
|
+
"nth-child": "(a=2,'odd'==v?b=1:'even'==v?b=0:a=1 in(v=v.split('n'))?(b=v[1],v[0]):(b=v[0],0),v=_.parentNode.childNodes,v=1+v.indexOf(_),0==a?v==b:('-'==a||0==(v-b)%a)&&(0<a||v<=b))",
|
|
27
|
+
"only-child": "(a=_.parentNode)&&a.firstChild==a.lastChild",
|
|
28
|
+
"only-of-type": "!p(_,_.tagName)&&!n(_,_.tagName)",
|
|
29
|
+
"optional": "!m(_,':required')",
|
|
30
|
+
"root": "(a=_.parentNode)&&!a.tagName",
|
|
31
|
+
".": "~_.className.split(/\\s+/).indexOf(a)",
|
|
32
|
+
"#": "_.id==a",
|
|
33
|
+
"^": "!a.indexOf(v)",
|
|
34
|
+
"|": "a.split('-')[0]==v",
|
|
35
|
+
"$": "a.slice(-v.length)==v",
|
|
36
|
+
"~": "~a.split(/\\s+/).indexOf(v)",
|
|
37
|
+
"*": "~a.indexOf(v)",
|
|
38
|
+
">>": "m(_.parentNode,v)",
|
|
39
|
+
"++": "m(_.previousElementSibling,v)",
|
|
40
|
+
"~~": "p(_,v)",
|
|
41
|
+
"": "c(_.parentNode,v)"
|
|
42
|
+
}
|
|
43
|
+
, closest = exports.closest = walk.bind(exports, "parentNode", 1)
|
|
44
|
+
, matches = exports.matches = (el, sel) => !!selectorFn(sel)(el)
|
|
45
|
+
, next = exports.next = (el, sel) => walk("nextSibling", 1, el.nextSibling, sel)
|
|
46
|
+
, prev = exports.prev = (el, sel) => walk("previousSibling", 1, el.previousSibling, sel)
|
|
44
47
|
|
|
45
|
-
selectorMap["nth-last-child"] = selectorMap["nth-child"].replace("1+", "v.length-")
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
if (str != null && typeof str !== "string") throw Error("Invalid selector")
|
|
49
|
-
return selectorCache[str || ""] ||
|
|
50
|
-
(selectorCache[str] = Function("m,c,n,p", "return function(_,v,a,b){return " +
|
|
51
|
-
str.split(selectorSplitRe).map(function(sel) {
|
|
52
|
-
var relation, from
|
|
53
|
-
, rules = ["_&&_.nodeType==1"]
|
|
54
|
-
, parentSel = sel.replace(selectorLastRe, function(_, _rel, a, start) {
|
|
55
|
-
from = start + _rel.length
|
|
56
|
-
relation = _rel.trim()
|
|
57
|
-
return ""
|
|
58
|
-
})
|
|
59
|
-
, tag = sel.slice(from).replace(selectorRe, function(_, op, key, subSel, fn, val, quotation) {
|
|
60
|
-
rules.push(
|
|
61
|
-
"((v='" +
|
|
62
|
-
(subSel || (quotation ? val.slice(1, -1) : val) || "").replace(/[\\']/g, "\\$&") +
|
|
63
|
-
"'),(a='" + key + "'),1)"
|
|
64
|
-
,
|
|
65
|
-
selectorMap[op == ":" ? key : op] ||
|
|
66
|
-
"(a=_.getAttribute(a))" +
|
|
67
|
-
(fn ? "&&" + selectorMap[fn] : val ? "==v" : "!==null")
|
|
68
|
-
)
|
|
69
|
-
return ""
|
|
70
|
-
})
|
|
49
|
+
selectorMap["nth-last-child"] = selectorMap["nth-child"].replace("1+", "v.length-")
|
|
71
50
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
)(
|
|
77
|
-
|
|
51
|
+
function selectorFn(str) {
|
|
52
|
+
if (str != null && typeof str !== "string") throw Error("Invalid selector")
|
|
53
|
+
return selectorCache[str || ""] ||
|
|
54
|
+
(selectorCache[str] = Function("m,c,n,p", "return (_,v,a,b)=>" +
|
|
55
|
+
selectorSplit(str).map(sel => {
|
|
56
|
+
var relation, from
|
|
57
|
+
, rules = ["_&&_.nodeType==1"]
|
|
58
|
+
, parentSel = sel.replace(selectorLastRe, (_, _rel, a, start) => {
|
|
59
|
+
from = start + _rel.length
|
|
60
|
+
relation = _rel.trim()
|
|
61
|
+
return ""
|
|
62
|
+
})
|
|
63
|
+
, tag = sel.slice(from).replace(selectorRe, (_, op, key, subSel, fn, val, quotation) => {
|
|
64
|
+
rules.push(
|
|
65
|
+
"((v='" +
|
|
66
|
+
(subSel || (quotation ? val.slice(1, -1) : val) || "").replace(/[\\']/g, "\\$&") +
|
|
67
|
+
"'),(a='" + key + "'),1)"
|
|
68
|
+
,
|
|
69
|
+
selectorMap[op == ":" ? key : op] ||
|
|
70
|
+
"(a=_.getAttribute(a))" +
|
|
71
|
+
(fn ? "&&" + selectorMap[fn] : val ? "==v" : "!==null")
|
|
72
|
+
)
|
|
73
|
+
return ""
|
|
74
|
+
})
|
|
78
75
|
|
|
76
|
+
if (tag && tag != "*") rules[0] += "&&_.tagName==(_.namespaceURI?'" + tag.toUpperCase() + "':'" + tag + "')"
|
|
77
|
+
if (parentSel) rules.push("(v='" + parentSel + "')", selectorMap[relation + relation])
|
|
78
|
+
return rules.join("&&")
|
|
79
|
+
}).join("||")
|
|
80
|
+
)(matches, closest, next, prev))
|
|
81
|
+
}
|
|
79
82
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
function selectorSplit(text) {
|
|
84
|
+
for (var char, inQuote, depth = 0, start = 0, pos = 0, len = text.length, out = []; pos < len; ) {
|
|
85
|
+
char = text[pos++]
|
|
86
|
+
if (char === "\\") {
|
|
87
|
+
pos++
|
|
88
|
+
} else if (inQuote) {
|
|
89
|
+
if (char === inQuote) inQuote = ""
|
|
90
|
+
} else if (char === "'" || char === "\"") {
|
|
91
|
+
inQuote = char
|
|
92
|
+
} else if (char === "(" || char === "[") {
|
|
93
|
+
depth++
|
|
94
|
+
} else if (char === ")" || char === "]") {
|
|
95
|
+
depth--
|
|
96
|
+
} else if (char === "," && depth === 0) {
|
|
97
|
+
out.push(text.slice(start, (start = pos) - 1).trim())
|
|
85
98
|
}
|
|
86
|
-
return first ? null : out
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function find(node, sel, first) {
|
|
90
|
-
return walk("firstChild", first, node.firstChild, sel, function(el) {
|
|
91
|
-
for (var next = el.nextSibling; !next && ((el = el.parentNode) !== node); ) next = el.nextSibling
|
|
92
|
-
return next
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function matches(el, sel) {
|
|
97
|
-
return !!selectorFn(sel)(el)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function next(el, sel) {
|
|
101
|
-
return walk("nextSibling", 1, el.nextSibling, sel)
|
|
102
99
|
}
|
|
100
|
+
out.push(text.slice(start).trim())
|
|
101
|
+
return out
|
|
102
|
+
}
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
function walk(attr, first, el, sel, nextFn) {
|
|
105
|
+
sel = selectorFn(sel)
|
|
106
|
+
for (var out = []; el; el = el[attr] || nextFn && nextFn(el)) if (sel(el)) {
|
|
107
|
+
if (first) return el
|
|
108
|
+
out.push(el)
|
|
106
109
|
}
|
|
110
|
+
return first ? null : out
|
|
111
|
+
}
|
|
107
112
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
113
|
+
function find(node, sel, first) {
|
|
114
|
+
return walk("firstChild", first, node.firstChild, sel, (el, pos) => {
|
|
115
|
+
for (pos = el.nextSibling; !pos && ((el = el.parentNode) !== node); ) pos = el.nextSibling
|
|
116
|
+
return pos
|
|
117
|
+
})
|
|
118
|
+
}
|
|
114
119
|
|