index.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import * as DomUtils from "domutils";
  2. import boolbase from "boolbase";
  3. import { compile as compileRaw, compileUnsafe, compileToken, } from "./compile.js";
  4. import { getNextSiblings } from "./pseudo-selectors/subselects.js";
  5. const defaultEquals = (a, b) => a === b;
  6. const defaultOptions = {
  7. adapter: DomUtils,
  8. equals: defaultEquals,
  9. };
  10. function convertOptionFormats(options) {
  11. var _a, _b, _c, _d;
  12. /*
  13. * We force one format of options to the other one.
  14. */
  15. // @ts-expect-error Default options may have incompatible `Node` / `ElementNode`.
  16. const opts = options !== null && options !== void 0 ? options : defaultOptions;
  17. // @ts-expect-error Same as above.
  18. (_a = opts.adapter) !== null && _a !== void 0 ? _a : (opts.adapter = DomUtils);
  19. // @ts-expect-error `equals` does not exist on `Options`
  20. (_b = opts.equals) !== null && _b !== void 0 ? _b : (opts.equals = (_d = (_c = opts.adapter) === null || _c === void 0 ? void 0 : _c.equals) !== null && _d !== void 0 ? _d : defaultEquals);
  21. return opts;
  22. }
  23. function wrapCompile(func) {
  24. return function addAdapter(selector, options, context) {
  25. const opts = convertOptionFormats(options);
  26. return func(selector, opts, context);
  27. };
  28. }
  29. /**
  30. * Compiles the query, returns a function.
  31. */
  32. export const compile = wrapCompile(compileRaw);
  33. export const _compileUnsafe = wrapCompile(compileUnsafe);
  34. export const _compileToken = wrapCompile(compileToken);
  35. function getSelectorFunc(searchFunc) {
  36. return function select(query, elements, options) {
  37. const opts = convertOptionFormats(options);
  38. if (typeof query !== "function") {
  39. query = compileUnsafe(query, opts, elements);
  40. }
  41. const filteredElements = prepareContext(elements, opts.adapter, query.shouldTestNextSiblings);
  42. return searchFunc(query, filteredElements, opts);
  43. };
  44. }
  45. export function prepareContext(elems, adapter, shouldTestNextSiblings = false) {
  46. /*
  47. * Add siblings if the query requires them.
  48. * See https://github.com/fb55/css-select/pull/43#issuecomment-225414692
  49. */
  50. if (shouldTestNextSiblings) {
  51. elems = appendNextSiblings(elems, adapter);
  52. }
  53. return Array.isArray(elems)
  54. ? adapter.removeSubsets(elems)
  55. : adapter.getChildren(elems);
  56. }
  57. function appendNextSiblings(elem, adapter) {
  58. // Order matters because jQuery seems to check the children before the siblings
  59. const elems = Array.isArray(elem) ? elem.slice(0) : [elem];
  60. const elemsLength = elems.length;
  61. for (let i = 0; i < elemsLength; i++) {
  62. const nextSiblings = getNextSiblings(elems[i], adapter);
  63. elems.push(...nextSiblings);
  64. }
  65. return elems;
  66. }
  67. /**
  68. * @template Node The generic Node type for the DOM adapter being used.
  69. * @template ElementNode The Node type for elements for the DOM adapter being used.
  70. * @param elems Elements to query. If it is an element, its children will be queried..
  71. * @param query can be either a CSS selector string or a compiled query function.
  72. * @param [options] options for querying the document.
  73. * @see compile for supported selector queries.
  74. * @returns All matching elements.
  75. *
  76. */
  77. export const selectAll = getSelectorFunc((query, elems, options) => query === boolbase.falseFunc || !elems || elems.length === 0
  78. ? []
  79. : options.adapter.findAll(query, elems));
  80. /**
  81. * @template Node The generic Node type for the DOM adapter being used.
  82. * @template ElementNode The Node type for elements for the DOM adapter being used.
  83. * @param elems Elements to query. If it is an element, its children will be queried..
  84. * @param query can be either a CSS selector string or a compiled query function.
  85. * @param [options] options for querying the document.
  86. * @see compile for supported selector queries.
  87. * @returns the first match, or null if there was no match.
  88. */
  89. export const selectOne = getSelectorFunc((query, elems, options) => query === boolbase.falseFunc || !elems || elems.length === 0
  90. ? null
  91. : options.adapter.findOne(query, elems));
  92. /**
  93. * Tests whether or not an element is matched by query.
  94. *
  95. * @template Node The generic Node type for the DOM adapter being used.
  96. * @template ElementNode The Node type for elements for the DOM adapter being used.
  97. * @param elem The element to test if it matches the query.
  98. * @param query can be either a CSS selector string or a compiled query function.
  99. * @param [options] options for querying the document.
  100. * @see compile for supported selector queries.
  101. * @returns
  102. */
  103. export function is(elem, query, options) {
  104. const opts = convertOptionFormats(options);
  105. return (typeof query === "function" ? query : compileRaw(query, opts))(elem);
  106. }
  107. /**
  108. * Alias for selectAll(query, elems, options).
  109. * @see [compile] for supported selector queries.
  110. */
  111. export default selectAll;
  112. // Export filters, pseudos and aliases to allow users to supply their own.
  113. /** @deprecated Use the `pseudos` option instead. */
  114. export { filters, pseudos, aliases } from "./pseudo-selectors/index.js";
  115. //# sourceMappingURL=index.js.map