@asamuzakjp/dom-selector 0.12.2 → 0.12.5

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/package.json CHANGED
@@ -42,5 +42,5 @@
42
42
  "test": "c8 --reporter=text mocha --exit test/**/*.test.js",
43
43
  "tsc": "npx tsc"
44
44
  },
45
- "version": "0.12.2"
45
+ "version": "0.12.5"
46
46
  }
package/src/js/matcher.js CHANGED
@@ -19,12 +19,17 @@ const FILTER_ACCEPT = 1;
19
19
  const FILTER_REJECT = 2;
20
20
  const FILTER_SHOW_ELEMENT = 1;
21
21
  const TEXT_NODE = 3;
22
+ const UNIVERSAL_SELECTOR = {
23
+ name: '*',
24
+ type: TYPE_SELECTOR
25
+ };
22
26
 
23
27
  /* regexp */
24
28
  const HEX_CAPTURE = /^([\da-f]{1,6}\s?)/i;
25
29
  const HTML_FORM_INPUT = /^(?:(?:inpu|selec)t|textarea)$/;
26
30
  const HTML_FORM_PARTS = /^(?:button|fieldset|opt(?:group|ion))$/;
27
31
  const HTML_INTERACT = /^d(?:etails|ialog)$/;
32
+ const INPUT_TYPE_BARRED = /^(?:(?:butto|hidde)n|reset)$/;
28
33
  const PSEUDO_FUNC = /^(?:(?:ha|i)s|not|where)$/;
29
34
  const PSEUDO_NTH = /^nth-(?:last-)?(?:child|of-type)$/;
30
35
  const WHITESPACE = /^[\n\r\f]/;
@@ -93,7 +98,7 @@ const unescapeSelector = (selector = '') => {
93
98
  selector.indexOf(String.fromCharCode(0x5c), 0) >= 0) {
94
99
  const arr = selector.split('\\');
95
100
  const l = arr.length;
96
- for (let i = 0; i < l; i++) {
101
+ for (let i = 1; i < l; i++) {
97
102
  let item = arr[i];
98
103
  if (i === l - 1 && item === '') {
99
104
  item = '\uFFFD';
@@ -114,7 +119,11 @@ const unescapeSelector = (selector = '') => {
114
119
  } catch (e) {
115
120
  str = '\uFFFD';
116
121
  }
117
- item = item.replace(`${hex}`, str);
122
+ let postStr = '';
123
+ if (item.length > hex.length) {
124
+ postStr = item.substring(hex.length);
125
+ }
126
+ item = `${str}${postStr}`;
118
127
  } else if (WHITESPACE.test(item)) {
119
128
  item = '\\' + item;
120
129
  }
@@ -950,7 +959,7 @@ const matchPseudoClassSelector = (
950
959
  break;
951
960
  case 'valid':
952
961
  if (HTML_FORM_INPUT.test(localName) ||
953
- /^(?:f(?:ieldset|orm)|button|output)$/.test(localName)) {
962
+ /^(?:f(?:ieldset|orm)|button)$/.test(localName)) {
954
963
  if (node.checkValidity()) {
955
964
  matched.push(node);
956
965
  }
@@ -958,27 +967,28 @@ const matchPseudoClassSelector = (
958
967
  break;
959
968
  case 'invalid':
960
969
  if (HTML_FORM_INPUT.test(localName) ||
961
- /^(?:f(?:ieldset|orm)|button|output)$/.test(localName)) {
970
+ /^(?:f(?:ieldset|orm)|button)$/.test(localName)) {
962
971
  if (!node.checkValidity()) {
963
972
  matched.push(node);
964
973
  }
965
974
  }
966
975
  break;
967
976
  case 'in-range':
968
- if (localName === 'input' &&
969
- node.hasAttribute('min') && node.hasAttribute('max')) {
970
- if (!(node.validity.rangeUnderflow ||
971
- node.validity.rangeOverflow)) {
972
- matched.push(node);
973
- }
977
+ if (localName === 'input' && !node.readonly &&
978
+ !(node.hasAttribute('type') &&
979
+ INPUT_TYPE_BARRED.test(node.getAttribute('type'))) &&
980
+ node.hasAttribute('min') && node.hasAttribute('max') &&
981
+ !(node.validity.rangeUnderflow || node.validity.rangeOverflow)) {
982
+ matched.push(node);
974
983
  }
975
984
  break;
976
985
  case 'out-of-range':
977
- if (localName === 'input' &&
978
- node.hasAttribute('min') && node.hasAttribute('max')) {
979
- if (node.validity.rangeUnderflow || node.validity.rangeOverflow) {
980
- matched.push(node);
981
- }
986
+ if (localName === 'input' && !node.readonly &&
987
+ !(node.hasAttribute('type') &&
988
+ INPUT_TYPE_BARRED.test(node.getAttribute('type'))) &&
989
+ node.hasAttribute('min') && node.hasAttribute('max') &&
990
+ (node.validity.rangeUnderflow || node.validity.rangeOverflow)) {
991
+ matched.push(node);
982
992
  }
983
993
  break;
984
994
  case 'required':
@@ -1451,10 +1461,7 @@ class Matcher {
1451
1461
  if (firstChild.type === PSEUDO_CLASS_SELECTOR &&
1452
1462
  PSEUDO_FUNC.test(unescapeSelector(firstChild.name)) &&
1453
1463
  node.nodeType === ELEMENT_NODE) {
1454
- const iteratorLeaf = {
1455
- name: '*',
1456
- type: TYPE_SELECTOR
1457
- };
1464
+ const iteratorLeaf = UNIVERSAL_SELECTOR;
1458
1465
  const iterator = this._createIterator(iteratorLeaf, node);
1459
1466
  let nextNode = iterator.nextNode();
1460
1467
  while (nextNode) {
@@ -1469,10 +1476,7 @@ class Matcher {
1469
1476
  if (firstChild.type === COMBINATOR ||
1470
1477
  (firstChild.type === PSEUDO_CLASS_SELECTOR &&
1471
1478
  PSEUDO_NTH.test(unescapeSelector(firstChild.name)))) {
1472
- iteratorLeaf = {
1473
- name: '*',
1474
- type: TYPE_SELECTOR
1475
- };
1479
+ iteratorLeaf = UNIVERSAL_SELECTOR;
1476
1480
  } else {
1477
1481
  iteratorLeaf = children.shift();
1478
1482
  }
@@ -1530,6 +1534,9 @@ class Matcher {
1530
1534
  leaves.push(items.shift());
1531
1535
  }
1532
1536
  }
1537
+ if (leaves.length === 1) {
1538
+ leaves.push(UNIVERSAL_SELECTOR);
1539
+ }
1533
1540
  const arr = this._matchCombinator(leaves, nextNode);
1534
1541
  if (!arr.length || arr.length === 1) {
1535
1542
  [nextNode] = arr;
package/src/js/parser.js CHANGED
@@ -23,16 +23,16 @@ const preprocess = (...args) => {
23
23
  throw new TypeError('1 argument required, but only 0 present');
24
24
  }
25
25
  let [selector] = args;
26
- if (typeof selector !== 'string') {
27
- if (selector === undefined || selector === null) {
28
- selector = Object.prototype.toString.call(selector)
29
- .slice(TYPE_FROM, TYPE_TO).toLowerCase();
30
- } else {
31
- throw new DOMException(`invalid selector ${selector}`, 'SyntaxError');
32
- }
26
+ if (typeof selector === 'string') {
27
+ selector = selector.replace(/\f|\r\n?/g, '\n')
28
+ .replace(/[\0\uD800-\uDFFF]|\\$/g, '\uFFFD').trim();
29
+ } else if (selector === undefined || selector === null) {
30
+ selector = Object.prototype.toString.call(selector)
31
+ .slice(TYPE_FROM, TYPE_TO).toLowerCase();
32
+ } else {
33
+ throw new DOMException(`invalid selector ${selector}`, 'SyntaxError');
33
34
  }
34
- return selector.replace(/\f|\r\n?/g, '\n')
35
- .replace(/[\0\uD800-\uDFFF]/g, '\uFFFD').trim();
35
+ return selector;
36
36
  };
37
37
 
38
38
  /**