@litejs/dom 24.12.0 → 25.1.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 +160 -34
- package/dom.js +33 -13
- package/package.json +3 -4
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 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,154 @@
|
|
|
1
1
|
|
|
2
2
|
/*! litejs.com/MIT-LICENSE.txt */
|
|
3
3
|
|
|
4
|
+
exports.selectorSplit = selectorSplit
|
|
4
5
|
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
5
6
|
exports.CSSStyleSheet = CSSStyleSheet
|
|
6
7
|
|
|
7
|
-
var
|
|
8
|
-
|
|
8
|
+
var fs = require("fs")
|
|
9
|
+
, path = require("path")
|
|
10
|
+
, urlRe = /(["']).*?\1|url\((['"]?)(?!\/|data:|https?:)(.*?)\2\)/g
|
|
11
|
+
, clearFn = (_, q, str, c) =>
|
|
12
|
+
q ? (q = str.indexOf("'") == -1 ? "'" : "\"", q + str.replace(q === "'" ? /\\(")/g : /\\(')/g, "$1")) + q :
|
|
13
|
+
c ? "" :
|
|
14
|
+
_.replace(/[\t\n]+/g, " ")
|
|
9
15
|
.replace(/ *([,;{}>~+\/]) */g, "$1")
|
|
10
|
-
.replace(
|
|
16
|
+
.replace(/;(?=})/g, "")
|
|
11
17
|
.replace(/: +/g, ":")
|
|
12
|
-
|
|
18
|
+
.replace(/([ :,])0\.([0-9])/g, "$1.$2")
|
|
19
|
+
, clear = s => s
|
|
20
|
+
.replace(/("|')((?:\\\1|[^\1])*?)\1|\s*(\/)\*(?:[^*]|\*(?!\/))*\*\/\s*|(?:[^"'\/]|\/(?!\*))+/g, clearFn)
|
|
21
|
+
.replace(/(["']).*?\1|url\(("|')([^'"()\s]+)\2\)/g, (m,q1,q2,u) => q1 ? m : "url(" + u + ")")
|
|
22
|
+
, read = (sheet, url, enc = "utf8") => fs.readFileSync(path.resolve(sheet.min.root || "", sheet.baseURI, url), enc)
|
|
23
|
+
, toRgb = {
|
|
24
|
+
rgb(r, g, b) {
|
|
25
|
+
var f = n => ((n | 0) + 256).toString(16).slice(1)
|
|
26
|
+
return f(r) + f(g) + f(b)
|
|
27
|
+
},
|
|
28
|
+
hsl(h, s, l) {
|
|
29
|
+
l /= 100
|
|
30
|
+
s /= 100 / (l < 0.5 ? l : 1 - l)
|
|
31
|
+
function f(n) {
|
|
32
|
+
n = (n + h / 30) % 12
|
|
33
|
+
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)
|
|
34
|
+
}
|
|
35
|
+
return f(0) + f(8) + f(4)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
, toRgba = (rgbHex, alpha) => ("rgba(" + rgbHex.replace(/../g, x => parseInt(x, 16)+",") + alpha + ")").replace("0.", ".")
|
|
39
|
+
, colorRe = /\b(rgb|hsl)a?\s*\(\s*(\d+)(?:deg)?[\s,]+(\d+)[\s,%]+(\d+)%?(?:[\s,\/]+(0?\.?\d+)(%?))?\s*\)/g
|
|
40
|
+
, 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
41
|
, styleHandler = {
|
|
14
42
|
get(style, prop) {
|
|
15
43
|
if (prop === "cssText") {
|
|
44
|
+
var min = style.parentRule && style.parentRule.parentStyleSheet.min
|
|
16
45
|
for (var out = [], i = style.length; i--; ) {
|
|
17
|
-
out[i] = style[i]
|
|
46
|
+
out[i] = joinProp(style[i], style.__[i] || style[style[i]])
|
|
18
47
|
}
|
|
19
48
|
return out.join(";")
|
|
20
49
|
}
|
|
21
50
|
return style[prop] || ""
|
|
51
|
+
function joinProp(name, value) {
|
|
52
|
+
if (min && min.color) value = value.replace(colorRe, colorFn)
|
|
53
|
+
return name + ":" + value
|
|
54
|
+
}
|
|
22
55
|
},
|
|
23
56
|
set(style, prop, val) {
|
|
24
57
|
if (prop === "cssText") {
|
|
25
58
|
var m, k
|
|
26
|
-
,
|
|
59
|
+
, sheet = style.parentRule && style.parentRule.parentStyleSheet
|
|
60
|
+
, min = sheet && sheet.min
|
|
61
|
+
, re = /([*_]?[-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)|\/\*!?((?:[^*]|\*(?!\/))*)\*\//ig
|
|
27
62
|
, len = 0
|
|
28
63
|
, lastIdx = {}
|
|
29
64
|
for (; (m = re.exec(val)); ) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
65
|
+
if (m[4]) {
|
|
66
|
+
if (min && len) style[k = style[len - 1]] = clear(transformValue(m[4].trim(), style[k]))
|
|
67
|
+
continue
|
|
68
|
+
} else {
|
|
69
|
+
k = m[1]
|
|
70
|
+
if (lastIdx[k] >= 0) style.__[lastIdx[k]] = style[k]
|
|
71
|
+
style[style[lastIdx[k] = len++] = k] = style[
|
|
72
|
+
k === "float" ? "cssFloat" : k.replace(/-([a-z])/g, (_, a) => a.toUpperCase())
|
|
73
|
+
] = clear(m[2]).trim()
|
|
74
|
+
}
|
|
35
75
|
}
|
|
36
76
|
style.length = len
|
|
37
77
|
} else {
|
|
38
78
|
if (!style[prop]) style[style.length++] = prop
|
|
39
79
|
style[prop] = style[prop === "cssFloat" ? "float" : prop.replace(/[A-Z]/g, "-$&").toLowerCase()] = clear(val)
|
|
40
80
|
}
|
|
81
|
+
function transformValue(cmd, v) {
|
|
82
|
+
var { DOMParser } = require("./dom.js")
|
|
83
|
+
if (cmd === "data-uri") {
|
|
84
|
+
return v.replace(urlRe, function(_, q1, q2, url) {
|
|
85
|
+
if (q1) return _
|
|
86
|
+
var ext = url.split(".").pop()
|
|
87
|
+
, enc = ext === "svg" ? "utf8" : "base64"
|
|
88
|
+
url = read(sheet, url, enc)
|
|
89
|
+
if (ext === "svg") {
|
|
90
|
+
enc = ""
|
|
91
|
+
ext += "+xml"
|
|
92
|
+
url = new DOMParser().parseFromString(url, "application/xml").toString(true).replace(/#/g, "%23")
|
|
93
|
+
}
|
|
94
|
+
return "url('data:image/" + ext + ";" + enc + "," + url + "')"
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
return v
|
|
98
|
+
}
|
|
41
99
|
}
|
|
42
100
|
}
|
|
43
101
|
, ruleTypes = {
|
|
44
102
|
style: {
|
|
103
|
+
type: 1,
|
|
45
104
|
get cssText() {
|
|
46
105
|
return this.style.length > 0 ? this.selectorText + "{" + this.style.cssText + "}" : ""
|
|
47
106
|
},
|
|
48
107
|
set cssText(text) {
|
|
49
108
|
var idx = text.indexOf("{")
|
|
50
|
-
this.selectorText = text.slice(0, idx).trim()
|
|
109
|
+
this.selectorText = clear(text.slice(0, idx).trim())
|
|
51
110
|
this.style = CSSStyleDeclaration(text.slice(idx + 1).replace(/}\s*/, ""), this)
|
|
52
111
|
}
|
|
53
112
|
},
|
|
54
113
|
import: {
|
|
55
114
|
get cssText() {
|
|
56
|
-
|
|
115
|
+
var sheet = this.parentStyleSheet
|
|
116
|
+
, min = sheet.min
|
|
117
|
+
, text = this.text
|
|
118
|
+
, urlFn = (m,q1,q2,u) => q1 ? m : "url('" + path.join(text.baseURI, u) + "')"
|
|
119
|
+
if (min && min.import) {
|
|
120
|
+
text = new CSSStyleSheet({
|
|
121
|
+
parentStyleSheet: sheet,
|
|
122
|
+
href: this.href,
|
|
123
|
+
min
|
|
124
|
+
}, read(sheet, this.href))
|
|
125
|
+
if (sheet.baseURI !== text.baseURI) {
|
|
126
|
+
text.rules.forEach(rule => {
|
|
127
|
+
if (rule.type === 1) for (let style = rule.style, i = style.length; i--; ) {
|
|
128
|
+
if (urlRe.test(style[style[i]])) style[style[i]] = style[style[i]].replace(urlRe, urlFn)
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
text += ""
|
|
133
|
+
}
|
|
134
|
+
return text
|
|
57
135
|
},
|
|
58
136
|
set cssText(text) {
|
|
59
|
-
this.
|
|
137
|
+
this.href = text.split(/['"()]+/)[1]
|
|
138
|
+
this.text = clear(text.replace(/url\(("|')(.+?)\1\)/g, "'$2'"))
|
|
60
139
|
}
|
|
61
140
|
},
|
|
62
141
|
"}": {
|
|
63
142
|
get cssText() {
|
|
64
|
-
var
|
|
65
|
-
|
|
143
|
+
var style = new CSSStyleSheet({})
|
|
144
|
+
style.replaceSync(this.text)
|
|
145
|
+
var body = "" + style
|
|
146
|
+
return body.length > 0 ? this.mediaText + "{" + body + "}" : ""
|
|
66
147
|
},
|
|
67
148
|
set cssText(text) {
|
|
68
149
|
var idx = text.indexOf("{")
|
|
69
150
|
this.mediaText = clear(text.slice(0, idx).trim())
|
|
70
|
-
this.
|
|
71
|
-
this.style.replaceSync(text.slice(idx + 1, -1))
|
|
151
|
+
this.text = text.slice(idx + 1, -1)
|
|
72
152
|
}
|
|
73
153
|
},
|
|
74
154
|
";": {
|
|
@@ -83,12 +163,12 @@ var clearFn = (_, q, str) => q ? (q == "\"" && str.indexOf("'") == -1 ? "'" + st
|
|
|
83
163
|
|
|
84
164
|
function CSSRule(text, parentStyleSheet, atType, parentRule = null) {
|
|
85
165
|
// Clear comments and trim
|
|
86
|
-
text = text.
|
|
166
|
+
text = text.trim()
|
|
87
167
|
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
|
|
168
|
+
, rule = Object.create(ruleTypes[type] || ruleTypes[type === "page" || type === "font-face" || type === "counter-style" ? "style" : atType])
|
|
90
169
|
rule.parentStyleSheet = parentStyleSheet
|
|
91
170
|
rule.parentRule = parentRule
|
|
171
|
+
rule.cssText = rule.type === 1 ? text : text.replace(/\/\*(?:[^*]|\*(?!\/))*\*\//g, "")
|
|
92
172
|
return rule
|
|
93
173
|
}
|
|
94
174
|
|
|
@@ -98,12 +178,21 @@ function CSSStyleDeclaration(text, parentRule = null) {
|
|
|
98
178
|
return style
|
|
99
179
|
}
|
|
100
180
|
|
|
101
|
-
function CSSStyleSheet(opts) {
|
|
181
|
+
function CSSStyleSheet(opts, text = "") {
|
|
102
182
|
Object.assign(this, opts)
|
|
103
|
-
|
|
183
|
+
if (opts && opts.href) {
|
|
184
|
+
this.baseURI = path.join(
|
|
185
|
+
(opts.parentStyleSheet || opts.ownerNode && opts.ownerNode.ownerDocument).baseURI || "",
|
|
186
|
+
opts.href,
|
|
187
|
+
".."
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
this.replaceSync(text)
|
|
104
191
|
}
|
|
105
192
|
|
|
106
193
|
CSSStyleSheet.prototype = {
|
|
194
|
+
baseURI: "",
|
|
195
|
+
root: "",
|
|
107
196
|
disabled: false,
|
|
108
197
|
type: "text/css",
|
|
109
198
|
deleteRule(idx) {
|
|
@@ -113,24 +202,61 @@ CSSStyleSheet.prototype = {
|
|
|
113
202
|
this.rules.splice(idx > -1 ? idx : this.rules.length, 0, CSSRule(rule, this))
|
|
114
203
|
},
|
|
115
204
|
replaceSync(text) {
|
|
116
|
-
var
|
|
117
|
-
, sheet = this
|
|
118
|
-
, re = /((?:("|')(?:\\.|(?!\2)[^\\])*?\2|[^"'}{;])+)|./ig
|
|
119
|
-
, block = 0
|
|
120
|
-
, pos = 0
|
|
205
|
+
var qpos, sheet = this
|
|
121
206
|
sheet.rules = sheet.cssRules = []
|
|
122
207
|
sheet.warnings = []
|
|
123
|
-
for (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
208
|
+
for (var char, inQuote, depth = 0, start = 0, pos = 0, len = text.length; pos < len; pos++) {
|
|
209
|
+
char = text[pos]
|
|
210
|
+
if (char === "\\" && inQuote !== "/") {
|
|
211
|
+
pos++
|
|
212
|
+
} else if (inQuote) {
|
|
213
|
+
if (char === inQuote) {
|
|
214
|
+
if (char !== "/" || text[pos - 1] === "*") {
|
|
215
|
+
if (char === "/" && depth < 1) {
|
|
216
|
+
// Remove root level comments
|
|
217
|
+
text = text.slice(0, qpos) + text.slice(pos + 1)
|
|
218
|
+
pos = qpos - 1
|
|
219
|
+
len = text.length
|
|
220
|
+
}
|
|
221
|
+
inQuote = ""
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
} else if (char === "'" || char === "\"" || char === "/" && text[pos+1] === "*") {
|
|
225
|
+
inQuote = char
|
|
226
|
+
qpos = pos
|
|
227
|
+
} else if (char === "{") {
|
|
228
|
+
depth++
|
|
229
|
+
} else if (char === "}" && --depth < 1 || char === ";" && depth < 1) {
|
|
230
|
+
if (depth < 0) throw "Invalid css"
|
|
231
|
+
sheet.rules.push(CSSRule(text.slice(start, start = pos + 1), sheet, char))
|
|
128
232
|
}
|
|
129
233
|
}
|
|
130
234
|
},
|
|
131
|
-
toString() {
|
|
235
|
+
toString(min) {
|
|
236
|
+
if (min) this.min = min
|
|
132
237
|
return this.rules.map(rule => rule.cssText).filter(Boolean).join("\n")
|
|
133
238
|
}
|
|
134
239
|
}
|
|
135
240
|
|
|
241
|
+
function selectorSplit(text) {
|
|
242
|
+
for (var char, inQuote, depth = 0, start = 0, pos = 0, len = text.length, out = []; pos < len; ) {
|
|
243
|
+
char = text[pos++]
|
|
244
|
+
if (char === "\\") {
|
|
245
|
+
pos++
|
|
246
|
+
} else if (inQuote) {
|
|
247
|
+
if (char === inQuote) inQuote = ""
|
|
248
|
+
} else if (char === "'" || char === "\"") {
|
|
249
|
+
inQuote = char
|
|
250
|
+
} else if (char === "(" || char === "[") {
|
|
251
|
+
depth++
|
|
252
|
+
} else if (char === ")" || char === "]") {
|
|
253
|
+
depth--
|
|
254
|
+
} else if (char === "," && depth === 0) {
|
|
255
|
+
out.push(text.slice(start, (start = pos) - 1).trim())
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
out.push(text.slice(start).trim())
|
|
259
|
+
return out
|
|
260
|
+
}
|
|
261
|
+
|
|
136
262
|
|
package/dom.js
CHANGED
|
@@ -13,10 +13,13 @@ var boolAttrs = {
|
|
|
13
13
|
, voidElements = {
|
|
14
14
|
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
15
|
}
|
|
16
|
+
, svgVoidElements = {
|
|
17
|
+
circle:1, ellipse:1, image:1, line:1, path:1, polygon:1, polyline:1, rect:1, stop:1, use:1,
|
|
18
|
+
}
|
|
16
19
|
, rawTextElements = { SCRIPT: /<(?=\/script)/i, STYLE: /<(?=\/style)/i }
|
|
17
20
|
, rawTextEscape = { SCRIPT: /<(?=\/script|!--)/ig, STYLE: /<(?=\/style|!--)/ig }
|
|
18
21
|
, hasOwn = voidElements.hasOwnProperty
|
|
19
|
-
, { CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
|
|
22
|
+
, { selectorSplit, CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
|
|
20
23
|
, selector = require("./selector.js")
|
|
21
24
|
, Node = {
|
|
22
25
|
ELEMENT_NODE: 1,
|
|
@@ -69,6 +72,7 @@ var boolAttrs = {
|
|
|
69
72
|
, attrRe = /([^=\s]+)(?:\s*=\s*(("|')((?:\\\3|[\s\S])*?)\3|[^\s"'`=<>]+)|)/g
|
|
70
73
|
, frag = doc.createDocumentFragment()
|
|
71
74
|
, tree = frag
|
|
75
|
+
, voidEl = doc.documentElement.tagName === "svg" ? svgVoidElements : voidElements
|
|
72
76
|
|
|
73
77
|
for (; (m = tagRe.exec(html)); ) {
|
|
74
78
|
if (m[4]) {
|
|
@@ -83,7 +87,7 @@ var boolAttrs = {
|
|
|
83
87
|
for (text = ""; (m = tagRe.exec(html)) && !re.test(m[0]); text += m[3] || m[0]);
|
|
84
88
|
child.textContent = text.replace(unescRe, unescFn)
|
|
85
89
|
if (!m) break
|
|
86
|
-
} else if (!
|
|
90
|
+
} else if (!voidEl[child.tagName] && !m[8]) tree = child
|
|
87
91
|
} else {
|
|
88
92
|
tree.appendChild(
|
|
89
93
|
m[2] ? doc.createComment(m[2].replace(unescRe, unescFn)) :
|
|
@@ -107,10 +111,7 @@ var boolAttrs = {
|
|
|
107
111
|
this.parentNode.replaceChild(frag, this)
|
|
108
112
|
},
|
|
109
113
|
get sheet() {
|
|
110
|
-
|
|
111
|
-
href: this.href,
|
|
112
|
-
ownerNode: this
|
|
113
|
-
})
|
|
114
|
+
return makeSheet(this)
|
|
114
115
|
},
|
|
115
116
|
get style() {
|
|
116
117
|
return this._style || (this._style = CSSStyleDeclaration(this.getAttribute("style") || ""))
|
|
@@ -168,9 +169,7 @@ var boolAttrs = {
|
|
|
168
169
|
, clone = new node.constructor(node.tagName || node.data)
|
|
169
170
|
clone.ownerDocument = node.ownerDocument
|
|
170
171
|
|
|
171
|
-
|
|
172
|
-
node.attributes.names().forEach(attr => clone.setAttribute(attr, node.getAttribute(attr)))
|
|
173
|
-
}
|
|
172
|
+
mergeAttributes(node, clone)
|
|
174
173
|
|
|
175
174
|
if (deep && node.hasChildNodes()) {
|
|
176
175
|
node.childNodes.forEach(child => clone.appendChild(child.cloneNode(deep)))
|
|
@@ -185,7 +184,7 @@ var boolAttrs = {
|
|
|
185
184
|
},
|
|
186
185
|
toString(min) {
|
|
187
186
|
return rawTextElements[this.tagName] ? (
|
|
188
|
-
this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + this
|
|
187
|
+
this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + makeSheet(this, min.css || true) + "\n" :
|
|
189
188
|
this.textContent
|
|
190
189
|
) : this.childNodes.map(node => node.toString(min)).join("")
|
|
191
190
|
}
|
|
@@ -296,7 +295,6 @@ NamedNodeMap.prototype = {
|
|
|
296
295
|
},
|
|
297
296
|
setNamedItem(attr) {
|
|
298
297
|
var oldAttr = this.getNamedItem(attr.name)
|
|
299
|
-
if (attr.name === "style") attr.value = CSSStyleDeclaration(attr.value).cssText
|
|
300
298
|
this[attr.name] = attr
|
|
301
299
|
return oldAttr
|
|
302
300
|
},
|
|
@@ -305,6 +303,7 @@ NamedNodeMap.prototype = {
|
|
|
305
303
|
, tagName = map.ownerElement.tagName
|
|
306
304
|
, isXml = map.ownerElement.ownerDocument.contentType === "application/xml"
|
|
307
305
|
return map.names().map(loName => {
|
|
306
|
+
if (loName === "style" && minify && map.ownerElement.style) { /* Access to style makes _style */ }
|
|
308
307
|
var attr = map.getNamedItem(loName)
|
|
309
308
|
, name = attr.name
|
|
310
309
|
, value = attr.value.replace(escRe, escFn)
|
|
@@ -352,8 +351,11 @@ extendNode(HTMLElement, Element, {
|
|
|
352
351
|
tagName: null,
|
|
353
352
|
toString(minify) {
|
|
354
353
|
var attrs = this.attributes.toString(minify)
|
|
355
|
-
|
|
356
|
-
|
|
354
|
+
, isXml = this.ownerDocument.contentType === "application/xml"
|
|
355
|
+
, voidEl = this.ownerDocument.documentElement.tagName === "svg" ? svgVoidElements : voidElements
|
|
356
|
+
return "<" + this.localName +
|
|
357
|
+
(attrs ? " " + (attrs.slice(-1) === "/" ? attrs + " " : attrs) : "") +
|
|
358
|
+
(voidEl[this.tagName] ? (isXml ? "/>" : ">") : ">" + Node.toString.call(this, minify) + "</" + this.localName + ">")
|
|
357
359
|
}
|
|
358
360
|
})
|
|
359
361
|
|
|
@@ -486,8 +488,26 @@ function getSibling(node, step, type) {
|
|
|
486
488
|
return type > 0 ? getElement(silbings, index + step, step, type) : silbings && silbings[index + step] || null
|
|
487
489
|
}
|
|
488
490
|
|
|
491
|
+
function makeSheet(el, min) {
|
|
492
|
+
if (el.tagName === "STYLE" || el.tagName === "LINK" && el.rel === "stylesheet" && el.href) return new CSSStyleSheet({
|
|
493
|
+
href: el.href,
|
|
494
|
+
ownerNode: el,
|
|
495
|
+
min
|
|
496
|
+
}, el.tagName === "STYLE" && el.textContent)
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function mergeAttributes(source, target) {
|
|
500
|
+
if (source && target && source.attributes) {
|
|
501
|
+
source.attributes.names().forEach(attr => target.setAttribute(attr, source.getAttribute(attr)))
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
489
505
|
exports.document = new Document()
|
|
490
506
|
exports.entities = entities
|
|
507
|
+
exports.mergeAttributes = mergeAttributes
|
|
508
|
+
exports.selectorSplit = selectorSplit
|
|
509
|
+
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
510
|
+
exports.CSSStyleSheet = CSSStyleSheet
|
|
491
511
|
exports.DOMParser = DOMParser
|
|
492
512
|
exports.Document = Document
|
|
493
513
|
exports.DocumentFragment = DocumentFragment
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litejs/dom",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "25.1.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
|
}
|