aureooms/node-recursive-build

View on GitHub
js/index.js

Summary

Maintainability
C
1 day
Test Coverage

'use strict';


/**
 * recbuild default options.
 *
 * @param name name of global namespace
 * @param index name of index files
 * @param intro name of intro files
 * @param outro name of outro files
 * @param struct name of struct files
 * @param rec whether dirs should have their own namespace
 * @param flat whether files should have their own namespace
 * @param strict whether the global namespace should be in strict mode
 * @param debug whether debug messages should be printed
 *
 *
 */

var dflt = {
    fullname : 'author-js-lib',
    name : 'lib',
    index : 'index.js',
    intro : 'intro.js',
    outro : 'outro.js',
    struct : 'struct.json',
    rec : true,
    flat : true,
    strict : true,
    debug : false
};


/**
 * recbuild template.
 *
 * @param <opt> options
 *
 */

var recbuild_t = function(opt) {

    var fs = require('fs');
    var util = require('util');
    var extend = require('node.extend');

    opt = extend({}, dflt, opt);

    // avoid variable names starting with numbers
    if ( opt.name[0] >= "0" && opt.name[0] <= "9" ) opt.name = "_" + opt.name ;

    var __INTRO__ = '( function ( ) {\n\n' +
        (opt.strict ? "'use strict' ;\n\n" : '' ) +
        'var definition = function ( exports , undefined ) {\n\n' ;
    var __INTRO2_ = '( function ( exports ) {\n\n';
    var __OUTRO__ = util.format(
        'return exports ;\n} ;\n' +
        'if ( typeof exports === "object" ) {\n' +
        '\tdefinition( exports ) ;\n' +
        '}\n' +
        'else if ( typeof define === "function" && define.amd ) {\n' +
        '\tdefine( "%s" , [ ] , function ( ) { return definition( { } ) ; } ) ;\n' +
        '}\n' +
        'else if ( typeof window === "object" && typeof window.document === "object" ) {\n' +
        '\tdefinition( window["%s"] = { } ) ;\n' +
        '}\n' +
        'else console.error( "unable to detect type of module to define for %s") ;\n' +
        '} )( ) ;',
    opt.fullname , opt.name , opt.fullname ) ;
    var __OUTRO2_ = function(sub){ return util.format("} )( exports['%s'] = { } ) ;", sub); };

    // DEBUG
    var msg_t = function(type){
        return function(){
            console.log([
                opt.fullname,
                type,
                util.format.apply(this, arguments)
            ].join(' '));
        };
    };

    var info = opt.debug ? msg_t('info') : function(){};
    var action = opt.debug ? msg_t('action') : function(){};

    var recbuild = function(dir, exports, level, fhandle, rhandle, origin) {

        if (origin === undefined) origin = true;

        var intro = false, outro = false, el = [];

        fs.readdirSync(dir).forEach(function(file) {

            if (file === opt.index || file === opt.struct) return;
            else if (file === opt.intro) intro = true;
            else if (file === opt.outro) outro = true;
            else el.push(file);

        });

        el.sort();

        if (origin) {
            if (intro) fhandle(dir + opt.intro);
            else       rhandle(__INTRO__);
        }

        el.forEach(function(e){
            var path = dir + e;

            if (fs.lstatSync(path).isDirectory()) {
                var child;
                if (fs.existsSync(path + '/' + opt.struct)) {
                    info("struct file found in '%s'", path);
                    var struct = JSON.parse( fs.readFileSync( path + '/' + opt.struct , "utf8" ) ) ;
                    child = recbuild_t(struct);

                }
                else{
                    // DEBUG
                    info("no struct file found in dir '%s'", path);
                    action(
                        "@ recbuild('%s/', %s, %d);",
                        path,
                        opt.rec ? util.format("exports['%s'] = { }", e) : 'exports',
                        level + 1
                    );

                    child = recbuild;

                }

                rhandle('/* ' + path + ' */');

                if (fs.existsSync(path + '/' + opt.intro)) fhandle(path + '/' + opt.intro);
                else if (opt.rec) rhandle(__INTRO2_);
                child(path + '/', e, level + 1, fhandle, rhandle, false);
                if (fs.existsSync(path + '/' + opt.outro)) fhandle(path + '/' + opt.outro);
                else if (opt.rec) rhandle(__OUTRO2_(e));
            }
            else if (level >= 0 && e.match(/.+\.js$/g) !== null) {

                info(".js file '%s'", path);
                rhandle('/* ' + path + ' */');

                if(opt.flat){

                    action("@ extend(true, exports, require('%s'));", path);

                    fhandle(path);
                }
                else{
                    var name = e.substr(0, e.length - 3);

                    action("@ exports['%s'] = require('%s');", name, path);

                    rhandle(__INTRO2_);
                    fhandle(path);
                    rhandle(__OUTRO2_(name));
                }

            }
        });

        if (origin) {
            if (outro) fhandle(dir + opt.outro);
            else       rhandle(__OUTRO__);
        }
    };

    return recbuild;

};

module.exports = recbuild_t;