querying.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /**
  2. * Find all elements matching the query. If not in XML mode, the query will ignore
  3. * the contents of `<template>` elements.
  4. *
  5. * @param query - Function that returns true if the element matches the query.
  6. * @param elems - Nodes to query. If a node is an element, its children will be queried.
  7. * @param options - Options for querying the document.
  8. * @returns All matching elements.
  9. */
  10. export function findAll(query, elems, options) {
  11. const { adapter, xmlMode = false } = options;
  12. const result = [];
  13. /** Stack of the arrays we are looking at. */
  14. const nodeStack = [elems];
  15. /** Stack of the indices within the arrays. */
  16. const indexStack = [0];
  17. for (;;) {
  18. // First, check if the current array has any more elements to look at.
  19. if (indexStack[0] >= nodeStack[0].length) {
  20. // If we have no more arrays to look at, we are done.
  21. if (nodeStack.length === 1) {
  22. return result;
  23. }
  24. nodeStack.shift();
  25. indexStack.shift();
  26. // Loop back to the start to continue with the next array.
  27. continue;
  28. }
  29. const elem = nodeStack[0][indexStack[0]++];
  30. if (!adapter.isTag(elem))
  31. continue;
  32. if (query(elem))
  33. result.push(elem);
  34. if (xmlMode || adapter.getName(elem) !== "template") {
  35. /*
  36. * Add the children to the stack. We are depth-first, so this is
  37. * the next array we look at.
  38. */
  39. const children = adapter.getChildren(elem);
  40. if (children.length > 0) {
  41. nodeStack.unshift(children);
  42. indexStack.unshift(0);
  43. }
  44. }
  45. }
  46. }
  47. /**
  48. * Find the first element matching the query. If not in XML mode, the query will ignore
  49. * the contents of `<template>` elements.
  50. *
  51. * @param query - Function that returns true if the element matches the query.
  52. * @param elems - Nodes to query. If a node is an element, its children will be queried.
  53. * @param options - Options for querying the document.
  54. * @returns The first matching element, or null if there was no match.
  55. */
  56. export function findOne(query, elems, options) {
  57. const { adapter, xmlMode = false } = options;
  58. /** Stack of the arrays we are looking at. */
  59. const nodeStack = [elems];
  60. /** Stack of the indices within the arrays. */
  61. const indexStack = [0];
  62. for (;;) {
  63. // First, check if the current array has any more elements to look at.
  64. if (indexStack[0] >= nodeStack[0].length) {
  65. // If we have no more arrays to look at, we are done.
  66. if (nodeStack.length === 1) {
  67. return null;
  68. }
  69. nodeStack.shift();
  70. indexStack.shift();
  71. // Loop back to the start to continue with the next array.
  72. continue;
  73. }
  74. const elem = nodeStack[0][indexStack[0]++];
  75. if (!adapter.isTag(elem))
  76. continue;
  77. if (query(elem))
  78. return elem;
  79. if (xmlMode || adapter.getName(elem) !== "template") {
  80. /*
  81. * Add the children to the stack. We are depth-first, so this is
  82. * the next array we look at.
  83. */
  84. const children = adapter.getChildren(elem);
  85. if (children.length > 0) {
  86. nodeStack.unshift(children);
  87. indexStack.unshift(0);
  88. }
  89. }
  90. }
  91. }
  92. export function getNextSiblings(elem, adapter) {
  93. const siblings = adapter.getSiblings(elem);
  94. if (siblings.length <= 1)
  95. return [];
  96. const elemIndex = siblings.indexOf(elem);
  97. if (elemIndex < 0 || elemIndex === siblings.length - 1)
  98. return [];
  99. return siblings.slice(elemIndex + 1).filter(adapter.isTag);
  100. }
  101. export function getElementParent(node, adapter) {
  102. const parent = adapter.getParent(node);
  103. return parent != null && adapter.isTag(parent) ? parent : null;
  104. }
  105. //# sourceMappingURL=querying.js.map