You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.1 KiB

2 years ago
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const picomatch = require('picomatch');
  4. const normalizePath = require('normalize-path');
  5. /**
  6. * @typedef {(testString: string) => boolean} AnymatchFn
  7. * @typedef {string|RegExp|AnymatchFn} AnymatchPattern
  8. * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher
  9. */
  10. const BANG = '!';
  11. const DEFAULT_OPTIONS = {returnIndex: false};
  12. const arrify = (item) => Array.isArray(item) ? item : [item];
  13. /**
  14. * @param {AnymatchPattern} matcher
  15. * @param {object} options
  16. * @returns {AnymatchFn}
  17. */
  18. const createPattern = (matcher, options) => {
  19. if (typeof matcher === 'function') {
  20. return matcher;
  21. }
  22. if (typeof matcher === 'string') {
  23. const glob = picomatch(matcher, options);
  24. return (string) => matcher === string || glob(string);
  25. }
  26. if (matcher instanceof RegExp) {
  27. return (string) => matcher.test(string);
  28. }
  29. return (string) => false;
  30. };
  31. /**
  32. * @param {Array<Function>} patterns
  33. * @param {Array<Function>} negPatterns
  34. * @param {String|Array} args
  35. * @param {Boolean} returnIndex
  36. * @returns {boolean|number}
  37. */
  38. const matchPatterns = (patterns, negPatterns, args, returnIndex) => {
  39. const isList = Array.isArray(args);
  40. const _path = isList ? args[0] : args;
  41. if (!isList && typeof _path !== 'string') {
  42. throw new TypeError('anymatch: second argument must be a string: got ' +
  43. Object.prototype.toString.call(_path))
  44. }
  45. const path = normalizePath(_path);
  46. for (let index = 0; index < negPatterns.length; index++) {
  47. const nglob = negPatterns[index];
  48. if (nglob(path)) {
  49. return returnIndex ? -1 : false;
  50. }
  51. }
  52. const applied = isList && [path].concat(args.slice(1));
  53. for (let index = 0; index < patterns.length; index++) {
  54. const pattern = patterns[index];
  55. if (isList ? pattern(...applied) : pattern(path)) {
  56. return returnIndex ? index : true;
  57. }
  58. }
  59. return returnIndex ? -1 : false;
  60. };
  61. /**
  62. * @param {AnymatchMatcher} matchers
  63. * @param {Array|string} testString
  64. * @param {object} options
  65. * @returns {boolean|number|Function}
  66. */
  67. const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => {
  68. if (matchers == null) {
  69. throw new TypeError('anymatch: specify first argument');
  70. }
  71. const opts = typeof options === 'boolean' ? {returnIndex: options} : options;
  72. const returnIndex = opts.returnIndex || false;
  73. // Early cache for matchers.
  74. const mtchers = arrify(matchers);
  75. const negatedGlobs = mtchers
  76. .filter(item => typeof item === 'string' && item.charAt(0) === BANG)
  77. .map(item => item.slice(1))
  78. .map(item => picomatch(item, opts));
  79. const patterns = mtchers
  80. .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG))
  81. .map(matcher => createPattern(matcher, opts));
  82. if (testString == null) {
  83. return (testString, ri = false) => {
  84. const returnIndex = typeof ri === 'boolean' ? ri : false;
  85. return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
  86. }
  87. }
  88. return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
  89. };
  90. anymatch.default = anymatch;
  91. module.exports = anymatch;