matcher.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import NodeType from './nodes/type';
  2. function isTag(node) {
  3. return node && node.nodeType === NodeType.ELEMENT_NODE;
  4. }
  5. function getAttributeValue(elem, name) {
  6. return isTag(elem) ? elem.getAttribute(name) : undefined;
  7. }
  8. function getName(elem) {
  9. return ((elem && elem.rawTagName) || '').toLowerCase();
  10. }
  11. function getChildren(node) {
  12. return node && node.childNodes;
  13. }
  14. function getParent(node) {
  15. return node ? node.parentNode : null;
  16. }
  17. function getText(node) {
  18. return node.text;
  19. }
  20. function removeSubsets(nodes) {
  21. let idx = nodes.length;
  22. let node;
  23. let ancestor;
  24. let replace;
  25. // Check if each node (or one of its ancestors) is already contained in the
  26. // array.
  27. while (--idx > -1) {
  28. node = ancestor = nodes[idx];
  29. // Temporarily remove the node under consideration
  30. nodes[idx] = null;
  31. replace = true;
  32. while (ancestor) {
  33. if (nodes.indexOf(ancestor) > -1) {
  34. replace = false;
  35. nodes.splice(idx, 1);
  36. break;
  37. }
  38. ancestor = getParent(ancestor);
  39. }
  40. // If the node has been found to be unique, re-insert it.
  41. if (replace) {
  42. nodes[idx] = node;
  43. }
  44. }
  45. return nodes;
  46. }
  47. function existsOne(test, elems) {
  48. return elems.some((elem) => {
  49. return isTag(elem) ? test(elem) || existsOne(test, getChildren(elem)) : false;
  50. });
  51. }
  52. function getSiblings(node) {
  53. const parent = getParent(node);
  54. return parent && getChildren(parent);
  55. }
  56. function hasAttrib(elem, name) {
  57. return getAttributeValue(elem, name) !== undefined;
  58. }
  59. function findOne(test, elems) {
  60. let elem = null;
  61. for (let i = 0, l = elems.length; i < l && !elem; i++) {
  62. const el = elems[i];
  63. if (test(el)) {
  64. elem = el;
  65. }
  66. else {
  67. const childs = getChildren(el);
  68. if (childs && childs.length > 0) {
  69. elem = findOne(test, childs);
  70. }
  71. }
  72. }
  73. return elem;
  74. }
  75. function findAll(test, nodes) {
  76. let result = [];
  77. for (let i = 0, j = nodes.length; i < j; i++) {
  78. if (!isTag(nodes[i]))
  79. continue;
  80. if (test(nodes[i]))
  81. result.push(nodes[i]);
  82. const childs = getChildren(nodes[i]);
  83. if (childs)
  84. result = result.concat(findAll(test, childs));
  85. }
  86. return result;
  87. }
  88. export default {
  89. isTag,
  90. getAttributeValue,
  91. getName,
  92. getChildren,
  93. getParent,
  94. getText,
  95. removeSubsets,
  96. existsOne,
  97. getSiblings,
  98. hasAttrib,
  99. findOne,
  100. findAll
  101. };