function expand(pattern, options) {
  if (typeof pattern !== 'string') {
    throw new TypeError('micromatch.expand(): argument should be a string.');
  }

  var glob = new Glob(pattern, options || {});
  var opts = glob.options;

  if (!utils.isGlob(pattern)) {
    glob.pattern = glob.pattern.replace(/([\/.])/g, '\\$1');
    return glob;
  }

  glob.pattern = glob.pattern.replace(/(\+)(?!\()/g, '\\$1');
  glob.pattern = glob.pattern.split('$').join('\\$');

  if (typeof opts.braces !== 'boolean' && typeof opts.nobraces !== 'boolean') {
    opts.braces = true;
  }

  if (glob.pattern === '.*') {
    return {
      pattern: '\\.' + star,
      tokens: tok,
      options: opts
    };
  }

  if (glob.pattern === '*') {
    return {
      pattern: oneStar(opts.dot),
      tokens: tok,
      options: opts
    };
  } // parse the glob pattern into tokens


  glob.parse();
  var tok = glob.tokens;
  tok.is.negated = opts.negated; // dotfile handling

  if ((opts.dotfiles === true || tok.is.dotfile) && opts.dot !== false) {
    opts.dotfiles = true;
    opts.dot = true;
  }

  if ((opts.dotdirs === true || tok.is.dotdir) && opts.dot !== false) {
    opts.dotdirs = true;
    opts.dot = true;
  } // check for braces with a dotfile pattern


  if (/[{,]\./.test(glob.pattern)) {
    opts.makeRe = false;
    opts.dot = true;
  }

  if (opts.nonegate !== true) {
    opts.negated = glob.negated;
  } // if the leading character is a dot or a slash, escape it


  if (glob.pattern.charAt(0) === '.' && glob.pattern.charAt(1) !== '/') {
    glob.pattern = '\\' + glob.pattern;
  }
  /**
   * Extended globs
   */
  // expand braces, e.g `{1..5}`


  glob.track('before braces');

  if (tok.is.braces) {
    glob.braces();
  }

  glob.track('after braces'); // expand extglobs, e.g `foo/!(a|b)`

  glob.track('before extglob');

  if (tok.is.extglob) {
    glob.extglob();
  }

  glob.track('after extglob'); // expand brackets, e.g `[[:alpha:]]`

  glob.track('before brackets');

  if (tok.is.brackets) {
    glob.brackets();
  }

  glob.track('after brackets'); // special patterns

  glob._replace('[!', '[^');

  glob._replace('(?', '(%~');

  glob._replace(/\[\]/, '\\[\\]');

  glob._replace('/[', '/' + (opts.dot ? dotfiles : nodot) + '[', true);

  glob._replace('/?', '/' + (opts.dot ? dotfiles : nodot) + '[^/]', true);

  glob._replace('/.', '/(?=.)\\.', true); // windows drives


  glob._replace(/^(\w):([\\\/]+?)/gi, '(?=.)$1:$2', true); // negate slashes in exclusion ranges


  if (glob.pattern.indexOf('[^') !== -1) {
    glob.pattern = negateSlash(glob.pattern);
  }

  if (opts.globstar !== false && glob.pattern === '**') {
    glob.pattern = globstar(opts.dot);
  } else {
    glob.pattern = balance(glob.pattern, '[', ']');
    glob.escape(glob.pattern); // if the pattern has `**`

    if (tok.is.globstar) {
      glob.pattern = collapse(glob.pattern, '/**');
      glob.pattern = collapse(glob.pattern, '**/');

      glob._replace('/**/', '(?:/' + globstar(opts.dot) + '/|/)', true);

      glob._replace(/\*{2,}/g, '**'); // 'foo/*'


      glob._replace(/(\w+)\*(?!\/)/g, '$1[^/]*?', true);

      glob._replace(/\*\*\/\*(\w)/g, globstar(opts.dot) + '\\/' + (opts.dot ? dotfiles : nodot) + '[^/]*?$1', true);

      if (opts.dot !== true) {
        glob._replace(/\*\*\/(.)/g, '(?:**\\/|)$1');
      } // 'foo/**' or '{**,*}', but not 'foo**'


      if (tok.path.dirname !== '' || /,\*\*|\*\*,/.test(glob.orig)) {
        glob._replace('**', globstar(opts.dot), true);
      }
    } // ends with /*


    glob._replace(/\/\*$/, '\\/' + oneStar(opts.dot), true); // ends with *, no slashes


    glob._replace(/(?!\/)\*$/, star, true); // has 'n*.' (partial wildcard w/ file extension)


    glob._replace(/([^\/]+)\*/, '$1' + oneStar(true), true); // has '*'


    glob._replace('*', oneStar(opts.dot), true);

    glob._replace('?.', '?\\.', true);

    glob._replace('?:', '?:', true);

    glob._replace(/\?+/g, function (match) {
      var len = match.length;

      if (len === 1) {
        return qmark;
      }

      return qmark + '{' + len + '}';
    }); // escape '.abc' => '\\.abc'


    glob._replace(/\.([*\w]+)/g, '\\.$1'); // fix '[^\\\\/]'


    glob._replace(/\[\^[\\\/]+\]/g, qmark); // '///' => '\/'


    glob._replace(/\/+/g, '\\/'); // '\\\\\\' => '\\'


    glob._replace(/\\{2,}/g, '\\');
  } // unescape previously escaped patterns


  glob.unescape(glob.pattern);

  glob._replace('__UNESC_STAR__', '*'); // escape dots that follow qmarks


  glob._replace('?.', '?\\.'); // remove unnecessary slashes in character classes


  glob._replace('[^\\/]', qmark);

  if (glob.pattern.length > 1) {
    if (/^[\[?*]/.test(glob.pattern)) {
      // only prepend the string if we don't want to match dotfiles
      glob.pattern = (opts.dot ? dotfiles : nodot) + glob.pattern;
    }
  }

  return glob;
}
Expand a glob pattern to resolve braces and
similar patterns before converting to regex.

@param  {String|Array} `pattern`
@param  {Array} `files`
@param  {Options} `opts`
@return {Array}