@asamuzakjp/dom-selector 0.15.5 → 0.15.7

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.15.5"
45
+ "version": "0.15.7"
46
46
  }
package/src/js/matcher.js CHANGED
@@ -73,14 +73,16 @@ const isNamespaceDeclared = (ns = '', node = {}) => {
73
73
  if (ns && typeof ns === 'string' && node.nodeType === ELEMENT_NODE) {
74
74
  const attr = `xmlns:${ns}`;
75
75
  const root = node.ownerDocument.documentElement;
76
- while (node) {
77
- if (node.hasAttribute(attr)) {
76
+ let parent = node;
77
+ while (parent) {
78
+ if (typeof parent.hasAttribute === 'function' &&
79
+ parent.hasAttribute(attr)) {
78
80
  res = true;
79
81
  break;
80
- } else if (node === root) {
82
+ } else if (parent === root) {
81
83
  break;
82
84
  }
83
- node = node.parentNode;
85
+ parent = parent.parentNode;
84
86
  }
85
87
  }
86
88
  return !!res;
@@ -600,54 +602,56 @@ const matchAttributeSelector = (ast = {}, node = {}) => {
600
602
  flags: astFlags, matcher: astMatcher, name: astName, type: astType,
601
603
  value: astValue
602
604
  } = ast;
603
- const { attributes, nodeType } = node;
605
+ if (typeof astFlags === 'string' && !/^[is]$/i.test(astFlags)) {
606
+ throw new DOMException('invalid attribute selector', 'SyntaxError');
607
+ }
608
+ const { attributes, nodeType, ownerDocument } = node;
604
609
  let res;
605
610
  if (astType === ATTRIBUTE_SELECTOR && nodeType === ELEMENT_NODE &&
606
611
  attributes?.length) {
607
- if (typeof astFlags === 'string' && !/^[is]$/i.test(astFlags)) {
608
- throw new DOMException('invalid attribute selector', 'SyntaxError');
609
- }
610
- const caseInsensitive =
611
- !(typeof astFlags === 'string' && /^s$/i.test(astFlags));
612
- const attrValues = [];
613
- const l = attributes.length;
614
612
  let { name: astAttrName } = astName;
615
613
  astAttrName = unescapeSelector(astAttrName);
614
+ let caseInsensitive;
615
+ if (ownerDocument?.contentType === 'text/html') {
616
+ if (typeof astFlags === 'string' && /^s$/i.test(astFlags)) {
617
+ caseInsensitive = false;
618
+ } else {
619
+ caseInsensitive = true;
620
+ }
621
+ } else if (typeof astFlags === 'string' && /^i$/i.test(astFlags)) {
622
+ caseInsensitive = true;
623
+ } else {
624
+ caseInsensitive = false;
625
+ }
616
626
  if (caseInsensitive) {
617
627
  astAttrName = astAttrName.toLowerCase();
618
628
  }
629
+ const l = attributes.length;
630
+ const attrValues = [];
619
631
  // namespaced
620
632
  if (/\|/.test(astAttrName)) {
621
633
  const [astAttrPrefix, astAttrLocalName] = astAttrName.split('|');
622
634
  let i = 0;
623
635
  while (i < l) {
624
- const { name: itemName, value: itemValue } = attributes.item(i);
636
+ let { name: itemName, value: itemValue } = attributes.item(i);
637
+ if (caseInsensitive) {
638
+ itemName = itemName.toLowerCase();
639
+ itemValue = itemValue.toLowerCase();
640
+ }
625
641
  switch (astAttrPrefix) {
626
642
  case '': {
627
643
  if (astAttrLocalName === itemName) {
628
- if (caseInsensitive) {
629
- attrValues.push(itemValue.toLowerCase());
630
- } else {
631
- attrValues.push(itemValue);
632
- }
644
+ attrValues.push(itemValue);
633
645
  }
634
646
  break;
635
647
  }
636
648
  case '*': {
637
649
  if (/:/.test(itemName)) {
638
650
  if (itemName.endsWith(`:${astAttrLocalName}`)) {
639
- if (caseInsensitive) {
640
- attrValues.push(itemValue.toLowerCase());
641
- } else {
642
- attrValues.push(itemValue);
643
- }
644
- }
645
- } else if (astAttrLocalName === itemName) {
646
- if (caseInsensitive) {
647
- attrValues.push(itemValue.toLowerCase());
648
- } else {
649
651
  attrValues.push(itemValue);
650
652
  }
653
+ } else if (astAttrLocalName === itemName) {
654
+ attrValues.push(itemValue);
651
655
  }
652
656
  break;
653
657
  }
@@ -656,11 +660,7 @@ const matchAttributeSelector = (ast = {}, node = {}) => {
656
660
  const [itemNamePrefix, itemNameLocalName] = itemName.split(':');
657
661
  if (astAttrPrefix === itemNamePrefix &&
658
662
  astAttrLocalName === itemNameLocalName) {
659
- if (caseInsensitive) {
660
- attrValues.push(itemValue.toLowerCase());
661
- } else {
662
- attrValues.push(itemValue);
663
- }
663
+ attrValues.push(itemValue);
664
664
  }
665
665
  }
666
666
  }
@@ -670,22 +670,18 @@ const matchAttributeSelector = (ast = {}, node = {}) => {
670
670
  } else {
671
671
  let i = 0;
672
672
  while (i < l) {
673
- const { name: itemName, value: itemValue } = attributes.item(i);
673
+ let { name: itemName, value: itemValue } = attributes.item(i);
674
+ if (caseInsensitive) {
675
+ itemName = itemName.toLowerCase();
676
+ itemValue = itemValue.toLowerCase();
677
+ }
674
678
  if (/:/.test(itemName)) {
675
679
  const [, itemNameLocalName] = itemName.split(':');
676
680
  if (astAttrName === itemNameLocalName) {
677
- if (caseInsensitive) {
678
- attrValues.push(itemValue.toLowerCase());
679
- } else {
680
- attrValues.push(itemValue);
681
- }
682
- }
683
- } else if (astAttrName === itemName) {
684
- if (caseInsensitive) {
685
- attrValues.push(itemValue.toLowerCase());
686
- } else {
687
681
  attrValues.push(itemValue);
688
682
  }
683
+ } else if (astAttrName === itemName) {
684
+ attrValues.push(itemValue);
689
685
  }
690
686
  i++;
691
687
  }
@@ -722,7 +718,7 @@ const matchAttributeSelector = (ast = {}, node = {}) => {
722
718
  break;
723
719
  }
724
720
  case '~=': {
725
- if (typeof attrValue === 'string') {
721
+ if (attrValue && typeof attrValue === 'string') {
726
722
  for (const item of attrValues) {
727
723
  const arr = item.split(/\s+/);
728
724
  if (arr.includes(attrValue)) {
package/src/js/parser.js CHANGED
@@ -82,6 +82,8 @@ const parseSelector = selector => {
82
82
  } catch (e) {
83
83
  if (e.message === '"]" is expected' && !selector.endsWith(']')) {
84
84
  res = parseSelector(`${selector}]`);
85
+ } else if (e.message === '")" is expected' && !selector.endsWith(')')) {
86
+ res = parseSelector(`${selector})`);
85
87
  } else {
86
88
  throw new DOMException(e.message, 'SyntaxError');
87
89
  }