<commit_before>'use strict';

var checker     = require('../util/check-wrapper');
var lang        = require('../util/lang');
var wrapper     = require('../util/wrapper');

var uglifyjs    = require('uglify-js');
var node_path   = require('path');
var fs          = require('fs-sync');
var profile     = require('cortex-profile');

var CORTEX_ROOT = profile.option('cortex_root');
var CORTEX_BUILT_ROOT = profile.option('built_root');

var ERROR_MESSAGE = {
    USE_PARENT_DIRECTORY: 'Modules "{mod}" outside the folder of main entrance may cause serious further problems.',
    NO_VERSION: 'Exact version of dependency "{mod}" has not defined in package.json. Use "ctx install {mod} --save"',
    SYNTAX_PARSE_ERROR:  'Source file "{path}" syntax parse error: "{err}"',
    NOT_FOUND: 'Source file "{path}" not found',
    ALREADY_WRAPPED: 'Source file "{path}" already has module wrapping, which will cause further problems',
    WRONG_USE_REQUIRE: 'Source file "{path}": `require` should have one and only one string as an argument',
    NO_PACKAGE_MAIN: 'Property "main" not found in package.json'
};

var REGEX_ENDS_WITH_JS = /\.js$/;

var ENSURE_PROPERTY = {
    name: {
        err: 'package.name must be defined'
    },

    version: {
        err: 'package.version must be defined'
    }
};

function check_package(pkg, on_error){
    var pass = true;

    Object.keys(ENSURE_PROPERTY).forEach(function(key, config) {
        if(!pkg[key]){
            pass = false;
            on_error(config.err);
        }

    });

    return pass;
}

function is_relative_path(str){
    return str.indexOf('../') === 0 || str.indexOf('./') === 0;
}

function fail(template, obj){
    process.stdout.write(lang.template(template, obj) + '\n');
    process.exit(1);
}

function warn(template, obj){
    process.stdout.write('Warn: ' + lang.template(template, obj) + '\n');
}

// with no fault tolerance with arguments
// no arguments overloading

// @param {Object} options
// - cwd: {node_path} absolute dir
// - separator: {string}
// - define: {string}
// - output: {node_path} the path of the ouput file, ending with '.js'
// - dist: {node_path}
// - files: {Array.<string>} array of absolute file paths to be built all of which will be built into options.output
module.exports = function(options, callback) {
    var local_built_folder;
    var cwd = options.cwd;
    var pkg = fs.readJSON( node_path.join(options.cwd, 'package.json') );
    var separator = options.separator;

    // main entrance:
    // {
    //      main: 'test/fixtures/main.js',
    //      name: 'module'
    //      version: '0.0.1'
    // }
    //
    // expected
    //      src: ''
    //
    // unexpected:
    //      src: 'test/folder/module.js'    -> ../folder/module.js
    //      src: 'folder/folder/module.js'  -> ../../folder/folder/module.js

    if(
        !check_package(pkg, function(err) {
            callback('Package.json: ' + err);
        })
    ){
        return;
    }

    var name = pkg.name;
    var version = pkg.version;

    // if options.dist exists, skip building
    if(options.dist){
        local_built_folder = options.dist;

    }else{
        // ROOT/test/fixtures/build/index.js
        var dest = options.output;

        // rebuild
        fs.delete(dest);

        local_built_folder = node_path.dirname(dest);

        var files = options.files;
        var dependencies = pkg.cortexExactDependencies || {};

        // -> 'module@0.0.1'
        var main_id = name + separator + version;

        // -> 'module@0.0.1/'
        var main_id_dir = main_id;

        var pkg_main;

        if( !pkg.main ){
            if( fs.exists(cwd, 'index.js')  ){
                warn(ERROR_MESSAGE.NO_PACKAGE_MAIN);
                warn('Fallback to CWD/index.js.')
                pkg_main = node_path.join(cwd, 'index.js');

            }else{
                fail(ERROR_MESSAGE.NO_PACKAGE_MAIN);
            }

        }else{
            // absolute pkg.main path
            pkg_main = node_path.join(cwd, pkg.main);
        }

        var pkg_main_dir = node_path.dirname(pkg_main);

        if(!REGEX_ENDS_WITH_JS.test(pkg_main)){
            pkg_main += '.js';
        }

        // Iterate over all specified file groups.
        files.forEach(function(file_path) {
            var id;
            var relative_path;
            var relative_id;
            var relative_id_dir;

            if(file_path === pkg_main){
                id = main_id;
                relative_id_dir = './';

            }else{

                // file_path: 'ROOT/test/fixtures/folder/foo.js'
                // -> 'folder/foo.js'
                relative_path = node_path.relative(pkg_main_dir, file_path);

                if(relative_path.indexOf('../') === 0){
                    fail(ERROR_MESSAGE.USE_PARENT_DIRECTORY, {mod: file_path});
                    return;
                }

                // -> 'folder/foo'
                relative_id = relative_path.replace(REGEX_ENDS_WITH_JS, '');

                // -> 'folder'
                relative_id_dir = node_path.dirname(relative_id);

                // -> 'module@0.0.1/folder/foo'
                id = node_path.join(main_id_dir, relative_id);
            }

            // Warn on and remove invalid source files (if nonull was set).
            if (!fs.exists(file_path)) {
                warn(ERROR_MESSAGE.NOT_FOUND, {path: file_path});
                return;
            }

            // read file
            var content = fs.read(file_path);
            var ast;

            // syntax parse may cause a javascript error
            try{
                ast = uglifyjs.parse(content);
            }catch(e){
                fail(ERROR_MESSAGE.SYNTAX_PARSE_ERROR, {path: file_path, err: e.toString()});
                return;
            }

            if(!checker.check(ast)){
                warn(ERROR_MESSAGE.ALREADY_WRAPPED, {path: file_path});
                return;
            }

            var deps = [];

            // use syntax analytics
            var walker = new uglifyjs.TreeWalker(function(node) {

                if(node.CTOR === uglifyjs.AST_Call){
                    var expression = node.expression;
                    var args = node.args;

                    if(expression.CTOR === uglifyjs.AST_SymbolRef && expression.name === 'require'){
                        var dep = args[0];

                        if(args.length === 1 && dep.CTOR === uglifyjs.AST_String){

                            deps.push(dep.value);

                        }else{
                            fail(ERROR_MESSAGE.WRONG_USE_REQUIRE, {path: file_path});
                        }
                    }
                }
            });

            ast.walk(walker);

            // suppose:
            //      ['./a', '../../b']
            // `deps` may have relative items, normalize them
            deps = deps.map(function(dep){

                if(is_relative_path(dep)){

                    // ./a -> folder/a
                    // ../../b -> ../b
                    var relative_dep_id = node_path.normalize( node_path.join(relative_id_dir, dep) );

                    if(relative_dep_id.indexOf('../') === 0){
                        fail(ERROR_MESSAGE.USE_PARENT_DIRECTORY, {mod: dep})
                    }

                    // -> module@0.0.1/folder/a
                    // maintain './a' if relative dependency
                    // dep

                }else{
                    var version = dependencies[dep];

                    // TODO:
                    // check if absolute version
                    if(!version){
                        fail(ERROR_MESSAGE.NO_VERSION, {mod: dep, path: file_path});
                    }

                    dep += separator + version;
                }

                return dep;
            });

            var wrapped = wrapper({
                define  : options.define,
                code    : content,
                deps    : deps,
                id      : id
            });

            if(wrapped){
                var dir = node_path.dirname(dest);

                if(!fs.exists(dir)){
                    fs.mkdir(dir);
                }

                fs.write(dest, wrapped + '\n\n', {
                    flag: 'a+'
                });

                // Print a success message.
                process.stdout.write('Append wrapped "' + file_path + '" to file "' + dest + '".\n');
            }
        });

    }// end if options.dist

    if(options.publish){
        // build move
        var stable_modules = fs.readJSON( node_path.join(CORTEX_ROOT, 'stable_modules') );
        var stable_versions = stable_modules[name] || [];

        // TODO:
        // checking global .cortex folder
        var global_built_folder = node_path.join(CORTEX_BUILT_ROOT, name, version);

        var global_built_folder_exists;

        if(fs.exists(local_built_folder)){

            if(
                // if already built
                !(global_built_folder_exists = fs.exists( global_built_folder )) ||

                // never replace stable build folders
                stable_versions.indexOf(version) === -1
            ){
                global_built_folder_exists && fs.delete(global_built_folder, {
                    force: true
                });

                process.stdout.write('Copying directory "' + local_built_folder + '/".\n');

                fs.copy(local_built_folder, global_built_folder, {
                    force: true
                });

            }else{
                warn('There\'s already stable built "' + name + '@' + version + '" found');
            }

        }else{
            warn('Build folder not found, skip building "' + name + '@' + version + '"');
        }
    }

    process.stdout.write('Success!\n');

    callback && callback();
};
<commit_msg>split big functions; fixes #52; fixes #53; fixes #55<commit_after>'use strict';

module.exports = build;

var checker     = require('../util/check-wrapper');
var lang        = require('../util/lang');
var wrapper     = require('../util/wrapper');

var i18n        = require('../i18n');
var message     = i18n.require('command-build');

var uglifyjs    = require('uglify-js');
var node_path   = require('path');
var fs          = require('fs-sync');
var profile     = require('cortex-profile');
var async       = require('async');

var CORTEX_ROOT         = profile.option('cortex_root');
var CORTEX_BUILT_ROOT   = profile.option('built_root');

var REGEX_ENDS_WITH_JS = /\.js$/;

var ENSURE_PROPERTY = {
    name: {
        err: 'package.name must be defined'
    },

    version: {
        err: 'package.version must be defined'
    }
};

function check_package(pkg){
    var err;

    Object.keys(ENSURE_PROPERTY).some(function(key, config) {
        if(!pkg[key]){
            err = config.err;
        }

        return err;
    });

    return err;
}

function is_relative_path(str){
    return str.indexOf('../') === 0 || str.indexOf('./') === 0;
}

// with no fault tolerance with arguments
// no arguments overloading

// @param {Object} options
// - cwd: {node_path} absolute dir
// - separator: {string}
// - define: {string}
// - output: {node_path} the path of the ouput file, ending with '.js'
// - dist: {node_path}
// - files: {Array.<string>} array of absolute file paths to be built all of which will be built into options.output
function build(options, callback) {
    var local_built_folder;
    var cwd = options.cwd;
    var pkg = fs.readJSON( node_path.join(options.cwd, 'package.json') );
    var separator = options.separator;

    // main entrance:
    // {
    //      main: 'test/fixtures/main.js',
    //      name: 'module'
    //      version: '0.0.1'
    // }
    //
    // expected
    //      src: ''
    //
    // unexpected:
    //      src: 'test/folder/module.js'    -> ../folder/module.js
    //      src: 'folder/folder/module.js'  -> ../../folder/folder/module.js

    var pkg_error = check_package(pkg);
    if(pkg_error){
        return callback(pkg_error);
    }

    var name = pkg.name;
    var version = pkg.version;

    // if options.dist exists, skip building
    if(options.dist){
        local_built_folder = options.dist;

    }else{
        // ROOT/test/fixtures/build/index.js
        var dest = options.output;

        // rebuild
        fs.delete(dest);

        local_built_folder = node_path.dirname(dest);

        var files = options.files;
        var dependencies = pkg.cortexExactDependencies || {};

        // -> 'module@0.0.1'
        var main_id = name + separator + version;

        // -> 'module@0.0.1/'
        var main_id_dir = main_id;

        var pkg_main;

        if( !pkg.main ){
            if( fs.exists(cwd, 'index.js')  ){
                logger.warn(ERROR_MESSAGE.NO_PACKAGE_MAIN);
                logger.warn('Fallback to CWD/index.js.')
                pkg_main = node_path.join(cwd, 'index.js');

            }else{
                return callback(ERROR_MESSAGE.NO_PACKAGE_MAIN);
            }

        }else{
            // absolute pkg.main path
            pkg_main = node_path.join(cwd, pkg.main);
        }

        var pkg_main_dir = node_path.dirname(pkg_main);

        if(!REGEX_ENDS_WITH_JS.test(pkg_main)){
            pkg_main += '.js';
        }

        // Iterate over all specified file groups.
        files.forEach(function(file_path) {

        });

    }// end if options.dist

    callback && callback();
};

build.prepare_data = function(options, callback) {

}

// generate the standard identifier of the current file
// @param {Object} options
// - file: {string} the pathname of the current file
// - main_file: {string} absolute url of the `main` property in package.json
// - main_dir: {string} dirname of main_file
// - main_id: {string} the standard identifier of the main module
build.generate_identifier = function(options, callback) {
    // the exact identifier
    var id;
    var file = options.file;

    // the relative dirname of the current module to the main module
    var relative_dir;

    if(file === options.main_file){
        id = options.main_id;
        relative_dir = '.';

    }else{
        var main_dir = options.main_dir;

        // the relative path of the current module to the main module
        // main_path: 'test/fixtures/main.js',
        // path: 'ROOT/test/fixtures/folder/foo.js'
        // -> 'folder/foo.js'
        var relative_path = node_path.relative(main_dir, file);

        if(relative_path.indexOf('../') === 0){
            return callback( logger.template(ERROR_MESSAGE.USE_PARENT_DIRECTORY, {mod: file}) );
        }

        // -> 'folder/foo'
        var relative_id = relative_path.replace(REGEX_ENDS_WITH_JS, '');

        // -> 'folder'
        relative_dir = node_path.dirname(relative_id);

        // -> 'module@0.0.1/folder/foo'
        id = node_path.join(main_dir, relative_id);
    }

    callback(null, {
        id: id,
        relative_dir: relative_dir
    });
};

build.write_module = function(options, callback) {
    // Warn on and remove invalid source files (if nonull was set).
    if (!fs.exists(file_path)) {
        logger.warn(ERROR_MESSAGE.NOT_FOUND, {path: file_path});
        return;
    }

    // read file
    var content = fs.read(file_path);

    var ast;

    // syntax parse may cause a javascript error
    try{
        ast = uglifyjs.parse(content);
    }catch(e){
        fail(ERROR_MESSAGE.SYNTAX_PARSE_ERROR, {path: file_path, err: e.toString()});
        return;
    }

    if(!checker.check(ast)){
        logger.warn(ERROR_MESSAGE.ALREADY_WRAPPED, {path: file_path});
        return;
    }

    var wrapped = wrapper({
        define  : options.define,
        code    : content,
        deps    : deps,
        id      : id
    });

    if(wrapped){
        var dir = node_path.dirname(dest);

        if(!fs.exists(dir)){
            fs.mkdir(dir);
        }

        fs.write(dest, wrapped + '\n\n', {
            flag: 'a+'
        });

        // Print a success message.
        process.stdout.write('Append wrapped "' + file_path + '" to file "' + dest + '".\n');
    }
}

// parse dependencies from the Abstract Syntax Tree
// @param {uglifyjs.AST_Node} ast
build.parse_dependencies = function(ast, callback) {
    var deps = [];
    var err;

    // use syntax analytics
    var walker = new uglifyjs.TreeWalker(function(node) {
        if(!err && node.CTOR === uglifyjs.AST_Call){
            var expression = node.expression;
            var args = node.args;

            if(expression.CTOR === uglifyjs.AST_SymbolRef && expression.name === 'require'){
                var dep = args[0];

                // require('async')
                if(args.length === 1 && dep.CTOR === uglifyjs.AST_String){
                    deps.push(dep.value);

                }else{
                    err = logger.template( ERROR_MESSAGE.WRONG_USE_REQUIRE, {path: file_path} );
                }
            }
        }
    });

    ast.walk(walker);

    if(err){
        callback(err);
    }else{
        callback(null, {
            deps: deps
        });
    }
};

// resolve the ids of the dependencies array into standard identifers
// @param {Object} options
// - dependencies: {Array} array of dependencies of the current module
// - pkg_dependencies: {Object} 'dependencies' of package.json
// - relative_dir: {string} the standard id of the current module. `options.relative_dir` is only used for checking
// - separator: {string} @

// @returns {string} resolved dependencies
build.resolve_dependencies = function(options, callback) {
    var relative_dir = options.relative_dir;

    // suppose:
    //      ['./a', '../../b']
    // `options.dependencies` may have relative items, validate them
    var deps = options.dependencies;

    var i = 0;
    var length = deps.length;
    var dep;
    var resolved = [];

    var err;

    for(; i < length; i ++){
        dep = deps[i];

        if(is_relative_path(dep)){

            // ./a -> folder/a
            // ../../b -> ../b
            var relative_dep_id = node_path.normalize( node_path.join(relative_dir, dep) );

            // it will cause serious problem if we depend on the modules outside the directory of the main module
            if(relative_dep_id.indexOf('../') === 0){
                err = logger.template(ERROR_MESSAGE.USE_PARENT_DIRECTORY, {mod: dep}) );
                break;

            } // else{
                // -> module@0.0.1/folder/a
                // maintain './a' if relative dependency
            // }

            // we only check relative modules but not change them
            resolved[i] = dep;

        // foreign modules
        }else{
            var version = dependencies[dep];

            if(!version){
                err = logger.template( ERROR_MESSAGE.NO_VERSION, {mod: dep, path: file_path} );
                break
            }

            dep += options.separator + version;
        }
    }

    if(err){
        callback(err);
    }else{
        callback(null, {
            dependencies: resolved
        });
    }
};

// publish modules to local server
// @param {Object} options
build.publish = function(options, callback) {
    // build move
    var stable_modules = fs.readJSON( node_path.join(CORTEX_ROOT, 'stable_modules') );
    var stable_versions = stable_modules[name] || [];

    // TODO:
    // checking global .cortex folder
    var global_built_folder = node_path.join(CORTEX_BUILT_ROOT, name, version);

    var global_built_folder_exists;

    if(fs.exists(local_built_folder)){

        if(
            // if already built
            !(global_built_folder_exists = fs.exists( global_built_folder )) ||

            // never replace stable build folders
            stable_versions.indexOf(version) === -1
        ){
            global_built_folder_exists && fs.delete(global_built_folder, {
                force: true
            });

            process.stdout.write('Copying directory "' + local_built_folder + '/".\n');

            fs.copy(local_built_folder, global_built_folder, {
                force: true
            });

        }else{
            logger.warn('There\'s already stable built "' + name + '@' + version + '" found');
        }

    }else{
        logger.warn('Build folder not found, skip building "' + name + '@' + version + '"');
    }
}
<|endoftext|>


<commit_before>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

  /*********************************************************************************/

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      /* solve using filter() & all() / any() */

      var nutlessProducts = _(products).filter(function (x) {return x.containsNuts === false});
      var noMushrooms = function (x) {return x!=="mushrooms"};

      for (var i=0; i<nutlessProducts.length; i++) {
        if _(nutlessProducts[i].ingredients).all(noMushrooms) {
          productsICanEat.push(nutlessProducts[i]);
        }
      }

      expect(productsICanEat.length).toBe(1);
  });

  /*********************************************************************************/

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(233168);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var nums = _.range(1000);

    var sum = _(nums).reduce(function(memo,x){
        if (x % 3===0 || x % 5 ===0) {
          return memo+x;
        }
        else {return memo}

    });

     /* try chaining range() and reduce() */
     /*I couldn't figure out how to chain the range() function because it doesn't take an array argument */

    expect(233168).toBe(sum);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<commit_msg>Added memo argument to reduce function in "adding multiples of 3 or 5" solution, solved "count ingredient occurrence" problem<commit_after>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

  /*********************************************************************************/

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      /* solve using filter() & all() / any() */

      var nutlessProducts = _(products).filter(function (x) {return x.containsNuts === false});
      var noMushrooms = function (x) {return x!=="mushrooms"};

      for (var i=0; i<nutlessProducts.length; i++) {
        if _(nutlessProducts[i].ingredients).all(noMushrooms) {
          productsICanEat.push(nutlessProducts[i]);
        }
      }

      expect(productsICanEat.length).toBe(1);
  });

  /*********************************************************************************/

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(233168);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var nums = _.range(1000);

    var sum = _(nums).reduce(function(memo,x){
        if (x % 3===0 || x % 5 ===0) {
          return memo+x;
        }
        else {return memo}

    },0
  );

     /* try chaining range() and reduce() */
     /*I couldn't figure out how to chain the range() function because it doesn't take an array argument */

    expect(233168).toBe(sum);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */
    var result = _(products).chain()
              .map(function(product) {return product.ingredients})
              .flatten()
              .reduce(function(memo,x){
                if (x === "mushrooms") {
                  memo++;

                }
                return memo;
              }, 0)
              .value();
    ingredientCount["mushrooms"] = result;

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<|endoftext|>


<commit_before>define(["requirejs-dplugins/has"], function (has) {
	// Flag for whether to create background iframe behind popups like Menus and Dialog.
	// A background iframe is useful to prevent problems with popups appearing behind applets/pdf files.
	has.add("config-bgIframe", false);

	// Flag to enable advanced bidi support
	has.add("bidi", false);

	// Flag to enable inheritance direction from any ancestor
	has.add("inherited-dir", false);

	if (typeof window !== undefined) {
		// Returns the name of the method to test if an element matches a CSS selector.
		has.add("dom-matches", function () {
			var node = document.body;
			if (node.matches) {
				return "matches";
			}
			if (node.webkitMatchesSelector) {
				return "webkitMatchesSelector";
			}
			if (node.mozMatchesSelector) {
				return "mozMatchesSelector";
			}
			if (node.msMatchesSelector) {
				return "msMatchesSelector";
			}
		});

		// Does platform have native support for document.registerElement() or a polyfill to simulate it?
		has.add("document-register-element", !!document.registerElement);

		// Test for how to monitor DOM nodes being inserted and removed from the document.
		// For DOMNodeInserted events, there are two variations:
		//		"root" - just notified about the root of each tree added to the document
		//		"all" - notified about all nodes added to the document
		has.add("MutationObserver", window.MutationObserver ? "MutationObserver" : window.WebKitMutationObserver ?
			"WebKitMutationObserver" : "");
		has.add("DOMNodeInserted", function () {
			var root = document.createElement("div"),
				child = document.createElement("div"),
				sawRoot, sawChild;
			root.id = "root";
			child.id = "child";
			root.appendChild(child);

			function listener(event) {
				if (event.target.id === "root") {
					sawRoot = true;
				}
				if (event.target.id === "child") {
					sawChild = true;
				}
			}

			document.body.addEventListener("DOMNodeInserted", listener);
			document.body.appendChild(root);
			document.body.removeChild(root);
			document.body.removeEventListener("DOMNodeInserted", listener);
			return sawChild ? "all" : sawRoot ? "root" : "";
		});

		// Can we use __proto__ to reset the prototype of DOMNodes?
		// It's not available on IE<11, and even on IE11 it makes the node's attributes
		// (ex: node.attributes, node.textContent) disappear, so disabling it on IE11 too.
		has.add("dom-proto-set", function () {
			var node = document.createElement("div");
			/* jshint camelcase: false */
			/* jshint proto: true */
			if (!node.__proto__) {
				return false;
			}
			node.__proto__ = {};
			/* jshint camelcase: true */
			/* jshint proto: false */
			return !!node.attributes;
		});
	}

	return has;
});<commit_msg>fix the window definition test in feature.js. fixes #401<commit_after>define(["requirejs-dplugins/has"], function (has) {
	// Flag for whether to create background iframe behind popups like Menus and Dialog.
	// A background iframe is useful to prevent problems with popups appearing behind applets/pdf files.
	has.add("config-bgIframe", false);

	// Flag to enable advanced bidi support
	has.add("bidi", false);

	// Flag to enable inheritance direction from any ancestor
	has.add("inherited-dir", false);

	if (typeof window !== "undefined") {
		// Returns the name of the method to test if an element matches a CSS selector.
		has.add("dom-matches", function () {
			var node = document.body;
			if (node.matches) {
				return "matches";
			}
			if (node.webkitMatchesSelector) {
				return "webkitMatchesSelector";
			}
			if (node.mozMatchesSelector) {
				return "mozMatchesSelector";
			}
			if (node.msMatchesSelector) {
				return "msMatchesSelector";
			}
		});

		// Does platform have native support for document.registerElement() or a polyfill to simulate it?
		has.add("document-register-element", !!document.registerElement);

		// Test for how to monitor DOM nodes being inserted and removed from the document.
		// For DOMNodeInserted events, there are two variations:
		//		"root" - just notified about the root of each tree added to the document
		//		"all" - notified about all nodes added to the document
		has.add("MutationObserver", window.MutationObserver ? "MutationObserver" : window.WebKitMutationObserver ?
			"WebKitMutationObserver" : "");
		has.add("DOMNodeInserted", function () {
			var root = document.createElement("div"),
				child = document.createElement("div"),
				sawRoot, sawChild;
			root.id = "root";
			child.id = "child";
			root.appendChild(child);

			function listener(event) {
				if (event.target.id === "root") {
					sawRoot = true;
				}
				if (event.target.id === "child") {
					sawChild = true;
				}
			}

			document.body.addEventListener("DOMNodeInserted", listener);
			document.body.appendChild(root);
			document.body.removeChild(root);
			document.body.removeEventListener("DOMNodeInserted", listener);
			return sawChild ? "all" : sawRoot ? "root" : "";
		});

		// Can we use __proto__ to reset the prototype of DOMNodes?
		// It's not available on IE<11, and even on IE11 it makes the node's attributes
		// (ex: node.attributes, node.textContent) disappear, so disabling it on IE11 too.
		has.add("dom-proto-set", function () {
			var node = document.createElement("div");
			/* jshint camelcase: false */
			/* jshint proto: true */
			if (!node.__proto__) {
				return false;
			}
			node.__proto__ = {};
			/* jshint camelcase: true */
			/* jshint proto: false */
			return !!node.attributes;
		});
	}

	return has;
});<|endoftext|>


<commit_before>module.exports = {
	'Commands': Commands,
	'Command': Command,
	'createHelp': createHelp
};

/**
 * A static collection class of <Command>.
 * Added <Command> instances become methods of this collection.
 *
 * @example
 * if (Commands.has('command')) {
 *   // call the command, being careful to preverse the instance
 *   Commands.prototype['command'].call(commands, msg, record);
 * }
 *
 * @constructor
 * @param {discord.Client} discordClient a discord.js instance; Note no check is performed to ensure initialization is complete
 * @param {Datastore} nedbConnection     a nedb instacnce; Note no check is performed to ensure initialization is complete
 * @parem {wotblitz} wotblitz            a wotblitz instance
 */
function Commands(discordClient, nedbConnection, wotblitz) {
	this.client = discordClient;
	this.db = nedbConnection;
	this.wotblitz = wotblitz;
}

/**
 * Add a <Command> into the Commands collections.
 *
 * @example
 * // add the "fn" of the given command to Commands.prototype
 * Commands.add(new Command());
 *
 * @param {Command} command an instance, must have "name" and "fn" properties
 */
Commands.add = function addCommand(command) {
	if (command && command.name && typeof command.name === 'string' && typeof command.fn === 'function') {
		Commands.prototype[command.name] = command.fn;
	} else {
		throw new Error('addCommand: command must have name & fn properties');
	}
};

/**
 * Existance of a command in the collection.
 *
 * @param {string} cmdName the command name to look for.
 * @returns {boolean} true when the command exists.
 */
Commands.has = function hasCommand(cmdName) {
	return (cmdName in Commands.prototype) || Commands.get(cmdName) !== null;
};

/**
 * Get the method name of a command from the collection.
 *
 * @param {string} cmdName the command name to look for.
 * @returns {string} the fully resolved method name for the command.
 */
Commands.get = function getCommand(cmdName) {
	for (const key in Commands.prototype) {
		if (key === cmdName || Commands.prototype[key].options.alias === cmdName) {
			return key;
		}
	}

	return null;
};

/**
 * A commandFn should be executed within context of the <Commands> collection.
 * @callback commandFn
 * @param {discord.Message} msg a discord.js message that contains the call to the command.
 * @param {Object} [record]     a query result that is passed when the option "passRecord" is true.
 * @param {...string} [args]    arguments provided after the command text, modify with the "argCount" and "argSplit" options.
 * @returns a {Promise} that resolves, optionally with an {Object} containing the sent message and/or database fields to update
 * in relation to the `record`.
 */

/**
 * Represents a single command.
 *
 * @constructor
 * @param {commandFn} fn      the actual function to be executed with this command is called.
 * @param {Object} [options]  parsing directions for discord client receiving the messages.
 * @param {Number} [options.argCount=0]        the number of arguments after command name in the message.
 * @param {string} [options.argSplit=' ']      the character(s) to split the message with.
 * @param {string} [options.description]       a helpful description of the command.
 * @param {boolean} [options.passRecord=false] pass the record of the discord user as the second argument of "fn".
 * @param {string[]} [options.signatures=[]]   possible chat text to initiate this command (use "@BOTNAME" as a placeholder).
 * @param {string} [name]     the method name to use instead of "fn.name".
 */
function Command(fn, options, name) {
	if (!fn.name && !name) throw new Error('No name provided for the command');

	fn.options = Object.assign({
		argCount: 0,
		argSplit: ' ',
		description: 'No description set.',
		passRecord: false,
		signatures: []
	}, options);

	this.name = name || fn.name;
	this.fn = fn;
}

/**
 * Create a default "help" command.
 *
 * @example
 * Commands.add(createHelp());
 * const commands = new Commands();
 * // help is a method of the "commands" instance.
 *
 * @returns {Command} instance suitable for adding to the <Commands> collection.
 */
function createHelp() {
	const options = {
		argCount: 1,
		description: 'List of all known commands or get help for a particular command.',
		signatures: [
			'@BOTNAME help [command]',
			'(in direct message) help [command]'
		]
	};

	return new Command(helpFn, options, 'help');

	function helpFn(msg, helpFor) {
		const lines = [];
		const name = this.client.user.username;
		const push = opt => {
			for (const sig of opt.signatures) {
				lines.push('`' + sig.replace('BOTNAME', name) + '` -- ' + opt.description);
			}
		};

		let command;

		if (helpFor) {
			command = Commands.get(helpFor);

			if (command !== null) {
				push(Commands.prototype[command].options);
			} else if (helpFor === 'help') {
				push(options);
			} else {
				lines.push('Unknown command: ' + helpFor);
			}
		} else {
			for (const key in Commands.prototype) {
				push(Commands.prototype[key].options);
			}

			if (!Commands.has('help')) push(options);
		}

		return Promise.all(lines.map(send => msg.author.send(send))).then(messages => {
			return {sentMsg: messages};
		});
	}
}
<commit_msg>Add documentation for command alias option.<commit_after>module.exports = {
	'Commands': Commands,
	'Command': Command,
	'createHelp': createHelp
};

/**
 * A static collection class of <Command>.
 * Added <Command> instances become methods of this collection.
 *
 * @example
 * if (Commands.has('command')) {
 *   // call the command, being careful to preverse the instance
 *   Commands.prototype['command'].call(commands, msg, record);
 * }
 *
 * @constructor
 * @param {discord.Client} discordClient a discord.js instance; Note no check is performed to ensure initialization is complete
 * @param {Datastore} nedbConnection     a nedb instacnce; Note no check is performed to ensure initialization is complete
 * @parem {wotblitz} wotblitz            a wotblitz instance
 */
function Commands(discordClient, nedbConnection, wotblitz) {
	this.client = discordClient;
	this.db = nedbConnection;
	this.wotblitz = wotblitz;
}

/**
 * Add a <Command> into the Commands collections.
 *
 * @example
 * // add the "fn" of the given command to Commands.prototype
 * Commands.add(new Command());
 *
 * @param {Command} command an instance, must have "name" and "fn" properties
 */
Commands.add = function addCommand(command) {
	if (command && command.name && typeof command.name === 'string' && typeof command.fn === 'function') {
		Commands.prototype[command.name] = command.fn;
	} else {
		throw new Error('addCommand: command must have name & fn properties');
	}
};

/**
 * Existance of a command in the collection.
 *
 * @param {string} cmdName the command name to look for.
 * @returns {boolean} true when the command exists.
 */
Commands.has = function hasCommand(cmdName) {
	return (cmdName in Commands.prototype) || Commands.get(cmdName) !== null;
};

/**
 * Get the method name of a command from the collection.
 *
 * @param {string} cmdName the command name to look for.
 * @returns {string} the fully resolved method name for the command.
 */
Commands.get = function getCommand(cmdName) {
	for (const key in Commands.prototype) {
		if (key === cmdName || Commands.prototype[key].options.alias === cmdName) {
			return key;
		}
	}

	return null;
};

/**
 * A commandFn should be executed within context of the <Commands> collection.
 * @callback commandFn
 * @param {discord.Message} msg a discord.js message that contains the call to the command.
 * @param {Object} [record]     a query result that is passed when the option "passRecord" is true.
 * @param {...string} [args]    arguments provided after the command text, modify with the "argCount" and "argSplit" options.
 * @returns a {Promise} that resolves, optionally with an {Object} containing the sent message and/or database fields to update
 * in relation to the `record`.
 */

/**
 * Represents a single command.
 *
 * @constructor
 * @param {commandFn} fn      the actual function to be executed with this command is called.
 * @param {Object} [options]  parsing directions for discord client receiving the messages.
 * @param {string} [options.alias]             alternative name used for lookup by {Commands#get}
 * @param {Number} [options.argCount=0]        the number of arguments after command name in the message.
 * @param {string} [options.argSplit=' ']      the character(s) to split the message with.
 * @param {string} [options.description]       a helpful description of the command.
 * @param {boolean} [options.passRecord=false] pass the record of the discord user as the second argument of "fn".
 * @param {string[]} [options.signatures=[]]   possible chat text to initiate this command (use "@BOTNAME" as a placeholder).
 * @param {string} [name]     the method name to use instead of "fn.name".
 */
function Command(fn, options, name) {
	if (!fn.name && !name) throw new Error('No name provided for the command');

	fn.options = Object.assign({
		argCount: 0,
		argSplit: ' ',
		description: 'No description set.',
		passRecord: false,
		signatures: []
	}, options);

	this.name = name || fn.name;
	this.fn = fn;
}

/**
 * Create a default "help" command.
 *
 * @example
 * Commands.add(createHelp());
 * const commands = new Commands();
 * // help is a method of the "commands" instance.
 *
 * @returns {Command} instance suitable for adding to the <Commands> collection.
 */
function createHelp() {
	const options = {
		argCount: 1,
		description: 'List of all known commands or get help for a particular command.',
		signatures: [
			'@BOTNAME help [command]',
			'(in direct message) help [command]'
		]
	};

	return new Command(helpFn, options, 'help');

	function helpFn(msg, helpFor) {
		const lines = [];
		const name = this.client.user.username;
		const push = opt => {
			for (const sig of opt.signatures) {
				lines.push('`' + sig.replace('BOTNAME', name) + '` -- ' + opt.description);
			}
		};

		let command;

		if (helpFor) {
			command = Commands.get(helpFor);

			if (command !== null) {
				push(Commands.prototype[command].options);
			} else if (helpFor === 'help') {
				push(options);
			} else {
				lines.push('Unknown command: ' + helpFor);
			}
		} else {
			for (const key in Commands.prototype) {
				push(Commands.prototype[key].options);
			}

			if (!Commands.has('help')) push(options);
		}

		return Promise.all(lines.map(send => msg.author.send(send))).then(messages => {
			return {sentMsg: messages};
		});
	}
}
<|endoftext|>


<commit_before>'use strict';

var watch = module.exports = {};

// var node_fs = require('fs');
var node_path       = require('path');
var stares          = require('stares');
var ignore          = require('ignore');
var pkg_helper      = require('../util/package');
var lang            = require('../util/lang');
var fs              = require('fs-sync');
var async           = require('async');

// @param {Object} options
// - cwd: {Array.<path>}
watch.run = function(options, callback) {
    var self = this;

    self.watcher = stares({
        port: self.context.profile.get('watcher_rpc_port')

    }).on('all', function (event, filepath) {
        // cortex commander will santitize filepath to the right root directory of the repo
        self._rebuild(filepath);

    // for master watcher process
    }).on('message', function (msg) {
        if ( ~ ['watch', 'unwatch'].indexOf(msg.task) ) {
            if ( process.pid !== msg.pid ) {
                self.logger.info('incomming {{cyan ' + msg.task + '}} request from process <' + msg.pid + '>.');
            }
        }
    });

    options.stop ?
        self.unwatch(options, callback) :
        self.watch(options, callback);
};

watch.watch = function (options, callback) {
    var self = this;

    var profile = self.context.profile;
    var watched = profile.get('watched');

    async.parallel(
        options.cwd.map(function (cwd) {
            if( ~ watched.indexOf(cwd) ){
                self.logger.warn('The current directory has already been watched.');
                return;
            }

            return function (done) {
                self._get_files(cwd, function (err, files) {
                    if(err){
                        return done(err);
                    }

                    self.watcher.watch(files, function (err) {
                        if(err){
                            return done(err);
                        }

                        self.logger.info('{{cyan watching}}', cwd, '...');
                        self.logger.debug('watched', arguments);
                        done(null);
                    });
                });
            };
        }),
        callback
    );
};

watch._get_files = function (cwd, callback) {
    pkg_helper.get_original_package(cwd, function (err, pkg) {
        if ( err ) {
            return callback(err);
        }

        var ignore_rules = lang.object_member_by_namespaces(pkg, 'cortex.ignore', []);

        var files = fs.expand('**', {
            cwd: cwd,
            dot: true

        }).filter(
            ignore().addIgnoreFile(
                ignore.select([
                    '.cortexignore',
                    '.npmignore',
                    '.gitignore'
                ])
            ).addPattern(ignore_rules).createFilter()

        // resolve the path, so the filepath won't get wrong if request to another process
        ).map(function (file) {
            return node_path.join(cwd, file);
        });

        callback(null, files);
    });
};

watch.unwatch = function (options, callback) {
    var self = this;
    var profile = self.context.profile;
    // var watched = profile.get('watched');

    async.parallel(
        options.cwd.map(function (cwd) {
            return function (done) {
                self._get_files(cwd, function (err, files) {
                    if(err){
                        return done(err);
                    }

                    self.watcher.unwatch(files, function (err, msg) {
                        if ( err ) {(err);
                        }

                        self.logger.info(cwd, '{{cyan unwatched}}');
                        self.logger.debug('unwatched', arguments);
                        done(null);
                    });
                });
            };
        }),
        callback
    );
};

// use this trick to prevent endless rebuilding
var locked = {};

watch._lock = function () {
    lang.makeArray(arguments).forEach(function (id) {
        locked[id] = true;
    });
};

watch._release = function () {
    lang.makeArray(arguments).forEach(function (id) {
        locked[id] = false;
    });
};

watch._is_locked = function (id) {
    return locked[id];
};

watch._rebuild = function (cwd) {
    var self = this;

    // If the current directory is already under building,
    // just ignore new tasks
    if ( self._is_locked(cwd) ) {
        return;
    }

    // lock it
    self._lock(cwd);

    self.logger.info('file "' + cwd + '" changed,', '{{cyan rebuild project...}}');

    // mock process.argv
    var argv = [
        '', '',
        'build',
        '--cwd',
        cwd
    ];

    var commander = self.context.commander;
    var parsed = commander.parse(argv, function(err, result, details){
        if ( err ) {
            return self.logger.info('{{red|bold ERR!}}', err);
        }

        var real_cwd = result.opt.cwd;

        // also lock the root directory of a repo
        self._lock(real_cwd);

        // exec cortex.commands.build method
        commander.run('build', result.opt, function(err) {
            self._release(cwd, real_cwd);

            if(err){
                self.logger.info('{{red|bold ERR!}}', err);
            }else{
                self.logger.info('{{bold OK!}} {{green|bold success.}}');
            }
        });
    });
};

<commit_msg>#248: command/watch: no longer depend on fs-sync<commit_after>'use strict';

var watch = module.exports = {};

// var node_fs = require('fs');
var node_path       = require('path');
var stares          = require('stares');
var ignore          = require('ignore');
var pkg_helper      = require('../util/package');
var lang            = require('../util/lang');
var expand          = require('fs-expand');
var async           = require('async');

// @param {Object} options
// - cwd: {Array.<path>}
watch.run = function(options, callback) {
    var self = this;

    self.watcher = stares({
        port: self.context.profile.get('watcher_rpc_port')

    }).on('all', function (event, filepath) {
        // cortex commander will santitize filepath to the right root directory of the repo
        self._rebuild(filepath);

    // for master watcher process
    }).on('message', function (msg) {
        if ( ~ ['watch', 'unwatch'].indexOf(msg.task) ) {
            if ( process.pid !== msg.pid ) {
                self.logger.info('incomming {{cyan ' + msg.task + '}} request from process <' + msg.pid + '>.');
            }
        }
    });

    options.stop ?
        self.unwatch(options, callback) :
        self.watch(options, callback);
};

watch.watch = function (options, callback) {
    var self = this;

    var profile = self.context.profile;
    var watched = profile.get('watched');

    async.parallel(
        options.cwd.map(function (cwd) {
            if( ~ watched.indexOf(cwd) ){
                self.logger.warn('The current directory has already been watched.');
                return;
            }

            return function (done) {
                self._get_files(cwd, function (err, files) {
                    if(err){
                        return done(err);
                    }

                    self.watcher.watch(files, function (err) {
                        if(err){
                            return done(err);
                        }

                        self.logger.info('{{cyan watching}}', cwd, '...');
                        self.logger.debug('watched', arguments);
                        done(null);
                    });
                });
            };
        }),
        callback
    );
};

watch._get_files = function (cwd, callback) {
    pkg_helper.get_original_package(cwd, function (err, pkg) {
        if ( err ) {
            return callback(err);
        }

        var ignore_rules = lang.object_member_by_namespaces(pkg, 'cortex.ignore', []);

        fs.expand('**', {
            cwd: cwd,
            dot: true

        }, function (err, files) {
            if ( err ) {
                return callback(err);
            }

            var filter = ignore()
                .addIgnoreFile(
                    ignore.select([
                        '.cortexignore',
                        '.npmignore',
                        '.gitignore'
                    ])
                ).
                addPattern(ignore_rules).
                createFilter();

            files = files
                .filter(filter)
                // resolve the path, so the filepath won't get wrong if request to another process
                .map(function (file) {
                    return node_path.join(cwd, file);
                });

            callback(null, files);
        });
    });
};

watch.unwatch = function (options, callback) {
    var self = this;
    var profile = self.context.profile;
    // var watched = profile.get('watched');

    async.parallel(
        options.cwd.map(function (cwd) {
            return function (done) {
                self._get_files(cwd, function (err, files) {
                    if(err){
                        return done(err);
                    }

                    self.watcher.unwatch(files, function (err, msg) {
                        if ( err ) {(err);
                        }

                        self.logger.info(cwd, '{{cyan unwatched}}');
                        self.logger.debug('unwatched', arguments);
                        done(null);
                    });
                });
            };
        }),
        callback
    );
};

// use this trick to prevent endless rebuilding
var locked = {};

watch._lock = function () {
    lang.makeArray(arguments).forEach(function (id) {
        locked[id] = true;
    });
};

watch._release = function () {
    lang.makeArray(arguments).forEach(function (id) {
        locked[id] = false;
    });
};

watch._is_locked = function (id) {
    return locked[id];
};

watch._rebuild = function (cwd) {
    var self = this;

    // If the current directory is already under building,
    // just ignore new tasks
    if ( self._is_locked(cwd) ) {
        return;
    }

    // lock it
    self._lock(cwd);

    self.logger.info('file "' + cwd + '" changed,', '{{cyan rebuild project...}}');

    // mock process.argv
    var argv = [
        '', '',
        'build',
        '--cwd',
        cwd
    ];

    var commander = self.context.commander;
    var parsed = commander.parse(argv, function(err, result, details){
        if ( err ) {
            return self.logger.info('{{red|bold ERR!}}', err);
        }

        var real_cwd = result.opt.cwd;

        // also lock the root directory of a repo
        self._lock(real_cwd);

        // exec cortex.commands.build method
        commander.run('build', result.opt, function(err) {
            self._release(cwd, real_cwd);

            if(err){
                self.logger.info('{{red|bold ERR!}}', err);
            }else{
                self.logger.info('{{bold OK!}} {{green|bold success.}}');
            }
        });
    });
};

<|endoftext|>


<commit_before>import Vue from 'vue';
import HeroesList from './components/heroes-list.vue';
import HeroInsert from './components/hero-insert.vue';
import App from './App.vue';

new Vue({
    el: '#app',
    render: h => h(App)
});
<commit_msg>FIX(vue) linting<commit_after>import Vue from 'vue';
import App from './App.vue';

new Vue({
    el: '#app',
    render: h => h(App)
});
<|endoftext|>


<commit_before>'use strict';

var chalk   = require('chalk');
var fs      = require('fs');
var path    = require('path');
var Command = require('../models/command');
var ui      = require('../ui');

module.exports = Command.extend({
  name: 'help',
  run: function(){
    ui.write('Available commands for ember-cdv:\n');
    fs.readdir(__dirname, function(err, files){
      files.forEach(function(file){
        if(path.basename(file) !== 'help.js') {
          command = new (require('./' + file))();
          command.displayHelp();
          ui.write('\n');
        }
      });
    });
  }
});
<commit_msg>fix var not being defined<commit_after>'use strict';

var chalk   = require('chalk');
var fs      = require('fs');
var path    = require('path');
var Command = require('../models/command');
var ui      = require('../ui');

module.exports = Command.extend({
  name: 'help',
  run: function(){
    ui.write('Available commands for ember-cdv:\n');
    fs.readdir(__dirname, function(err, files){
      files.forEach(function(file){
        var command;
        if(path.basename(file) !== 'help.js') {
          command = new (require('./' + file))();
          command.displayHelp();
          ui.write('\n');
        }
      });
    });
  }
});
<|endoftext|>


<commit_before>
import {message} from 'antd'

function json_format(json){
  try{
    return JSON.stringify(JSON.parse(json), null, '   ');
  }catch(e){
    return json;
  }
}

function postman(importDataModule){

  function parseUrl(url){
    let parser = document.createElement('a');
    parser.href = url;
    return {
      protocol: parser.protocol,
      hostname: parser.hostname,
      port: parser.port,
      pathname: parser.pathname,
      search: parser.search,
      host: parser.host
    }
  }

  function checkInterRepeat(interData){
    let obj = {};
    let arr = [];
    for(let item in interData){
      // console.log(interData[item].url + "-" + interData[item].method);
      let key = interData[item].request.url + "|" + interData[item].request.method;
      if(!obj[key]){
        arr.push(interData[item]);
        obj[key] = true;
      }
    }
    return arr;
  }

  function handleReq_query(query){
    let res = [];
    if(query&&query.length){
      for(let item in query){
        res.push({
          name: query[item].key,
          desc: query[item].description,
          required: query[item].enable
        });
      }
    }
    return res;
  }
  // function handleReq_headers(headers){
  //   let res = [];
  //   if(headers&&headers.length){
  //     for(let item in headers){
  //       res.push({
  //         name: headers[item].key,
  //         desc: headers[item].description,
  //         value: headers[item].value,
  //         required: headers[item].enable
  //       });
  //     }
  //   }
  //   return res;
  // }

  function handleReq_body_form(body_form){
    let res = [];
    if(body_form && typeof body_form === 'object'){
      for(let item in body_form){
        res.push({
          name: body_form[item].name,
          type: 'text'
        });
      }
    }
    return res;
  }

  function handlePath(path){
    path = path.replace(/{{(\w*)}}/,"");
    path = parseUrl(path).pathname;
    if(path.charAt(0) != "/"){
      path = "/" + path;
    }
    if(path.charAt(path.length-1) === "/"){
      path = path.substr(0,path.length-1);
    }
    return path;
  }

  function run(res){
    try{
      res = JSON.parse(res);
      res = res.log.entries;
      res = res.filter(item=>{
        if(!item)return false;
        return item.response.content.mimeType.indexOf('application/json') === 0;
      })

      let interfaceData = {apis: []};
      res = checkInterRepeat.bind(this)(res);
      if(res && res.length){
        for(let item in res){
          let data = importHar.bind(this)(res[item]);
          interfaceData.apis.push(data);
        }
      }
      return interfaceData;

    }catch(e){
      console.error(e);
      message.error("数据格式有误");
    }

  }

  function importHar(data,key){
    let reflect = {//数据字段映射关系
      title: "url",
      path: "url",
      method: "method",
      desc: "description",
      req_query: "queryString",
      req_body_form: "params",
      req_body_other: "text"
    };
    let allKey = ["title","path","method","req_query","req_body_type","req_body_form","req_body_other", "res_body_type", "res_body","req_headers"];
    key = key || allKey;
    let res = {};

    let reqType = 'json', header;
    data.request.headers.forEach(item=>{
      if(!item ||item.name ||item.value) return null;
      if(/content-type/i.test(item.name) && item.value.index('application/json') === 0){
        reqType = 'json';
        header = 'application/json';
      }else if(/content-type/i.test(item.name) && item.value.index('application/x-www-form-urlencoded') === 0){
        header = 'application/x-www-form-urlencoded'
        reqType = 'form';
      }else if(/content-type/i.test(item.name) && item.value.index('multipart/form-data') === 0){
        header = 'multipart/form-data'
        reqType = 'form';
      }
    })

    for(let item in key){
      item = key[item];
      if(item === "req_query"){
        res[item] = handleReq_query.bind(this)(data.request[reflect[item]]);
      }else if(item === "req_body_form" && reqType === 'form' && data.request.postData){
        if(header === 'application/x-www-form-urlencoded'){
          res[item] = handleReq_body_form.bind(this)(data.request.postData[reflect[item]]);
        }else if(header === 'multipart/form-data' ){
          res[item] = [];
        }

      }else if(item === "req_headers"){
        res[item] = [{
          name: 'Content-Type',
          value: header
        }];
      }else if(item === "req_body_type"){
        res[item] = reqType;
      }else if(item === "path"){
        res[item] = handlePath.bind(this)(data.request[reflect[item]]);
      }else if(item === "title"){
        let path = handlePath.bind(this)(data.request[reflect["path"]]);
        if(data.request[reflect[item]].indexOf(path) > -1){
          res[item] = path;
          if(res[item] && res[item].indexOf("/:") > -1){
            res[item] = res[item].substr(0,res[item].indexOf("/:"));
          }
        }else{
          res[item] = data.request[reflect[item]];
        }
      }else if(item === 'res_body_type'){
        res[item] = 'json';
      }else if(item === 'res_body'){
        res[item] = json_format(data.response.content.text);
      }
      else{
        res[item] = data.request[reflect[item]];
      }
    }
    return res;
  }

  if(!importDataModule || typeof importDataModule !== 'object'){
    console.error('obj参数必需是一个对象');
    return null;
  }

  importDataModule.har = {
    name: 'HAR',
    run: run,
    desc: '使用chrome录制请求功能，具体使用请查看文档'
  }
}

module.exports = function(){

  this.bindHook('import_data', postman)
}<commit_msg>fix: har plugin query params bug<commit_after>
import {message} from 'antd'

function json_format(json){
  try{
    return JSON.stringify(JSON.parse(json), null, '   ');
  }catch(e){
    return json;
  }
}

function postman(importDataModule){

  function parseUrl(url){
    let parser = document.createElement('a');
    parser.href = url;
    return {
      protocol: parser.protocol,
      hostname: parser.hostname,
      port: parser.port,
      pathname: parser.pathname,
      search: parser.search,
      host: parser.host
    }
  }

  function checkInterRepeat(interData){
    let obj = {};
    let arr = [];
    for(let item in interData){
      // console.log(interData[item].url + "-" + interData[item].method);
      let key = interData[item].request.url + "|" + interData[item].request.method;
      if(!obj[key]){
        arr.push(interData[item]);
        obj[key] = true;
      }
    }
    return arr;
  }

  function handleReq_query(query){
    let res = [];
    if(query&&query.length){
      for(let item in query){
        res.push({
          name: query[item].name
        });
      }
    }
    return res;
  }
  // function handleReq_headers(headers){
  //   let res = [];
  //   if(headers&&headers.length){
  //     for(let item in headers){
  //       res.push({
  //         name: headers[item].key,
  //         desc: headers[item].description,
  //         value: headers[item].value,
  //         required: headers[item].enable
  //       });
  //     }
  //   }
  //   return res;
  // }

  function handleReq_body_form(body_form){
    let res = [];
    if(body_form && typeof body_form === 'object'){
      for(let item in body_form){
        res.push({
          name: body_form[item].name,
          type: 'text'
        });
      }
    }
    return res;
  }

  function handlePath(path){
    path = path.replace(/{{(\w*)}}/,"");
    path = parseUrl(path).pathname;
    if(path.charAt(0) != "/"){
      path = "/" + path;
    }
    if(path.charAt(path.length-1) === "/"){
      path = path.substr(0,path.length-1);
    }
    return path;
  }

  function run(res){
    try{
      res = JSON.parse(res);
      res = res.log.entries;
      res = res.filter(item=>{
        if(!item)return false;
        return item.response.content.mimeType.indexOf('application/json') === 0;
      })

      let interfaceData = {apis: []};
      res = checkInterRepeat.bind(this)(res);
      if(res && res.length){
        for(let item in res){
          let data = importHar.bind(this)(res[item]);
          interfaceData.apis.push(data);
        }
      }
      return interfaceData;

    }catch(e){
      console.error(e);
      message.error("数据格式有误");
    }

  }

  function importHar(data,key){
    let reflect = {//数据字段映射关系
      title: "url",
      path: "url",
      method: "method",
      desc: "description",
      req_query: "queryString",
      req_body_form: "params",
      req_body_other: "text"
    };
    let allKey = ["title","path","method","req_query","req_body_type","req_body_form","req_body_other", "res_body_type", "res_body","req_headers"];
    key = key || allKey;
    let res = {};

    let reqType = 'json', header;
    data.request.headers.forEach(item=>{
      if(!item ||item.name ||item.value) return null;
      if(/content-type/i.test(item.name) && item.value.index('application/json') === 0){
        reqType = 'json';
        header = 'application/json';
      }else if(/content-type/i.test(item.name) && item.value.index('application/x-www-form-urlencoded') === 0){
        header = 'application/x-www-form-urlencoded'
        reqType = 'form';
      }else if(/content-type/i.test(item.name) && item.value.index('multipart/form-data') === 0){
        header = 'multipart/form-data'
        reqType = 'form';
      }
    })

    for(let item in key){
      item = key[item];
      if(item === "req_query"){
        res[item] = handleReq_query.bind(this)(data.request[reflect[item]]);
      }else if(item === "req_body_form" && reqType === 'form' && data.request.postData){
        if(header === 'application/x-www-form-urlencoded'){
          res[item] = handleReq_body_form.bind(this)(data.request.postData[reflect[item]]);
        }else if(header === 'multipart/form-data' ){
          res[item] = [];
        }

      }else if(item === "req_headers"){
        res[item] = [{
          name: 'Content-Type',
          value: header
        }];
      }else if(item === "req_body_type"){
        res[item] = reqType;
      }else if(item === "path"){
        res[item] = handlePath.bind(this)(data.request[reflect[item]]);
      }else if(item === "title"){
        let path = handlePath.bind(this)(data.request[reflect["path"]]);
        if(data.request[reflect[item]].indexOf(path) > -1){
          res[item] = path;
          if(res[item] && res[item].indexOf("/:") > -1){
            res[item] = res[item].substr(0,res[item].indexOf("/:"));
          }
        }else{
          res[item] = data.request[reflect[item]];
        }
      }else if(item === 'res_body_type'){
        res[item] = 'json';
      }else if(item === 'res_body'){
        res[item] = json_format(data.response.content.text);
      }
      else{
        res[item] = data.request[reflect[item]];
      }
    }
    return res;
  }

  if(!importDataModule || typeof importDataModule !== 'object'){
    console.error('obj参数必需是一个对象');
    return null;
  }

  importDataModule.har = {
    name: 'HAR',
    run: run,
    desc: '使用chrome录制请求功能，具体使用请查看文档'
  }
}

module.exports = function(){

  this.bindHook('import_data', postman)
}<|endoftext|>


<commit_before>/*
 * classList.js: Cross-browser full element.classList implementation.
 * 2012-11-15
 *
 * By Eli Grey, http://eligrey.com
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */

/* global self, document, DOMException */

/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
(function(view) {
  if (!('HTMLElement' in view) && !('Element' in view)) {
    return;
  }

  var classListProp = "classList";
  var protoProp = "prototype";
  var elemCtrProto = (view.HTMLElement || view.Element)[protoProp];
  var objCtr = Object;
  var strTrim = String[protoProp].trim || function() {
    return this.replace(/^\s+|\s+$/g, "");
  };
  var arrIndexOf = Array[protoProp].indexOf || function(item) {
    for (var i = 0; i < this.length; i++) {
      if (i in this && this[i] === item) {
        return i;
      }
    }
    return -1;
  };
  // Vendors: please allow content code to instantiate DOMExceptions
  var DOMEx = function(type, message) {
    this.name = type;
    this.code = DOMException[type];
    this.message = message;
  };
  var checkTokenAndGetIndex = function(classList, token) {
    if (token === "") {
      throw new DOMEx("SYNTAX_ERR", "An invalid or illegal string was specified");
    }
    if (/\s/.test(token)) {
      throw new DOMEx("INVALID_CHARACTER_ERR", "String contains an invalid character");
    }
    return arrIndexOf.call(classList, token);
  };
  var ClassList = function(elem) {
    var trimmedClasses = strTrim.call(elem.className);
    var classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
    for (var i = 0; i < classes.length; i++) {
      this.push(classes[i]);
    }
    this._updateClassName = function() {
      elem.className = this.toString();
    };
  };
  var classListProto = ClassList[protoProp] = [];
  var classListGetter = function() {
    return new ClassList(this);
  };
// Most DOMException implementations don't allow calling DOMException's toString()
// on non-DOMExceptions. Error's toString() is sufficient here.
  DOMEx[protoProp] = Error[protoProp];
  classListProto.item = function(i) {
    return this[i] || null;
  };
  classListProto.contains = function(token) {
    token += "";
    return checkTokenAndGetIndex(this, token) !== -1;
  };
  classListProto.add = function() {
    var tokens = arguments;
    var i = 0;
    var l = tokens.length;
    var token;
    var updated = false;
    do {
      token = tokens[i] + "";
      if (checkTokenAndGetIndex(this, token) === -1) {
        this.push(token);
        updated = true;
      }
    }
    while (++i < l);

    if (updated) {
      this._updateClassName();
    }
  };
  classListProto.remove = function() {
    var tokens = arguments;
    var i = 0;
    var index;
    var l = tokens.length;
    var token;
    var updated = false;
    do {
      token = tokens[i] + "";
      index = checkTokenAndGetIndex(this, token);
      if (index !== -1) {
        this.splice(index, 1);
        updated = true;
      }
    }
    while (++i < l);

    if (updated) {
      this._updateClassName();
    }
  };
  classListProto.toggle = function(token, forse) {
    token += "";

    var result = this.contains(token);
    var method = result ? forse !== true && "remove" : forse !== false && "add";

    if (method) {
      this[method](token);
    }

    return !result;
  };
  classListProto.toString = function() {
    return this.join(" ");
  };

  if (objCtr.defineProperty) {
    var classListPropDesc = { get: classListGetter, enumerable: true, configurable: true };
    try {
      objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
    }
    // IE 8 doesn't support enumerable:true
    catch (ex) {
      if (ex.number === -0x7FF5EC54) {
        classListPropDesc.enumerable = false;
        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
      }
    }
  }
  else if (objCtr[protoProp].__defineGetter__) {
    elemCtrProto.__defineGetter__(classListProp, classListGetter);
  }

}(self));
<commit_msg>Updated classList.js to latest version from GitHub<commit_after>/*
 * classList.js: Cross-browser full element.classList implementation.
 * 2012-11-15
 *
 * By Eli Grey, http://eligrey.com
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */
/*global self, document, DOMException */
/*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/
if ("document" in self && !(
  "classList" in document.createElement("_") &&
  "classList" in document.createElementNS("http://www.w3.org/2000/svg", "svg")
)) {
  (function (view) {
    "use strict";
    if (!('Element' in view)) {
      return;
    }
    var classListProp = "classList";
    var protoProp = "prototype";
    var elemCtrProto = view.Element[protoProp];
    var objCtr = Object;
    var strTrim = String[protoProp].trim || function () {
      return this.replace(/^\s+|\s+$/g, "");
    };
    var arrIndexOf = Array[protoProp].indexOf || function (item) {
      for (var i = 0; i < this.length; ++i) {
        if (i in this && this[i] === item) {
          return i;
        }
      }
      return -1;
    };
    var DOMEx = function (type, message) {
      this.name    = type;
      this.code    = DOMException[type];
      this.message = message;
    };
    var checkTokenAndGetIndex = function (classList, token) {
      if (token === "") {
        throw new DOMEx("SYNTAX_ERR", "An invalid or illegal string was specified");
      }
      if (/\s/.test(token)) {
        throw new DOMEx("INVALID_CHARACTER_ERR", "String contains an invalid character");
      }
      return arrIndexOf.call(classList, token);
    };
    var ClassList = function (elem) {
      var trimmedClasses = strTrim.call(elem.getAttribute("class") || "");
      var classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [];
      for (var i = 0; i < classes.length; ++i) {
        this.push(classes[i]);
      }
      this._updateClassName = function () {
        elem.setAttribute("class", this.toString());
      };
    };
    var classListProto = ClassList[protoProp] = [];
    var classListGetter = function () {
      return new ClassList(this);
    };
    // Most DOMException implementations don't allow calling DOMException's toString()
    // on non-DOMExceptions. Error's toString() is sufficient here.
    DOMEx[protoProp] = Error[protoProp];
    classListProto.item = function (i) {
      return this[i] || null;
    };
    classListProto.contains = function (token) {
      token += "";
      return checkTokenAndGetIndex(this, token) !== -1;
    };
    classListProto.add = function () {
      var tokens = arguments;
      var i = 0;
      var l = tokens.length;
      var token;
      var updated = false;
      do {
        token = tokens[i] + "";
        if (checkTokenAndGetIndex(this, token) === -1) {
          this.push(token);
          updated = true;
        }
      }
      while (++i < l);
      if (updated) {
        this._updateClassName();
      }
    };
    classListProto.remove = function () {
      var tokens = arguments;
      var i = 0;
      var l = tokens.length;
      var token;
      var updated = false;
      var index;
      do {
        token = tokens[i] + "";
        index = checkTokenAndGetIndex(this, token);
        if (index !== -1) {
          this.splice(index, 1);
          updated = true;
        }
      }
      while (++i < l);
      if (updated) {
        this._updateClassName();
      }
    };
    classListProto.toggle = function (token, forse) {
      token += "";
      var result = this.contains(token);
      var method = result ? forse !== true && "remove" : forse !== false && "add";
      if (method) {
        this[method](token);
      }
      return !result;
    };
    classListProto.toString = function () {
      return this.join(" ");
    };
    if (objCtr.defineProperty) {
      var classListPropDesc = {
        get          : classListGetter,
        enumerable   : true,
        configurable : true
      };
      try {
        objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
      }
      catch (ex) { // IE 8 doesn't support enumerable:true
        if (ex.number === -0x7FF5EC54) {
          classListPropDesc.enumerable = false;
          objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
        }
      }
    }
    else if (objCtr[protoProp].__defineGetter__) {
      elemCtrProto.__defineGetter__(classListProp, classListGetter);
    }
  }(self));
}
<|endoftext|>


<commit_before>/**
 *
 */
define(function (require, exports, module) {

    var zhCN = require('datatableZh');
    var editorCN = require('i18n');
    exports.index = function ($, itemTableId) {
        var itemEditor = new $.fn.dataTable.Editor({
            ajax: {
                create: {
                    type: 'POST',
                    url: '/admin/stock-out-item',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                edit: {
                    type: 'PUT',
                    url: '/admin/stock-out-item/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                remove: {
                    type: 'DELETE',
                    url: '/admin/stock-out-item/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                }
            },
            i18n: editorCN,
            table: "#" + itemTableId,
            idSrc: 'id',
            fields: [
                { 'label': '商品', 'name': 'fmeterial_id', 'type': 'select', 'options': materials},
                {'label': '销售单位', 'name': 'fsale_unit',},
                {'label': '基本单位', 'name': 'fbase_unit',},
                {'label': '订单数量', 'name': 'fqty',},
            ]
        });

        var itemTable = $("#" + itemTableId).DataTable({
            dom: "Bfrtip",
            language: zhCN,
            processing: true,
            serverSide: true,
            select: true,
            paging: true,
            rowId: "id",
            ajax: '/admin/stock-out-item/pagination',
            columns: [
                {'data': 'id'},
                {
                    'data': 'fstock_out_id',
                    render: function (data, type, full) {
                        if (full.stockout != null)
                            return full.stockout.fbill_no
                        else
                            return "";
                    }
                },
                {
                    'data': 'fmaterial_id',
                    render: function (data, type, full) {
                        if (full.material != null)
                            return full.material.fname
                        else
                            return "";
                    }
                },
                {'data': 'fsale_unit'},
                {'data': 'fbase_unit'},
                {'data': 'fqty'},
                {'data': 'fbase_qty'},

            ],
            buttons: [
                // { text: '新增', action: function () { }  },
                // { text: '编辑', className: 'edit', enabled: false },
                // { text: '删除', className: 'delete', enabled: false },
                {extend: "create", text: '新增', editor: itemEditor},
                {extend: "edit", text: '编辑', editor: itemEditor},
                {extend: "remove", text: '删除', editor: itemEditor},
                {extend: 'excel', text: '导出Excel'},
                {extend: 'print', text: '打印'},
                //{extend: 'colvis', text: '列显示'}
            ]
        });

        // table.on( 'select', checkBtn).on( 'deselect', checkBtn);
        //
        // function checkBtn(e, dt, type, indexes) {
        //     var count = table.rows( { selected: true } ).count();
        //     table.buttons( ['.edit', '.delete'] ).enable(count > 0);
        // }

    }

});<commit_msg>bug fix<commit_after>/**
 *
 */
define(function (require, exports, module) {

    var zhCN = require('datatableZh');
    var editorCN = require('i18n');
    exports.index = function ($, itemTableId) {
        var itemEditor = new $.fn.dataTable.Editor({
            ajax: {
                create: {
                    type: 'POST',
                    url: '/admin/stock-out-item',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                edit: {
                    type: 'PUT',
                    url: '/admin/stock-out-item/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                },
                remove: {
                    type: 'DELETE',
                    url: '/admin/stock-out-item/_id_',
                    data: {_token: $('meta[name="_token"]').attr('content')},
                }
            },
            i18n: editorCN,
            table: "#" + itemTableId,
            idSrc: 'id',
            fields: [
                { 'label': '商品', 'name': 'fmaterial_id', 'type': 'select', 'options': materials},
                {'label': '销售单位', 'name': 'fsale_unit',},
                {'label': '基本单位', 'name': 'fbase_unit',},
                {'label': '订单数量', 'name': 'fqty',},
            ]
        });

        var itemTable = $("#" + itemTableId).DataTable({
            dom: "Bfrtip",
            language: zhCN,
            processing: true,
            serverSide: true,
            select: true,
            paging: true,
            rowId: "id",
            ajax: '/admin/stock-out-item/pagination',
            columns: [
                {'data': 'id'},
                {
                    'data': 'fstock_out_id',
                    render: function (data, type, full) {
                        if (full.stockout != null)
                            return full.stockout.fbill_no
                        else
                            return "";
                    }
                },
                {
                    'data': 'fmaterial_id',
                    render: function (data, type, full) {
                        if (full.material != null)
                            return full.material.fname
                        else
                            return "";
                    }
                },
                {'data': 'fsale_unit'},
                {'data': 'fbase_unit'},
                {'data': 'fqty'},
                {'data': 'fbase_qty'},

            ],
            buttons: [
                // { text: '新增', action: function () { }  },
                // { text: '编辑', className: 'edit', enabled: false },
                // { text: '删除', className: 'delete', enabled: false },
                {extend: "create", text: '新增', editor: itemEditor},
                {extend: "edit", text: '编辑', editor: itemEditor},
                {extend: "remove", text: '删除', editor: itemEditor},
                {extend: 'excel', text: '导出Excel'},
                {extend: 'print', text: '打印'},
                //{extend: 'colvis', text: '列显示'}
            ]
        });

        // table.on( 'select', checkBtn).on( 'deselect', checkBtn);
        //
        // function checkBtn(e, dt, type, indexes) {
        //     var count = table.rows( { selected: true } ).count();
        //     table.buttons( ['.edit', '.delete'] ).enable(count > 0);
        // }

    }

});<|endoftext|>


<commit_before>/* eslint-disable import/no-unresolved */
import React, {
  Component,
  PropTypes,
} from 'react';

import {
  StyleSheet,
  Text,
  View,
} from 'react-native';

class Section extends Component {

  constructor(props) {
    super(props);
    this.state = {
      highlightedRowIndex: undefined,
    };

    this.handleHighlightRow = index => !this.state.highlightedRowIndex && this.setState({ highlightedRowIndex: index });
    this.handleUnHighlightRow = () => this.setState({ highlightedRowIndex: undefined });
  }
  render() {
    const {
      allowFontScaling,
      children,
      footerComponent,
      headerComponent,
      headerTextColor,
      hideSeparator,
      footerTextColor,
      sectionTintColor,
      separatorInsetLeft,
      separatorInsetRight,
      separatorTintColor,
    } = this.props;

    const header = this.props.header ? this.props.header : false;
    const footer = this.props.footer ? this.props.footer : false;

    /**
     * Merge styles with props
     */
    // eslint-disable-next-line no-underscore-dangle
    const _styles = {
      section: [
        ...{},
        styles.section,
        { backgroundColor: sectionTintColor },
      ],
      sectionheader__text: [
        ...{},
        styles.sectionheader__text,
        { color: headerTextColor },
      ],
      sectionfooter__text: [
        ...{},
        styles.sectionfooter__text,
        { color: footerTextColor },
      ],
      separator_inner: [
        ...{},
        styles.separator_inner,
        {
          backgroundColor: separatorTintColor,
          marginLeft: separatorInsetLeft,
          marginRight: separatorInsetRight,
        },
      ],
    };

    /**
     * Render Cell and add Border
     * @param  {Cell} child [description]
     * @param  {Int} index [description]
     * @return {View}       [description]
     */
    const renderChild = (child, index) => {
      const propsToAdd = {
        onHighlightRow: () => this.handleHighlightRow(index),
        onUnHighlightRow: this.handleUnHighlightRow,
      };

      // Skip rendering of separator
      if (hideSeparator || children.length === 1 || index === children.length - 1) {
        return React.cloneElement(child, propsToAdd);
      }

      _styles.separator = [
        ...{},
        styles.separator,
        {
          backgroundColor: child.props.backgroundColor,
        },
      ];

      const invisibleSeparator = this.state.highlightedRowIndex === index || this.state.highlightedRowIndex === index + 1;

      if (invisibleSeparator) {
        _styles.separator_inner = [
          ...{},
          _styles.separator_inner,
          {
            backgroundColor: 'transparent',
          },
        ];
      }

      return (
        <View>
          {React.cloneElement(child, propsToAdd)}
          <View style={_styles.separator}>
            <View style={_styles.separator_inner} />
          </View>
        </View>
      );
    };

    /**
     * Render header if defined
     * @return {View} View with Text
     */
    const renderHeader = () => {
      if (header) {
        return (
          <View style={styles.sectionheader}>
            <Text
              allowFontScaling={allowFontScaling}
              style={_styles.sectionheader__text}
            >
              {header}
            </Text>
          </View>
        );
      }
      return undefined;
    };

    /**
     * Render footer if defined
     * @return {View} View with Text
     */
    const renderFooter = () => {
      if (footer) {
        return (
          <View style={styles.sectionfooter}>
            <Text
              allowFontScaling={allowFontScaling}
              style={_styles.sectionfooter__text}
            >
              {footer}
            </Text>
          </View>
        );
      }
      return undefined;
    };

    return (
      <View style={_styles.section}>
        {headerComponent || renderHeader()}
        <View style={styles.section_inner}>
          {React.Children.map(children, renderChild)}
        </View>
        {footerComponent || renderFooter()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  section: {
    paddingTop: 15,
    paddingBottom: 15,
  },
  section_inner: {
    borderTopWidth: StyleSheet.hairlineWidth,
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderColor: '#c8c7cc',
  },
  sectionheader: {
    paddingLeft: 15,
    paddingRight: 15,
    paddingBottom: 5,
  },
  sectionheader__text: {
    fontSize: 13,
  },
  sectionfooter: {
    paddingLeft: 15,
    paddingRight: 15,
    paddingTop: 10,
  },
  sectionfooter__text: {
    fontSize: 13,
  },
  separator: {
  },
  separator_inner: {
    height: StyleSheet.hairlineWidth,
  },
});

Section.propTypes = {
  allowFontScaling: PropTypes.bool,
  children: PropTypes.node,
  footerComponent: PropTypes.element,
  headerComponent: PropTypes.element,
  footer: PropTypes.string,
  footerTextColor: PropTypes.string,
  header: PropTypes.string,
  headerTextColor: PropTypes.string,
  hideSeparator: PropTypes.bool,
  sectionTintColor: PropTypes.string,
  separatorInsetLeft: PropTypes.number,
  separatorInsetRight: PropTypes.number,
  separatorTintColor: PropTypes.string,
};

Section.defaultProps = {
  allowFontScaling: true,
  headerTextColor: '#6d6d72',
  hideSeparator: false,
  sectionTintColor: '#EFEFF4',
  footerTextColor: '#6d6d72',
  separatorInsetLeft: 15,
  separatorInsetRight: 0,
  separatorTintColor: '#c8c7cc',
};

export default Section;
<commit_msg>fix scope error<commit_after>/* eslint-disable import/no-unresolved */
import React, {
  Component,
  PropTypes,
} from 'react';

import {
  StyleSheet,
  Text,
  View,
} from 'react-native';

class Section extends Component {

  constructor(props) {
    super(props);
    this.state = {
      highlightedRowIndex: undefined,
    };

    this.handleHighlightRow = index => !this.state.highlightedRowIndex && this.setState({ highlightedRowIndex: index });
    this.handleUnHighlightRow = () => this.setState({ highlightedRowIndex: undefined });
  }
  render() {
    const {
      allowFontScaling,
      children,
      footerComponent,
      headerComponent,
      headerTextColor,
      hideSeparator,
      footerTextColor,
      sectionTintColor,
      separatorInsetLeft,
      separatorInsetRight,
      separatorTintColor,
    } = this.props;

    const header = this.props.header ? this.props.header : false;
    const footer = this.props.footer ? this.props.footer : false;

    /**
     * Merge styles with props
     */
    // eslint-disable-next-line no-underscore-dangle
    const _styles = {
      section: [
        ...{},
        styles.section,
        { backgroundColor: sectionTintColor },
      ],
      sectionheader__text: [
        ...{},
        styles.sectionheader__text,
        { color: headerTextColor },
      ],
      sectionfooter__text: [
        ...{},
        styles.sectionfooter__text,
        { color: footerTextColor },
      ],
      separator_inner: [
        ...{},
        styles.separator_inner,
        {
          backgroundColor: separatorTintColor,
          marginLeft: separatorInsetLeft,
          marginRight: separatorInsetRight,
        },
      ],
    };

    /**
     * Render Cell and add Border
     * @param  {Cell} child [description]
     * @param  {Int} index [description]
     * @return {View}       [description]
     */
    const renderChild = (child, index) => {
      const propsToAdd = {
        onHighlightRow: () => this.handleHighlightRow(index),
        onUnHighlightRow: this.handleUnHighlightRow,
      };

      // Skip rendering of separator
      if (hideSeparator || children.length === 1 || index === children.length - 1) {
        return React.cloneElement(child, propsToAdd);
      }

      const _localstyles = Object.assign({}, _styles);
      _localstyles.separator = [
        ...{},
        styles.separator,
        {
          backgroundColor: child.props.backgroundColor,
        },
      ];

      const invisibleSeparator = this.state.highlightedRowIndex === index || this.state.highlightedRowIndex === index + 1;

      if (invisibleSeparator) {
        _localstyles.separator_inner = [
          ...{},
          _styles.separator_inner,
          {
            backgroundColor: 'transparent',
          },
        ];
      }

      return (
        <View>
          {React.cloneElement(child, propsToAdd)}
          <View style={_localstyles.separator}>
            <View style={_localstyles.separator_inner} />
          </View>
        </View>
      );
    };

    /**
     * Render header if defined
     * @return {View} View with Text
     */
    const renderHeader = () => {
      if (header) {
        return (
          <View style={styles.sectionheader}>
            <Text
              allowFontScaling={allowFontScaling}
              style={_styles.sectionheader__text}
            >
              {header}
            </Text>
          </View>
        );
      }
      return undefined;
    };

    /**
     * Render footer if defined
     * @return {View} View with Text
     */
    const renderFooter = () => {
      if (footer) {
        return (
          <View style={styles.sectionfooter}>
            <Text
              allowFontScaling={allowFontScaling}
              style={_styles.sectionfooter__text}
            >
              {footer}
            </Text>
          </View>
        );
      }
      return undefined;
    };

    return (
      <View style={_styles.section}>
        {headerComponent || renderHeader()}
        <View style={styles.section_inner}>
          {React.Children.map(children, renderChild)}
        </View>
        {footerComponent || renderFooter()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  section: {
    paddingTop: 15,
    paddingBottom: 15,
  },
  section_inner: {
    borderTopWidth: StyleSheet.hairlineWidth,
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderColor: '#c8c7cc',
  },
  sectionheader: {
    paddingLeft: 15,
    paddingRight: 15,
    paddingBottom: 5,
  },
  sectionheader__text: {
    fontSize: 13,
  },
  sectionfooter: {
    paddingLeft: 15,
    paddingRight: 15,
    paddingTop: 10,
  },
  sectionfooter__text: {
    fontSize: 13,
  },
  separator: {
  },
  separator_inner: {
    height: StyleSheet.hairlineWidth,
  },
});

Section.propTypes = {
  allowFontScaling: PropTypes.bool,
  children: PropTypes.node,
  footerComponent: PropTypes.element,
  headerComponent: PropTypes.element,
  footer: PropTypes.string,
  footerTextColor: PropTypes.string,
  header: PropTypes.string,
  headerTextColor: PropTypes.string,
  hideSeparator: PropTypes.bool,
  sectionTintColor: PropTypes.string,
  separatorInsetLeft: PropTypes.number,
  separatorInsetRight: PropTypes.number,
  separatorTintColor: PropTypes.string,
};

Section.defaultProps = {
  allowFontScaling: true,
  headerTextColor: '#6d6d72',
  hideSeparator: false,
  sectionTintColor: '#EFEFF4',
  footerTextColor: '#6d6d72',
  separatorInsetLeft: 15,
  separatorInsetRight: 0,
  separatorTintColor: '#c8c7cc',
};

export default Section;
<|endoftext|>