@litejs/dom 24.12.0 → 25.5.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/README.md +14 -8
- package/css.js +168 -34
- package/dom.js +89 -53
- package/net.js +2 -0
- package/package.json +3 -4
- package/selector.js +1 -1
- package/interactive.js +0 -18
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
LiteJS DOM – [![Coverage][1]][2] [![Size][3]][4] [![Buy Me A Tea][5]][6]
|
|
11
11
|
==========
|
|
12
12
|
|
|
13
|
-
Dependency-free DOM library for handling HTML files on server-side.
|
|
13
|
+
Dependency-free DOM library for handling HTML, XML and CSS files on server-side.
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
```javascript
|
|
17
|
-
import { document, DOMParser, XMLSerializer } from "@litejs/dom";
|
|
18
|
-
import { XMLHttpRequest } from "@litejs/dom/net.js";
|
|
19
17
|
// const { document } = require("@litejs/dom");
|
|
18
|
+
import { document, CSSStyleSheet, DOMParser, XMLSerializer } from "@litejs/dom";
|
|
19
|
+
import { XMLHttpRequest } from "@litejs/dom/net.js";
|
|
20
20
|
|
|
21
21
|
// Build DOM manually
|
|
22
22
|
const el = document.createElement("h1");
|
|
@@ -27,13 +27,13 @@ const fragment = document.createDocumentFragment();
|
|
|
27
27
|
fragment.appendChild(document.createTextNode("hello"));
|
|
28
28
|
el.appendChild(fragment);
|
|
29
29
|
|
|
30
|
-
// Replace the DOM tree with
|
|
30
|
+
// Replace the DOM tree with HTML
|
|
31
31
|
el.innerHTML = "<b>hello world</b>";
|
|
32
|
-
el.toString();
|
|
32
|
+
console.log(el.toString());
|
|
33
33
|
// <h1 id="123" class="large"><b>hello world</b></h1>
|
|
34
34
|
|
|
35
|
-
//
|
|
36
|
-
el.toString(true);
|
|
35
|
+
// Minify HTML
|
|
36
|
+
console.log(el.toString(true));
|
|
37
37
|
// <h1 id=123 class=large><b>hello world</b></h1>
|
|
38
38
|
|
|
39
39
|
el.querySelectorAll("b");
|
|
@@ -49,6 +49,12 @@ xhr.onload = function() {
|
|
|
49
49
|
console.log(doc.querySelector("title").textContent);
|
|
50
50
|
}
|
|
51
51
|
xhr.send();
|
|
52
|
+
|
|
53
|
+
// Minify CSS
|
|
54
|
+
const sheet = new CSSStyleSheet({ min: { color: true } })
|
|
55
|
+
sheet.replaceSync(".a { color: hsl(0 0% 100%) }")
|
|
56
|
+
console.log(sheet.toString())
|
|
57
|
+
// .a{color:#fff}
|
|
52
58
|
```
|
|
53
59
|
|
|
54
60
|
## Contributing
|
|
@@ -57,7 +63,7 @@ Follow [Coding Style Guide](https://github.com/litejs/litejs/wiki/Style-Guide),
|
|
|
57
63
|
run tests `npm install; npm test`.
|
|
58
64
|
|
|
59
65
|
|
|
60
|
-
> Copyright (c) 2014-
|
|
66
|
+
> Copyright (c) 2014-2025 Lauri Rooden <lauri@rooden.ee>
|
|
61
67
|
[MIT License](https://litejs.com/MIT-LICENSE.txt) |
|
|
62
68
|
[GitHub repo](https://github.com/litejs/dom) |
|
|
63
69
|
[npm package](https://npmjs.org/package/@litejs/dom) |
|
package/css.js
CHANGED
|
@@ -1,74 +1,162 @@
|
|
|
1
1
|
|
|
2
2
|
/*! litejs.com/MIT-LICENSE.txt */
|
|
3
3
|
|
|
4
|
+
"use strict"
|
|
5
|
+
|
|
6
|
+
exports.selectorSplit = selectorSplit
|
|
4
7
|
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
5
8
|
exports.CSSStyleSheet = CSSStyleSheet
|
|
6
9
|
|
|
7
|
-
var
|
|
8
|
-
|
|
10
|
+
var fs = require("fs")
|
|
11
|
+
, path = require("path")
|
|
12
|
+
, read = (sheet, url, enc = "utf8") => fs.readFileSync(path.resolve(sheet.min.root || "", sheet.baseURI, url).split(/[+#]/)[0], enc)
|
|
13
|
+
, plugins = exports.plugins = {
|
|
14
|
+
"data-uri": function(sheet, v) {
|
|
15
|
+
var { DOMParser } = require("./dom.js")
|
|
16
|
+
return v.replace(urlRe, function(_, q1, q2, url) {
|
|
17
|
+
if (q1) return _
|
|
18
|
+
var frag = url.split("#").pop()
|
|
19
|
+
, ext = url.split(/[?#]/)[0].split(".").pop()
|
|
20
|
+
, enc = ext === "svg" ? "utf8" : "base64"
|
|
21
|
+
url = read(sheet, url, enc)
|
|
22
|
+
if (ext === "svg") {
|
|
23
|
+
url = new DOMParser().parseFromString(url, "application/xml")
|
|
24
|
+
if (frag && (frag = url.getElementById(frag))) {
|
|
25
|
+
frag.removeAttribute("id")
|
|
26
|
+
url.documentElement.childNodes = frag.tagName === "g" ? frag.childNodes : [ frag ]
|
|
27
|
+
}
|
|
28
|
+
url = url.toString(true).replace(/#/g, "%23")
|
|
29
|
+
enc = ""
|
|
30
|
+
ext += "+xml"
|
|
31
|
+
}
|
|
32
|
+
return "url('data:image/" + ext + ";" + enc + "," + url + "')"
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
, urlRe = /(["']).*?\1|url\((['"]?)(?!\/|data:|https?:)(.*?)\2\)/g
|
|
37
|
+
, clearFn = (_, q, str, c) =>
|
|
38
|
+
q ? (q = str.indexOf("'") == -1 ? "'" : "\"", q + str.replace(q === "'" ? /\\(")/g : /\\(')/g, "$1")) + q :
|
|
39
|
+
c ? "" :
|
|
40
|
+
_.replace(/[\t\n]+/g, " ")
|
|
9
41
|
.replace(/ *([,;{}>~+\/]) */g, "$1")
|
|
10
|
-
.replace(
|
|
42
|
+
.replace(/;(?=})/g, "")
|
|
11
43
|
.replace(/: +/g, ":")
|
|
12
|
-
|
|
44
|
+
.replace(/([ :,])0\.([0-9])/g, "$1.$2")
|
|
45
|
+
, clear = s => s
|
|
46
|
+
.replace(/("|')((?:\\\1|[^\1])*?)\1|\s*(\/)\*(?:[^*]|\*(?!\/))*\*\/\s*|(?:[^"'\/]|\/(?!\*))+/g, clearFn)
|
|
47
|
+
.replace(/(["']).*?\1|url\(("|')([^'"()\s]+)\2\)/g, (m,q1,q2,u) => q1 ? m : "url(" + u + ")")
|
|
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
|
+
},
|
|
53
|
+
hsl(h, s, l) {
|
|
54
|
+
l /= 100
|
|
55
|
+
s /= 100 / (l < 0.5 ? l : 1 - l)
|
|
56
|
+
function f(n) {
|
|
57
|
+
n = (n + h / 30) % 12
|
|
58
|
+
return (0 | 256.5 + (255 * (l - s * (n < 2 || n > 10 ? -1 : n < 4 ? n - 3 : n > 8 ? 9 - n : 1)))).toString(16).slice(1)
|
|
59
|
+
}
|
|
60
|
+
return f(0) + f(8) + f(4)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
, toRgba = (rgbHex, alpha) => ("rgba(" + rgbHex.replace(/../g, x => parseInt(x, 16)+",") + alpha + ")").replace("0.", ".")
|
|
64
|
+
, colorRe = /\b(rgb|hsl)a?\s*\(\s*(\d+)(?:deg)?[\s,]+(\d+)[\s,%]+(\d+)%?(?:[\s,\/]+(0?\.?\d+)(%?))?\s*\)/g
|
|
65
|
+
, colorFn = (_, name, a, b, c, d, p) => (_ = toRgb[name](a, b, c), (p ? d/=100 : d) < 1 ? toRgba(_, d) : "#" + _.replace(/(\w)\1(\w)\2(\w)\3/, "$1$2$3"))
|
|
13
66
|
, styleHandler = {
|
|
14
67
|
get(style, prop) {
|
|
15
68
|
if (prop === "cssText") {
|
|
69
|
+
var min = style.parentRule && style.parentRule.parentStyleSheet.min
|
|
16
70
|
for (var out = [], i = style.length; i--; ) {
|
|
17
|
-
out[i] = style[i]
|
|
71
|
+
out[i] = joinProp(style[i], style.__[i] || style[style[i]])
|
|
18
72
|
}
|
|
19
73
|
return out.join(";")
|
|
20
74
|
}
|
|
21
75
|
return style[prop] || ""
|
|
76
|
+
function joinProp(name, value) {
|
|
77
|
+
if (min && min.color) value = value.replace(colorRe, colorFn)
|
|
78
|
+
return name + ":" + value
|
|
79
|
+
}
|
|
22
80
|
},
|
|
23
81
|
set(style, prop, val) {
|
|
24
82
|
if (prop === "cssText") {
|
|
25
83
|
var m, k
|
|
26
|
-
,
|
|
84
|
+
, sheet = style.parentRule && style.parentRule.parentStyleSheet
|
|
85
|
+
, min = sheet && sheet.min
|
|
86
|
+
, re = /([*_]?[-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)|\/\*!?((?:[^*]|\*(?!\/))*)\*\//ig
|
|
27
87
|
, len = 0
|
|
28
88
|
, lastIdx = {}
|
|
29
89
|
for (; (m = re.exec(val)); ) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
90
|
+
if (m[4]) {
|
|
91
|
+
if (min && len && plugins[m[4] = m[4].trim()]) style[k = style[len - 1]] = clear(plugins[m[4]](sheet, style[k]))
|
|
92
|
+
continue
|
|
93
|
+
} else {
|
|
94
|
+
k = m[1]
|
|
95
|
+
if (lastIdx[k] >= 0) style.__[lastIdx[k]] = style[k]
|
|
96
|
+
style[style[lastIdx[k] = len++] = k] = style[
|
|
97
|
+
k === "float" ? "cssFloat" : k.replace(/-([a-z])/g, (_, a) => a.toUpperCase())
|
|
98
|
+
] = clear(m[2]).trim()
|
|
99
|
+
}
|
|
35
100
|
}
|
|
36
101
|
style.length = len
|
|
37
102
|
} else {
|
|
38
103
|
if (!style[prop]) style[style.length++] = prop
|
|
39
104
|
style[prop] = style[prop === "cssFloat" ? "float" : prop.replace(/[A-Z]/g, "-$&").toLowerCase()] = clear(val)
|
|
40
105
|
}
|
|
106
|
+
return true
|
|
41
107
|
}
|
|
42
108
|
}
|
|
43
109
|
, ruleTypes = {
|
|
44
110
|
style: {
|
|
111
|
+
type: 1,
|
|
45
112
|
get cssText() {
|
|
46
113
|
return this.style.length > 0 ? this.selectorText + "{" + this.style.cssText + "}" : ""
|
|
47
114
|
},
|
|
48
115
|
set cssText(text) {
|
|
49
116
|
var idx = text.indexOf("{")
|
|
50
|
-
this.selectorText = text.slice(0, idx).trim()
|
|
117
|
+
this.selectorText = clear(text.slice(0, idx).trim())
|
|
51
118
|
this.style = CSSStyleDeclaration(text.slice(idx + 1).replace(/}\s*/, ""), this)
|
|
52
119
|
}
|
|
53
120
|
},
|
|
54
121
|
import: {
|
|
55
122
|
get cssText() {
|
|
56
|
-
|
|
123
|
+
var sheet = this.parentStyleSheet
|
|
124
|
+
, min = sheet.min
|
|
125
|
+
, text = this.text
|
|
126
|
+
, urlFn = (m,q1,q2,u) => q1 ? m : "url('" + path.join(text.baseURI, u) + "')"
|
|
127
|
+
if (min && min.import) {
|
|
128
|
+
text = new CSSStyleSheet({
|
|
129
|
+
parentStyleSheet: sheet,
|
|
130
|
+
href: this.href,
|
|
131
|
+
min
|
|
132
|
+
}, read(sheet, this.href))
|
|
133
|
+
if (sheet.baseURI !== text.baseURI) {
|
|
134
|
+
text.rules.forEach(rule => {
|
|
135
|
+
if (rule.type === 1) for (let style = rule.style, i = style.length; i--; ) {
|
|
136
|
+
if (urlRe.test(style[style[i]])) style[style[i]] = style[style[i]].replace(urlRe, urlFn)
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
text += ""
|
|
141
|
+
}
|
|
142
|
+
return text
|
|
57
143
|
},
|
|
58
144
|
set cssText(text) {
|
|
59
|
-
this.
|
|
145
|
+
this.href = text.split(/['"()]+/)[1]
|
|
146
|
+
this.text = clear(text.replace(/url\(("|')(.+?)\1\)/g, "'$2'"))
|
|
60
147
|
}
|
|
61
148
|
},
|
|
62
149
|
"}": {
|
|
63
150
|
get cssText() {
|
|
64
|
-
var
|
|
65
|
-
|
|
151
|
+
var style = new CSSStyleSheet({})
|
|
152
|
+
style.replaceSync(this.text)
|
|
153
|
+
var body = "" + style
|
|
154
|
+
return body.length > 0 ? this.mediaText + "{" + body + "}" : ""
|
|
66
155
|
},
|
|
67
156
|
set cssText(text) {
|
|
68
157
|
var idx = text.indexOf("{")
|
|
69
158
|
this.mediaText = clear(text.slice(0, idx).trim())
|
|
70
|
-
this.
|
|
71
|
-
this.style.replaceSync(text.slice(idx + 1, -1))
|
|
159
|
+
this.text = text.slice(idx + 1, -1)
|
|
72
160
|
}
|
|
73
161
|
},
|
|
74
162
|
";": {
|
|
@@ -83,12 +171,12 @@ var clearFn = (_, q, str) => q ? (q == "\"" && str.indexOf("'") == -1 ? "'" + st
|
|
|
83
171
|
|
|
84
172
|
function CSSRule(text, parentStyleSheet, atType, parentRule = null) {
|
|
85
173
|
// Clear comments and trim
|
|
86
|
-
text = text.
|
|
174
|
+
text = text.trim()
|
|
87
175
|
var type = text[0] === "@" && text.slice(1, text.indexOf(" ")) || "style"
|
|
88
|
-
, rule = Object.create(ruleTypes[type] || ruleTypes[type === "font-face" || type === "counter-style" ? "style" : atType])
|
|
89
|
-
rule.cssText = text
|
|
176
|
+
, rule = Object.create(ruleTypes[type] || ruleTypes[type === "page" || type === "font-face" || type === "counter-style" ? "style" : atType])
|
|
90
177
|
rule.parentStyleSheet = parentStyleSheet
|
|
91
178
|
rule.parentRule = parentRule
|
|
179
|
+
rule.cssText = rule.type === 1 ? text : text.replace(/\/\*(?:[^*]|\*(?!\/))*\*\//g, "")
|
|
92
180
|
return rule
|
|
93
181
|
}
|
|
94
182
|
|
|
@@ -98,12 +186,21 @@ function CSSStyleDeclaration(text, parentRule = null) {
|
|
|
98
186
|
return style
|
|
99
187
|
}
|
|
100
188
|
|
|
101
|
-
function CSSStyleSheet(opts) {
|
|
189
|
+
function CSSStyleSheet(opts, text = "") {
|
|
102
190
|
Object.assign(this, opts)
|
|
103
|
-
|
|
191
|
+
if (opts && opts.href) {
|
|
192
|
+
this.baseURI = path.join(
|
|
193
|
+
(opts.parentStyleSheet || opts.ownerNode && opts.ownerNode.ownerDocument).baseURI || "",
|
|
194
|
+
opts.href,
|
|
195
|
+
".."
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
this.replaceSync(text)
|
|
104
199
|
}
|
|
105
200
|
|
|
106
201
|
CSSStyleSheet.prototype = {
|
|
202
|
+
baseURI: "",
|
|
203
|
+
root: "",
|
|
107
204
|
disabled: false,
|
|
108
205
|
type: "text/css",
|
|
109
206
|
deleteRule(idx) {
|
|
@@ -113,24 +210,61 @@ CSSStyleSheet.prototype = {
|
|
|
113
210
|
this.rules.splice(idx > -1 ? idx : this.rules.length, 0, CSSRule(rule, this))
|
|
114
211
|
},
|
|
115
212
|
replaceSync(text) {
|
|
116
|
-
var
|
|
117
|
-
, sheet = this
|
|
118
|
-
, re = /((?:("|')(?:\\.|(?!\2)[^\\])*?\2|[^"'}{;])+)|./ig
|
|
119
|
-
, block = 0
|
|
120
|
-
, pos = 0
|
|
213
|
+
var qpos, sheet = this
|
|
121
214
|
sheet.rules = sheet.cssRules = []
|
|
122
215
|
sheet.warnings = []
|
|
123
|
-
for (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
216
|
+
for (var char, inQuote, depth = 0, start = 0, pos = 0, len = text.length; pos < len; pos++) {
|
|
217
|
+
char = text[pos]
|
|
218
|
+
if (char === "\\" && inQuote !== "/") {
|
|
219
|
+
pos++
|
|
220
|
+
} else if (inQuote) {
|
|
221
|
+
if (char === inQuote) {
|
|
222
|
+
if (char !== "/" || text[pos - 1] === "*") {
|
|
223
|
+
if (char === "/" && depth < 1) {
|
|
224
|
+
// Remove root level comments
|
|
225
|
+
text = text.slice(0, qpos) + text.slice(pos + 1)
|
|
226
|
+
pos = qpos - 1
|
|
227
|
+
len = text.length
|
|
228
|
+
}
|
|
229
|
+
inQuote = ""
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} else if (char === "'" || char === "\"" || char === "/" && text[pos+1] === "*") {
|
|
233
|
+
inQuote = char
|
|
234
|
+
qpos = pos
|
|
235
|
+
} else if (char === "{") {
|
|
236
|
+
depth++
|
|
237
|
+
} else if (char === "}" && --depth < 1 || char === ";" && depth < 1) {
|
|
238
|
+
if (depth < 0) throw "Invalid css"
|
|
239
|
+
sheet.rules.push(CSSRule(text.slice(start, start = pos + 1), sheet, char))
|
|
128
240
|
}
|
|
129
241
|
}
|
|
130
242
|
},
|
|
131
|
-
toString() {
|
|
243
|
+
toString(min) {
|
|
244
|
+
if (min) this.min = min
|
|
132
245
|
return this.rules.map(rule => rule.cssText).filter(Boolean).join("\n")
|
|
133
246
|
}
|
|
134
247
|
}
|
|
135
248
|
|
|
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
|
+
|
|
136
270
|
|
package/dom.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*! litejs.com/MIT-LICENSE.txt */
|
|
3
3
|
|
|
4
|
+
"use strict"
|
|
5
|
+
|
|
4
6
|
var boolAttrs = {
|
|
5
7
|
async:1, autoplay:1, loop:1, checked:1, defer:1, disabled:1, muted:1, multiple:1, nomodule:1, playsinline:1, readonly:1, required:1, selected:1
|
|
6
8
|
}
|
|
@@ -13,10 +15,13 @@ var boolAttrs = {
|
|
|
13
15
|
, voidElements = {
|
|
14
16
|
AREA:1, BASE:1, BR:1, COL:1, EMBED:1, HR:1, IMG:1, INPUT:1, KEYGEN:1, LINK:1, MENUITEM:1, META:1, PARAM:1, SOURCE:1, TRACK:1, WBR:1
|
|
15
17
|
}
|
|
18
|
+
, svgVoidElements = {
|
|
19
|
+
circle:1, ellipse:1, image:1, line:1, path:1, polygon:1, polyline:1, rect:1, stop:1, use:1,
|
|
20
|
+
}
|
|
16
21
|
, rawTextElements = { SCRIPT: /<(?=\/script)/i, STYLE: /<(?=\/style)/i }
|
|
17
22
|
, rawTextEscape = { SCRIPT: /<(?=\/script|!--)/ig, STYLE: /<(?=\/style|!--)/ig }
|
|
18
23
|
, hasOwn = voidElements.hasOwnProperty
|
|
19
|
-
, { CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
|
|
24
|
+
, { selectorSplit, CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
|
|
20
25
|
, selector = require("./selector.js")
|
|
21
26
|
, Node = {
|
|
22
27
|
ELEMENT_NODE: 1,
|
|
@@ -41,9 +46,12 @@ var boolAttrs = {
|
|
|
41
46
|
},
|
|
42
47
|
set textContent(text) {
|
|
43
48
|
if (this.nodeType === 3 || this.nodeType === 8) this.data = text
|
|
44
|
-
else
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
else {
|
|
50
|
+
removeChilds(this)
|
|
51
|
+
this.appendChild(this.ownerDocument.createTextNode(
|
|
52
|
+
rawTextEscape[this.tagName] ? text.replace(rawTextEscape[this.tagName], "<\\") : text
|
|
53
|
+
))
|
|
54
|
+
}
|
|
47
55
|
},
|
|
48
56
|
get firstChild() {
|
|
49
57
|
return this.childNodes && this.childNodes[0] || null
|
|
@@ -69,6 +77,7 @@ var boolAttrs = {
|
|
|
69
77
|
, attrRe = /([^=\s]+)(?:\s*=\s*(("|')((?:\\\3|[\s\S])*?)\3|[^\s"'`=<>]+)|)/g
|
|
70
78
|
, frag = doc.createDocumentFragment()
|
|
71
79
|
, tree = frag
|
|
80
|
+
, voidEl = doc.documentElement.tagName === "svg" ? svgVoidElements : voidElements
|
|
72
81
|
|
|
73
82
|
for (; (m = tagRe.exec(html)); ) {
|
|
74
83
|
if (m[4]) {
|
|
@@ -83,7 +92,7 @@ var boolAttrs = {
|
|
|
83
92
|
for (text = ""; (m = tagRe.exec(html)) && !re.test(m[0]); text += m[3] || m[0]);
|
|
84
93
|
child.textContent = text.replace(unescRe, unescFn)
|
|
85
94
|
if (!m) break
|
|
86
|
-
} else if (!
|
|
95
|
+
} else if (!voidEl[child.tagName] && !m[8]) tree = child
|
|
87
96
|
} else {
|
|
88
97
|
tree.appendChild(
|
|
89
98
|
m[2] ? doc.createComment(m[2].replace(unescRe, unescFn)) :
|
|
@@ -92,7 +101,8 @@ var boolAttrs = {
|
|
|
92
101
|
)
|
|
93
102
|
}
|
|
94
103
|
}
|
|
95
|
-
|
|
104
|
+
removeChilds(node)
|
|
105
|
+
node.appendChild(frag)
|
|
96
106
|
|
|
97
107
|
function setAttr(_, name, value, q, qvalue) {
|
|
98
108
|
child.setAttribute(name, (q ? qvalue : value || "").replace(unescRe, unescFn))
|
|
@@ -107,10 +117,7 @@ var boolAttrs = {
|
|
|
107
117
|
this.parentNode.replaceChild(frag, this)
|
|
108
118
|
},
|
|
109
119
|
get sheet() {
|
|
110
|
-
|
|
111
|
-
href: this.href,
|
|
112
|
-
ownerNode: this
|
|
113
|
-
})
|
|
120
|
+
return makeSheet(this)
|
|
114
121
|
},
|
|
115
122
|
get style() {
|
|
116
123
|
return this._style || (this._style = CSSStyleDeclaration(this.getAttribute("style") || ""))
|
|
@@ -118,6 +125,21 @@ var boolAttrs = {
|
|
|
118
125
|
set style(value) {
|
|
119
126
|
this.style.cssText = value
|
|
120
127
|
},
|
|
128
|
+
appendChild(el) {
|
|
129
|
+
return this.insertBefore(el)
|
|
130
|
+
},
|
|
131
|
+
cloneNode(deep) {
|
|
132
|
+
var node = this
|
|
133
|
+
, clone = new node.constructor(node.tagName || node.data)
|
|
134
|
+
clone.ownerDocument = node.ownerDocument
|
|
135
|
+
|
|
136
|
+
mergeAttributes(node, clone)
|
|
137
|
+
|
|
138
|
+
if (deep && node.hasChildNodes()) {
|
|
139
|
+
node.childNodes.forEach(child => clone.appendChild(child.cloneNode(deep)))
|
|
140
|
+
}
|
|
141
|
+
return clone
|
|
142
|
+
},
|
|
121
143
|
contains(el) {
|
|
122
144
|
for (; el; el = el.parentNode) if (el === this) return true
|
|
123
145
|
return false
|
|
@@ -125,12 +147,6 @@ var boolAttrs = {
|
|
|
125
147
|
hasChildNodes() {
|
|
126
148
|
return !!this.firstChild
|
|
127
149
|
},
|
|
128
|
-
getElementById(id) {
|
|
129
|
-
return selector.find(this, "#" + id, 1)
|
|
130
|
-
},
|
|
131
|
-
appendChild(el) {
|
|
132
|
-
return this.insertBefore(el)
|
|
133
|
-
},
|
|
134
150
|
insertBefore(el, ref) {
|
|
135
151
|
var node = this
|
|
136
152
|
, childs = node.childNodes
|
|
@@ -163,20 +179,6 @@ var boolAttrs = {
|
|
|
163
179
|
this.insertBefore(el, ref)
|
|
164
180
|
return this.removeChild(ref)
|
|
165
181
|
},
|
|
166
|
-
cloneNode(deep) {
|
|
167
|
-
var node = this
|
|
168
|
-
, clone = new node.constructor(node.tagName || node.data)
|
|
169
|
-
clone.ownerDocument = node.ownerDocument
|
|
170
|
-
|
|
171
|
-
if (node.attributes) {
|
|
172
|
-
node.attributes.names().forEach(attr => clone.setAttribute(attr, node.getAttribute(attr)))
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (deep && node.hasChildNodes()) {
|
|
176
|
-
node.childNodes.forEach(child => clone.appendChild(child.cloneNode(deep)))
|
|
177
|
-
}
|
|
178
|
-
return clone
|
|
179
|
-
},
|
|
180
182
|
querySelector(sel) {
|
|
181
183
|
return selector.find(this, sel, 1)
|
|
182
184
|
},
|
|
@@ -185,7 +187,7 @@ var boolAttrs = {
|
|
|
185
187
|
},
|
|
186
188
|
toString(min) {
|
|
187
189
|
return rawTextElements[this.tagName] ? (
|
|
188
|
-
this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + this
|
|
190
|
+
this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + makeSheet(this, min.css || true) + "\n" :
|
|
189
191
|
this.textContent
|
|
190
192
|
) : this.childNodes.map(node => node.toString(min)).join("")
|
|
191
193
|
}
|
|
@@ -203,7 +205,10 @@ var boolAttrs = {
|
|
|
203
205
|
get previousElementSibling() {
|
|
204
206
|
return getSibling(this, -1, 1)
|
|
205
207
|
},
|
|
206
|
-
replaceChildren
|
|
208
|
+
replaceChildren() {
|
|
209
|
+
removeChilds(this)
|
|
210
|
+
for (var i = 0, l = arguments.length; i < l; ) this.insertBefore(arguments[i++])
|
|
211
|
+
},
|
|
207
212
|
hasAttribute(name) {
|
|
208
213
|
return this.attributes.getNamedItem(name) != null
|
|
209
214
|
},
|
|
@@ -236,18 +241,18 @@ var boolAttrs = {
|
|
|
236
241
|
"§": "§", "²": "²", "³": "³", "¥": "¥"
|
|
237
242
|
}
|
|
238
243
|
|
|
239
|
-
Object.keys(boolAttrs).forEach(addGetter, { isBool: true, readonly: "readOnly" })
|
|
240
|
-
numAttrs.split(" ").forEach(addGetter, { isNum: true })
|
|
241
|
-
strAttrs.split(" ").forEach(addGetter, { "for": "htmlFor", "class": "className" })
|
|
244
|
+
Object.keys(boolAttrs).forEach(key => addGetter(key, { isBool: true, readonly: "readOnly" }))
|
|
245
|
+
numAttrs.split(" ").forEach(key => addGetter(key, { isNum: true }))
|
|
246
|
+
strAttrs.split(" ").forEach(key => addGetter(key, { "for": "htmlFor", "class": "className" }))
|
|
242
247
|
|
|
243
|
-
function addGetter(key) {
|
|
248
|
+
function addGetter(key, opts) {
|
|
244
249
|
var attr = key.toLowerCase()
|
|
245
|
-
Object.defineProperty(Element,
|
|
250
|
+
Object.defineProperty(Element, opts[key] || key, {
|
|
246
251
|
configurable: true,
|
|
247
252
|
enumerable: true,
|
|
248
253
|
get: (
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
opts.isBool ? function() { return this.hasAttribute(attr) } :
|
|
255
|
+
opts.isNum ? function() { return +this.getAttribute(attr) || 0 } :
|
|
251
256
|
function() { return this.getAttribute(attr) || "" }
|
|
252
257
|
),
|
|
253
258
|
set(value) {
|
|
@@ -264,7 +269,7 @@ function addGetter(key) {
|
|
|
264
269
|
|
|
265
270
|
function Attr(node, name, value) {
|
|
266
271
|
this.ownerElement = node
|
|
267
|
-
this.name = name
|
|
272
|
+
this.name = name
|
|
268
273
|
this.value = "" + value
|
|
269
274
|
}
|
|
270
275
|
|
|
@@ -296,8 +301,7 @@ NamedNodeMap.prototype = {
|
|
|
296
301
|
},
|
|
297
302
|
setNamedItem(attr) {
|
|
298
303
|
var oldAttr = this.getNamedItem(attr.name)
|
|
299
|
-
|
|
300
|
-
this[attr.name] = attr
|
|
304
|
+
this[attr.name.toLowerCase()] = attr
|
|
301
305
|
return oldAttr
|
|
302
306
|
},
|
|
303
307
|
toString(minify) {
|
|
@@ -305,6 +309,7 @@ NamedNodeMap.prototype = {
|
|
|
305
309
|
, tagName = map.ownerElement.tagName
|
|
306
310
|
, isXml = map.ownerElement.ownerDocument.contentType === "application/xml"
|
|
307
311
|
return map.names().map(loName => {
|
|
312
|
+
if (loName === "style" && minify && map.ownerElement.style) { /* Access to style makes _style */ }
|
|
308
313
|
var attr = map.getNamedItem(loName)
|
|
309
314
|
, name = attr.name
|
|
310
315
|
, value = attr.value.replace(escRe, escFn)
|
|
@@ -316,6 +321,7 @@ NamedNodeMap.prototype = {
|
|
|
316
321
|
if (!quotedAttrRe.test(value)) return name + "=" + value
|
|
317
322
|
if (value.split("\"").length > value.split("'").length) return name + "='" + value.replace(/'/g, "'") + "'"
|
|
318
323
|
}
|
|
324
|
+
name = loName
|
|
319
325
|
}
|
|
320
326
|
return name + "=\"" + value.replace(/"/g, """) + "\""
|
|
321
327
|
}).filter(Boolean).join(" ")
|
|
@@ -340,20 +346,29 @@ function HTMLElement(tag) {
|
|
|
340
346
|
}
|
|
341
347
|
|
|
342
348
|
extendNode(HTMLElement, Element, {
|
|
349
|
+
localName: null,
|
|
350
|
+
namespaceURI: "http://www.w3.org/1999/xhtml",
|
|
343
351
|
nodeType: 1,
|
|
344
|
-
|
|
345
|
-
|
|
352
|
+
tagName: null,
|
|
353
|
+
blur() {
|
|
354
|
+
this.ownerDocument.activeElement = null
|
|
346
355
|
},
|
|
347
356
|
closest(sel) {
|
|
348
357
|
return selector.closest(this, sel)
|
|
349
358
|
},
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
359
|
+
focus() {
|
|
360
|
+
this.ownerDocument.activeElement = this
|
|
361
|
+
},
|
|
362
|
+
matches(sel) {
|
|
363
|
+
return selector.matches(this, sel)
|
|
364
|
+
},
|
|
353
365
|
toString(minify) {
|
|
354
366
|
var attrs = this.attributes.toString(minify)
|
|
355
|
-
|
|
356
|
-
|
|
367
|
+
, isXml = this.ownerDocument.contentType === "application/xml"
|
|
368
|
+
, voidEl = this.ownerDocument.documentElement.tagName === "svg" ? svgVoidElements : voidElements
|
|
369
|
+
return "<" + this.localName +
|
|
370
|
+
(attrs ? " " + (attrs.slice(-1) === "/" ? attrs + " " : attrs) : "") +
|
|
371
|
+
(voidEl[this.tagName] ? (isXml ? "/>" : ">") : ">" + Node.toString.call(this, minify) + "</" + this.localName + ">")
|
|
357
372
|
}
|
|
358
373
|
})
|
|
359
374
|
|
|
@@ -434,7 +449,10 @@ extendNode(Document, Element, {
|
|
|
434
449
|
createTextNode: own(Text),
|
|
435
450
|
createComment: own(Comment),
|
|
436
451
|
createDocumentType: own(DocumentType), //Should be document.implementation.createDocumentType(name, publicId, systemId)
|
|
437
|
-
createDocumentFragment: own(DocumentFragment)
|
|
452
|
+
createDocumentFragment: own(DocumentFragment),
|
|
453
|
+
getElementById(id) {
|
|
454
|
+
return selector.find(this, "#" + id, 1)
|
|
455
|
+
}
|
|
438
456
|
})
|
|
439
457
|
|
|
440
458
|
function DOMParser() {}
|
|
@@ -468,9 +486,9 @@ function extendNode(obj, extras) {
|
|
|
468
486
|
obj.prototype.constructor = obj
|
|
469
487
|
}
|
|
470
488
|
|
|
471
|
-
function
|
|
472
|
-
|
|
473
|
-
|
|
489
|
+
function removeChilds(node) {
|
|
490
|
+
node.childNodes.forEach(child => child.parentNode = null)
|
|
491
|
+
node.childNodes.length = 0
|
|
474
492
|
}
|
|
475
493
|
|
|
476
494
|
function getElement(childs, index, step, type) {
|
|
@@ -486,8 +504,26 @@ function getSibling(node, step, type) {
|
|
|
486
504
|
return type > 0 ? getElement(silbings, index + step, step, type) : silbings && silbings[index + step] || null
|
|
487
505
|
}
|
|
488
506
|
|
|
507
|
+
function makeSheet(el, min) {
|
|
508
|
+
if (el.tagName === "STYLE" || el.tagName === "LINK" && el.rel === "stylesheet" && el.href) return new CSSStyleSheet({
|
|
509
|
+
href: el.href,
|
|
510
|
+
ownerNode: el,
|
|
511
|
+
min
|
|
512
|
+
}, el.tagName === "STYLE" && el.textContent)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function mergeAttributes(source, target) {
|
|
516
|
+
if (source && target && source.attributes) {
|
|
517
|
+
source.attributes.names().forEach(attr => target.setAttribute(attr, source.getAttribute(attr)))
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
489
521
|
exports.document = new Document()
|
|
490
522
|
exports.entities = entities
|
|
523
|
+
exports.mergeAttributes = mergeAttributes
|
|
524
|
+
exports.selectorSplit = selectorSplit
|
|
525
|
+
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
526
|
+
exports.CSSStyleSheet = CSSStyleSheet
|
|
491
527
|
exports.DOMParser = DOMParser
|
|
492
528
|
exports.Document = Document
|
|
493
529
|
exports.DocumentFragment = DocumentFragment
|
package/net.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litejs/dom",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "25.5.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>",
|
|
@@ -20,11 +20,10 @@
|
|
|
20
20
|
"*.js"
|
|
21
21
|
],
|
|
22
22
|
"scripts": {
|
|
23
|
-
"
|
|
24
|
-
"test": "lj t test/*.js"
|
|
23
|
+
"test": "lj t"
|
|
25
24
|
},
|
|
26
25
|
"repository": "github:litejs/dom",
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"@litejs/cli": "
|
|
27
|
+
"@litejs/cli": "25.1.0"
|
|
29
28
|
}
|
|
30
29
|
}
|
package/selector.js
CHANGED
package/interactive.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/*! litejs.com/MIT-LICENSE.txt */
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var DOM = module.exports = require(".")
|
|
7
|
-
, HTMLElementExtra = {
|
|
8
|
-
focus() {
|
|
9
|
-
this.ownerDocument.activeElement = this
|
|
10
|
-
},
|
|
11
|
-
blur() {
|
|
12
|
-
this.ownerDocument.activeElement = null
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
Object.assign(DOM.HTMLElement.prototype, HTMLElementExtra)
|
|
17
|
-
|
|
18
|
-
|