Parse pattern files and then flesh out individual pattern objects and
build collection data.

@param {Object} options
@return {Promise} resolving to pattern/collection data
166013
function parsePatterns(options) {
  return readFileTree(
    options.src.patterns,
    options.keys.patterns,
    options
  ).then(patternObj => {
    return Promise.all(buildCollections(patternObj, options)).then(
      () => patternObj,
      error => DrizzleError.error(error, options.debug)
    );
  });
}
520047
static function compilePattern($pattern, array $options = array())
    {

        $len = strlen($pattern);
        /**
         * contains:
         *
         *   array( 'text', $text ),
         *   array( 'variable', $match[0][0][0], $regexp, $var);
         *
         */
        $tokens = array();
        $variables = array();
        $pos = 0;

        /**
         *  the path like:
         *
         *      /blog/to/:year/:month
         *
         *  will be separated like:
         *      
         *      [
         *          '/blog/to',  (text token)
         *          '/:year',    (reg exp token)
         *          '/:month',   (reg exp token)
         *      ]
         */
        $matches = self::splitTokens($pattern);


        // build tokens
        foreach ($matches as $matchIdx => $match) {
            // match[0][1] // matched position for pattern.

            /*
             * Split tokens from abstract pattern
             * to rebuild regexp pattern.
             */
            if ($text = substr($pattern, $pos, $match[0][1] - $pos)) {
                $tokens[] = array( self::TOKEN_TYPE_TEXT, $text);
            }

            // the first char from pattern (which is the seperater)
            // and the first char from the next match pattern
            $seps = array($pattern[$pos]);


            // collect the separator tokens from the next matched pattern
            if (isset($matches[$matchIdx + 1])) {
                $nextMatch = $matches[$matchIdx + 1];

                // check if the next pattern is an optional pattern
                if ($nextMatch[0][0][0] === '(') {

                    $r = self::compilePattern($nextMatch[2][0] ,array());
                    if (isset($r['tokens'][0][1])) {
                        $seps[] = $r['tokens'][0][1][0];
                    }

                } else if ($nextMatch[0][0][0] === ':') { // variable token

                } else {
                    $seps[] = $nextMatch[0][0][0];
                }
            }


            $pos = $match[0][1] + strlen($match[0][0]);


            // generate optional pattern recursively
            if ($match[0][0][0] == '(' ){
                $optional = $match[2][0];
                $subroute = self::compilePattern($optional ,array(
                    'default'   => isset($options['default']) ? $options['default'] : null,
                    'require'   => isset($options['require']) ? $options['require'] : null,
                    'variables' => isset($options['variables']) ? $options['variables'] : null,
                ));

                $tokens[] = array( 
                    self::TOKEN_TYPE_OPTIONAL,
                    $optional[0],
                    $subroute['regex'],
                );
                foreach( $subroute['variables'] as $var ) {
                    $variables[] = $var;
                }
            } else {
                // generate a variable token 
                $varName = $match[1][0];

                // if we defined a pattern for this variable, we should use the given pattern..
                if ( isset( $options['require'][$varName] ) && $req = $options['require'][$varName]) {
                    $regexp = $req;
                } else {
                    if ($pos !== $len) {
                        $seps[] = $pattern[$pos];
                    }
                    // use the default pattern (which is based on the separater charactors we got)
                    $regexp = sprintf('[^%s]+', preg_quote(implode('', array_unique($seps)), '#'));
                }

                // append token item
                $tokens[] = array(self::TOKEN_TYPE_VARIABLE, 
                    $match[0][0][0], 
                    $regexp, 
                    $varName);

                // append variable name
                $variables[] = $varName;
            }
        }

        if ($pos < $len) {
            $tokens[] = array(self::TOKEN_TYPE_TEXT, substr($pattern, $pos));
        }

        // find the first optional token
        $firstOptional = INF;
        for ($i = count($tokens) - 1; $i >= 0; $i--) {
            if ( self::TOKEN_TYPE_VARIABLE === $tokens[$i][0] 
                && isset($options['default'][ $tokens[$i][3] ]) )
            {
                $firstOptional = $i;
            } 
            else 
            {
                break;
            }
        }

        // compute the matching regexp
        $regex = '';

        // indentation level
        $indent = 1;


        // token item structure:
        //   [0] => token type,
        //   [1] => separator
        //   [2] => pattern
        //   [3] => name, 

        // first optional token and only one token.
        if (1 === count($tokens) && 0 === $firstOptional) {
            $token = $tokens[0];
            ++$indent;

            // output regexp with separator and
            $regex .= str_repeat(' ', $indent * 4) . sprintf("%s(?:\n", preg_quote($token[1], '#'));

            // regular expression with place holder name. (?P<name>pattern)
            $regex .= str_repeat(' ', $indent * 4) . sprintf("(?P<%s>%s)\n", $token[3], $token[2]);

        } else {
            foreach ($tokens as $i => $token) {

                switch ( $token[0] ) {
                case self::TOKEN_TYPE_TEXT:
                    $regex .= str_repeat(' ', $indent * 4) . preg_quote($token[1], '#')."\n";
                    break;
                case self::TOKEN_TYPE_OPTIONAL:
                    // the question mark is for optional, the optional item may contains multiple tokens and patterns
                    $regex .= str_repeat(' ', $indent * 4) . "(?:\n" . $token[2] . str_repeat(' ', $indent * 4) . ")?\n";
                    break;
                default:
                    // append new pattern group for the optional pattern
                    if ($i >= $firstOptional) {
                        $regex .= str_repeat(' ', $indent * 4) . "(?:\n";
                        ++$indent;
                    }
                    $regex .= str_repeat(' ', $indent * 4). sprintf("%s(?P<%s>%s)\n", preg_quote($token[1], '#'), $token[3], $token[2]);
                    break;
                }
            }
        }

        // close groups
        while (--$indent) {
            $regex .= str_repeat(' ', $indent * 4).")?\n";
        }

        // save variables
        $options['variables'] = $variables;
        $options['regex'] = $regex;
        $options['tokens'] = $tokens;
        return $options;
    }
677328
function collectionLoader(collection, config) {
  collection._addView = collection.addView.bind(collection);
  var fn = collection.view;

  collection.define('view', function() {
    var view = fn.apply(this, arguments);
    utils.contents.sync(view);
    return view;
  });

  /**
   * Patches the `.addViews` method to support glob patterns.
   *
   * @param {Object|String} `key` View name or object.
   * @param {Object} `value` View options, when key is a string.
   * @return {Object}
   */

  collection.define('addView', function(key, value) {
    return this._addView.apply(this, arguments);
  });

  /**
   * Patches the `.addViews` method to support glob patterns.
   *
   * @param {Object|String} `key` View name or object.
   * @param {Object} `value` View options, when key is a string.
   * @return {Object}
   */

  collection.define('addViews', function(key, value) {
    this.load.apply(this, arguments);
    return this;
  });

  collection.define('loadView', function(filepath, options) {
    this.load.apply(this, arguments);
    return this;
  });

  collection.define('loadViews', function(patterns, options) {
    this.load.apply(this, arguments);
    return this;
  });

  collection.define('load', function() {
    return load('_addView', config).apply(this, arguments);
  });
}
980896
function readFile (file, options) {
    // return new Promise that will be resolved with data
    return new Promise((resolve, reject) => {
        // create write stream
        this.createReadStream(file, options).then(stream => {
            // create new concat stream that will call back with stream data
            var concatStream = ConcatStream(buffer => {
                // resolve with string if encoding set or buffer
                var data = defined(options) && defined(options.encoding)
                    ? buffer.toString(options.encoding)
                    : buffer
                // resolve with data
                resolve(data)
            })
            // reject on errors
            stream.on('error', reject)
            // pipe read stream to concat stream which will resolve when done
            stream.pipe(concatStream)
        })
        // pass rejection
        .catch(reject)
    })
}
1158693
function writeCollections(drizzleData) {
  return Promise.all(walkCollections(drizzleData.patterns, drizzleData)).then(
    writePromises => drizzleData,
    error => DrizzleError.error(error, drizzleData.options.debug)
  );
}
155648
function parse_files(files, options) {
  let nodes = {
    // root section node
    '': {
      id: '',
      type: 'section',
      children: [],
      description: '',
      short_description: '',
      href: '#',
      root: true,
      file: '',
      line: 0
    }
  };

  files.forEach(file => {
    let fn = NDoc.parsers[path.extname(file)];

    if (!fn) return;

    /* eslint-disable no-console */
    console.info('Parsing file: ' + file);

    let file_nodes = fn(file, options);

    // TODO:  fail on name clash here as well -- as we might get name clash
    //        from different parsers, or even differnret files
    _.extend(nodes, file_nodes);
  });

  return nodes;
}
1353162
function resolveAll(fileContent) {
			var matches      = [].concat(fileContent.match(regexFile)).filter(Boolean).map(extractFile);
			var pathsMatches = [].concat(fileContent.match(regexPath)).filter(Boolean).map(extractFile);

			if (matches.length === 0 && pathsMatches.length === 0) {
				return new RSVP.Promise(function(resolve) {
					resolve(fileContent)
				});
			}

			var promises      = [].concat(matches.map(resolveFile)).filter(Boolean);
			var promisesPaths = [].concat(pathsMatches.map(resolvePath)).filter(Boolean);

			return RSVP.all(promises.concat(promisesPaths)).then(function() {
				for (var i = 0, len = matches.length; i < len; i++) {
					fileContent = fileContent.replace(matches[i], replacements[i]);
				}
				return fileContent;
			});

		}
1319305
function(file, opts) {
	if (util.isObject(file) || util.isArray(file)) {
		return file;
	}

	var options = util.extend({
		asText: false, // true, false, 'pretty'
		javascript: false, // true, false
		scope: '', // directory to look for initial file
		variables: {
			// contains a key->value object with variables to @extends
		}
	}, opts);

	file = util.template(file, options.variables);

	/*****************************************************************************
	*  Initialize
	*****************************************************************************/

	var file_path;

	// If the file path is absolute use it
	// If not then prepend the current scope of the previous file.
	if (path.resolve(file) === path.normalize(file)) {
		file_path = path.normalize(file);
	}
	else {
		file_path = path.normalize(
			options.scope ? options.scope + '/' + file : file
		);
	}
	var class_json = parseFile(file_path, options);

	// Stores JSON objects of files that have to be merged together:
	// ["a", "b"]
	var file_list = util.isArray(class_json[indicators.EXTENDS]) ?
		class_json[indicators.EXTENDS] :
		class_json[indicators.EXTENDS] != null ?
			[ class_json[indicators.EXTENDS] ] :
			[];

	// Delete @extends from base_json to avoid infinitive recursion
	delete class_json[indicators.EXTENDS];

	// Push class_json to the path list:
	file_list.push(class_json);
	/*****************************************************************************
	*  Merge file by file
	*****************************************************************************/

	// default config for each file required:
	// set asText = false so we get an object returned
	// set scope = file's directory so there can be relative references
	var json_config = util.defaults({
		asText: false,
		scope: path.dirname(file_path),

		// _as is a hack so that we know its we are calling the function recursive
		_as: ANTI_SANITIZER
	}, options);

	// super_json is our output, start by containing first file in array
	var super_json = fromFile(file_list.shift(), json_config);

	// TODO: Figure out when to sanitize super_json hopefully we don't have to
	//   santize all returns. I'm not sure about this, and I'm not sure if we
	//   can even sanitize super_json when we return it.
	//   Is super_json used by anyone recursively?

	while (file_list.length) {
		var json = fromFile(file_list.shift(), json_config);

		merge(super_json, json);
	}

	// If this file is called from the outside eg json_merger.from...
	//   File('file_which_doesnt_extends_another_file.json')
	//   we need to sanitize the file and remove all indicators
	if (options._as != ANTI_SANITIZER) {
		super_json = util.sanitizeValue(super_json);
	}

	/*****************************************************************************
	*  Return super_json
	*****************************************************************************/
	if (options.asText) {
		return stringify(super_json, options);
	}
	else {
		return super_json;
	}
}
799098
function (options) {

		this.options = options;
		this._data = [];
		this._dataDto = [];
		this._dataCollections = [];
		this._swaggerImport = this._readSwaggerImportFile();
		this._validation = this._readValidationFile();
		this._isSwaggerImportAvailable = (typeof options.swaggerImport === 'object');
		this._isCustomDTOToClassAvailable = (typeof options.customDTOToClassTemplate === 'string');

		this._readApi();
		this._readDtos();
		this._readCollections();
	}
781443
function( patterns, options ){

        options = options || {};

        var deferred = Q.defer(),
            updateHTMLFile = this.updateHTMLFile,
            results = {
                success: [],
                error: []
            };

        globby( patterns, options, function( err, files ){
            if( err ){
                deferred.reject( err );
                return;
            }

            files.reduce( function( previousUpdating, currentTargetFilePath ){
                return previousUpdating.then(
                    function( previousPath ){
                        if( previousPath ){
                            results.success.push( previousPath );
                        }
                        return updateHTMLFile( currentTargetFilePath );
                    }
                );
            }, Q() )
                .then(
                    function( lastPath ){
                        results.success.push( lastPath );
                        deferred.resolve( results );
                    },
                    function( e ){
                        deferred.reject( e );
                    }
                );
        } );

        return deferred.promise;
    }
479353
function Collection(options) {
  if (!(this instanceof Collection)) {
    return new Collection(options);
  }

  Base.call(this, {}, options);
  this.is('Collection');
  this.items = {};

  this.use(utils.option());
  this.use(utils.plugin());
  this.init(options || {});
}
807219
function findFiles( options ) {

  var cwd = options.cwd ? path.resolve( options.cwd ) : CWD;

  var patterns = makeSureArray( options.src ).map( function( pattern ) {
    return new Pattern( pattern, options.micromatch );
  } );

  return new MotaObservable( function( observer ) {

    var reader = new Reader( patterns, cwd, observer );

    reader.readDir( cwd ).then(
      observer.complete.bind( observer ),
      observer.error.bind( observer )
    );

    return function() {
      reader.cancel();
    };

  } );

}
1074730
function(file, options, callback) {
        fs.readFile(file, options, function(err, data) {
            if (err) {
                return callback(err);
            }
            module.exports.parse(data.toString(), function(parseErr, lines) {
                if (parseErr) {
                    return callback(parseErr);
                }
                callback(undefined, lines);
            });
        });
    }
227083
function (options) {
            var collections = {};

            if (_.size(this.collections)) {
                for (var i = 0; i < this.collections.length; i++) {
                    collections[this.collections[i]] = options.ctl.ctx.collections[this.collections[i]];
                    if (!collections[this.collections[i]]) {
                        throw new Error('Could not resolve collection ' + this.collections[i] + ' for collection view ' + options.name);
                    }
                }
                this.collections = collections;
            } else if (_.isString(this.collection)) {
                this.collection = options.ctl.ctx.collections[this.collection];
                if (!this.collection) {
                    throw new Error('Could not resolve collection ' + this.collection + ' for collection view ' + options.name);
                }
            } else {
                throw new Error('No collection associated with collection view ' + options.name);
            }
            flexo.CollectionView.call(this, options);
        }
125040
async function isInPattern(filePath, pattern, options, callback) {
  if (!pattern) {
    callback(null, false);
  } else {
    options = options || {};
    // var result = false;
    var isDirectory = await exports.isDirectory(filePath);
    if (isDirectory) {
      options.includeFolders = true;
    }
    if (!Array.isArray(pattern)) {
      var inPattern = await isInPatternSingle(filePath, pattern, options);
      callback(null, inPattern);
    } else {
      var isIn = false;
      for (const patt of pattern) {
        var inPattern = await isInPatternSingle(filePath, patt, options);
        if (inPattern) {
          isIn = true;
        }
      }
      callback(null, isIn);
    }
  }
}
1188641
function Matcher(options) {

        options = options || {};

        /**
         * ### Matcher.x
         *
         * The row-index of the last returned match by Matcher.getMatch
         *
         * @see Matcher.getMatch
         */
        this.x = null;

        /**
         * ### Matcher.y
         *
         * The column-index of the last returned match by Matcher.getMatch
         *
         * @see Matcher.getMatch
         */
        this.y = null;

        /**
         * ### Matcher.matches
         *
         * Nested array of matches (with position-numbers)
         *
         * Nests a new array for each round, and within each round
         * individual matches are also array. For example:
         *
         * ```javascript
         *
         * // Matching array.
         * [
         *
         *   // First round.
         *   [ [ p1, p2 ], [ p3, p4 ], ... ],
         *
         *   // Second round.
         *   [ [ p2, p3 ], [ p4, p1 ], ... ],
         *
         *   // Further rounds.
         * ];
         * ```
         *
         * @see Matcher.setMatches
         */
        this.matches = null;

        /**
         * ### Matcher.resolvedMatches
         *
         * Nested array of matches (with id-strings)
         *
         * Exactly Matcher.matches, but with with ids instead of numbers
         *
         * This method is used both by getMatch and getMatchObject (if
         * a single match is requested).
         *
         * @see Matcher.matches
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.resolvedMatchesById
         * @see Matcher.setIds
         * @see Matcher.setAssignerCb
         * @see Matcher.match
         */
        this.resolvedMatches = null;

        /**
         * ### Matcher.resolvedMatchesObj
         *
         * Array of maps id to partner, one map per round
         *
         * ```javascript
         *
         * // Matching array.
         * [
         *
         *   // First round.
         *   { p1: 'p2', p2: 'p1', p3: 'p4', p4: 'p3',  ... },
         *
         *   // Second round.
         *   { p2: 'p3', p3: 'p2', p4: 'p1', p1: 'p4',  ... },
         *
         *   // Further rounds.
         * ];
         * ```
         *
         * @see Matcher.resolvedMatches
         * @see Matcher.resolvedMatchesById
         * @see Matcher.setIds
         * @see Matcher.match
         */
        this.resolvedMatchesObj = null;

        /**
         * ### Matcher.resolvedMatchesById
         *
         * Maps ids to a sequence of matches
         *
         * ```javascript
         *
         * // Matching object.
         * {
         *
         *   // All rounds.
         *   p1: [ 'p2', 'p4', ... ],
         *   p2: [ 'p1', 'p3', ... ],
         *   p3: [ 'p4', 'p2', ... ],
         *   p4: [ 'p3', 'p1', ... ]
         *   ...
         *
         * };
         * ```
         *
         * @see Matcher.resolvedMatches
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.setIds
         * @see Matcher.match
         */
        this.resolvedMatchesById = null;

        /**
         * ### Matcher.ids
         *
         * Array ids to match
         *
         * @see Matcher.setIds
         */
        this.ids = null;

        /**
         * ### Matcher.ids
         *
         * Array mapping each ordinal position to an id
         *
         * @see Matcher.ids
         * @see Matcher.assignerCb
         */
        this.assignedIds = null;

        /**
         * ### Matcher.idsMap
         *
         * Map ids to match
         *
         * @see Matcher.setIds
         */
        this.idsMap = null;

        /**
         * ### Matcher.assignedIdsMap
         *
         * Map ids to ordinal position in matches
         *
         * @see Matcher.idsMap
         * @see Matcher.assignedIds
         */
        this.assignedIdsMap = null;

        /**
         * ### Matcher.assignerCb
         *
         * Callback that assigns ids to positions
         *
         * An assigner callback must take as input an array of ids,
         * reorder them according to some criteria, and return it.
         * The order of the items in the returned array will be used to
         * match the numbers in the `matches` array.
         *
         * @see Matcher.ids
         * @see Matcher.matches
         * @see Matcher.assignedIds
         */
        this.assignerCb = Matcher.randomAssigner;

        /**
         * ## Matcher.missingId
         *
         * An id used to replace missing players ids
         */
        this.missingId = Matcher.missingId;

        /**
         * ## Matcher.missingId
         *
         * An id used by matching algorithms to complete unfinished matches
         */
        this.bye = Matcher.bye;

        /**
         * ## Matcher.doObjLists
         *
         * Flag that obj lists should be created when `match` is invoked
         *
         * @see Matcher.resolvedMatchesObj
         * @see Matcher.matcher
         */
        this.doObjLists = true;

        /**
         * ## Matcher.doIdLists
         *
         * Flag that id lists should be created when `match` is invoked
         *
         * @see Matcher.resolvedMatchesById
         * @see Matcher.matcher
         */
        this.doIdLists = true;

        /**
         * ## Matcher.doRoles
         *
         * Flag that roles should be assigned when `match` is invoked
         *
         * Requires roles to be set, otherwise an error is thrown
         *
         * @see Matcher.roles
         * @see Matcher.roler
         * @see Matcher.matcher
         */
        this.doRoles = false;

        /**
         * ## Matcher.roler
         *
         * Handles assigning roles to matches
         *
         * If null here, is initialized by `init` if doRoles is TRUE.
         *
         * @see Matcher.doRoles
         * @see Matcher.init
         */
        this.roler = options.roler || null;

        /**
         * ## Matcher.roles
         *
         * Roles map created if `doRoles` is TRUE
         *
         * @see Matcher.doRoles
         * @see Matcher.roler
         * @see Matcher.matcher
         */
        this.roler = options.roler || null;

        // Init.
        this.init(options);
    }
74883
function compose(patterns, options, matcher) {
  let matchers;

  return memoize('compose', String(patterns), options, function() {
    return function(file) {
      // delay composition until it's invoked the first time,
      // after that it won't be called again
      if (!matchers) {
        matchers = [];
        for (var i = 0; i < patterns.length; i++) {
          matchers.push(matcher(patterns[i], options));
        }
      }

      let len = matchers.length;
      while (len--) {
        if (matchers[len](file) === true) {
          return true;
        }
      }
      return false;
    };
  });
}