@litejs/dom 25.12.0 → 26.3.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 CHANGED
@@ -51,9 +51,10 @@ xhr.onload = function() {
51
51
  xhr.send();
52
52
 
53
53
  // Minify CSS
54
- const sheet = new CSSStyleSheet({ min: { color: true } })
54
+ import { CSS } from "@litejs/dom/css.js";
55
+ const sheet = new CSSStyleSheet()
55
56
  sheet.replaceSync(".a { color: hsl(0 0% 100%) }")
56
- console.log(sheet.toString())
57
+ console.log(CSS.minify(sheet, { color: true }))
57
58
  // .a{color:#fff}
58
59
  ```
59
60
 
@@ -63,7 +64,7 @@ Follow [Coding Style Guide](https://github.com/litejs/litejs/wiki/Style-Guide),
63
64
  run tests `npm install; npm test`.
64
65
 
65
66
 
66
- > Copyright (c) 2014-2025 Lauri Rooden <lauri@rooden.ee>
67
+ > Copyright (c) 2014-2026 Lauri Rooden <lauri@rooden.ee>
67
68
  [MIT License](https://litejs.com/MIT-LICENSE.txt) |
68
69
  [GitHub repo](https://github.com/litejs/dom) |
69
70
  [npm package](https://npmjs.org/package/@litejs/dom) |
package/css.js CHANGED
@@ -6,18 +6,72 @@
6
6
  exports.CSSStyleDeclaration = CSSStyleDeclaration
7
7
  exports.CSSStyleSheet = CSSStyleSheet
8
8
 
9
- var fs = require("fs")
10
- , path = require("path")
11
- , read = (sheet, url, enc = "utf8") => fs.readFileSync(path.resolve(sheet.min.root || "", sheet.baseURI, url).split(/[+#]/)[0], enc)
9
+ /* c8 ignore next */
10
+ var URL = global.URL || require("url").URL
11
+ , varRe = /var\((--[^,)]+)(?:,([^)]+))?\)/g
12
+ , CSS = exports.CSS = {
13
+ escape(sel) {
14
+ return ("" + sel).replace(/[^a-zA-Z0-9_\u00A0-\uFFFF-]/g, "\\$&").replace(/^(-?)([0-9])/, "$1\\3$2 ")
15
+ },
16
+ minify(sheet, opts) {
17
+ var rules = sheet.cssRules || sheet.rules
18
+ , root = opts && opts.root || ""
19
+ , vars = opts && opts.var ? {} : null
20
+ , varFn = vars && function(_, n) { return vars[n] || _ }
21
+ return Array.prototype.map.call(rules, rule => {
22
+ if (vars && rule.selectorText === ":root") {
23
+ if (rule.style) for (var i = 0; i < rule.style.length; i++) {
24
+ var n = rule.style[i]
25
+ if (n.slice(0, 2) === "--") vars[n] = rule.style[n].replace(varRe, varFn)
26
+ }
27
+ return ""
28
+ }
29
+ // Handle @import inlining
30
+ if (opts && opts.import && rule.href) {
31
+ var imported = new CSSStyleSheet({
32
+ href: rule.href,
33
+ parentStyleSheet: sheet
34
+ }, read(root, rule.href, sheet.baseURI))
35
+ , urlFn = (m,q1,q2,u) => q1 ? m : "url('" + new URL(u, toUrl(imported.baseURI)).pathname.slice(1) + "')"
36
+ if (sheet.baseURI !== imported.baseURI) {
37
+ updateImportUrls(imported, urlFn)
38
+ }
39
+ return CSS.minify(imported, opts)
40
+ }
41
+
42
+ // Handle plugins on style rules
43
+ if (rule.style && rule.style._plugins) {
44
+ for (var style = rule.style, j = 0; j < style._plugins.length; j++) {
45
+ var idx = style._plugins[j][0]
46
+ , pn = style._plugins[j][1]
47
+ , k = style[idx]
48
+ style[k] = clear(plugins[pn](root, sheet.baseURI, style[k]))
49
+ }
50
+ }
51
+
52
+ var text = clear(rule.cssText)
53
+ if (!text || /\{\s*\}$/.test(text)) return ""
54
+ if (vars) text = text.replace(varRe, (_, v, fb) => vars[v] || fb || _)
55
+ if (opts && opts.color) text = text.replace(colorRe, colorFn)
56
+ if (opts && opts.url) text = text.replace(urlRe, (m, q1, q2, u) => q1 ? m : "url(" + opts.url(u) + ")")
57
+ return text
58
+ }).filter(Boolean).join("\n")
59
+ }
60
+ }
61
+ , toUrl = (dir) => new URL((dir || ".").replace(/\/+$/, "") + "/", "file:///").href
62
+ , read = (root, url, baseURI, enc = "utf8") => require("fs").readFileSync(
63
+ new URL(url, new URL((baseURI || ".") + "/", new URL((root || ".").replace(/\/+$/, "") + "/", "file:///" + process.cwd() + "/"))).pathname.replace(/^\/(?=\w:)|[+#].*/, ""),
64
+ enc
65
+ )
12
66
  , plugins = exports.plugins = {
13
- "data-uri": function(sheet, v) {
67
+ "data-uri": function(root, baseURI, v) {
14
68
  var { DOMParser } = require("./dom.js")
15
69
  return v.replace(urlRe, function(_, q1, q2, url) {
16
70
  if (q1) return _
17
71
  var frag = url.split("#")[1]
18
72
  , ext = url.split(/[?#]/)[0].split(".").pop()
19
73
  , enc = ext === "svg" ? "utf8" : "base64"
20
- url = read(sheet, url, enc)
74
+ url = read(root, url, baseURI, enc)
21
75
  if (ext === "svg") {
22
76
  url = new DOMParser().parseFromString(url, "application/xml")
23
77
  if (frag && (frag = url.getElementById(frag))) {
@@ -37,12 +91,12 @@ var fs = require("fs")
37
91
  q ? (q = str.indexOf("'") == -1 ? "'" : "\"", q + str.replace(q === "'" ? /\\(")/g : /\\(')/g, "$1")) + q :
38
92
  c ? "" :
39
93
  _.replace(/[\t\n]+/g, " ")
40
- .replace(/ *([,;{}>~+\/]) */g, "$1")
94
+ .replace(/ +(?=[,;{}>~+\/])/g, "").replace(/([,;{}>~+\/]) +/g, "$1")
41
95
  .replace(/;(?=})/g, "")
42
96
  .replace(/: +/g, ":")
43
97
  .replace(/([ :,])0\.([0-9])/g, "$1.$2")
44
98
  , clear = s => s
45
- .replace(/("|')((?:\\\1|[^\1])*?)\1|\s*(\/)\*(?:[^*]|\*(?!\/))*\*\/\s*|(?:[^"'\/]|\/(?!\*))+/g, clearFn)
99
+ .replace(/("|')((?:\\.|[^\\\1])*?)\1|\s*(\/)\*(?:[^*]|\*(?!\/))*\*\/\s*|(?:[^"'\/]|\/(?!\*))+/g, clearFn)
46
100
  .replace(/(["']).*?\1|url\(("|')([^'"()\s]+)\2\)/g, (m,q1,q2,u) => q1 ? m : "url(" + u + ")")
47
101
  , hex = n => (0 | +n + 256.5).toString(16).slice(1)
48
102
  , toRgb = {
@@ -63,29 +117,25 @@ var fs = require("fs")
63
117
  , styleHandler = {
64
118
  get(style, prop) {
65
119
  if (prop === "cssText") {
66
- var min = style.parentRule && style.parentRule.parentStyleSheet.min
67
- for (var out = [], i = style.length; i--; ) {
68
- out[i] = joinProp(style[i], style.__[i] || style[style[i]])
120
+ for (var out = [], name, value, i = style.length; i--; ) {
121
+ name = style[i]
122
+ value = style.__[i] || style[name]
123
+ out[i] = name + ":" + value
69
124
  }
70
125
  return out.join(";")
71
126
  }
72
127
  return style[prop] || ""
73
- function joinProp(name, value) {
74
- if (min && min.color) value = value.replace(colorRe, colorFn)
75
- return name + ":" + value
76
- }
77
128
  },
78
129
  set(style, prop, val) {
79
130
  if (prop === "cssText") {
80
131
  var m, k
81
- , sheet = style.parentRule && style.parentRule.parentStyleSheet
82
- , min = sheet && sheet.min
83
132
  , re = /([*_]?[-a-z]+)\s*:((?:("|')(?:\\.|(?!\3)[^\\])*?\3|[^"';])+)|\/\*!?((?:[^*]|\*(?!\/))*)\*\//ig
84
133
  , len = 0
85
134
  , lastIdx = {}
135
+ , _plugins = []
86
136
  for (; (m = re.exec(val)); ) {
87
137
  if (m[4]) {
88
- if (min && len && plugins[m[4] = m[4].trim()]) style[k = style[len - 1]] = clear(plugins[m[4]](sheet, style[k]))
138
+ if (len && plugins[m[4] = m[4].trim()]) _plugins.push([len - 1, m[4]])
89
139
  } else {
90
140
  k = m[1]
91
141
  if (lastIdx[k] >= 0) style.__[lastIdx[k]] = style[k]
@@ -95,6 +145,7 @@ var fs = require("fs")
95
145
  }
96
146
  }
97
147
  style.length = len
148
+ if (_plugins.length) style._plugins = _plugins
98
149
  } else {
99
150
  if (!style[prop]) style[style.length++] = prop
100
151
  style[prop] = style[prop === "cssFloat" ? "float" : prop.replace(/[A-Z]/g, "-$&").toLowerCase()] = clear(val)
@@ -116,26 +167,7 @@ var fs = require("fs")
116
167
  },
117
168
  import: {
118
169
  get cssText() {
119
- var sheet = this.parentStyleSheet
120
- , min = sheet.min
121
- , text = this.text
122
- , urlFn = (m,q1,q2,u) => q1 ? m : "url('" + path.join(text.baseURI, u) + "')"
123
- if (min && min.import) {
124
- text = new CSSStyleSheet({
125
- parentStyleSheet: sheet,
126
- href: this.href,
127
- min
128
- }, read(sheet, this.href))
129
- if (sheet.baseURI !== text.baseURI) {
130
- text.rules.forEach(rule => {
131
- if (rule.type === 1) for (let style = rule.style, i = style.length; i--; ) {
132
- if (urlRe.test(style[style[i]])) style[style[i]] = style[style[i]].replace(urlRe, urlFn)
133
- }
134
- })
135
- }
136
- text += ""
137
- }
138
- return text
170
+ return this.text
139
171
  },
140
172
  set cssText(text) {
141
173
  this.href = text.split(/['"()]+/)[1]
@@ -144,9 +176,7 @@ var fs = require("fs")
144
176
  },
145
177
  "}": {
146
178
  get cssText() {
147
- var style = new CSSStyleSheet({})
148
- style.replaceSync(this.text)
149
- var body = "" + style
179
+ var body = "" + new CSSStyleSheet({}, this.text)
150
180
  return body.length > 0 ? this.mediaText + "{" + body + "}" : ""
151
181
  },
152
182
  set cssText(text) {
@@ -185,18 +215,31 @@ function CSSStyleDeclaration(text, parentRule = null) {
185
215
  function CSSStyleSheet(opts, text = "") {
186
216
  Object.assign(this, opts)
187
217
  if (opts && opts.href) {
188
- this.baseURI = path.join(
189
- (opts.parentStyleSheet || opts.ownerNode && opts.ownerNode.ownerDocument).baseURI || "",
190
- opts.href,
191
- ".."
192
- )
218
+ this.baseURI = new URL(".", new URL(opts.href, toUrl(
219
+ (opts.parentStyleSheet || opts.ownerNode && opts.ownerNode.ownerDocument).baseURI || ""
220
+ ))).pathname.slice(1).replace(/\/$/, "")
193
221
  }
194
222
  this.replaceSync(text)
195
223
  }
196
224
 
225
+ function updateImportUrls(sheet, urlFn) {
226
+ sheet.rules.forEach(rule => {
227
+ if (rule.type === 1) {
228
+ for (let style = rule.style, val, i = style.length; i--; ) {
229
+ val = style[style[i]]
230
+ if (urlRe.test(val)) style[style[i]] = val.replace(urlRe, urlFn)
231
+ }
232
+ } else if (rule.mediaText != null && rule.text != null) {
233
+ var nested = new CSSStyleSheet({})
234
+ nested.replaceSync(rule.text)
235
+ updateImportUrls(nested, urlFn)
236
+ rule.text = nested.toString()
237
+ }
238
+ })
239
+ }
240
+
197
241
  CSSStyleSheet.prototype = {
198
242
  baseURI: "",
199
- root: "",
200
243
  disabled: false,
201
244
  type: "text/css",
202
245
  deleteRule(idx) {
@@ -237,8 +280,7 @@ CSSStyleSheet.prototype = {
237
280
  }
238
281
  if (depth > 0) throw Error("Unclosed block")
239
282
  },
240
- toString(min) {
241
- if (min) this.min = min
283
+ toString() {
242
284
  return this.rules.map(rule => rule.cssText).filter(Boolean).join("\n")
243
285
  }
244
286
  }
package/dom.js CHANGED
@@ -4,9 +4,10 @@
4
4
  "use strict"
5
5
 
6
6
  var boolAttrs = {
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
7
+ async:1, autoplay:1, loop:1, checked:2, defer:1, disabled:1, muted:1, multiple:1, nomodule:1, playsinline:1, readonly:1, required:1, selected:2
8
8
  }
9
- , numAttrs = "height maxLength minLength size tabIndex width"
9
+ , numAttrs = "height size tabIndex width"
10
+ , numAttrsNeg = "maxLength minLength"
10
11
  , strAttrs = "accept accesskey autocapitalize autofocus capture class contenteditable crossorigin dir for hidden href id integrity lang name nonce rel slot spellcheck src title type translate"
11
12
  , defaultAttrs = {
12
13
  "form method get":1, "input type text":1,
@@ -18,12 +19,12 @@ var boolAttrs = {
18
19
  , svgVoidElements = {
19
20
  circle:1, ellipse:1, image:1, line:1, path:1, polygon:1, polyline:1, rect:1, stop:1, use:1,
20
21
  }
22
+ , listeners = new WeakMap()
21
23
  , rawTextElements = { SCRIPT: /<(?=\/script)/i, STYLE: /<(?=\/style)/i }
22
24
  , rawTextEscape = { SCRIPT: /<(?=\/script|!--)/ig, STYLE: /<(?=\/style|!--)/ig }
23
25
  , hasOwn = voidElements.hasOwnProperty
24
- , { CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
26
+ , { CSS, CSSStyleDeclaration, CSSStyleSheet } = require("./css.js")
25
27
  , selector = require("./selector.js")
26
- , cssEscape = sel => ("" + sel).replace(/[^a-zA-Z0-9_\u00A0-\uFFFF-]/g, "\\$&").replace(/^(-?)([0-9])/, "$1\\3$2 ")
27
28
  , Node = {
28
29
  ELEMENT_NODE: 1,
29
30
  TEXT_NODE: 3,
@@ -140,8 +141,8 @@ var boolAttrs = {
140
141
  var node = this
141
142
  if (node === other) return 0
142
143
  if (node.getRootNode() !== other.getRootNode()) return Node.DOCUMENT_POSITION_DISCONNECTED
143
- if (node.contains(other)) return Node.DOCUMENT_POSITION_CONTAINS
144
- if (other.contains(node)) return Node.DOCUMENT_POSITION_CONTAINED_BY
144
+ if (node.contains(other)) return Node.DOCUMENT_POSITION_CONTAINED_BY | Node.DOCUMENT_POSITION_FOLLOWING
145
+ if (other.contains(node)) return Node.DOCUMENT_POSITION_CONTAINS | Node.DOCUMENT_POSITION_PRECEDING
145
146
 
146
147
  for (; node; node = node.nextSibling || node.parentNode && node.parentNode.nextSibling) {
147
148
  if (node === other) return Node.DOCUMENT_POSITION_FOLLOWING
@@ -199,7 +200,7 @@ var boolAttrs = {
199
200
  },
200
201
  toString(min) {
201
202
  return rawTextElements[this.tagName] ? (
202
- this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + makeSheet(this, min.css || true) + "\n" :
203
+ this.tagName === "STYLE" && (min === true || min && min.css) ? "\n" + CSS.minify(makeSheet(this), typeof min.css === "object" ? min.css : null) + "\n" :
203
204
  this.textContent
204
205
  ) : this.childNodes.map(node => node.toString(min)).join("")
205
206
  },
@@ -277,8 +278,9 @@ var boolAttrs = {
277
278
  "&sect;": "§", "&sup2;": "²", "&sup3;": "³", "&yen;": "¥"
278
279
  }
279
280
 
280
- Object.keys(boolAttrs).forEach(key => addGetter(key, { isBool: true, readonly: "readOnly" }))
281
+ Object.keys(boolAttrs).forEach(key => addGetter(key, { isBool: true, isDirty: boolAttrs[key] > 1, readonly: "readOnly" }))
281
282
  numAttrs.split(" ").forEach(key => addGetter(key, { isNum: true }))
283
+ numAttrsNeg.split(" ").forEach(key => addGetter(key, { isNum: true, numDefault: -1 }))
282
284
  strAttrs.split(" ").forEach(key => addGetter(key, { "for": "htmlFor", "class": "className" }))
283
285
 
284
286
  function addGetter(key, opts) {
@@ -287,19 +289,28 @@ function addGetter(key, opts) {
287
289
  configurable: true,
288
290
  enumerable: true,
289
291
  get: (
292
+ opts.isDirty ? function() { return "_" + attr in this ? this["_" + attr] : this.hasAttribute(attr) } :
290
293
  opts.isBool ? function() { return this.hasAttribute(attr) } :
291
- opts.isNum ? function() { return +this.getAttribute(attr) || 0 } :
294
+ opts.isNum ? function() { var v = this.getAttribute(attr); return v != null ? (+v || 0) : (opts.numDefault || 0) } :
292
295
  function() { return this.getAttribute(attr) || "" }
293
296
  ),
294
297
  set(value) {
295
- this.setAttribute(attr, value)
298
+ if (opts.isDirty) this["_" + attr] = !!value
299
+ else if (opts.isBool && !value) this.removeAttribute(attr)
300
+ else this.setAttribute(attr, value)
296
301
  }
297
302
  })
298
303
  }
299
304
 
300
305
  ;["hasAttribute", "getAttribute", "setAttribute", "removeAttribute"].forEach(name => {
301
306
  Element[name + "NS"] = function(ns, a, b) {
302
- return this[name].call(this, a, b)
307
+ if (name !== "setAttribute" && ns) {
308
+ var lo = (":" + a).toLowerCase()
309
+ for (var key in this.attributes) {
310
+ if (key.endsWith(lo)) return this[name](key)
311
+ }
312
+ }
313
+ return this[name](a, b)
303
314
  }
304
315
  })
305
316
 
@@ -309,9 +320,23 @@ function Attr(node, name, value) {
309
320
  this.value = "" + value
310
321
  }
311
322
 
323
+ function Event(type, opts) {
324
+ Object.assign(this, {type, bubbles: false, cancelable: false, defaultPrevented: false}, opts)
325
+ }
326
+ Event.prototype = {
327
+ stopPropagation() {
328
+ this.bubbles = false
329
+ },
330
+ preventDefault() {
331
+ if (this.cancelable) this.defaultPrevented = true
332
+ }
333
+ }
334
+
312
335
  function NamedNodeMap(node) {
313
- Object.defineProperty(this, "length", { get() { return this.names().length } })
314
- Object.defineProperty(this, "ownerElement", { value: node })
336
+ Object.defineProperties(this, {
337
+ length: { get() { return this.names().length } },
338
+ ownerElement: { value: node }
339
+ })
315
340
  }
316
341
 
317
342
  NamedNodeMap.prototype = {
@@ -386,15 +411,39 @@ extendNode(HTMLElement, Element, {
386
411
  namespaceURI: "http://www.w3.org/1999/xhtml",
387
412
  nodeType: 1,
388
413
  tagName: null,
414
+ get elements() {
415
+ return this.tagName === "FORM" ? selector.find(this, "input,select,textarea,button") : undefined
416
+ },
389
417
  get sheet() {
390
418
  return makeSheet(this)
391
419
  },
392
420
  blur() {
393
- this.ownerDocument.activeElement = null
421
+ this.ownerDocument.activeElement = this.ownerDocument.body || null
422
+ },
423
+ click() {
424
+ this.dispatchEvent(new Event("click", { bubbles: true, cancelable: true }))
394
425
  },
395
426
  closest(sel) {
396
427
  return selector.closest(this, sel)
397
428
  },
429
+ addEventListener(type, fn) {
430
+ var map = listeners.get(this)
431
+ if (!map) listeners.set(this, map = {})
432
+ ;(map[type] || (map[type] = [])).push(fn)
433
+ },
434
+ dispatchEvent(ev) {
435
+ if (!ev.target) ev.target = this
436
+ var fns = (listeners.get(this) || {})[ev.type]
437
+ if (fns) fns.forEach(function(fn) { fn.call(this, ev) }, this)
438
+ if (ev.bubbles && this.parentNode && this.parentNode.dispatchEvent) {
439
+ this.parentNode.dispatchEvent(ev)
440
+ }
441
+ },
442
+ removeEventListener(type, fn) {
443
+ var fns = (listeners.get(this) || {})[type]
444
+ , i = fns ? fns.indexOf(fn) : -1
445
+ if (i > -1) fns.splice(i, 1)
446
+ },
398
447
  focus() {
399
448
  this.ownerDocument.activeElement = this
400
449
  },
@@ -422,7 +471,7 @@ function ElementNS(namespace, tag) {
422
471
  ElementNS.prototype = HTMLElement.prototype
423
472
 
424
473
  function Text(data) {
425
- this.data = data
474
+ this.data = "" + data
426
475
  }
427
476
 
428
477
  extendNode(Text, {
@@ -453,11 +502,6 @@ extendNode(DocumentType, {
453
502
  nodeType: 10,
454
503
  toString() {
455
504
  return "<" + this.data + ">"
456
- // var node = document.doctype
457
- // return "<!DOCTYPE " + node.name +
458
- // (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') +
459
- // (!node.publicId && node.systemId ? ' SYSTEM' : '') +
460
- // (node.systemId ? ' "' + node.systemId + '"' : '') + '>'
461
505
  }
462
506
  })
463
507
 
@@ -517,11 +561,8 @@ function own(Class) {
517
561
 
518
562
  function extendNode(obj, extras) {
519
563
  obj.prototype = Object.create(Node)
520
- for (var descriptor, key, i = 1; (extras = arguments[i++]); ) {
521
- for (key in extras) {
522
- descriptor = Object.getOwnPropertyDescriptor(extras, key)
523
- Object.defineProperty(obj.prototype, key, descriptor)
524
- }
564
+ for (var i = 1; (extras = arguments[i++]); ) {
565
+ Object.defineProperties(obj.prototype, Object.getOwnPropertyDescriptors(extras))
525
566
  }
526
567
  obj.prototype.constructor = obj
527
568
  }
@@ -531,9 +572,9 @@ function removeChilds(node) {
531
572
  node.childNodes.length = 0
532
573
  }
533
574
 
534
- function getElement(childs, index, step, type) {
575
+ function getElement(childs, index, step) {
535
576
  if (childs && index > -1) for (; childs[index]; index += step) {
536
- if (childs[index].nodeType === type) return childs[index]
577
+ if (childs[index].nodeType === 1) return childs[index]
537
578
  }
538
579
  return null
539
580
  }
@@ -541,14 +582,13 @@ function getElement(childs, index, step, type) {
541
582
  function getSibling(node, step, type) {
542
583
  var silbings = node.parentNode && node.parentNode.childNodes
543
584
  , index = silbings ? silbings.indexOf(node) : -1
544
- return type > 0 ? getElement(silbings, index + step, step, type) : silbings && silbings[index + step] || null
585
+ return type ? getElement(silbings, index + step, step) : silbings && silbings[index + step] || null
545
586
  }
546
587
 
547
- function makeSheet(el, min) {
588
+ function makeSheet(el) {
548
589
  if (el.tagName === "STYLE" || el.tagName === "LINK" && el.rel === "stylesheet" && el.href) return new CSSStyleSheet({
549
590
  href: el.href,
550
- ownerNode: el,
551
- min
591
+ ownerNode: el
552
592
  }, el.tagName === "STYLE" && el.textContent)
553
593
  }
554
594
 
@@ -562,12 +602,13 @@ exports.document = new Document()
562
602
  exports.entities = entities
563
603
  exports.mergeAttributes = mergeAttributes
564
604
  exports.selectorSplit = selector.selectorSplit
565
- exports.cssEscape = cssEscape
605
+ exports.CSS = CSS
566
606
  exports.CSSStyleDeclaration = CSSStyleDeclaration
567
607
  exports.CSSStyleSheet = CSSStyleSheet
568
608
  exports.DOMParser = DOMParser
569
609
  exports.Document = Document
570
610
  exports.DocumentFragment = DocumentFragment
611
+ exports.Event = Event
571
612
  exports.HTMLElement = HTMLElement
572
613
  exports.Node = Node
573
614
  exports.XMLSerializer = XMLSerializer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litejs/dom",
3
- "version": "25.12.0",
3
+ "version": "26.3.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>",
@@ -29,6 +29,6 @@
29
29
  "url": "https://github.com/litejs/dom.git"
30
30
  },
31
31
  "devDependencies": {
32
- "@litejs/cli": "25.1.0"
32
+ "@litejs/cli": "26.3.0"
33
33
  }
34
34
  }
package/selector.js CHANGED
@@ -6,9 +6,7 @@
6
6
  exports.find = find
7
7
  exports.selectorSplit = selectorSplit
8
8
 
9
- var selectorCache = {
10
- "": () => {}
11
- }
9
+ var selectorCache = {}
12
10
  , selectorRe = /([.#:[])([-\w]+)(?:\(((?:[^()]|\([^)]+\))+?)\)|([~^$*|]?)=(("|')(?:\\.|[^\\])*?\6|[-\w]+))?]?/g
13
11
  , selectorLastRe = /([\s>+~]*)(?:("|')(?:\\.|[^\\])*?\2|\((?:[^()]|\([^()]+\))+?\)|~=|[^'"()\s>+~])+$/
14
12
  , selectorMap = exports.selectorMap = {
@@ -41,7 +39,7 @@ var selectorCache = {
41
39
  "": "c(_.parentNode,v)"
42
40
  }
43
41
  , closest = exports.closest = walk.bind(exports, "parentNode", 1)
44
- , matches = exports.matches = (el, sel) => !!selectorFn(sel)(el)
42
+ , matches = exports.matches = (el, sel) => !!(sel && selectorFn(sel)(el))
45
43
  , next = exports.next = (el, sel) => walk("nextSibling", 1, el.nextSibling, sel)
46
44
  , prev = exports.prev = (el, sel) => walk("previousSibling", 1, el.previousSibling, sel)
47
45
 
@@ -49,8 +47,8 @@ var selectorCache = {
49
47
  selectorMap["nth-last-child"] = selectorMap["nth-child"].replace("1+", "v.length-")
50
48
 
51
49
  function selectorFn(str) {
52
- if (str != null && typeof str !== "string") throw Error("Invalid selector")
53
- return selectorCache[str || ""] ||
50
+ if (!str || typeof str !== "string") throw Error("Invalid selector")
51
+ return selectorCache[str] ||
54
52
  (selectorCache[str] = Function("m,c,n,p", "return (_,v,a,b)=>" +
55
53
  selectorSplit(str).map(sel => {
56
54
  var relation, from
@@ -61,6 +59,7 @@ function selectorFn(str) {
61
59
  return ""
62
60
  })
63
61
  , tag = sel.slice(from).replace(selectorRe, (_, op, key, subSel, fn, val, quotation) => {
62
+ if (key[0] == + key[0]) throw Error("Invalid selector")
64
63
  rules.push(
65
64
  "((v='" +
66
65
  (subSel || (quotation ? val.slice(1, -1) : val) || "").replace(/[\\']/g, "\\$&") +
package/types/index.d.ts CHANGED
@@ -188,4 +188,7 @@ export const document: Document
188
188
  export const entities: Record<string, string>
189
189
  export function mergeAttributes(source: HTMLElement | null, target: HTMLElement | null): void
190
190
  export function selectorSplit(selector: string): string[]
191
- export function cssEscape(selector: string | number): string
191
+ export const CSS: {
192
+ escape(selector: string | number): string
193
+ minify(sheet: CSSStyleSheet, min?: { color?: boolean }): string
194
+ }