html-validate 9.1.2 → 9.2.0

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/dist/es/core.js CHANGED
@@ -425,6 +425,11 @@ class UserError extends NestedError {
425
425
  super(message, nested);
426
426
  Error.captureStackTrace(this, UserError);
427
427
  this.name = UserError.name;
428
+ Object.defineProperty(this, "isUserError", {
429
+ value: true,
430
+ enumerable: false,
431
+ writable: false
432
+ });
428
433
  }
429
434
  /**
430
435
  * @public
@@ -463,6 +468,10 @@ class InheritError extends UserError {
463
468
  }
464
469
  }
465
470
 
471
+ function isUserError(error) {
472
+ return Boolean(error && typeof error === "object" && "isUserError" in error);
473
+ }
474
+
466
475
  function getSummary(schema, obj, errors) {
467
476
  const output = betterAjvErrors(schema, obj, errors, {
468
477
  format: "js"
@@ -1937,7 +1946,7 @@ const table = {
1937
1946
  "nth-child": nthChild,
1938
1947
  scope
1939
1948
  };
1940
- function factory$1(name, context) {
1949
+ function factory(name, context) {
1941
1950
  const fn = table[name];
1942
1951
  if (fn) {
1943
1952
  return fn.bind(context);
@@ -2036,7 +2045,7 @@ function isQuotationMark(ch) {
2036
2045
  function isPseudoElement(ch, buffer) {
2037
2046
  return ch === ":" && buffer === ":";
2038
2047
  }
2039
- function* splitPattern$1(pattern) {
2048
+ function* splitPattern(pattern) {
2040
2049
  if (pattern === "") {
2041
2050
  return;
2042
2051
  }
@@ -2138,7 +2147,7 @@ class PseudoClassMatcher extends Matcher {
2138
2147
  this.args = args;
2139
2148
  }
2140
2149
  match(node, context) {
2141
- const fn = factory$1(this.name, context);
2150
+ const fn = factory(this.name, context);
2142
2151
  return fn(node, this.args);
2143
2152
  }
2144
2153
  }
@@ -2156,7 +2165,7 @@ class Pattern {
2156
2165
  this.selector = pattern;
2157
2166
  this.combinator = parseCombinator(match.shift(), pattern);
2158
2167
  this.tagName = match.shift() || "*";
2159
- this.pattern = Array.from(splitPattern$1(match[0]), (it) => this.createMatcher(it));
2168
+ this.pattern = Array.from(splitPattern(match[0]), (it) => this.createMatcher(it));
2160
2169
  }
2161
2170
  match(node, context) {
2162
2171
  return node.is(this.tagName) && this.pattern.every((cur) => cur.match(node, context));
@@ -13313,7 +13322,7 @@ class HtmlValidate {
13313
13322
  }
13314
13323
 
13315
13324
  const name = "html-validate";
13316
- const version = "9.1.2";
13325
+ const version = "9.2.0";
13317
13326
  const bugs = "https://gitlab.com/html-validate/html-validate/issues/new";
13318
13327
 
13319
13328
  function definePlugin(plugin) {
@@ -13629,778 +13638,803 @@ function compatibilityCheckImpl(name, declared, options) {
13629
13638
  return false;
13630
13639
  }
13631
13640
 
13632
- // A simple implementation of make-array
13633
- function makeArray (subject) {
13634
- return Array.isArray(subject)
13635
- ? subject
13636
- : [subject]
13637
- }
13638
-
13639
- const UNDEFINED = undefined;
13640
- const EMPTY = '';
13641
- const SPACE = ' ';
13642
- const ESCAPE = '\\';
13643
- const REGEX_TEST_BLANK_LINE = /^\s+$/;
13644
- const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
13645
- const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
13646
- const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
13647
- const REGEX_SPLITALL_CRLF = /\r?\n/g;
13648
-
13649
- // Invalid:
13650
- // - /foo,
13651
- // - ./foo,
13652
- // - ../foo,
13653
- // - .
13654
- // - ..
13655
- // Valid:
13656
- // - .foo
13657
- const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/;
13658
-
13659
- const REGEX_TEST_TRAILING_SLASH = /\/$/;
13660
-
13661
- const SLASH = '/';
13662
-
13663
- // Do not use ternary expression here, since "istanbul ignore next" is buggy
13664
- let TMP_KEY_IGNORE = 'node-ignore';
13665
- /* istanbul ignore else */
13666
- if (typeof Symbol !== 'undefined') {
13667
- TMP_KEY_IGNORE = Symbol.for('node-ignore');
13668
- }
13669
- const KEY_IGNORE = TMP_KEY_IGNORE;
13670
-
13671
- const define = (object, key, value) => {
13672
- Object.defineProperty(object, key, {value});
13673
- return value
13674
- };
13675
-
13676
- const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
13677
-
13678
- const RETURN_FALSE = () => false;
13679
-
13680
- // Sanitize the range of a regular expression
13681
- // The cases are complicated, see test cases for details
13682
- const sanitizeRange = range => range.replace(
13683
- REGEX_REGEXP_RANGE,
13684
- (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
13685
- ? match
13686
- // Invalid range (out of order) which is ok for gitignore rules but
13687
- // fatal for JavaScript regular expression, so eliminate it.
13688
- : EMPTY
13689
- );
13690
-
13691
- // See fixtures #59
13692
- const cleanRangeBackSlash = slashes => {
13693
- const {length} = slashes;
13694
- return slashes.slice(0, length - length % 2)
13695
- };
13696
-
13697
- // > If the pattern ends with a slash,
13698
- // > it is removed for the purpose of the following description,
13699
- // > but it would only find a match with a directory.
13700
- // > In other words, foo/ will match a directory foo and paths underneath it,
13701
- // > but will not match a regular file or a symbolic link foo
13702
- // > (this is consistent with the way how pathspec works in general in Git).
13703
- // '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
13704
- // -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
13705
- // you could use option `mark: true` with `glob`
13706
-
13707
- // '`foo/`' should not continue with the '`..`'
13708
- const REPLACERS = [
13709
-
13710
- [
13711
- // Remove BOM
13712
- // TODO:
13713
- // Other similar zero-width characters?
13714
- /^\uFEFF/,
13715
- () => EMPTY
13716
- ],
13717
-
13718
- // > Trailing spaces are ignored unless they are quoted with backslash ("\")
13719
- [
13720
- // (a\ ) -> (a )
13721
- // (a ) -> (a)
13722
- // (a ) -> (a)
13723
- // (a \ ) -> (a )
13724
- /((?:\\\\)*?)(\\?\s+)$/,
13725
- (_, m1, m2) => m1 + (
13726
- m2.indexOf('\\') === 0
13727
- ? SPACE
13728
- : EMPTY
13729
- )
13730
- ],
13731
-
13732
- // Replace (\ ) with ' '
13733
- // (\ ) -> ' '
13734
- // (\\ ) -> '\\ '
13735
- // (\\\ ) -> '\\ '
13736
- [
13737
- /(\\+?)\s/g,
13738
- (_, m1) => {
13739
- const {length} = m1;
13740
- return m1.slice(0, length - length % 2) + SPACE
13741
- }
13742
- ],
13743
-
13744
- // Escape metacharacters
13745
- // which is written down by users but means special for regular expressions.
13746
-
13747
- // > There are 12 characters with special meanings:
13748
- // > - the backslash \,
13749
- // > - the caret ^,
13750
- // > - the dollar sign $,
13751
- // > - the period or dot .,
13752
- // > - the vertical bar or pipe symbol |,
13753
- // > - the question mark ?,
13754
- // > - the asterisk or star *,
13755
- // > - the plus sign +,
13756
- // > - the opening parenthesis (,
13757
- // > - the closing parenthesis ),
13758
- // > - and the opening square bracket [,
13759
- // > - the opening curly brace {,
13760
- // > These special characters are often called "metacharacters".
13761
- [
13762
- /[\\$.|*+(){^]/g,
13763
- match => `\\${match}`
13764
- ],
13765
-
13766
- [
13767
- // > a question mark (?) matches a single character
13768
- /(?!\\)\?/g,
13769
- () => '[^/]'
13770
- ],
13771
-
13772
- // leading slash
13773
- [
13774
-
13775
- // > A leading slash matches the beginning of the pathname.
13776
- // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
13777
- // A leading slash matches the beginning of the pathname
13778
- /^\//,
13779
- () => '^'
13780
- ],
13781
-
13782
- // replace special metacharacter slash after the leading slash
13783
- [
13784
- /\//g,
13785
- () => '\\/'
13786
- ],
13787
-
13788
- [
13789
- // > A leading "**" followed by a slash means match in all directories.
13790
- // > For example, "**/foo" matches file or directory "foo" anywhere,
13791
- // > the same as pattern "foo".
13792
- // > "**/foo/bar" matches file or directory "bar" anywhere that is directly
13793
- // > under directory "foo".
13794
- // Notice that the '*'s have been replaced as '\\*'
13795
- /^\^*\\\*\\\*\\\//,
13796
-
13797
- // '**/foo' <-> 'foo'
13798
- () => '^(?:.*\\/)?'
13799
- ],
13800
-
13801
- // starting
13802
- [
13803
- // there will be no leading '/'
13804
- // (which has been replaced by section "leading slash")
13805
- // If starts with '**', adding a '^' to the regular expression also works
13806
- /^(?=[^^])/,
13807
- function startingReplacer () {
13808
- // If has a slash `/` at the beginning or middle
13809
- return !/\/(?!$)/.test(this)
13810
- // > Prior to 2.22.1
13811
- // > If the pattern does not contain a slash /,
13812
- // > Git treats it as a shell glob pattern
13813
- // Actually, if there is only a trailing slash,
13814
- // git also treats it as a shell glob pattern
13815
-
13816
- // After 2.22.1 (compatible but clearer)
13817
- // > If there is a separator at the beginning or middle (or both)
13818
- // > of the pattern, then the pattern is relative to the directory
13819
- // > level of the particular .gitignore file itself.
13820
- // > Otherwise the pattern may also match at any level below
13821
- // > the .gitignore level.
13822
- ? '(?:^|\\/)'
13823
-
13824
- // > Otherwise, Git treats the pattern as a shell glob suitable for
13825
- // > consumption by fnmatch(3)
13826
- : '^'
13827
- }
13828
- ],
13829
-
13830
- // two globstars
13831
- [
13832
- // Use lookahead assertions so that we could match more than one `'/**'`
13833
- /\\\/\\\*\\\*(?=\\\/|$)/g,
13834
-
13835
- // Zero, one or several directories
13836
- // should not use '*', or it will be replaced by the next replacer
13837
-
13838
- // Check if it is not the last `'/**'`
13839
- (_, index, str) => index + 6 < str.length
13840
-
13841
- // case: /**/
13842
- // > A slash followed by two consecutive asterisks then a slash matches
13843
- // > zero or more directories.
13844
- // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
13845
- // '/**/'
13846
- ? '(?:\\/[^\\/]+)*'
13847
-
13848
- // case: /**
13849
- // > A trailing `"/**"` matches everything inside.
13850
-
13851
- // #21: everything inside but it should not include the current folder
13852
- : '\\/.+'
13853
- ],
13854
-
13855
- // normal intermediate wildcards
13856
- [
13857
- // Never replace escaped '*'
13858
- // ignore rule '\*' will match the path '*'
13859
-
13860
- // 'abc.*/' -> go
13861
- // 'abc.*' -> skip this rule,
13862
- // coz trailing single wildcard will be handed by [trailing wildcard]
13863
- /(^|[^\\]+)(\\\*)+(?=.+)/g,
13864
-
13865
- // '*.js' matches '.js'
13866
- // '*.js' doesn't match 'abc'
13867
- (_, p1, p2) => {
13868
- // 1.
13869
- // > An asterisk "*" matches anything except a slash.
13870
- // 2.
13871
- // > Other consecutive asterisks are considered regular asterisks
13872
- // > and will match according to the previous rules.
13873
- const unescaped = p2.replace(/\\\*/g, '[^\\/]*');
13874
- return p1 + unescaped
13875
- }
13876
- ],
13877
-
13878
- [
13879
- // unescape, revert step 3 except for back slash
13880
- // For example, if a user escape a '\\*',
13881
- // after step 3, the result will be '\\\\\\*'
13882
- /\\\\\\(?=[$.|*+(){^])/g,
13883
- () => ESCAPE
13884
- ],
13885
-
13886
- [
13887
- // '\\\\' -> '\\'
13888
- /\\\\/g,
13889
- () => ESCAPE
13890
- ],
13891
-
13892
- [
13893
- // > The range notation, e.g. [a-zA-Z],
13894
- // > can be used to match one of the characters in a range.
13895
-
13896
- // `\` is escaped by step 3
13897
- /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
13898
- (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE
13899
- // '\\[bar]' -> '\\\\[bar\\]'
13900
- ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`
13901
- : close === ']'
13902
- ? endEscape.length % 2 === 0
13903
- // A normal case, and it is a range notation
13904
- // '[bar]'
13905
- // '[bar\\\\]'
13906
- ? `[${sanitizeRange(range)}${endEscape}]`
13907
- // Invalid range notaton
13908
- // '[bar\\]' -> '[bar\\\\]'
13909
- : '[]'
13910
- : '[]'
13911
- ],
13912
-
13913
- // ending
13914
- [
13915
- // 'js' will not match 'js.'
13916
- // 'ab' will not match 'abc'
13917
- /(?:[^*])$/,
13918
-
13919
- // WTF!
13920
- // https://git-scm.com/docs/gitignore
13921
- // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
13922
- // which re-fixes #24, #38
13923
-
13924
- // > If there is a separator at the end of the pattern then the pattern
13925
- // > will only match directories, otherwise the pattern can match both
13926
- // > files and directories.
13927
-
13928
- // 'js*' will not match 'a.js'
13929
- // 'js/' will not match 'a.js'
13930
- // 'js' will match 'a.js' and 'a.js/'
13931
- match => /\/$/.test(match)
13932
- // foo/ will not match 'foo'
13933
- ? `${match}$`
13934
- // foo matches 'foo' and 'foo/'
13935
- : `${match}(?=$|\\/$)`
13936
- ]
13937
- ];
13938
-
13939
- const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
13940
- const MODE_IGNORE = 'regex';
13941
- const MODE_CHECK_IGNORE = 'checkRegex';
13942
- const UNDERSCORE = '_';
13943
-
13944
- const TRAILING_WILD_CARD_REPLACERS = {
13945
- [MODE_IGNORE] (_, p1) {
13946
- const prefix = p1
13947
- // '\^':
13948
- // '/*' does not match EMPTY
13949
- // '/*' does not match everything
13950
-
13951
- // '\\\/':
13952
- // 'abc/*' does not match 'abc/'
13953
- ? `${p1}[^/]+`
13954
-
13955
- // 'a*' matches 'a'
13956
- // 'a*' matches 'aa'
13957
- : '[^/]*';
13958
-
13959
- return `${prefix}(?=$|\\/$)`
13960
- },
13961
-
13962
- [MODE_CHECK_IGNORE] (_, p1) {
13963
- // When doing `git check-ignore`
13964
- const prefix = p1
13965
- // '\\\/':
13966
- // 'abc/*' DOES match 'abc/' !
13967
- ? `${p1}[^/]*`
13968
-
13969
- // 'a*' matches 'a'
13970
- // 'a*' matches 'aa'
13971
- : '[^/]*';
13972
-
13973
- return `${prefix}(?=$|\\/$)`
13974
- }
13975
- };
13976
-
13977
- // @param {pattern}
13978
- const makeRegexPrefix = pattern => REPLACERS.reduce(
13979
- (prev, [matcher, replacer]) =>
13980
- prev.replace(matcher, replacer.bind(pattern)),
13981
- pattern
13982
- );
13983
-
13984
- const isString = subject => typeof subject === 'string';
13985
-
13986
- // > A blank line matches no files, so it can serve as a separator for readability.
13987
- const checkPattern = pattern => pattern
13988
- && isString(pattern)
13989
- && !REGEX_TEST_BLANK_LINE.test(pattern)
13990
- && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
13991
-
13992
- // > A line starting with # serves as a comment.
13993
- && pattern.indexOf('#') !== 0;
13994
-
13995
- const splitPattern = pattern => pattern
13996
- .split(REGEX_SPLITALL_CRLF)
13997
- .filter(Boolean);
13998
-
13999
- class IgnoreRule {
14000
- constructor (
14001
- pattern,
14002
- mark,
14003
- body,
14004
- ignoreCase,
14005
- negative,
14006
- prefix
14007
- ) {
14008
- this.pattern = pattern;
14009
- this.mark = mark;
14010
- this.negative = negative;
14011
-
14012
- define(this, 'body', body);
14013
- define(this, 'ignoreCase', ignoreCase);
14014
- define(this, 'regexPrefix', prefix);
14015
- }
14016
-
14017
- get regex () {
14018
- const key = UNDERSCORE + MODE_IGNORE;
14019
-
14020
- if (this[key]) {
14021
- return this[key]
14022
- }
14023
-
14024
- return this._make(MODE_IGNORE, key)
14025
- }
14026
-
14027
- get checkRegex () {
14028
- const key = UNDERSCORE + MODE_CHECK_IGNORE;
14029
-
14030
- if (this[key]) {
14031
- return this[key]
14032
- }
14033
-
14034
- return this._make(MODE_CHECK_IGNORE, key)
14035
- }
14036
-
14037
- _make (mode, key) {
14038
- const str = this.regexPrefix.replace(
14039
- REGEX_REPLACE_TRAILING_WILDCARD,
14040
-
14041
- // It does not need to bind pattern
14042
- TRAILING_WILD_CARD_REPLACERS[mode]
14043
- );
14044
-
14045
- const regex = this.ignoreCase
14046
- ? new RegExp(str, 'i')
14047
- : new RegExp(str);
14048
-
14049
- return define(this, key, regex)
14050
- }
14051
- }
14052
-
14053
- const createRule = ({
14054
- pattern,
14055
- mark
14056
- }, ignoreCase) => {
14057
- let negative = false;
14058
- let body = pattern;
14059
-
14060
- // > An optional prefix "!" which negates the pattern;
14061
- if (body.indexOf('!') === 0) {
14062
- negative = true;
14063
- body = body.substr(1);
14064
- }
13641
+ var ignore$1 = {exports: {}};
14065
13642
 
14066
- body = body
14067
- // > Put a backslash ("\") in front of the first "!" for patterns that
14068
- // > begin with a literal "!", for example, `"\!important!.txt"`.
14069
- .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')
14070
- // > Put a backslash ("\") in front of the first hash for patterns that
14071
- // > begin with a hash.
14072
- .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#');
13643
+ var hasRequiredIgnore;
14073
13644
 
14074
- const regexPrefix = makeRegexPrefix(body);
14075
-
14076
- return new IgnoreRule(
14077
- pattern,
14078
- mark,
14079
- body,
14080
- ignoreCase,
14081
- negative,
14082
- regexPrefix
14083
- )
14084
- };
14085
-
14086
- class RuleManager {
14087
- constructor (ignoreCase) {
14088
- this._ignoreCase = ignoreCase;
14089
- this._rules = [];
14090
- }
14091
-
14092
- _add (pattern) {
14093
- // #32
14094
- if (pattern && pattern[KEY_IGNORE]) {
14095
- this._rules = this._rules.concat(pattern._rules._rules);
14096
- this._added = true;
14097
- return
14098
- }
14099
-
14100
- if (isString(pattern)) {
14101
- pattern = {
14102
- pattern
14103
- };
14104
- }
14105
-
14106
- if (checkPattern(pattern.pattern)) {
14107
- const rule = createRule(pattern, this._ignoreCase);
14108
- this._added = true;
14109
- this._rules.push(rule);
14110
- }
14111
- }
13645
+ function requireIgnore () {
13646
+ if (hasRequiredIgnore) return ignore$1.exports;
13647
+ hasRequiredIgnore = 1;
13648
+ // A simple implementation of make-array
13649
+ function makeArray (subject) {
13650
+ return Array.isArray(subject)
13651
+ ? subject
13652
+ : [subject]
13653
+ }
14112
13654
 
14113
- // @param {Array<string> | string | Ignore} pattern
14114
- add (pattern) {
14115
- this._added = false;
13655
+ const UNDEFINED = undefined;
13656
+ const EMPTY = '';
13657
+ const SPACE = ' ';
13658
+ const ESCAPE = '\\';
13659
+ const REGEX_TEST_BLANK_LINE = /^\s+$/;
13660
+ const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/;
13661
+ const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
13662
+ const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/;
13663
+ const REGEX_SPLITALL_CRLF = /\r?\n/g;
13664
+
13665
+ // Invalid:
13666
+ // - /foo,
13667
+ // - ./foo,
13668
+ // - ../foo,
13669
+ // - .
13670
+ // - ..
13671
+ // Valid:
13672
+ // - .foo
13673
+ const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/;
13674
+
13675
+ const REGEX_TEST_TRAILING_SLASH = /\/$/;
13676
+
13677
+ const SLASH = '/';
13678
+
13679
+ // Do not use ternary expression here, since "istanbul ignore next" is buggy
13680
+ let TMP_KEY_IGNORE = 'node-ignore';
13681
+ /* istanbul ignore else */
13682
+ if (typeof Symbol !== 'undefined') {
13683
+ TMP_KEY_IGNORE = Symbol.for('node-ignore');
13684
+ }
13685
+ const KEY_IGNORE = TMP_KEY_IGNORE;
14116
13686
 
14117
- makeArray(
14118
- isString(pattern)
14119
- ? splitPattern(pattern)
14120
- : pattern
14121
- ).forEach(this._add, this);
13687
+ const define = (object, key, value) => {
13688
+ Object.defineProperty(object, key, {value});
13689
+ return value
13690
+ };
14122
13691
 
14123
- return this._added
14124
- }
13692
+ const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
13693
+
13694
+ const RETURN_FALSE = () => false;
13695
+
13696
+ // Sanitize the range of a regular expression
13697
+ // The cases are complicated, see test cases for details
13698
+ const sanitizeRange = range => range.replace(
13699
+ REGEX_REGEXP_RANGE,
13700
+ (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
13701
+ ? match
13702
+ // Invalid range (out of order) which is ok for gitignore rules but
13703
+ // fatal for JavaScript regular expression, so eliminate it.
13704
+ : EMPTY
13705
+ );
13706
+
13707
+ // See fixtures #59
13708
+ const cleanRangeBackSlash = slashes => {
13709
+ const {length} = slashes;
13710
+ return slashes.slice(0, length - length % 2)
13711
+ };
14125
13712
 
14126
- // Test one single path without recursively checking parent directories
14127
- //
14128
- // - checkUnignored `boolean` whether should check if the path is unignored,
14129
- // setting `checkUnignored` to `false` could reduce additional
14130
- // path matching.
14131
- // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
13713
+ // > If the pattern ends with a slash,
13714
+ // > it is removed for the purpose of the following description,
13715
+ // > but it would only find a match with a directory.
13716
+ // > In other words, foo/ will match a directory foo and paths underneath it,
13717
+ // > but will not match a regular file or a symbolic link foo
13718
+ // > (this is consistent with the way how pathspec works in general in Git).
13719
+ // '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
13720
+ // -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
13721
+ // you could use option `mark: true` with `glob`
13722
+
13723
+ // '`foo/`' should not continue with the '`..`'
13724
+ const REPLACERS = [
13725
+
13726
+ [
13727
+ // Remove BOM
13728
+ // TODO:
13729
+ // Other similar zero-width characters?
13730
+ /^\uFEFF/,
13731
+ () => EMPTY
13732
+ ],
13733
+
13734
+ // > Trailing spaces are ignored unless they are quoted with backslash ("\")
13735
+ [
13736
+ // (a\ ) -> (a )
13737
+ // (a ) -> (a)
13738
+ // (a ) -> (a)
13739
+ // (a \ ) -> (a )
13740
+ /((?:\\\\)*?)(\\?\s+)$/,
13741
+ (_, m1, m2) => m1 + (
13742
+ m2.indexOf('\\') === 0
13743
+ ? SPACE
13744
+ : EMPTY
13745
+ )
13746
+ ],
13747
+
13748
+ // Replace (\ ) with ' '
13749
+ // (\ ) -> ' '
13750
+ // (\\ ) -> '\\ '
13751
+ // (\\\ ) -> '\\ '
13752
+ [
13753
+ /(\\+?)\s/g,
13754
+ (_, m1) => {
13755
+ const {length} = m1;
13756
+ return m1.slice(0, length - length % 2) + SPACE
13757
+ }
13758
+ ],
13759
+
13760
+ // Escape metacharacters
13761
+ // which is written down by users but means special for regular expressions.
13762
+
13763
+ // > There are 12 characters with special meanings:
13764
+ // > - the backslash \,
13765
+ // > - the caret ^,
13766
+ // > - the dollar sign $,
13767
+ // > - the period or dot .,
13768
+ // > - the vertical bar or pipe symbol |,
13769
+ // > - the question mark ?,
13770
+ // > - the asterisk or star *,
13771
+ // > - the plus sign +,
13772
+ // > - the opening parenthesis (,
13773
+ // > - the closing parenthesis ),
13774
+ // > - and the opening square bracket [,
13775
+ // > - the opening curly brace {,
13776
+ // > These special characters are often called "metacharacters".
13777
+ [
13778
+ /[\\$.|*+(){^]/g,
13779
+ match => `\\${match}`
13780
+ ],
13781
+
13782
+ [
13783
+ // > a question mark (?) matches a single character
13784
+ /(?!\\)\?/g,
13785
+ () => '[^/]'
13786
+ ],
13787
+
13788
+ // leading slash
13789
+ [
13790
+
13791
+ // > A leading slash matches the beginning of the pathname.
13792
+ // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
13793
+ // A leading slash matches the beginning of the pathname
13794
+ /^\//,
13795
+ () => '^'
13796
+ ],
13797
+
13798
+ // replace special metacharacter slash after the leading slash
13799
+ [
13800
+ /\//g,
13801
+ () => '\\/'
13802
+ ],
13803
+
13804
+ [
13805
+ // > A leading "**" followed by a slash means match in all directories.
13806
+ // > For example, "**/foo" matches file or directory "foo" anywhere,
13807
+ // > the same as pattern "foo".
13808
+ // > "**/foo/bar" matches file or directory "bar" anywhere that is directly
13809
+ // > under directory "foo".
13810
+ // Notice that the '*'s have been replaced as '\\*'
13811
+ /^\^*\\\*\\\*\\\//,
13812
+
13813
+ // '**/foo' <-> 'foo'
13814
+ () => '^(?:.*\\/)?'
13815
+ ],
13816
+
13817
+ // starting
13818
+ [
13819
+ // there will be no leading '/'
13820
+ // (which has been replaced by section "leading slash")
13821
+ // If starts with '**', adding a '^' to the regular expression also works
13822
+ /^(?=[^^])/,
13823
+ function startingReplacer () {
13824
+ // If has a slash `/` at the beginning or middle
13825
+ return !/\/(?!$)/.test(this)
13826
+ // > Prior to 2.22.1
13827
+ // > If the pattern does not contain a slash /,
13828
+ // > Git treats it as a shell glob pattern
13829
+ // Actually, if there is only a trailing slash,
13830
+ // git also treats it as a shell glob pattern
13831
+
13832
+ // After 2.22.1 (compatible but clearer)
13833
+ // > If there is a separator at the beginning or middle (or both)
13834
+ // > of the pattern, then the pattern is relative to the directory
13835
+ // > level of the particular .gitignore file itself.
13836
+ // > Otherwise the pattern may also match at any level below
13837
+ // > the .gitignore level.
13838
+ ? '(?:^|\\/)'
13839
+
13840
+ // > Otherwise, Git treats the pattern as a shell glob suitable for
13841
+ // > consumption by fnmatch(3)
13842
+ : '^'
13843
+ }
13844
+ ],
13845
+
13846
+ // two globstars
13847
+ [
13848
+ // Use lookahead assertions so that we could match more than one `'/**'`
13849
+ /\\\/\\\*\\\*(?=\\\/|$)/g,
13850
+
13851
+ // Zero, one or several directories
13852
+ // should not use '*', or it will be replaced by the next replacer
13853
+
13854
+ // Check if it is not the last `'/**'`
13855
+ (_, index, str) => index + 6 < str.length
13856
+
13857
+ // case: /**/
13858
+ // > A slash followed by two consecutive asterisks then a slash matches
13859
+ // > zero or more directories.
13860
+ // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
13861
+ // '/**/'
13862
+ ? '(?:\\/[^\\/]+)*'
13863
+
13864
+ // case: /**
13865
+ // > A trailing `"/**"` matches everything inside.
13866
+
13867
+ // #21: everything inside but it should not include the current folder
13868
+ : '\\/.+'
13869
+ ],
13870
+
13871
+ // normal intermediate wildcards
13872
+ [
13873
+ // Never replace escaped '*'
13874
+ // ignore rule '\*' will match the path '*'
13875
+
13876
+ // 'abc.*/' -> go
13877
+ // 'abc.*' -> skip this rule,
13878
+ // coz trailing single wildcard will be handed by [trailing wildcard]
13879
+ /(^|[^\\]+)(\\\*)+(?=.+)/g,
13880
+
13881
+ // '*.js' matches '.js'
13882
+ // '*.js' doesn't match 'abc'
13883
+ (_, p1, p2) => {
13884
+ // 1.
13885
+ // > An asterisk "*" matches anything except a slash.
13886
+ // 2.
13887
+ // > Other consecutive asterisks are considered regular asterisks
13888
+ // > and will match according to the previous rules.
13889
+ const unescaped = p2.replace(/\\\*/g, '[^\\/]*');
13890
+ return p1 + unescaped
13891
+ }
13892
+ ],
13893
+
13894
+ [
13895
+ // unescape, revert step 3 except for back slash
13896
+ // For example, if a user escape a '\\*',
13897
+ // after step 3, the result will be '\\\\\\*'
13898
+ /\\\\\\(?=[$.|*+(){^])/g,
13899
+ () => ESCAPE
13900
+ ],
13901
+
13902
+ [
13903
+ // '\\\\' -> '\\'
13904
+ /\\\\/g,
13905
+ () => ESCAPE
13906
+ ],
13907
+
13908
+ [
13909
+ // > The range notation, e.g. [a-zA-Z],
13910
+ // > can be used to match one of the characters in a range.
13911
+
13912
+ // `\` is escaped by step 3
13913
+ /(\\)?\[([^\]/]*?)(\\*)($|\])/g,
13914
+ (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE
13915
+ // '\\[bar]' -> '\\\\[bar\\]'
13916
+ ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`
13917
+ : close === ']'
13918
+ ? endEscape.length % 2 === 0
13919
+ // A normal case, and it is a range notation
13920
+ // '[bar]'
13921
+ // '[bar\\\\]'
13922
+ ? `[${sanitizeRange(range)}${endEscape}]`
13923
+ // Invalid range notaton
13924
+ // '[bar\\]' -> '[bar\\\\]'
13925
+ : '[]'
13926
+ : '[]'
13927
+ ],
13928
+
13929
+ // ending
13930
+ [
13931
+ // 'js' will not match 'js.'
13932
+ // 'ab' will not match 'abc'
13933
+ /(?:[^*])$/,
13934
+
13935
+ // WTF!
13936
+ // https://git-scm.com/docs/gitignore
13937
+ // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
13938
+ // which re-fixes #24, #38
13939
+
13940
+ // > If there is a separator at the end of the pattern then the pattern
13941
+ // > will only match directories, otherwise the pattern can match both
13942
+ // > files and directories.
13943
+
13944
+ // 'js*' will not match 'a.js'
13945
+ // 'js/' will not match 'a.js'
13946
+ // 'js' will match 'a.js' and 'a.js/'
13947
+ match => /\/$/.test(match)
13948
+ // foo/ will not match 'foo'
13949
+ ? `${match}$`
13950
+ // foo matches 'foo' and 'foo/'
13951
+ : `${match}(?=$|\\/$)`
13952
+ ]
13953
+ ];
13954
+
13955
+ const REGEX_REPLACE_TRAILING_WILDCARD = /(^|\\\/)?\\\*$/;
13956
+ const MODE_IGNORE = 'regex';
13957
+ const MODE_CHECK_IGNORE = 'checkRegex';
13958
+ const UNDERSCORE = '_';
13959
+
13960
+ const TRAILING_WILD_CARD_REPLACERS = {
13961
+ [MODE_IGNORE] (_, p1) {
13962
+ const prefix = p1
13963
+ // '\^':
13964
+ // '/*' does not match EMPTY
13965
+ // '/*' does not match everything
13966
+
13967
+ // '\\\/':
13968
+ // 'abc/*' does not match 'abc/'
13969
+ ? `${p1}[^/]+`
13970
+
13971
+ // 'a*' matches 'a'
13972
+ // 'a*' matches 'aa'
13973
+ : '[^/]*';
13974
+
13975
+ return `${prefix}(?=$|\\/$)`
13976
+ },
13977
+
13978
+ [MODE_CHECK_IGNORE] (_, p1) {
13979
+ // When doing `git check-ignore`
13980
+ const prefix = p1
13981
+ // '\\\/':
13982
+ // 'abc/*' DOES match 'abc/' !
13983
+ ? `${p1}[^/]*`
13984
+
13985
+ // 'a*' matches 'a'
13986
+ // 'a*' matches 'aa'
13987
+ : '[^/]*';
13988
+
13989
+ return `${prefix}(?=$|\\/$)`
13990
+ }
13991
+ };
14132
13992
 
14133
- // @returns {TestResult} true if a file is ignored
14134
- test (path, checkUnignored, mode) {
14135
- let ignored = false;
14136
- let unignored = false;
14137
- let matchedRule;
13993
+ // @param {pattern}
13994
+ const makeRegexPrefix = pattern => REPLACERS.reduce(
13995
+ (prev, [matcher, replacer]) =>
13996
+ prev.replace(matcher, replacer.bind(pattern)),
13997
+ pattern
13998
+ );
13999
+
14000
+ const isString = subject => typeof subject === 'string';
14001
+
14002
+ // > A blank line matches no files, so it can serve as a separator for readability.
14003
+ const checkPattern = pattern => pattern
14004
+ && isString(pattern)
14005
+ && !REGEX_TEST_BLANK_LINE.test(pattern)
14006
+ && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
14007
+
14008
+ // > A line starting with # serves as a comment.
14009
+ && pattern.indexOf('#') !== 0;
14010
+
14011
+ const splitPattern = pattern => pattern
14012
+ .split(REGEX_SPLITALL_CRLF)
14013
+ .filter(Boolean);
14014
+
14015
+ class IgnoreRule {
14016
+ constructor (
14017
+ pattern,
14018
+ mark,
14019
+ body,
14020
+ ignoreCase,
14021
+ negative,
14022
+ prefix
14023
+ ) {
14024
+ this.pattern = pattern;
14025
+ this.mark = mark;
14026
+ this.negative = negative;
14027
+
14028
+ define(this, 'body', body);
14029
+ define(this, 'ignoreCase', ignoreCase);
14030
+ define(this, 'regexPrefix', prefix);
14031
+ }
14032
+
14033
+ get regex () {
14034
+ const key = UNDERSCORE + MODE_IGNORE;
14035
+
14036
+ if (this[key]) {
14037
+ return this[key]
14038
+ }
14039
+
14040
+ return this._make(MODE_IGNORE, key)
14041
+ }
14042
+
14043
+ get checkRegex () {
14044
+ const key = UNDERSCORE + MODE_CHECK_IGNORE;
14045
+
14046
+ if (this[key]) {
14047
+ return this[key]
14048
+ }
14049
+
14050
+ return this._make(MODE_CHECK_IGNORE, key)
14051
+ }
14052
+
14053
+ _make (mode, key) {
14054
+ const str = this.regexPrefix.replace(
14055
+ REGEX_REPLACE_TRAILING_WILDCARD,
14056
+
14057
+ // It does not need to bind pattern
14058
+ TRAILING_WILD_CARD_REPLACERS[mode]
14059
+ );
14060
+
14061
+ const regex = this.ignoreCase
14062
+ ? new RegExp(str, 'i')
14063
+ : new RegExp(str);
14064
+
14065
+ return define(this, key, regex)
14066
+ }
14067
+ }
14138
14068
 
14139
- this._rules.forEach(rule => {
14140
- const {negative} = rule;
14069
+ const createRule = ({
14070
+ pattern,
14071
+ mark
14072
+ }, ignoreCase) => {
14073
+ let negative = false;
14074
+ let body = pattern;
14075
+
14076
+ // > An optional prefix "!" which negates the pattern;
14077
+ if (body.indexOf('!') === 0) {
14078
+ negative = true;
14079
+ body = body.substr(1);
14080
+ }
14081
+
14082
+ body = body
14083
+ // > Put a backslash ("\") in front of the first "!" for patterns that
14084
+ // > begin with a literal "!", for example, `"\!important!.txt"`.
14085
+ .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')
14086
+ // > Put a backslash ("\") in front of the first hash for patterns that
14087
+ // > begin with a hash.
14088
+ .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#');
14089
+
14090
+ const regexPrefix = makeRegexPrefix(body);
14091
+
14092
+ return new IgnoreRule(
14093
+ pattern,
14094
+ mark,
14095
+ body,
14096
+ ignoreCase,
14097
+ negative,
14098
+ regexPrefix
14099
+ )
14100
+ };
14141
14101
 
14142
- // | ignored : unignored
14143
- // -------- | ---------------------------------------
14144
- // negative | 0:0 | 0:1 | 1:0 | 1:1
14145
- // -------- | ------- | ------- | ------- | --------
14146
- // 0 | TEST | TEST | SKIP | X
14147
- // 1 | TESTIF | SKIP | TEST | X
14102
+ class RuleManager {
14103
+ constructor (ignoreCase) {
14104
+ this._ignoreCase = ignoreCase;
14105
+ this._rules = [];
14106
+ }
14107
+
14108
+ _add (pattern) {
14109
+ // #32
14110
+ if (pattern && pattern[KEY_IGNORE]) {
14111
+ this._rules = this._rules.concat(pattern._rules._rules);
14112
+ this._added = true;
14113
+ return
14114
+ }
14115
+
14116
+ if (isString(pattern)) {
14117
+ pattern = {
14118
+ pattern
14119
+ };
14120
+ }
14121
+
14122
+ if (checkPattern(pattern.pattern)) {
14123
+ const rule = createRule(pattern, this._ignoreCase);
14124
+ this._added = true;
14125
+ this._rules.push(rule);
14126
+ }
14127
+ }
14128
+
14129
+ // @param {Array<string> | string | Ignore} pattern
14130
+ add (pattern) {
14131
+ this._added = false;
14132
+
14133
+ makeArray(
14134
+ isString(pattern)
14135
+ ? splitPattern(pattern)
14136
+ : pattern
14137
+ ).forEach(this._add, this);
14138
+
14139
+ return this._added
14140
+ }
14141
+
14142
+ // Test one single path without recursively checking parent directories
14143
+ //
14144
+ // - checkUnignored `boolean` whether should check if the path is unignored,
14145
+ // setting `checkUnignored` to `false` could reduce additional
14146
+ // path matching.
14147
+ // - check `string` either `MODE_IGNORE` or `MODE_CHECK_IGNORE`
14148
+
14149
+ // @returns {TestResult} true if a file is ignored
14150
+ test (path, checkUnignored, mode) {
14151
+ let ignored = false;
14152
+ let unignored = false;
14153
+ let matchedRule;
14154
+
14155
+ this._rules.forEach(rule => {
14156
+ const {negative} = rule;
14157
+
14158
+ // | ignored : unignored
14159
+ // -------- | ---------------------------------------
14160
+ // negative | 0:0 | 0:1 | 1:0 | 1:1
14161
+ // -------- | ------- | ------- | ------- | --------
14162
+ // 0 | TEST | TEST | SKIP | X
14163
+ // 1 | TESTIF | SKIP | TEST | X
14164
+
14165
+ // - SKIP: always skip
14166
+ // - TEST: always test
14167
+ // - TESTIF: only test if checkUnignored
14168
+ // - X: that never happen
14169
+ if (
14170
+ unignored === negative && ignored !== unignored
14171
+ || negative && !ignored && !unignored && !checkUnignored
14172
+ ) {
14173
+ return
14174
+ }
14175
+
14176
+ const matched = rule[mode].test(path);
14177
+
14178
+ if (!matched) {
14179
+ return
14180
+ }
14181
+
14182
+ ignored = !negative;
14183
+ unignored = negative;
14184
+
14185
+ matchedRule = negative
14186
+ ? UNDEFINED
14187
+ : rule;
14188
+ });
14189
+
14190
+ const ret = {
14191
+ ignored,
14192
+ unignored
14193
+ };
14194
+
14195
+ if (matchedRule) {
14196
+ ret.rule = matchedRule;
14197
+ }
14198
+
14199
+ return ret
14200
+ }
14201
+ }
14148
14202
 
14149
- // - SKIP: always skip
14150
- // - TEST: always test
14151
- // - TESTIF: only test if checkUnignored
14152
- // - X: that never happen
14153
- if (
14154
- unignored === negative && ignored !== unignored
14155
- || negative && !ignored && !unignored && !checkUnignored
14156
- ) {
14157
- return
14158
- }
14203
+ const throwError = (message, Ctor) => {
14204
+ throw new Ctor(message)
14205
+ };
14159
14206
 
14160
- const matched = rule[mode].test(path);
14207
+ const checkPath = (path, originalPath, doThrow) => {
14208
+ if (!isString(path)) {
14209
+ return doThrow(
14210
+ `path must be a string, but got \`${originalPath}\``,
14211
+ TypeError
14212
+ )
14213
+ }
14214
+
14215
+ // We don't know if we should ignore EMPTY, so throw
14216
+ if (!path) {
14217
+ return doThrow(`path must not be empty`, TypeError)
14218
+ }
14219
+
14220
+ // Check if it is a relative path
14221
+ if (checkPath.isNotRelative(path)) {
14222
+ const r = '`path.relative()`d';
14223
+ return doThrow(
14224
+ `path should be a ${r} string, but got "${originalPath}"`,
14225
+ RangeError
14226
+ )
14227
+ }
14228
+
14229
+ return true
14230
+ };
14161
14231
 
14162
- if (!matched) {
14163
- return
14164
- }
14232
+ const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path);
14233
+
14234
+ checkPath.isNotRelative = isNotRelative;
14235
+
14236
+ // On windows, the following function will be replaced
14237
+ /* istanbul ignore next */
14238
+ checkPath.convert = p => p;
14239
+
14240
+
14241
+ class Ignore {
14242
+ constructor ({
14243
+ ignorecase = true,
14244
+ ignoreCase = ignorecase,
14245
+ allowRelativePaths = false
14246
+ } = {}) {
14247
+ define(this, KEY_IGNORE, true);
14248
+
14249
+ this._rules = new RuleManager(ignoreCase);
14250
+ this._strictPathCheck = !allowRelativePaths;
14251
+ this._initCache();
14252
+ }
14253
+
14254
+ _initCache () {
14255
+ // A cache for the result of `.ignores()`
14256
+ this._ignoreCache = Object.create(null);
14257
+
14258
+ // A cache for the result of `.test()`
14259
+ this._testCache = Object.create(null);
14260
+ }
14261
+
14262
+ add (pattern) {
14263
+ if (this._rules.add(pattern)) {
14264
+ // Some rules have just added to the ignore,
14265
+ // making the behavior changed,
14266
+ // so we need to re-initialize the result cache
14267
+ this._initCache();
14268
+ }
14269
+
14270
+ return this
14271
+ }
14272
+
14273
+ // legacy
14274
+ addPattern (pattern) {
14275
+ return this.add(pattern)
14276
+ }
14277
+
14278
+ // @returns {TestResult}
14279
+ _test (originalPath, cache, checkUnignored, slices) {
14280
+ const path = originalPath
14281
+ // Supports nullable path
14282
+ && checkPath.convert(originalPath);
14283
+
14284
+ checkPath(
14285
+ path,
14286
+ originalPath,
14287
+ this._strictPathCheck
14288
+ ? throwError
14289
+ : RETURN_FALSE
14290
+ );
14291
+
14292
+ return this._t(path, cache, checkUnignored, slices)
14293
+ }
14294
+
14295
+ checkIgnore (path) {
14296
+ // If the path doest not end with a slash, `.ignores()` is much equivalent
14297
+ // to `git check-ignore`
14298
+ if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
14299
+ return this.test(path)
14300
+ }
14301
+
14302
+ const slices = path.split(SLASH).filter(Boolean);
14303
+ slices.pop();
14304
+
14305
+ if (slices.length) {
14306
+ const parent = this._t(
14307
+ slices.join(SLASH) + SLASH,
14308
+ this._testCache,
14309
+ true,
14310
+ slices
14311
+ );
14312
+
14313
+ if (parent.ignored) {
14314
+ return parent
14315
+ }
14316
+ }
14317
+
14318
+ return this._rules.test(path, false, MODE_CHECK_IGNORE)
14319
+ }
14320
+
14321
+ _t (
14322
+ // The path to be tested
14323
+ path,
14324
+
14325
+ // The cache for the result of a certain checking
14326
+ cache,
14327
+
14328
+ // Whether should check if the path is unignored
14329
+ checkUnignored,
14330
+
14331
+ // The path slices
14332
+ slices
14333
+ ) {
14334
+ if (path in cache) {
14335
+ return cache[path]
14336
+ }
14337
+
14338
+ if (!slices) {
14339
+ // path/to/a.js
14340
+ // ['path', 'to', 'a.js']
14341
+ slices = path.split(SLASH).filter(Boolean);
14342
+ }
14343
+
14344
+ slices.pop();
14345
+
14346
+ // If the path has no parent directory, just test it
14347
+ if (!slices.length) {
14348
+ return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE)
14349
+ }
14350
+
14351
+ const parent = this._t(
14352
+ slices.join(SLASH) + SLASH,
14353
+ cache,
14354
+ checkUnignored,
14355
+ slices
14356
+ );
14357
+
14358
+ // If the path contains a parent directory, check the parent first
14359
+ return cache[path] = parent.ignored
14360
+ // > It is not possible to re-include a file if a parent directory of
14361
+ // > that file is excluded.
14362
+ ? parent
14363
+ : this._rules.test(path, checkUnignored, MODE_IGNORE)
14364
+ }
14365
+
14366
+ ignores (path) {
14367
+ return this._test(path, this._ignoreCache, false).ignored
14368
+ }
14369
+
14370
+ createFilter () {
14371
+ return path => !this.ignores(path)
14372
+ }
14373
+
14374
+ filter (paths) {
14375
+ return makeArray(paths).filter(this.createFilter())
14376
+ }
14377
+
14378
+ // @returns {TestResult}
14379
+ test (path) {
14380
+ return this._test(path, this._testCache, true)
14381
+ }
14382
+ }
14165
14383
 
14166
- ignored = !negative;
14167
- unignored = negative;
14384
+ const factory = options => new Ignore(options);
14385
+
14386
+ const isPathValid = path =>
14387
+ checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
14388
+
14389
+
14390
+ // Windows
14391
+ // --------------------------------------------------------------
14392
+ /* istanbul ignore next */
14393
+ if (
14394
+ // Detect `process` so that it can run in browsers.
14395
+ typeof process !== 'undefined'
14396
+ && (
14397
+ process.env && process.env.IGNORE_TEST_WIN32
14398
+ || process.platform === 'win32'
14399
+ )
14400
+ ) {
14401
+ /* eslint no-control-regex: "off" */
14402
+ const makePosix = str => /^\\\\\?\\/.test(str)
14403
+ || /["<>|\u0000-\u001F]+/u.test(str)
14404
+ ? str
14405
+ : str.replace(/\\/g, '/');
14406
+
14407
+ checkPath.convert = makePosix;
14408
+
14409
+ // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/'
14410
+ // 'd:\\foo'
14411
+ const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
14412
+ checkPath.isNotRelative = path =>
14413
+ REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path)
14414
+ || isNotRelative(path);
14415
+ }
14168
14416
 
14169
- matchedRule = negative
14170
- ? UNDEFINED
14171
- : rule;
14172
- });
14417
+ // COMMONJS_EXPORTS ////////////////////////////////////////////////////////////
14173
14418
 
14174
- const ret = {
14175
- ignored,
14176
- unignored
14177
- };
14419
+ ignore$1.exports = factory;
14178
14420
 
14179
- if (matchedRule) {
14180
- ret.rule = matchedRule;
14181
- }
14421
+ // Although it is an anti-pattern,
14422
+ // it is still widely misused by a lot of libraries in github
14423
+ // Ref: https://github.com/search?q=ignore.default%28%29&type=code
14424
+ factory.default = factory;
14182
14425
 
14183
- return ret
14184
- }
14426
+ ignore$1.exports.isPathValid = isPathValid;
14427
+ return ignore$1.exports;
14185
14428
  }
14186
14429
 
14187
- const throwError = (message, Ctor) => {
14188
- throw new Ctor(message)
14189
- };
14190
-
14191
- const checkPath = (path, originalPath, doThrow) => {
14192
- if (!isString(path)) {
14193
- return doThrow(
14194
- `path must be a string, but got \`${originalPath}\``,
14195
- TypeError
14196
- )
14197
- }
14198
-
14199
- // We don't know if we should ignore EMPTY, so throw
14200
- if (!path) {
14201
- return doThrow(`path must not be empty`, TypeError)
14202
- }
14203
-
14204
- // Check if it is a relative path
14205
- if (checkPath.isNotRelative(path)) {
14206
- const r = '`path.relative()`d';
14207
- return doThrow(
14208
- `path should be a ${r} string, but got "${originalPath}"`,
14209
- RangeError
14210
- )
14211
- }
14430
+ var ignoreExports = /*@__PURE__*/ requireIgnore();
14431
+ var ignore = /*@__PURE__*/getDefaultExportFromCjs(ignoreExports);
14212
14432
 
14213
- return true
14433
+ const engines = {
14434
+ node: "^18.19.0 || >= 20.6.0"
14214
14435
  };
14215
14436
 
14216
- const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path);
14217
-
14218
- checkPath.isNotRelative = isNotRelative;
14219
-
14220
- // On windows, the following function will be replaced
14221
- /* istanbul ignore next */
14222
- checkPath.convert = p => p;
14223
-
14224
-
14225
- class Ignore {
14226
- constructor ({
14227
- ignorecase = true,
14228
- ignoreCase = ignorecase,
14229
- allowRelativePaths = false
14230
- } = {}) {
14231
- define(this, KEY_IGNORE, true);
14232
-
14233
- this._rules = new RuleManager(ignoreCase);
14234
- this._strictPathCheck = !allowRelativePaths;
14235
- this._initCache();
14236
- }
14237
-
14238
- _initCache () {
14239
- // A cache for the result of `.ignores()`
14240
- this._ignoreCache = Object.create(null);
14241
-
14242
- // A cache for the result of `.test()`
14243
- this._testCache = Object.create(null);
14244
- }
14245
-
14246
- add (pattern) {
14247
- if (this._rules.add(pattern)) {
14248
- // Some rules have just added to the ignore,
14249
- // making the behavior changed,
14250
- // so we need to re-initialize the result cache
14251
- this._initCache();
14252
- }
14253
-
14254
- return this
14255
- }
14256
-
14257
- // legacy
14258
- addPattern (pattern) {
14259
- return this.add(pattern)
14260
- }
14261
-
14262
- // @returns {TestResult}
14263
- _test (originalPath, cache, checkUnignored, slices) {
14264
- const path = originalPath
14265
- // Supports nullable path
14266
- && checkPath.convert(originalPath);
14267
-
14268
- checkPath(
14269
- path,
14270
- originalPath,
14271
- this._strictPathCheck
14272
- ? throwError
14273
- : RETURN_FALSE
14274
- );
14275
-
14276
- return this._t(path, cache, checkUnignored, slices)
14277
- }
14278
-
14279
- checkIgnore (path) {
14280
- // If the path doest not end with a slash, `.ignores()` is much equivalent
14281
- // to `git check-ignore`
14282
- if (!REGEX_TEST_TRAILING_SLASH.test(path)) {
14283
- return this.test(path)
14284
- }
14285
-
14286
- const slices = path.split(SLASH).filter(Boolean);
14287
- slices.pop();
14288
-
14289
- if (slices.length) {
14290
- const parent = this._t(
14291
- slices.join(SLASH) + SLASH,
14292
- this._testCache,
14293
- true,
14294
- slices
14295
- );
14296
-
14297
- if (parent.ignored) {
14298
- return parent
14299
- }
14300
- }
14301
-
14302
- return this._rules.test(path, false, MODE_CHECK_IGNORE)
14303
- }
14304
-
14305
- _t (
14306
- // The path to be tested
14307
- path,
14308
-
14309
- // The cache for the result of a certain checking
14310
- cache,
14311
-
14312
- // Whether should check if the path is unignored
14313
- checkUnignored,
14314
-
14315
- // The path slices
14316
- slices
14317
- ) {
14318
- if (path in cache) {
14319
- return cache[path]
14320
- }
14321
-
14322
- if (!slices) {
14323
- // path/to/a.js
14324
- // ['path', 'to', 'a.js']
14325
- slices = path.split(SLASH).filter(Boolean);
14326
- }
14327
-
14328
- slices.pop();
14329
-
14330
- // If the path has no parent directory, just test it
14331
- if (!slices.length) {
14332
- return cache[path] = this._rules.test(path, checkUnignored, MODE_IGNORE)
14333
- }
14334
-
14335
- const parent = this._t(
14336
- slices.join(SLASH) + SLASH,
14337
- cache,
14338
- checkUnignored,
14339
- slices
14340
- );
14341
-
14342
- // If the path contains a parent directory, check the parent first
14343
- return cache[path] = parent.ignored
14344
- // > It is not possible to re-include a file if a parent directory of
14345
- // > that file is excluded.
14346
- ? parent
14347
- : this._rules.test(path, checkUnignored, MODE_IGNORE)
14348
- }
14349
-
14350
- ignores (path) {
14351
- return this._test(path, this._ignoreCache, false).ignored
14352
- }
14353
-
14354
- createFilter () {
14355
- return path => !this.ignores(path)
14356
- }
14357
-
14358
- filter (paths) {
14359
- return makeArray(paths).filter(this.createFilter())
14360
- }
14361
-
14362
- // @returns {TestResult}
14363
- test (path) {
14364
- return this._test(path, this._testCache, true)
14365
- }
14366
- }
14367
-
14368
- const factory = options => new Ignore(options);
14369
-
14370
- const isPathValid = path =>
14371
- checkPath(path && checkPath.convert(path), path, RETURN_FALSE);
14372
-
14373
- factory.isPathValid = isPathValid;
14374
-
14375
-
14376
- // Windows
14377
- // --------------------------------------------------------------
14378
- /* istanbul ignore next */
14379
- if (
14380
- // Detect `process` so that it can run in browsers.
14381
- typeof process !== 'undefined'
14382
- && (
14383
- process.env && process.env.IGNORE_TEST_WIN32
14384
- || process.platform === 'win32'
14385
- )
14386
- ) {
14387
- /* eslint no-control-regex: "off" */
14388
- const makePosix = str => /^\\\\\?\\/.test(str)
14389
- || /["<>|\u0000-\u001F]+/u.test(str)
14390
- ? str
14391
- : str.replace(/\\/g, '/');
14392
-
14393
- checkPath.convert = makePosix;
14394
-
14395
- // 'C:\\foo' <- 'C:\\foo' has been converted to 'C:/'
14396
- // 'd:\\foo'
14397
- const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
14398
- checkPath.isNotRelative = path =>
14399
- REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path)
14400
- || isNotRelative(path);
14401
- }
14402
-
14403
14437
  var workerPath = "./jest-worker.js";
14404
14438
 
14405
- export { Attribute as A, Reporter as B, Config as C, DOMNode as D, definePlugin as E, ruleExists as F, walk as G, HtmlValidate as H, EventHandler as I, compatibilityCheckImpl as J, isThenable as K, workerPath as L, MetaCopyableProperty as M, NodeClosed as N, codeframe as O, Parser as P, name as Q, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, bugs as X, ConfigError as a, ConfigLoader as b, defineConfig as c, deepmerge as d, ensureError as e, factory as f, getFormatter as g, StaticConfigLoader as h, DOMTokenList as i, DOMTree as j, DynamicValue as k, HtmlElement as l, NodeType as m, NestedError as n, SchemaValidationError as o, presets as p, MetaTable as q, TextContent$1 as r, staticResolver as s, Rule as t, ariaNaming as u, version as v, TextClassification as w, classifyNodeText as x, keywordPatternMatcher as y, sliceLocation as z };
14439
+ export { Attribute as A, sliceLocation as B, Config as C, DOMNode as D, Reporter as E, definePlugin as F, ruleExists as G, HtmlValidate as H, walk as I, EventHandler as J, engines as K, compatibilityCheckImpl as L, MetaCopyableProperty as M, NodeClosed as N, isThenable as O, Parser as P, workerPath as Q, ResolvedConfig as R, Severity as S, TextNode as T, UserError as U, Validator as V, WrappedError as W, codeframe as X, name as Y, bugs as Z, ConfigError as a, ConfigLoader as b, defineConfig as c, deepmerge as d, ensureError as e, StaticConfigLoader as f, getFormatter as g, DOMTokenList as h, ignore as i, DOMTree as j, DynamicValue as k, HtmlElement as l, NodeType as m, NestedError as n, SchemaValidationError as o, presets as p, isUserError as q, MetaTable as r, staticResolver as s, TextContent$1 as t, Rule as u, version as v, ariaNaming as w, TextClassification as x, classifyNodeText as y, keywordPatternMatcher as z };
14406
14440
  //# sourceMappingURL=core.js.map