lib/fume.js
function Fume(sources, config) {

        config = config || {};
        config.nameTagPrefix = config.nameTagPrefix || NAME_TAG_PREFIX;
        config.preferTagPrefix = config.preferTagPrefix || PREFER_TAG_PREFIX;
        config.amdTagPrefix = config.amdTagPrefix || AMD_TAG_PREFIX;
        config.cjsTagPrefix = config.cjsTagPrefix || CJS_TAG_PREFIX;
        this.config = config;

        var nameTagRe = new RegExp(
                    "^.*?" +
                    this.config.nameTagPrefix +
                    "\\s*(\\w+)\\W*$"
            ),
            preferTagRe = new RegExp(
                    "^.*?" +
                    this.config.preferTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            ),
            amdTagRe = new RegExp(
                    "^.*?" +
                    this.config.amdTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            ),
            cjsTagRe = new RegExp(
                    "^.*?" +
                    this.config.cjsTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            );

        // parse the sources and get needed information
        sources.forEach(function (source) {

            source.dir = path.dirname(source.path);
            source.tree = parse(source.code);
            source.factory = source.tree.body[0];
            source.amdMaps = {};
            source.cjsMaps = {};
            source.preferMaps = {};

            if (source.factory.type !== 'FunctionDeclaration')
                throw Error("Expected a factory function at '" +
                    source.path + "'");

            source.args = source.factory.params;

            // get comment lines before the factory function:
            var m = source.code.match(cmtLinesRe);
            // this RegExp should always match
            if (!m) throw Error("Unable to parse pre-factory annotation");
            var cLines = m[1].split(/[\n\r]/);

            // extract annotation from the comment lines:
            cLines.forEach(function (line) {

                // attempt to detect the factory name:

                // first try:
                // the parse tree doesn't include comments, so we need to look
                // at the source. a simple regex to detect the @name tag
                // anywhere before the factory function:
                var m = line.match(nameTagRe);
                if (m) source.name = m[1];

                // second try:
                // if name tag isn't specified, take the function's name:
                source.name = source.name || source.factory.id.name;

                // check if this name is already taken by another factory:
                if (sources.some(function (other) {
                    return other !== source &&
                        other.dir === source.dir &&
                        other.name === source.name;
                }))
                    throw Error(
                            "Factory path '" +
                            path.join(source.dir, source.name) +
                            "' cannot be specified more than once"
                    );

                // detect prefer mapping:
                m = line.match(preferTagRe);
                if (m) source.preferMaps[m[1]] = m[2];

                // detect AMD mapping:
                m = line.match(amdTagRe);
                if (m) source.amdMaps[m[1]] = m[2];

                // detect CJS mapping:
                m = line.match(cjsTagRe);
                if (m) source.cjsMaps[m[1]] = m[2];

            });

        });

        // detect sibling dependencies
        sources.forEach(function (source) {

            source.factory.params.forEach(function (param) {

                // find the siblings which can qualify as this dependency
                param.candidatePaths = sources.filter(function (other) {
                    return other !== source && other.name === param.name;
                }).map(function (other) {
                    return other.path;
                });

            });

        });

        return sources.reduce(function (p, e, i, o) {
            p[e.path] = new Factory(e);
            return p;
        }, {});

    }
function Fume(sources, config) {

        config = config || {};
        config.nameTagPrefix = config.nameTagPrefix || NAME_TAG_PREFIX;
        config.preferTagPrefix = config.preferTagPrefix || PREFER_TAG_PREFIX;
        config.amdTagPrefix = config.amdTagPrefix || AMD_TAG_PREFIX;
        config.cjsTagPrefix = config.cjsTagPrefix || CJS_TAG_PREFIX;
        this.config = config;

        var nameTagRe = new RegExp(
                    "^.*?" +
                    this.config.nameTagPrefix +
                    "\\s*(\\w+)\\W*$"
            ),
            preferTagRe = new RegExp(
                    "^.*?" +
                    this.config.preferTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            ),
            amdTagRe = new RegExp(
                    "^.*?" +
                    this.config.amdTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            ),
            cjsTagRe = new RegExp(
                    "^.*?" +
                    this.config.cjsTagPrefix +
                    "\\s*(\\S+)\\s+(\\S+)\\W*$"
            );

        // parse the sources and get needed information
        sources.forEach(function (source) {

            source.dir = path.dirname(source.path);
            source.tree = parse(source.code);
            source.factory = source.tree.body[0];
            source.amdMaps = {};
            source.cjsMaps = {};
            source.preferMaps = {};

            if (source.factory.type !== 'FunctionDeclaration')
                throw Error("Expected a factory function at '" +
                    source.path + "'");

            source.args = source.factory.params;

            // get comment lines before the factory function:
            var m = source.code.match(cmtLinesRe);
            // this RegExp should always match
            if (!m) throw Error("Unable to parse pre-factory annotation");
            var cLines = m[1].split(/[\n\r]/);

            // extract annotation from the comment lines:
            cLines.forEach(function (line) {

                // attempt to detect the factory name:

                // first try:
                // the parse tree doesn't include comments, so we need to look
                // at the source. a simple regex to detect the @name tag
                // anywhere before the factory function:
                var m = line.match(nameTagRe);
                if (m) source.name = m[1];

                // second try:
                // if name tag isn't specified, take the function's name:
                source.name = source.name || source.factory.id.name;

                // check if this name is already taken by another factory:
                if (sources.some(function (other) {
                    return other !== source &&
                        other.dir === source.dir &&
                        other.name === source.name;
                }))
                    throw Error(
                            "Factory path '" +
                            path.join(source.dir, source.name) +
                            "' cannot be specified more than once"
                    );

                // detect prefer mapping:
                m = line.match(preferTagRe);
                if (m) source.preferMaps[m[1]] = m[2];

                // detect AMD mapping:
                m = line.match(amdTagRe);
                if (m) source.amdMaps[m[1]] = m[2];

                // detect CJS mapping:
                m = line.match(cjsTagRe);
                if (m) source.cjsMaps[m[1]] = m[2];

            });

        });

        // detect sibling dependencies
        sources.forEach(function (source) {

            source.factory.params.forEach(function (param) {

                // find the siblings which can qualify as this dependency
                param.candidatePaths = sources.filter(function (other) {
                    return other !== source && other.name === param.name;
                }).map(function (other) {
                    return other.path;
                });

            });

        });

        return sources.reduce(function (p, e, i, o) {
            p[e.path] = new Factory(e);
            return p;
        }, {});

    }
function Fume ( sources , config ) { config = config || { } ; config . nameTagPrefix = config . nameTagPrefix || NAME_TAG_PREFIX ; config . preferTagPrefix = config . preferTagPrefix || PREFER_TAG_PREFIX ; config . amdTagPrefix = config . amdTagPrefix || AMD_TAG_PREFIX ; config . cjsTagPrefix = config . cjsTagPrefix || CJS_TAG_PREFIX ; this . config = config ; var nameTagRe = new RegExp ( "^.*?" + this . config . nameTagPrefix + "\\s*(\\w+)\\W*$" ) , preferTagRe = new RegExp ( "^.*?" + this . config . preferTagPrefix + "\\s*(\\S+)\\s+(\\S+)\\W*$" ) , amdTagRe = new RegExp ( "^.*?" + this . config . amdTagPrefix + "\\s*(\\S+)\\s+(\\S+)\\W*$" ) , cjsTagRe = new RegExp ( "^.*?" + this . config . cjsTagPrefix + "\\s*(\\S+)\\s+(\\S+)\\W*$" ) ; // parse the sources and get needed information sources . forEach ( function ( source ) { source . dir = path . dirname ( source . path ) ; source . tree = parse ( source . code ) ; source . factory = source . tree . body [ 0 ] ; source . amdMaps = { } ; source . cjsMaps = { } ; source . preferMaps = { } ; if ( source . factory . type !== 'FunctionDeclaration' ) throw Error ( "Expected a factory function at '" + source . path + "'" ) ; source . args = source . factory . params ; // get comment lines before the factory function: var m = source . code . match ( cmtLinesRe ) ; // this RegExp should always match if ( ! m ) throw Error ( "Unable to parse pre-factory annotation" ) ; var cLines = m [ 1 ] . split ( / [\n\r] / ) ; // extract annotation from the comment lines: cLines . forEach ( function ( line ) { // attempt to detect the factory name: // first try: // the parse tree doesn't include comments, so we need to look // at the source. a simple regex to detect the @name tag // anywhere before the factory function: var m = line . match ( nameTagRe ) ; if ( m ) source . name = m [ 1 ] ; // second try: // if name tag isn't specified, take the function's name: source . name = source . name || source . factory . id . name ; // check if this name is already taken by another factory: if ( sources . some ( function ( other ) { return other !== source && other . dir === source . dir && other . name === source . name ; } ) ) throw Error ( "Factory path '" + path . join ( source . dir , source . name ) + "' cannot be specified more than once" ) ; // detect prefer mapping: m = line . match ( preferTagRe ) ; if ( m ) source . preferMaps [ m [ 1 ] ] = m [ 2 ] ; // detect AMD mapping: m = line . match ( amdTagRe ) ; if ( m ) source . amdMaps [ m [ 1 ] ] = m [ 2 ] ; // detect CJS mapping: m = line . match ( cjsTagRe ) ; if ( m ) source . cjsMaps [ m [ 1 ] ] = m [ 2 ] ; } ) ; } ) ; // detect sibling dependencies sources . forEach ( function ( source ) { source . factory . params . forEach ( function ( param ) { // find the siblings which can qualify as this dependency param . candidatePaths = sources . filter ( function ( other ) { return other !== source && other . name === param . name ; } ) . map ( function ( other ) { return other . path ; } ) ; } ) ; } ) ; return sources . reduce ( function ( p , e , i , o ) { p [ e . path ] = new Factory ( e ) ; return p ; } , { } ) ; }
Parse the list of sources
Parse the list of sources