<commit_before>/**
 * Functions related to the finding, loading and manipulation of Kanso packages
 *
 * @module
 */

var settings = require('./settings'),
    plugins_module = require('./plugins'),
    async = require('../deps/async'),
    path = require('path');


/**
 * Loads a package, passing it through all plugin preprocessors before returning
 * the resulting document.
 *
 * Each preprocessor is passed the path to the package directory, the settings
 * loaded from its kanso.json file and the document returned from the previous
 * preprocessor.
 *
 * @param {Array} plugins
 * @param {String} name - the name / path of the package to lookup
 * @param {Array} paths - an array of package lookup paths
 * @param {String} source - the current package that paths are relative to
 * @param {Function} callback
 */

exports.load = function (plugins, name, paths, source, callback) {
    exports.resolve(name, paths, source, function (err, p) {
        if (err) {
            return callback(err);
        }
        settings.load(p, function (err, cfg) {
            if (err) {
                return callback(err);
            }
            var preprocessors = plugins_module.preprocessors(plugins);
            async.reduce(preprocessors, {}, function (doc, fn, cb) {
                fn(true, p, cfg, doc, cb);
            },
            function (err, doc) {
                callback(err, doc, cfg);
            });
        });
    });
};


/**
 * Looks up the path to a specified package, returning an error if not found.
 *
 * @param {String} name - the name / path of the package to lookup
 * @param {Array} paths - an array of package lookup paths
 * @param {String} source - the current package that paths are relative to
 * @param {Function} callback
 */

exports.resolve = function (name, paths, source, callback) {
    souce = source || process.cwd();
    var candidates = [];
    if (name[0] === '/') {
        // absolute path to a specific package directory
        candidates.push(name);
    }
    else if (name[0] === '.') {
        // relative path to a specific package directory
        candidates.push(path.normalize(path.join(source, name)));
    }
    else {
        candidates = candidates.concat(paths.map(function (dir) {
            return path.join(dir, name);
        }));
    }
    async.forEachSeries(candidates, function (c, cb) {
        path.exists(path.join(c, 'kanso.json'), function (exists) {
            if (exists) {
                return callback(null, c);
            }
            cb();
        });
    },
    function () {
        return callback(new Error("Cannot find package '" + name + "'"));
    });
};
<commit_msg>stringifyFunctions before returning from packages.load<commit_after>/**
 * Functions related to the finding, loading and manipulation of Kanso packages
 *
 * @module
 */

var settings = require('./settings'),
    plugins_module = require('./plugins'),
    async = require('../deps/async'),
    utils = require('./utils'),
    path = require('path');


/**
 * Loads a package, passing it through all plugin preprocessors before returning
 * the resulting document.
 *
 * Each preprocessor is passed the path to the package directory, the settings
 * loaded from its kanso.json file and the document returned from the previous
 * preprocessor.
 *
 * @param {Array} plugins
 * @param {String} name - the name / path of the package to lookup
 * @param {Array} paths - an array of package lookup paths
 * @param {String} source - the current package that paths are relative to
 * @param {Function} callback
 */

exports.load = function (plugins, name, paths, source, callback) {
    exports.resolve(name, paths, source, function (err, p) {
        if (err) {
            return callback(err);
        }
        settings.load(p, function (err, cfg) {
            if (err) {
                return callback(err);
            }
            var preprocessors = plugins_module.preprocessors(plugins);
            async.reduce(preprocessors, {}, function (doc, fn, cb) {
                fn(true, p, cfg, doc, cb);
            },
            function (err, doc) {
                callback(err, utils.stringifyFunctions(doc), cfg);
            });
        });
    });
};


/**
 * Looks up the path to a specified package, returning an error if not found.
 *
 * @param {String} name - the name / path of the package to lookup
 * @param {Array} paths - an array of package lookup paths
 * @param {String} source - the current package that paths are relative to
 * @param {Function} callback
 */

exports.resolve = function (name, paths, source, callback) {
    souce = source || process.cwd();
    var candidates = [];
    if (name[0] === '/') {
        // absolute path to a specific package directory
        candidates.push(name);
    }
    else if (name[0] === '.') {
        // relative path to a specific package directory
        candidates.push(path.normalize(path.join(source, name)));
    }
    else {
        candidates = candidates.concat(paths.map(function (dir) {
            return path.join(dir, name);
        }));
    }
    async.forEachSeries(candidates, function (c, cb) {
        path.exists(path.join(c, 'kanso.json'), function (exists) {
            if (exists) {
                return callback(null, c);
            }
            cb();
        });
    },
    function () {
        return callback(new Error("Cannot find package '" + name + "'"));
    });
};

{'fraction_non_alphanumeric': 0.12617252161118264, 'fraction_numerical': 0.0007356998344675372, 'mean_word_length': 2.3567901234567903, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1303508', 'n_tokens_mistral': 1463, 'n_tokens_neox': 1455, 'n_words': 508}