@litejs/dom 23.4.0 → 23.8.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 +8 -14
- package/index.js +100 -69
- package/package.json +4 -18
package/README.md
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
LiteJS DOM – [![Coverage][1]][2] [![Size][3]][4] [![Buy Me A Tea][5]][6]
|
|
11
11
|
==========
|
|
12
12
|
|
|
13
|
-
A small DOM library for server-side testing, rendering, and handling of HTML files.
|
|
13
|
+
A small DOM library for server-side testing, rendering, and handling of HTML files.
|
|
14
|
+
[DOM spec](https://dom.spec.whatwg.org/) |
|
|
15
|
+
[Selectors Level 3](http://www.w3.org/TR/selectors/)
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
Examples
|
|
@@ -61,28 +63,20 @@ el.querySelectorAll("b");
|
|
|
61
63
|
## Contributing
|
|
62
64
|
|
|
63
65
|
Follow [Coding Style Guide](https://github.com/litejs/litejs/wiki/Style-Guide)
|
|
64
|
-
|
|
65
|
-
Run tests
|
|
66
|
+
and run tests.
|
|
66
67
|
|
|
67
68
|
```
|
|
68
69
|
npm install
|
|
69
70
|
npm test
|
|
70
71
|
```
|
|
71
72
|
|
|
73
|
+
## Licence
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
Copyright (c) 2014-2023 Lauri Rooden <lauri@rooden.ee>
|
|
76
|
+
[MIT License](https://litejs.com/MIT-LICENSE.txt) |
|
|
75
77
|
[GitHub repo](https://github.com/litejs/dom) |
|
|
76
78
|
[npm package](https://npmjs.org/package/@litejs/dom) |
|
|
77
|
-
[
|
|
78
|
-
[Selectors Level 3](http://www.w3.org/TR/selectors/) |
|
|
79
|
-
[Coveralls coverage][2]
|
|
79
|
+
[coverage][2] |
|
|
80
80
|
[Buy Me A Tea][6]
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
## Licence
|
|
84
|
-
|
|
85
|
-
Copyright (c) 2014-2023 Lauri Rooden <lauri@rooden.ee>
|
|
86
|
-
[The MIT License](http://lauri.rooden.ee/mit-license.txt)
|
|
87
|
-
|
|
88
|
-
|
package/index.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
var boolAttrs = {
|
|
7
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
|
|
8
8
|
}
|
|
9
|
+
, numAttrs = "height maxLength minLength size tabIndex width"
|
|
10
|
+
, strAttrs = "accept accesskey autocapitalize autofocus capture class contenteditable crossorigin dir for hidden href id integrity lang name nonce slot spellcheck src title type translate"
|
|
9
11
|
, defaultAttrs = {
|
|
10
12
|
"form method get":1, "input type text":1,
|
|
11
13
|
"script type text/javascript":1, "style type text/css":1
|
|
@@ -81,7 +83,7 @@ var boolAttrs = {
|
|
|
81
83
|
}
|
|
82
84
|
tree.appendChild(child)
|
|
83
85
|
if ((re = rawTextElements[child.tagName])) {
|
|
84
|
-
for (text = ""; (m = tagRe.exec(html)) && !re.test(m[0]); text += m[3] || m[
|
|
86
|
+
for (text = ""; (m = tagRe.exec(html)) && !re.test(m[0]); text += m[3] || m[0]);
|
|
85
87
|
child.textContent = text.replace(unescRe, unescFn)
|
|
86
88
|
} else if (!voidElements[child.tagName] && !m[8]) tree = child
|
|
87
89
|
} else {
|
|
@@ -109,23 +111,11 @@ var boolAttrs = {
|
|
|
109
111
|
this.parentNode.replaceChild(frag, this)
|
|
110
112
|
return html
|
|
111
113
|
},
|
|
112
|
-
get htmlFor() {
|
|
113
|
-
return this["for"]
|
|
114
|
-
},
|
|
115
|
-
set htmlFor(value) {
|
|
116
|
-
this["for"] = value
|
|
117
|
-
},
|
|
118
|
-
get className() {
|
|
119
|
-
return this["class"] || ""
|
|
120
|
-
},
|
|
121
|
-
set className(value) {
|
|
122
|
-
this["class"] = value
|
|
123
|
-
},
|
|
124
114
|
get style() {
|
|
125
|
-
return this.
|
|
115
|
+
return this._style || (this._style = new CSSStyleDeclaration(this.getAttribute("style") || ""))
|
|
126
116
|
},
|
|
127
117
|
set style(value) {
|
|
128
|
-
this.
|
|
118
|
+
this.setAttribute("style", value)
|
|
129
119
|
},
|
|
130
120
|
contains: function (el) {
|
|
131
121
|
for (; el; el = el.parentNode) if (el === this) return true
|
|
@@ -134,6 +124,9 @@ var boolAttrs = {
|
|
|
134
124
|
hasChildNodes: function() {
|
|
135
125
|
return this.childNodes && this.childNodes.length > 0
|
|
136
126
|
},
|
|
127
|
+
getElementById: function(id) {
|
|
128
|
+
return selector.find(this, "#" + id, 1)
|
|
129
|
+
},
|
|
137
130
|
appendChild: function(el) {
|
|
138
131
|
return this.insertBefore(el)
|
|
139
132
|
},
|
|
@@ -186,6 +179,12 @@ var boolAttrs = {
|
|
|
186
179
|
}
|
|
187
180
|
return clone
|
|
188
181
|
},
|
|
182
|
+
querySelector: function(sel) {
|
|
183
|
+
return selector.find(this, sel, 1)
|
|
184
|
+
},
|
|
185
|
+
querySelectorAll: function(sel) {
|
|
186
|
+
return selector.find(this, sel)
|
|
187
|
+
},
|
|
189
188
|
toString: function(minify) {
|
|
190
189
|
return rawTextElements[this.tagName] ? this.textContent : this.hasChildNodes() ? this.childNodes.reduce(function(memo, node) {
|
|
191
190
|
return memo + node.toString(minify)
|
|
@@ -207,33 +206,23 @@ var boolAttrs = {
|
|
|
207
206
|
},
|
|
208
207
|
replaceChildren: replaceChildren,
|
|
209
208
|
hasAttribute: function(name) {
|
|
210
|
-
|
|
211
|
-
return hasOwn.call(this, name === "style" ? "styleMap" : name)
|
|
209
|
+
return this.attributes.getNamedItem(name) != null
|
|
212
210
|
},
|
|
213
211
|
getAttribute: function(name) {
|
|
214
|
-
|
|
212
|
+
var attr = this.attributes.getNamedItem(name)
|
|
213
|
+
return attr ? attr.value : null
|
|
215
214
|
},
|
|
216
215
|
setAttribute: function(name, value) {
|
|
217
|
-
this
|
|
216
|
+
this.attributes.setNamedItem(name, value)
|
|
218
217
|
},
|
|
219
218
|
removeAttribute: function(name) {
|
|
220
|
-
|
|
221
|
-
delete this[name === "style" ? "styleMap" : name]
|
|
222
|
-
},
|
|
223
|
-
getElementById: function(id) {
|
|
224
|
-
return selector.find(this, "#" + id, 1)
|
|
219
|
+
this.attributes.removeNamedItem(name)
|
|
225
220
|
},
|
|
226
221
|
getElementsByTagName: function(tag) {
|
|
227
222
|
return selector.find(this, tag)
|
|
228
223
|
},
|
|
229
224
|
getElementsByClassName: function(sel) {
|
|
230
225
|
return selector.find(this, "." + sel.replace(/\s+/g, "."))
|
|
231
|
-
},
|
|
232
|
-
querySelector: function(sel) {
|
|
233
|
-
return selector.find(this, sel, 1)
|
|
234
|
-
},
|
|
235
|
-
querySelectorAll: function(sel) {
|
|
236
|
-
return selector.find(this, sel)
|
|
237
226
|
}
|
|
238
227
|
}
|
|
239
228
|
, quotedAttrRe = /[\s"'`=<>]/
|
|
@@ -246,6 +235,26 @@ var boolAttrs = {
|
|
|
246
235
|
"§": "§", "²": "²", "³": "³", "¥": "¥"
|
|
247
236
|
}
|
|
248
237
|
|
|
238
|
+
Object.keys(boolAttrs).forEach(addGetter, { isBool: true, readonly: "readOnly" })
|
|
239
|
+
numAttrs.split(" ").forEach(addGetter, { isNum: true })
|
|
240
|
+
strAttrs.split(" ").forEach(addGetter, { "for": "htmlFor", "class": "className" })
|
|
241
|
+
|
|
242
|
+
function addGetter(key) {
|
|
243
|
+
var attr = key.toLowerCase()
|
|
244
|
+
Object.defineProperty(Element, this[key] || key, {
|
|
245
|
+
configurable: true,
|
|
246
|
+
enumerable: true,
|
|
247
|
+
get: (
|
|
248
|
+
this.isBool ? function() { return this.hasAttribute(attr) } :
|
|
249
|
+
this.isNum ? function() { return +this.getAttribute(attr) || 0 } :
|
|
250
|
+
function() { return this.getAttribute(attr) || "" }
|
|
251
|
+
),
|
|
252
|
+
set: function(value) {
|
|
253
|
+
this.setAttribute(attr, value)
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
|
|
249
258
|
function escFn(chr) {
|
|
250
259
|
return chr === "<" ? "<" : "&"
|
|
251
260
|
}
|
|
@@ -260,35 +269,73 @@ function unescFn(ent, hex, num) {
|
|
|
260
269
|
}
|
|
261
270
|
})
|
|
262
271
|
|
|
263
|
-
function Attr(node, name) {
|
|
272
|
+
function Attr(node, name, value) {
|
|
264
273
|
this.ownerElement = node
|
|
265
274
|
this.name = name.toLowerCase()
|
|
275
|
+
this.value = "" + value
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function NamedNodeMap(node) {
|
|
279
|
+
Object.defineProperty(this, "length", { get: function() { return this.names().length } })
|
|
280
|
+
Object.defineProperty(this, "ownerElement", { value: node })
|
|
266
281
|
}
|
|
267
282
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
283
|
+
NamedNodeMap.prototype = {
|
|
284
|
+
names: function() {
|
|
285
|
+
this.getNamedItem("style")
|
|
286
|
+
return Object.keys(this)
|
|
287
|
+
},
|
|
288
|
+
getNamedItem: function(name) {
|
|
289
|
+
var loName = name.toLowerCase()
|
|
290
|
+
, attr = this[loName] || null
|
|
291
|
+
if (loName === "style" && this.ownerElement._style) {
|
|
292
|
+
if (attr === null) attr = this[loName] = new Attr(this.ownerElement, name, "")
|
|
293
|
+
attr.value = this.ownerElement._style.valueOf()
|
|
294
|
+
delete this.ownerElement._style
|
|
295
|
+
}
|
|
296
|
+
return attr
|
|
297
|
+
},
|
|
298
|
+
removeNamedItem: function(name) {
|
|
299
|
+
var loName = name.toLowerCase()
|
|
300
|
+
, attr = this[loName] || null
|
|
301
|
+
if (loName === "style") delete this.ownerElement._style
|
|
302
|
+
if (attr !== null) delete this[loName]
|
|
303
|
+
return attr
|
|
304
|
+
},
|
|
305
|
+
setNamedItem: function(name, value) {
|
|
306
|
+
this.removeNamedItem(name)
|
|
307
|
+
var loName = name.toLowerCase()
|
|
308
|
+
if (loName === "style") value = new CSSStyleDeclaration(value).valueOf()
|
|
309
|
+
this[loName] = new Attr(this.ownerElement, name, value)
|
|
310
|
+
},
|
|
271
311
|
toString: function(minify) {
|
|
272
|
-
var
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
312
|
+
var map = this
|
|
313
|
+
, tagName = map.ownerElement.tagName
|
|
314
|
+
, isXml = map.ownerElement.ownerDocument.contentType === "application/xml"
|
|
315
|
+
return map.names().map(function(loName) {
|
|
316
|
+
var attr = map.getNamedItem(loName)
|
|
317
|
+
, name = attr.name
|
|
318
|
+
, value = attr.value.replace(escRe, escFn)
|
|
319
|
+
if (!isXml) {
|
|
320
|
+
if (hasOwn.call(boolAttrs, loName)) return name
|
|
321
|
+
if (minify) {
|
|
322
|
+
if (hasOwn.call(defaultAttrs, (tagName + " " + name + " " + value).toLowerCase())) return
|
|
323
|
+
if (!quotedAttrRe.test(value)) return name + "=" + value
|
|
324
|
+
if (value.split("\"").length > value.split("'").length) return name + "='" + value.replace(/'/g, "'") + "'"
|
|
325
|
+
}
|
|
279
326
|
}
|
|
280
|
-
|
|
281
|
-
|
|
327
|
+
return name + "=\"" + value.replace(/"/g, """) + "\""
|
|
328
|
+
}).filter(Boolean).join(" ")
|
|
282
329
|
}
|
|
283
330
|
}
|
|
284
331
|
|
|
285
|
-
function
|
|
332
|
+
function CSSStyleDeclaration(style) {
|
|
286
333
|
for (var m, re = /(?:^|;)\s*([-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)(?=;|$)/ig; (m = re.exec(style)); ) {
|
|
287
334
|
this[m[1] === "float" ? "cssFloat" : camelCase(m[1])] = m[2].trim()
|
|
288
335
|
}
|
|
289
336
|
}
|
|
290
337
|
|
|
291
|
-
|
|
338
|
+
CSSStyleDeclaration.prototype.valueOf = function() {
|
|
292
339
|
return Object.keys(this).map(function(key) {
|
|
293
340
|
return (key === "cssFloat" ? "float:" : hyphenCase(key) + ":") + this[key]
|
|
294
341
|
}, this).join(";")
|
|
@@ -298,28 +345,21 @@ function DocumentFragment() {
|
|
|
298
345
|
this.childNodes = []
|
|
299
346
|
}
|
|
300
347
|
|
|
301
|
-
extendNode(DocumentFragment,
|
|
348
|
+
extendNode(DocumentFragment, Node, {
|
|
302
349
|
nodeType: 11,
|
|
303
350
|
nodeName: "#document-fragment"
|
|
304
351
|
})
|
|
305
352
|
|
|
306
353
|
function HTMLElement(tag) {
|
|
307
354
|
var el = this
|
|
308
|
-
el.
|
|
309
|
-
el.localName = tag.toLowerCase()
|
|
355
|
+
el.attributes = new NamedNodeMap(el)
|
|
310
356
|
el.childNodes = []
|
|
357
|
+
el.localName = tag.toLowerCase()
|
|
358
|
+
el.nodeName = el.tagName = tag.toUpperCase()
|
|
311
359
|
}
|
|
312
360
|
|
|
313
361
|
extendNode(HTMLElement, Element, {
|
|
314
362
|
nodeType: 1,
|
|
315
|
-
get attributes() {
|
|
316
|
-
var key
|
|
317
|
-
, attrs = []
|
|
318
|
-
, el = this
|
|
319
|
-
for (key in el) if (key === escAttr(key) && el.hasAttribute(key))
|
|
320
|
-
attrs.push(new Attr(el, escAttr(key)))
|
|
321
|
-
return attrs
|
|
322
|
-
},
|
|
323
363
|
matches: function(sel) {
|
|
324
364
|
return selector.matches(this, sel)
|
|
325
365
|
},
|
|
@@ -329,9 +369,8 @@ extendNode(HTMLElement, Element, {
|
|
|
329
369
|
namespaceURI: "http://www.w3.org/1999/xhtml",
|
|
330
370
|
localName: null,
|
|
331
371
|
tagName: null,
|
|
332
|
-
styleMap: null,
|
|
333
372
|
toString: function(minify) {
|
|
334
|
-
var attrs =
|
|
373
|
+
var attrs = this.attributes.toString(minify)
|
|
335
374
|
return "<" + this.localName + (attrs ? " " + attrs + (attrs.slice(-1) === "/" ? " >" : ">") : ">") +
|
|
336
375
|
(voidElements[this.tagName] ? "" : Node.toString.call(this, minify) + "</" + this.localName + ">")
|
|
337
376
|
}
|
|
@@ -339,9 +378,10 @@ extendNode(HTMLElement, Element, {
|
|
|
339
378
|
|
|
340
379
|
function ElementNS(namespace, tag) {
|
|
341
380
|
var el = this
|
|
381
|
+
el.attributes = new NamedNodeMap(el)
|
|
382
|
+
el.childNodes = []
|
|
342
383
|
el.namespaceURI = namespace
|
|
343
384
|
el.nodeName = el.tagName = el.localName = tag
|
|
344
|
-
el.childNodes = []
|
|
345
385
|
}
|
|
346
386
|
|
|
347
387
|
ElementNS.prototype = HTMLElement.prototype
|
|
@@ -456,11 +496,6 @@ function getSibling(node, step, type) {
|
|
|
456
496
|
return type > 0 ? getElement(silbings, index + step, step, type) : silbings[index + step] || null
|
|
457
497
|
}
|
|
458
498
|
|
|
459
|
-
function escAttr(name) {
|
|
460
|
-
name = name.toLowerCase()
|
|
461
|
-
return name === "constructor" || name === "attributes" ? name.toUpperCase() : name
|
|
462
|
-
}
|
|
463
|
-
|
|
464
499
|
function camelCase(str) {
|
|
465
500
|
return str.replace(/-([a-z])/g, function(_, a) { return a.toUpperCase() })
|
|
466
501
|
}
|
|
@@ -469,14 +504,10 @@ function hyphenCase(str) {
|
|
|
469
504
|
return str.replace(/[A-Z]/g, "-$&").toLowerCase()
|
|
470
505
|
}
|
|
471
506
|
|
|
472
|
-
function toMinString(item) {
|
|
473
|
-
return item.toString(true)
|
|
474
|
-
}
|
|
475
|
-
|
|
476
507
|
exports.document = new Document()
|
|
477
508
|
exports.DOMParser = DOMParser
|
|
478
509
|
exports.XMLSerializer = XMLSerializer
|
|
479
|
-
exports.
|
|
510
|
+
exports.CSSStyleDeclaration = CSSStyleDeclaration
|
|
480
511
|
exports.Node = Node
|
|
481
512
|
exports.HTMLElement = HTMLElement
|
|
482
513
|
exports.DocumentFragment = DocumentFragment
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@litejs/dom",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.8.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>",
|
|
@@ -16,29 +16,15 @@
|
|
|
16
16
|
"*.js"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"test": "lj test --coverage --ignore=net.js --brief test/index.js && jshint *.js",
|
|
19
|
+
"test": "lj test --coverage --ignore=net.js --brief test/index.js && jshint --config .github/jshint.json *.js",
|
|
20
20
|
"test-fast": "lj test --brief test/index.js"
|
|
21
21
|
},
|
|
22
22
|
"repository": "github:litejs/dom",
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@litejs/cli": "23.
|
|
24
|
+
"@litejs/cli": "23.8.0",
|
|
25
25
|
"jshint": "2.13.6"
|
|
26
26
|
},
|
|
27
27
|
"litejs": {
|
|
28
|
-
"build": false
|
|
29
|
-
"global": false
|
|
30
|
-
},
|
|
31
|
-
"jshintConfig": {
|
|
32
|
-
"esversion": 5,
|
|
33
|
-
"asi": true,
|
|
34
|
-
"evil": true,
|
|
35
|
-
"laxcomma": true,
|
|
36
|
-
"maxdepth": 6,
|
|
37
|
-
"node": true,
|
|
38
|
-
"nonbsp": true,
|
|
39
|
-
"undef": true,
|
|
40
|
-
"unused": true,
|
|
41
|
-
"shadow": "outer",
|
|
42
|
-
"quotmark": "double"
|
|
28
|
+
"build": false
|
|
43
29
|
}
|
|
44
30
|
}
|