|                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |  | // A simple implementation of make-array
function makeArray (subject) {  return Array.isArray(subject)    ? subject    : [subject]}
const EMPTY = ''const SPACE = ' 'const ESCAPE = '\\'const REGEX_TEST_BLANK_LINE = /^\s+$/const REGEX_INVALID_TRAILING_BACKSLASH = /(?:[^\\]|^)\\$/const REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION = /^\\!/const REGEX_REPLACE_LEADING_EXCAPED_HASH = /^\\#/const REGEX_SPLITALL_CRLF = /\r?\n/g// /foo,
// ./foo,
// ../foo,
// .
// ..
const REGEX_TEST_INVALID_PATH = /^\.*\/|^\.+$/
const SLASH = '/'
// Do not use ternary expression here, since "istanbul ignore next" is buggy
let TMP_KEY_IGNORE = 'node-ignore'/* istanbul ignore else */if (typeof Symbol !== 'undefined') {  TMP_KEY_IGNORE = Symbol.for('node-ignore')}const KEY_IGNORE = TMP_KEY_IGNORE
const define = (object, key, value) =>  Object.defineProperty(object, key, {value})
const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g
const RETURN_FALSE = () => false
// Sanitize the range of a regular expression
// The cases are complicated, see test cases for details
const sanitizeRange = range => range.replace(  REGEX_REGEXP_RANGE,  (match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)    ? match    // Invalid range (out of order) which is ok for gitignore rules but
    //   fatal for JavaScript regular expression, so eliminate it.
    : EMPTY)
// See fixtures #59
const cleanRangeBackSlash = slashes => {  const {length} = slashes  return slashes.slice(0, length - length % 2)}
// > If the pattern ends with a slash,
// > it is removed for the purpose of the following description,
// > but it would only find a match with a directory.
// > In other words, foo/ will match a directory foo and paths underneath it,
// > but will not match a regular file or a symbolic link foo
// >  (this is consistent with the way how pathspec works in general in Git).
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
//      you could use option `mark: true` with `glob`
// '`foo/`' should not continue with the '`..`'
const REPLACERS = [
  [    // remove BOM
    // TODO:
    // Other similar zero-width characters?
    /^\uFEFF/,    () => EMPTY  ],
  // > Trailing spaces are ignored unless they are quoted with backslash ("\")
  [    // (a\ ) -> (a )
    // (a  ) -> (a)
    // (a ) -> (a)
    // (a \ ) -> (a  )
    /((?:\\\\)*?)(\\?\s+)$/,    (_, m1, m2) => m1 + (      m2.indexOf('\\') === 0        ? SPACE        : EMPTY    )  ],
  // replace (\ ) with ' '
  // (\ ) -> ' '
  // (\\ ) -> '\\ '
  // (\\\ ) -> '\\ '
  [    /(\\+?)\s/g,    (_, m1) => {      const {length} = m1      return m1.slice(0, length - length % 2) + SPACE    }  ],
  // Escape metacharacters
  // which is written down by users but means special for regular expressions.
  // > There are 12 characters with special meanings:
  // > - the backslash \,
  // > - the caret ^,
  // > - the dollar sign $,
  // > - the period or dot .,
  // > - the vertical bar or pipe symbol |,
  // > - the question mark ?,
  // > - the asterisk or star *,
  // > - the plus sign +,
  // > - the opening parenthesis (,
  // > - the closing parenthesis ),
  // > - and the opening square bracket [,
  // > - the opening curly brace {,
  // > These special characters are often called "metacharacters".
  [    /[\\$.|*+(){^]/g,    match => `\\${match}`  ],
  [    // > a question mark (?) matches a single character
    /(?!\\)\?/g,    () => '[^/]'  ],
  // leading slash
  [
    // > A leading slash matches the beginning of the pathname.
    // > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
    // A leading slash matches the beginning of the pathname
    /^\//,    () => '^'  ],
  // replace special metacharacter slash after the leading slash
  [    /\//g,    () => '\\/'  ],
  [    // > A leading "**" followed by a slash means match in all directories.
    // > For example, "**/foo" matches file or directory "foo" anywhere,
    // > the same as pattern "foo".
    // > "**/foo/bar" matches file or directory "bar" anywhere that is directly
    // >   under directory "foo".
    // Notice that the '*'s have been replaced as '\\*'
    /^\^*\\\*\\\*\\\//,
    // '**/foo' <-> 'foo'
    () => '^(?:.*\\/)?'  ],
  // starting
  [    // there will be no leading '/'
    //   (which has been replaced by section "leading slash")
    // If starts with '**', adding a '^' to the regular expression also works
    /^(?=[^^])/,    function startingReplacer () {      // If has a slash `/` at the beginning or middle
      return !/\/(?!$)/.test(this)        // > Prior to 2.22.1
        // > If the pattern does not contain a slash /,
        // >   Git treats it as a shell glob pattern
        // Actually, if there is only a trailing slash,
        //   git also treats it as a shell glob pattern
        // After 2.22.1 (compatible but clearer)
        // > If there is a separator at the beginning or middle (or both)
        // > of the pattern, then the pattern is relative to the directory
        // > level of the particular .gitignore file itself.
        // > Otherwise the pattern may also match at any level below
        // > the .gitignore level.
        ? '(?:^|\\/)'
        // > Otherwise, Git treats the pattern as a shell glob suitable for
        // >   consumption by fnmatch(3)
        : '^'    }  ],
  // two globstars
  [    // Use lookahead assertions so that we could match more than one `'/**'`
    /\\\/\\\*\\\*(?=\\\/|$)/g,
    // Zero, one or several directories
    // should not use '*', or it will be replaced by the next replacer
    // Check if it is not the last `'/**'`
    (_, index, str) => index + 6 < str.length
      // case: /**/
      // > A slash followed by two consecutive asterisks then a slash matches
      // >   zero or more directories.
      // > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
      // '/**/'
      ? '(?:\\/[^\\/]+)*'
      // case: /**
      // > A trailing `"/**"` matches everything inside.
      // #21: everything inside but it should not include the current folder
      : '\\/.+'  ],
  // normal intermediate wildcards
  [    // Never replace escaped '*'
    // ignore rule '\*' will match the path '*'
    // 'abc.*/' -> go
    // 'abc.*'  -> skip this rule,
    //    coz trailing single wildcard will be handed by [trailing wildcard]
    /(^|[^\\]+)(\\\*)+(?=.+)/g,
    // '*.js' matches '.js'
    // '*.js' doesn't match 'abc'
    (_, p1, p2) => {      // 1.
      // > An asterisk "*" matches anything except a slash.
      // 2.
      // > Other consecutive asterisks are considered regular asterisks
      // > and will match according to the previous rules.
      const unescaped = p2.replace(/\\\*/g, '[^\\/]*')      return p1 + unescaped    }  ],
  [    // unescape, revert step 3 except for back slash
    // For example, if a user escape a '\\*',
    // after step 3, the result will be '\\\\\\*'
    /\\\\\\(?=[$.|*+(){^])/g,    () => ESCAPE  ],
  [    // '\\\\' -> '\\'
    /\\\\/g,    () => ESCAPE  ],
  [    // > The range notation, e.g. [a-zA-Z],
    // > can be used to match one of the characters in a range.
    // `\` is escaped by step 3
    /(\\)?\[([^\]/]*?)(\\*)($|\])/g,    (match, leadEscape, range, endEscape, close) => leadEscape === ESCAPE      // '\\[bar]' -> '\\\\[bar\\]'
      ? `\\[${range}${cleanRangeBackSlash(endEscape)}${close}`      : close === ']'        ? endEscape.length % 2 === 0          // A normal case, and it is a range notation
          // '[bar]'
          // '[bar\\\\]'
          ? `[${sanitizeRange(range)}${endEscape}]`          // Invalid range notaton
          // '[bar\\]' -> '[bar\\\\]'
          : '[]'        : '[]'  ],
  // ending
  [    // 'js' will not match 'js.'
    // 'ab' will not match 'abc'
    /(?:[^*])$/,
    // WTF!
    // https://git-scm.com/docs/gitignore
    // changes in [2.22.1](https://git-scm.com/docs/gitignore/2.22.1)
    // which re-fixes #24, #38
    // > If there is a separator at the end of the pattern then the pattern
    // > will only match directories, otherwise the pattern can match both
    // > files and directories.
    // 'js*' will not match 'a.js'
    // 'js/' will not match 'a.js'
    // 'js' will match 'a.js' and 'a.js/'
    match => /\/$/.test(match)      // foo/ will not match 'foo'
      ? `${match}$`      // foo matches 'foo' and 'foo/'
      : `${match}(?=$|\\/$)`  ],
  // trailing wildcard
  [    /(\^|\\\/)?\\\*$/,    (_, p1) => {      const prefix = p1        // '\^':
        // '/*' does not match EMPTY
        // '/*' does not match everything
        // '\\\/':
        // 'abc/*' does not match 'abc/'
        ? `${p1}[^/]+`
        // 'a*' matches 'a'
        // 'a*' matches 'aa'
        : '[^/]*'
      return `${prefix}(?=$|\\/$)`    }  ],]
// A simple cache, because an ignore rule only has only one certain meaning
const regexCache = Object.create(null)
// @param {pattern}
const makeRegex = (pattern, ignoreCase) => {  let source = regexCache[pattern]
  if (!source) {    source = REPLACERS.reduce(      (prev, [matcher, replacer]) =>        prev.replace(matcher, replacer.bind(pattern)),      pattern    )    regexCache[pattern] = source  }
  return ignoreCase    ? new RegExp(source, 'i')    : new RegExp(source)}
const isString = subject => typeof subject === 'string'
// > A blank line matches no files, so it can serve as a separator for readability.
const checkPattern = pattern => pattern  && isString(pattern)  && !REGEX_TEST_BLANK_LINE.test(pattern)  && !REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)
  // > A line starting with # serves as a comment.
  && pattern.indexOf('#') !== 0
const splitPattern = pattern => pattern.split(REGEX_SPLITALL_CRLF)
class IgnoreRule {  constructor (    origin,    pattern,    negative,    regex  ) {    this.origin = origin    this.pattern = pattern    this.negative = negative    this.regex = regex  }}
const createRule = (pattern, ignoreCase) => {  const origin = pattern  let negative = false
  // > An optional prefix "!" which negates the pattern;
  if (pattern.indexOf('!') === 0) {    negative = true    pattern = pattern.substr(1)  }
  pattern = pattern  // > Put a backslash ("\") in front of the first "!" for patterns that
  // >   begin with a literal "!", for example, `"\!important!.txt"`.
  .replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION, '!')  // > Put a backslash ("\") in front of the first hash for patterns that
  // >   begin with a hash.
  .replace(REGEX_REPLACE_LEADING_EXCAPED_HASH, '#')
  const regex = makeRegex(pattern, ignoreCase)
  return new IgnoreRule(    origin,    pattern,    negative,    regex  )}
const throwError = (message, Ctor) => {  throw new Ctor(message)}
const checkPath = (path, originalPath, doThrow) => {  if (!isString(path)) {    return doThrow(      `path must be a string, but got \`${originalPath}\``,      TypeError    )  }
  // We don't know if we should ignore EMPTY, so throw
  if (!path) {    return doThrow(`path must not be empty`, TypeError)  }
  // Check if it is a relative path
  if (checkPath.isNotRelative(path)) {    const r = '`path.relative()`d'    return doThrow(      `path should be a ${r} string, but got "${originalPath}"`,      RangeError    )  }
  return true}
const isNotRelative = path => REGEX_TEST_INVALID_PATH.test(path)
checkPath.isNotRelative = isNotRelativecheckPath.convert = p => p
class Ignore {  constructor ({    ignorecase = true,    ignoreCase = ignorecase,    allowRelativePaths = false  } = {}) {    define(this, KEY_IGNORE, true)
    this._rules = []    this._ignoreCase = ignoreCase    this._allowRelativePaths = allowRelativePaths    this._initCache()  }
  _initCache () {    this._ignoreCache = Object.create(null)    this._testCache = Object.create(null)  }
  _addPattern (pattern) {    // #32
    if (pattern && pattern[KEY_IGNORE]) {      this._rules = this._rules.concat(pattern._rules)      this._added = true      return    }
    if (checkPattern(pattern)) {      const rule = createRule(pattern, this._ignoreCase)      this._added = true      this._rules.push(rule)    }  }
  // @param {Array<string> | string | Ignore} pattern
  add (pattern) {    this._added = false
    makeArray(      isString(pattern)        ? splitPattern(pattern)        : pattern    ).forEach(this._addPattern, this)
    // Some rules have just added to the ignore,
    // making the behavior changed.
    if (this._added) {      this._initCache()    }
    return this  }
  // legacy
  addPattern (pattern) {    return this.add(pattern)  }
  //          |           ignored : unignored
  // negative |   0:0   |   0:1   |   1:0   |   1:1
  // -------- | ------- | ------- | ------- | --------
  //     0    |  TEST   |  TEST   |  SKIP   |    X
  //     1    |  TESTIF |  SKIP   |  TEST   |    X
  // - SKIP: always skip
  // - TEST: always test
  // - TESTIF: only test if checkUnignored
  // - X: that never happen
  // @param {boolean} whether should check if the path is unignored,
  //   setting `checkUnignored` to `false` could reduce additional
  //   path matching.
  // @returns {TestResult} true if a file is ignored
  _testOne (path, checkUnignored) {    let ignored = false    let unignored = false
    this._rules.forEach(rule => {      const {negative} = rule      if (        unignored === negative && ignored !== unignored        || negative && !ignored && !unignored && !checkUnignored      ) {        return      }
      const matched = rule.regex.test(path)
      if (matched) {        ignored = !negative        unignored = negative      }    })
    return {      ignored,      unignored    }  }
  // @returns {TestResult}
  _test (originalPath, cache, checkUnignored, slices) {    const path = originalPath      // Supports nullable path
      && checkPath.convert(originalPath)
    checkPath(      path,      originalPath,      this._allowRelativePaths        ? RETURN_FALSE        : throwError    )
    return this._t(path, cache, checkUnignored, slices)  }
  _t (path, cache, checkUnignored, slices) {    if (path in cache) {      return cache[path]    }
    if (!slices) {      // path/to/a.js
      // ['path', 'to', 'a.js']
      slices = path.split(SLASH)    }
    slices.pop()
    // If the path has no parent directory, just test it
    if (!slices.length) {      return cache[path] = this._testOne(path, checkUnignored)    }
    const parent = this._t(      slices.join(SLASH) + SLASH,      cache,      checkUnignored,      slices    )
    // If the path contains a parent directory, check the parent first
    return cache[path] = parent.ignored      // > It is not possible to re-include a file if a parent directory of
      // >   that file is excluded.
      ? parent      : this._testOne(path, checkUnignored)  }
  ignores (path) {    return this._test(path, this._ignoreCache, false).ignored  }
  createFilter () {    return path => !this.ignores(path)  }
  filter (paths) {    return makeArray(paths).filter(this.createFilter())  }
  // @returns {TestResult}
  test (path) {    return this._test(path, this._testCache, true)  }}
const factory = options => new Ignore(options)
const isPathValid = path =>  checkPath(path && checkPath.convert(path), path, RETURN_FALSE)
factory.isPathValid = isPathValid
// Fixes typescript
factory.default = factory
module.exports = factory
// Windows
// --------------------------------------------------------------
/* istanbul ignore if */if (  // Detect `process` so that it can run in browsers.
  typeof process !== 'undefined'  && (    process.env && process.env.IGNORE_TEST_WIN32    || process.platform === 'win32'  )) {  /* eslint no-control-regex: "off" */  const makePosix = str => /^\\\\\?\\/.test(str)  || /["<>|\u0000-\u001F]+/u.test(str)    ? str    : str.replace(/\\/g, '/')
  checkPath.convert = makePosix
  // 'C:\\foo'     <- 'C:\\foo' has been converted to 'C:/'
  // 'd:\\foo'
  const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i  checkPath.isNotRelative = path =>    REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path)    || isNotRelative(path)}
 |