<commit_before>var Q = require('q'),
    FS = require('fs'),
    UTIL = require('util'),
    SVGO = require('./svgo'),
    info = JSON.parse(require('fs').readFileSync(__dirname + '/../package.json')),
    datauriPrefix = 'data:image/svg+xml;base64,';

/**
 * Command-Option-Argument.
 *
 * @see https://github.com/veged/coa
 *
 * @module coa
 */
module.exports = require('coa').Cmd()
    .helpful()
    .name(info.name)
    .title(info.description)
    .opt()
        .name('version').title('Version')
        .short('v').long('version')
        .only()
        .flag()
        .act(function() {
            return info.version;
        })
        .end()
    .opt()
        .name('input').title('Input: stdin (default) | filename | Data URI base64 string')
        .short('i').long('input')
        .def(process.stdin)
        .val(function(val) {
            // https://github.com/joyent/node/issues/2130
            process.stdin.pause();

            // if value is a string and not a Data URI string
            if (typeof val === 'string' && !isDatauri(val)) {
                // then create stream
                val = FS.createReadStream(val, { encoding: 'utf8' });
                val.pause();
            }

            // else return value as is (stdin by default or Data URI string)
            return val || this.reject('Option --input must have a value.');
        })
        .end()
    .opt()
        .name('output').title('Output: stdout (default) | filename')
        .short('o').long('output')
        .output()
        .end()
    .opt()
        .name('config').title('Local config file to extend default')
        .short('c').long('config')
        .val(function(val) {
            return val || this.reject('Option --config must have a value.');
        })
        .end()
    .opt()
        .name('disable').title('Disable plugin by name')
        .long('disable')
        .arr()
        .val(function(val) {
            return val || this.reject('Option --disable must have a value.');
        })
        .end()
    .opt()
        .name('enable').title('Enable plugin by name')
        .long('enable')
        .arr()
        .val(function(val) {
            return val || this.reject('Option --enable must have a value.');
        })
        .end()
    .opt()
        .name('datauri').title('Output as Data URI base64 string')
        .long('datauri')
        .flag()
        .end()
    .opt()
        .name('pretty').title('Make SVG pretty printed')
        .long('pretty')
        .flag()
        .end()
    .opt()
        .name('test').title('Make a visual comparison of two files (PhantomJS pre-required)')
        .long('test')
        .flag()
        .end()
    .act(function(options) {

        var input = [],
            deferred = Q.defer(),
            startTime = new Date(),
            endTime,
            startBytes,
            endBytes;

        // if run as just 'svgo' display help and exit
        if (options.input.isTTY) return this.usage();

        // datauri base64 string
        if (typeof options.input === 'string') {
            deferred.resolve(convertDatauriInput(options.input));
        // stdin or file stream
        } else {
            options.input
                .on('data', function(chunk) {
                    input.push(chunk);
                })
                .once('end', function() {
                    deferred.resolve(convertDatauriInput(input.join()));
                })
                .resume();
        }

        return deferred.promise
            .then(function(svg) {
                startBytes = Buffer.byteLength(svg, 'utf-8');

                return SVGO(svg, { coa: options });
            })
            .then(function(svgmin) {
                endTime = new Date();
                endBytes = Buffer.byteLength(svgmin.data, 'utf-8');

                // --datauri
                if (options.datauri) {
                    // convert to Data URI base64 string
                    svgmin.data = datauriPrefix + new Buffer(svgmin.data).toString('base64');
                }

                var output = options.output;

                output.write(svgmin.data);

                if (output === process.stdout) {
                    output.write('\n');
                } else {
                    output.end();

                    // print time info
                    printTimeInfo(startTime, endTime);

                    // print optimization profit info
                    printProfitInfo(startBytes, endBytes);

                    // --test
                    if (options.test) {
                        // make a visual comparison of two files with PhantomJS and print info
                        printPhantomTestInfo(
                            options.input.path,
                            options.output.path,
                            svgmin.info.width || 500,
                            svgmin.info.height || 500
                        );
                    }
                }

            });

    });

/**
 * Check if string is a Data URI base64.
 *
 * @param {String} str input string
 *
 * @return {Boolean}
 */
function isDatauri(str) {

    return str.substring(0, 26) === datauriPrefix;

}

/**
 * Convert Data URI base64 string to plain SVG.
 *
 * @param {String} str input string
 *
 * @return {String} output string
 */
function convertDatauriInput(str) {

    // if datauri base64 string
    if (isDatauri(str)) {
        // then convert
        str = new Buffer(str.substring(26), 'base64').toString('utf8');
    }

    return str;

}

/**
 * Print time info.
 *
 * @param {Date} startTime start time
 * @param {Date} endTime end time
 */
function printTimeInfo(startTime, endTime) {

    UTIL.puts('\nDone in ' + (endTime - startTime) + ' ms!\n');

}

/**
 * Print optimization profit info.
 *
 * @param {Number} inBytes input file byteLength
 * @param {Number} outBytes output file byteLength
 */
function printProfitInfo(inBytes, outBytes) {

    var profitPercents = 100 - outBytes * 100 / inBytes;

    UTIL.puts(
        (Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB - ' +
        (Math.round(profitPercents * 10) / 10) + '% = ' +
        (Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB\n'
    );

}

/**
 * Make a visual comparison of two files with PhantomJS and print info.
 *
 * @param {String} file1 file1 path
 * @param {String} file2 file2 path
 * @param {Number} width width
 * @param {Number} height height
 */
function printPhantomTestInfo(file1, file2, width, height) {

    var PHANTOM = require('./phantom');

    UTIL.print('Visual comparison: ');

    PHANTOM.test(file1, file2, width, height)
        .then(function(code) {

            var answer;

            if (code === 1) {
                answer = 'OK';
            } else if (code === 2) {
                answer = 'Oops, files are not visually identical!\n\nIf you do not see any visual differences with your eyes then ALL IS OK and there are only very minor floating point numbers rounding errors in some browsers.\nBut if you see significant errors then things are bad :), please create an issue at https://github.com/svg/svgo/issues';
            } else if (code === 3) {
                answer = 'Error while rendering SVG\nPlease create an issue at https://github.com/svg/svgo/issues';
            } else if (code === 127) {
                answer = 'Error, you need to install PhantomJS first http://phantomjs.org/download.html';
            } else {
                answer = 'Error, something went wrong\nPlease create an issue at https://github.com/svg/svgo/issues';
            }

            UTIL.print(answer + '\n\n');

        });

}
<commit_msg>lib/coa: open file for writing only when we are ready (fix #2)<commit_after>var Q = require('q'),
    FS = require('fs'),
    UTIL = require('util'),
    SVGO = require('./svgo'),
    info = JSON.parse(require('fs').readFileSync(__dirname + '/../package.json')),
    datauriPrefix = 'data:image/svg+xml;base64,';

/**
 * Command-Option-Argument.
 *
 * @see https://github.com/veged/coa
 *
 * @module coa
 */
module.exports = require('coa').Cmd()
    .helpful()
    .name(info.name)
    .title(info.description)
    .opt()
        .name('version').title('Version')
        .short('v').long('version')
        .only()
        .flag()
        .act(function() {
            return info.version;
        })
        .end()
    .opt()
        .name('input').title('Input: stdin (default) | filename | Data URI base64 string')
        .short('i').long('input')
        .def(process.stdin)
        .val(function(val) {
            // https://github.com/joyent/node/issues/2130
            process.stdin.pause();

            // if value is a string and not a Data URI string
            if (typeof val === 'string' && !isDatauri(val)) {
                // then create stream
                val = FS.createReadStream(val, { encoding: 'utf8' });
                val.pause();
            }

            // else return value as is (stdin by default or Data URI string)
            return val || this.reject('Option --input must have a value.');
        })
        .end()
    .opt()
        .name('output').title('Output: stdout (default) | filename')
        .short('o').long('output')
        .def(process.stdout)
        .val(function(val) {
            return val || this.reject('Option --output must have a value.');
        })
        .end()
    .opt()
        .name('config').title('Local config file to extend default')
        .short('c').long('config')
        .val(function(val) {
            return val || this.reject('Option --config must have a value.');
        })
        .end()
    .opt()
        .name('disable').title('Disable plugin by name')
        .long('disable')
        .arr()
        .val(function(val) {
            return val || this.reject('Option --disable must have a value.');
        })
        .end()
    .opt()
        .name('enable').title('Enable plugin by name')
        .long('enable')
        .arr()
        .val(function(val) {
            return val || this.reject('Option --enable must have a value.');
        })
        .end()
    .opt()
        .name('datauri').title('Output as Data URI base64 string')
        .long('datauri')
        .flag()
        .end()
    .opt()
        .name('pretty').title('Make SVG pretty printed')
        .long('pretty')
        .flag()
        .end()
    .opt()
        .name('test').title('Make a visual comparison of two files (PhantomJS pre-required)')
        .long('test')
        .flag()
        .end()
    .act(function(options) {

        var input = options.input,
            output = options.output,
            inputData = [],
            deferred = Q.defer(),
            startTime = new Date(),
            endTime,
            startBytes,
            endBytes;

        // if run as just 'svgo' display help and exit
        if (input.isTTY) return this.usage();

        // datauri base64 string
        if (typeof input === 'string') {
            deferred.resolve(convertDatauriInput(input));
        // stdin or file stream
        } else {
            input
                .on('data', function(chunk) {
                    inputData.push(chunk);
                })
                .once('end', function() {
                    deferred.resolve(convertDatauriInput(inputData.join()));
                })
                .resume();
        }

        return deferred.promise
            .then(function(svg) {
                startBytes = Buffer.byteLength(svg, 'utf-8');

                return SVGO(svg, { coa: options });
            })
            .then(function(svgmin) {
                endTime = new Date();
                endBytes = Buffer.byteLength(svgmin.data, 'utf-8');

                // --datauri
                if (options.datauri) {
                    // convert to Data URI base64 string
                    svgmin.data = datauriPrefix + new Buffer(svgmin.data).toString('base64');
                }

                // var output = options.output;

                if (typeof output === 'string') {
                    output = FS.createWriteStream(output, { encoding: 'utf8' });
                }

                output.write(svgmin.data);

                if (output === process.stdout) {
                    output.write('\n');
                } else {
                    output.end();

                    // print time info
                    printTimeInfo(startTime, endTime);

                    // print optimization profit info
                    printProfitInfo(startBytes, endBytes);

                    // --test
                    if (options.test) {
                        // make a visual comparison of two files with PhantomJS and print info
                        printPhantomTestInfo(
                            input.path,
                            output.path,
                            svgmin.info.width || 500,
                            svgmin.info.height || 500
                        );
                    }
                }

            });

    });

/**
 * Check if string is a Data URI base64.
 *
 * @param {String} str input string
 *
 * @return {Boolean}
 */
function isDatauri(str) {

    return str.substring(0, 26) === datauriPrefix;

}

/**
 * Convert Data URI base64 string to plain SVG.
 *
 * @param {String} str input string
 *
 * @return {String} output string
 */
function convertDatauriInput(str) {

    // if datauri base64 string
    if (isDatauri(str)) {
        // then convert
        str = new Buffer(str.substring(26), 'base64').toString('utf8');
    }

    return str;

}

/**
 * Print time info.
 *
 * @param {Date} startTime start time
 * @param {Date} endTime end time
 */
function printTimeInfo(startTime, endTime) {

    UTIL.puts('\nDone in ' + (endTime - startTime) + ' ms!\n');

}

/**
 * Print optimization profit info.
 *
 * @param {Number} inBytes input file byteLength
 * @param {Number} outBytes output file byteLength
 */
function printProfitInfo(inBytes, outBytes) {

    var profitPercents = 100 - outBytes * 100 / inBytes;

    UTIL.puts(
        (Math.round((inBytes / 1024) * 1000) / 1000) + ' KiB - ' +
        (Math.round(profitPercents * 10) / 10) + '% = ' +
        (Math.round((outBytes / 1024) * 1000) / 1000) + ' KiB\n'
    );

}

/**
 * Make a visual comparison of two files with PhantomJS and print info.
 *
 * @param {String} file1 file1 path
 * @param {String} file2 file2 path
 * @param {Number} width width
 * @param {Number} height height
 */
function printPhantomTestInfo(file1, file2, width, height) {

    var PHANTOM = require('./phantom');

    UTIL.print('Visual comparison: ');

    PHANTOM.test(file1, file2, width, height)
        .then(function(code) {

            var answer;

            if (code === 1) {
                answer = 'OK';
            } else if (code === 2) {
                answer = 'Oops, files are not visually identical!\n\nIf you do not see any visual differences with your eyes then ALL IS OK and there are only very minor floating point numbers rounding errors in some browsers.\nBut if you see significant errors then things are bad :), please create an issue at https://github.com/svg/svgo/issues';
            } else if (code === 3) {
                answer = 'Error while rendering SVG\nPlease create an issue at https://github.com/svg/svgo/issues';
            } else if (code === 127) {
                answer = 'Error, you need to install PhantomJS first http://phantomjs.org/download.html';
            } else {
                answer = 'Error, something went wrong\nPlease create an issue at https://github.com/svg/svgo/issues';
            }

            UTIL.print(answer + '\n\n');

        });

}
<|endoftext|>


<commit_before>/*jslint node: true */

"use strict";

var os = require("os"),
    request = require("request");

var config = {
    liveDomain: "x.x.x",
    liveUrl: "liveUrl",
    liveDb: "myLiveDBName",
    testingUrl: "testingUrl",
    testingDb: "myTestingDBName",
    design: "design",
    configured: false
};

function configure(params) {
    config.liveDomain = params.liveDomain || config.liveDomain;
    config.liveUrl = params.liveUrl || config.liveUrl;
    config.liveDb = "/" + (params.liveDb || config.liveDb);
    config.testingUrl = params.testingUrl || config.testingUrl;
    config.testingDb = "/" + (params.testingDb || config.testingDb);
    config.design = params.design || config.design;

    config.configured = true;
}
exports.configure = configure;

function isLiveInstance() {
    var hostname = os.hostname(),
        isLive = false;

    if (hostname.search(config.liveDomain) >= 0) {
        isLive = true;
    }

    return isLive;
}

function getCouchDBInstance() {
    var isLive, couchURL, couchDB, couchDesign;

    isLive = isLiveInstance();

    couchURL = isLive ? config.liveUrl : config.testingUrl;
    couchDB = isLive ? couchURL + config.liveDb : couchURL + config.testingDb;
    couchDesign = "/_design/" + config.design;

    return {
        couchURL: couchURL,
        couchDB: couchDB,
        couchDesign: couchDesign
    };
}

function putPortfolioOnCRM(params, callback) {
    var couch = getCouchDBInstance(),
        symbols,
        weights,
        ref,
        ret,
        risk,
        perf,
        highs,
        lows,
        ptf,
        now,
        ddNow,
        mmNow,
        yyyyNow,
        HHNow,
        MMNow,
        SSNow,
        ddRef,
        mmRef,
        yyyyRef;

    symbols = params.symbols;
    weights = params.weights;
    ref = params.ref;
    ret = parseFloat(params.ret);
    risk = params.risk;
    perf = params.perf || [];
    highs = params.highs;
    lows = params.lows;

    ref = new Date(ref); // from String to Date object
    now = new Date();

    ddNow = now.getDate();
    mmNow = now.getMonth() + 1;
    yyyyNow = now.getFullYear();
    HHNow = now.getHours();
    MMNow = now.getMinutes();
    SSNow = now.getSeconds();

    ddRef = ref.getDate();
    mmRef = ref.getMonth() + 1;
    yyyyRef = ref.getFullYear();

    ptf = {
        /*eslint-disable camelcase */
        created_at: yyyyNow + "/" + // yyyy/mm/dd hh:mm:ss
            (mmNow < 10 ? "0" + mmNow : mmNow) + "/" +
            (ddNow < 10 ? "0" + ddNow : ddNow) + " " +
            (HHNow < 10 ? "0" + HHNow : HHNow) + ":" +
            (MMNow < 10 ? "0" + MMNow : MMNow) + ":" +
            (SSNow < 10 ? "0" + SSNow : SSNow),
        /*eslint-enable camelcase */
        assets: symbols,
        weights: weights,
        ref: yyyyRef + "/" + // yyyy/mm/dd
            (mmRef < 10 ? "0" + mmRef : mmRef) + "/" +
            (ddRef < 10 ? "0" + ddRef : ddRef),
        ret: Math.pow(1 + ret, 52) - 1, // annualized: ret weekly
        risk: risk * Math.sqrt(52), // annualized: risk weekly
        perf: perf.length > 0 ? perf[perf.length - 1] : 0,
        constraints: {
            lowBounds: lows,
            highBounds: highs
        }
    };

    request({
        method: "POST",
        uri: couch.couchDB,
        json: ptf
    }, function (error, response, data) {
        var res = {};

        res.id = "";

        if (!error) {
            res = data;
        }
        callback(error, res.id);
    });
}
exports.putPortfolioOnCRM = putPortfolioOnCRM;

function getPortfolio(params, callback) {
    var couch = getCouchDBInstance();

    request({
        method: "GET",
        uri: couch.couchDB + "/" + params.id
    }, function (error, response, data) {
        var res = {};

        if (!error) {
            res = data;
        }

        callback(error, res);
    });
}
exports.getPortfolio = getPortfolio;

function getView(name, options, callback) {
    var couch = getCouchDBInstance(),
        view = couch.couchDesign + "/_view/" + name,
        opt,
        opts = "?";

    for (opt in options) {
        if (options.hasOwnProperty(opt)) {
            opts += opt + "=" + options[opt] + "&";
        }
    }

    request({
        method: "GET",
        uri: couch.couchDB + view + opts,
        json: true
    }, function (error, response, data) {
        callback(error, data);
    });
}

function getPortfolioCount(callback) {
    getView("viewByRef", {
        group: false,
        reduce: true
    }, callback); // rows[0].value
}
exports.getPortfolioCount = getPortfolioCount;

function getLastCreatedPortfolios(limit, callback) {
    getView("viewByCreatedAt", {
        limit: limit || 5,
        descending: true
    }, callback);
}
exports.getLastCreatedPortfolios = getLastCreatedPortfolios;

function getHighProfileRiskPortfolios(limit, callback) {
    getView("viewByRisk", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getHighProfileRiskPortfolios = getHighProfileRiskPortfolios;

function getLowProfileRiskPortfolios(limit, callback) {
    getView("viewByRisk", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getLowProfileRiskPortfolios = getLowProfileRiskPortfolios;

function getHighProfileReturnPortfolios(limit, callback) {
    getView("viewByRet", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getHighProfileReturnPortfolios = getHighProfileReturnPortfolios;

function getLowProfileReturnPortfolios(limit, callback) {
    getView("viewByRet", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getLowProfileReturnPortfolios = getLowProfileReturnPortfolios;

function getBestPerformingPortfolios(limit, callback) {
    getView("viewByPerf", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getBestPerformingPortfolios = getBestPerformingPortfolios;

function getWorstPerformingPortfolios(limit, callback) {
    return getView("viewByPerf", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getWorstPerformingPortfolios = getWorstPerformingPortfolios;

function getMostUsedAssets(callback) {
    getView("viewMostUsedAssets", {
        group: false,
        reduce: true
    }, function (error, data) {
        var key, n = 10, mostUsedSymbols, mostUsedSymbolsSortable = [];

        mostUsedSymbols = data.rows[0].value;

        for (key in mostUsedSymbols) {
            if (mostUsedSymbols.hasOwnProperty(key)) {
                mostUsedSymbolsSortable.push([key, mostUsedSymbols[key]]);
            }
        }

        mostUsedSymbolsSortable.sort(function (a, b) {
            return b[1] - a[1];
        });

        if (mostUsedSymbolsSortable.length > n) {
            mostUsedSymbolsSortable.splice(n,
                mostUsedSymbolsSortable.length - n - 1);
        }

        callback(error, mostUsedSymbolsSortable);
    });
    // key: "stock", value: {stock: frequency}
}
exports.getMostUsedAssets = getMostUsedAssets;
<commit_msg>Check data in getMostUsedAssets.<commit_after>/*jslint node: true */

"use strict";

var os = require("os"),
    request = require("request");

var config = {
    liveDomain: "x.x.x",
    liveUrl: "liveUrl",
    liveDb: "myLiveDBName",
    testingUrl: "testingUrl",
    testingDb: "myTestingDBName",
    design: "design",
    configured: false
};

function configure(params) {
    config.liveDomain = params.liveDomain || config.liveDomain;
    config.liveUrl = params.liveUrl || config.liveUrl;
    config.liveDb = "/" + (params.liveDb || config.liveDb);
    config.testingUrl = params.testingUrl || config.testingUrl;
    config.testingDb = "/" + (params.testingDb || config.testingDb);
    config.design = params.design || config.design;

    config.configured = true;
}
exports.configure = configure;

function isLiveInstance() {
    var hostname = os.hostname(),
        isLive = false;

    if (hostname.search(config.liveDomain) >= 0) {
        isLive = true;
    }

    return isLive;
}

function getCouchDBInstance() {
    var isLive, couchURL, couchDB, couchDesign;

    isLive = isLiveInstance();

    couchURL = isLive ? config.liveUrl : config.testingUrl;
    couchDB = isLive ? couchURL + config.liveDb : couchURL + config.testingDb;
    couchDesign = "/_design/" + config.design;

    return {
        couchURL: couchURL,
        couchDB: couchDB,
        couchDesign: couchDesign
    };
}

function putPortfolioOnCRM(params, callback) {
    var couch = getCouchDBInstance(),
        symbols,
        weights,
        ref,
        ret,
        risk,
        perf,
        highs,
        lows,
        ptf,
        now,
        ddNow,
        mmNow,
        yyyyNow,
        HHNow,
        MMNow,
        SSNow,
        ddRef,
        mmRef,
        yyyyRef;

    symbols = params.symbols;
    weights = params.weights;
    ref = params.ref;
    ret = parseFloat(params.ret);
    risk = params.risk;
    perf = params.perf || [];
    highs = params.highs;
    lows = params.lows;

    ref = new Date(ref); // from String to Date object
    now = new Date();

    ddNow = now.getDate();
    mmNow = now.getMonth() + 1;
    yyyyNow = now.getFullYear();
    HHNow = now.getHours();
    MMNow = now.getMinutes();
    SSNow = now.getSeconds();

    ddRef = ref.getDate();
    mmRef = ref.getMonth() + 1;
    yyyyRef = ref.getFullYear();

    ptf = {
        /*eslint-disable camelcase */
        created_at: yyyyNow + "/" + // yyyy/mm/dd hh:mm:ss
            (mmNow < 10 ? "0" + mmNow : mmNow) + "/" +
            (ddNow < 10 ? "0" + ddNow : ddNow) + " " +
            (HHNow < 10 ? "0" + HHNow : HHNow) + ":" +
            (MMNow < 10 ? "0" + MMNow : MMNow) + ":" +
            (SSNow < 10 ? "0" + SSNow : SSNow),
        /*eslint-enable camelcase */
        assets: symbols,
        weights: weights,
        ref: yyyyRef + "/" + // yyyy/mm/dd
            (mmRef < 10 ? "0" + mmRef : mmRef) + "/" +
            (ddRef < 10 ? "0" + ddRef : ddRef),
        ret: Math.pow(1 + ret, 52) - 1, // annualized: ret weekly
        risk: risk * Math.sqrt(52), // annualized: risk weekly
        perf: perf.length > 0 ? perf[perf.length - 1] : 0,
        constraints: {
            lowBounds: lows,
            highBounds: highs
        }
    };

    request({
        method: "POST",
        uri: couch.couchDB,
        json: ptf
    }, function (error, response, data) {
        var res = {};

        res.id = "";

        if (!error) {
            res = data;
        }
        callback(error, res.id);
    });
}
exports.putPortfolioOnCRM = putPortfolioOnCRM;

function getPortfolio(params, callback) {
    var couch = getCouchDBInstance();

    request({
        method: "GET",
        uri: couch.couchDB + "/" + params.id
    }, function (error, response, data) {
        var res = {};

        if (!error) {
            res = data;
        }

        callback(error, res);
    });
}
exports.getPortfolio = getPortfolio;

function getView(name, options, callback) {
    var couch = getCouchDBInstance(),
        view = couch.couchDesign + "/_view/" + name,
        opt,
        opts = "?";

    for (opt in options) {
        if (options.hasOwnProperty(opt)) {
            opts += opt + "=" + options[opt] + "&";
        }
    }

    request({
        method: "GET",
        uri: couch.couchDB + view + opts,
        json: true
    }, function (error, response, data) {
        callback(error, data);
    });
}

function getPortfolioCount(callback) {
    getView("viewByRef", {
        group: false,
        reduce: true
    }, callback); // rows[0].value
}
exports.getPortfolioCount = getPortfolioCount;

function getLastCreatedPortfolios(limit, callback) {
    getView("viewByCreatedAt", {
        limit: limit || 5,
        descending: true
    }, callback);
}
exports.getLastCreatedPortfolios = getLastCreatedPortfolios;

function getHighProfileRiskPortfolios(limit, callback) {
    getView("viewByRisk", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getHighProfileRiskPortfolios = getHighProfileRiskPortfolios;

function getLowProfileRiskPortfolios(limit, callback) {
    getView("viewByRisk", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getLowProfileRiskPortfolios = getLowProfileRiskPortfolios;

function getHighProfileReturnPortfolios(limit, callback) {
    getView("viewByRet", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getHighProfileReturnPortfolios = getHighProfileReturnPortfolios;

function getLowProfileReturnPortfolios(limit, callback) {
    getView("viewByRet", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getLowProfileReturnPortfolios = getLowProfileReturnPortfolios;

function getBestPerformingPortfolios(limit, callback) {
    getView("viewByPerf", {
        limit: limit || 3,
        descending: true
    }, callback);
}
exports.getBestPerformingPortfolios = getBestPerformingPortfolios;

function getWorstPerformingPortfolios(limit, callback) {
    return getView("viewByPerf", {
        limit: limit || 3,
        ascending: true
    }, callback);
}
exports.getWorstPerformingPortfolios = getWorstPerformingPortfolios;

function getMostUsedAssets(callback) {
    getView("viewMostUsedAssets", {
        group: false,
        reduce: true
    }, function (error, data) {
        var key, n = 10, mostUsedSymbols, mostUsedSymbolsSortable = [];

        if (data) {
            mostUsedSymbols = data.rows[0].value;
        } else {
            callback("Most used assets not available", null);
            return;
        }

        for (key in mostUsedSymbols) {
            if (mostUsedSymbols.hasOwnProperty(key)) {
                mostUsedSymbolsSortable.push([key, mostUsedSymbols[key]]);
            }
        }

        mostUsedSymbolsSortable.sort(function (a, b) {
            return b[1] - a[1];
        });

        if (mostUsedSymbolsSortable.length > n) {
            mostUsedSymbolsSortable.splice(n,
                mostUsedSymbolsSortable.length - n - 1);
        }

        callback(error, mostUsedSymbolsSortable);
    });
    // key: "stock", value: {stock: frequency}
}
exports.getMostUsedAssets = getMostUsedAssets;
<|endoftext|>


<commit_before>/*  Copyright (C) 2016  173210 <root.3.173210@live.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

window.onerror = function(message) {
	alert(message);
}

var open = window.indexedDB.open("tweets", 4);
var openDone = false;

function showError(event) {
	alert(event.target.error);
}

function changeStatusRunning(element) {
	element.className = "running";
}

function changeStatus(element, status) {
	element.textContent = status;
}

function showProgress(element, loaded, total) {
	element.value = loaded / total * 100;
}

open.onerror = showError;

open.onsuccess = function() {
	openDone = true;
}

document.getElementById("file").onchange = function() {
	var file = this;
	file.disabled = true;

	var reader = new FileReader();

	reader.onerror = showError;

	var readerProgress = document.getElementById("reader-progress");
	var readerStatus = document.getElementById("reader-status");

	reader.onloadstart = function() {
		changeStatusRunning(readerStatus);
	}

	reader.onprogress = function(event) {
		if (event.lengthComputable) {
			changeStatus(readerStatus,
				"Reading (" + event.loaded + "/" + event.total + " bytes)");

			showProgress(readerProgress, event.loaded, event.total);
		}
	}

	reader.onload = function(event) {
		reader.onprogress(event);

		var parseProgress = document.getElementById("parse-progress");
		var parseStatus = document.getElementById("parse-status");
		changeStatusRunning(parseStatus);

		var entry = "";
		var rows = [];
		var row = [];
		for (var i = 0; i < this.result.length;) {
			switch (this.result[i]) {
			case ",":
				row.push(entry);
				entry = "";
				i++;
				break;

			case "\n":
				row.push(entry);
				rows.push(row);
				entry = "";
				row = [];
				i++;
				break;

			case "\"":
				while (true) {
					i++;
					if (this.result[i] == "\"") {
						i++;
						if (this.result[i] == "\"") {
							entry += "\"";
						} else {
							break;
						}
					} else {
						entry += this.result[i];
					}
				}

				break;

			default:
				entry += this.result[i];
				i++;
				break;
			}

			changeStatus(parseStatus, "Parsing ("
				+ i + "/" + this.result.length + " bytes, "
				+ rows.length + " entries)");

			showProgress(parseProgress, i, this.result.length);
		}

		open.onsuccess = function() {
			var storeProgress = document.getElementById("store-progress");
			var storeStatus = document.getElementById("store-status");
			changeStatusRunning(storeStatus);

			var store = open.result
				.transaction("tweets", "readwrite")
				.objectStore("tweets");
			var text = document.createElement("textarea");

			for (i = 1; i < rows.length; i++) {
				var object = { };
				for (var j = 0; j < rows[i].length; j++) {
					text.innerHTML = rows[i][j];
					object[rows[0][j]] = text.value;
					}

				store.add(object).onerror = showError;

				changeStatus(storeStatus, "Storing ("
					+ i + "/" + (rows.length - 1)
					+ " tweets)");

				showProgress(storeProgress, i, rows.length);
			}

			var doneStatus = document.getElementById("done-status");
			changeStatusRunning(doneStatus);
			changeStatus(doneStatus,
				"Done (Type \"tweets\" in the omnibox and press tab to search tweets)");
		}

		if (openDone)
			open.onsuccess();
	}

	reader.readAsText(this.files[0]);
}
<commit_msg>import: Assert all requests has been done<commit_after>/*  Copyright (C) 2016  173210 <root.3.173210@live.com>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

window.onerror = function(message) {
	alert(message);
}

var open = window.indexedDB.open("tweets", 4);
var openDone = false;

function showError(event) {
	alert(event.target.error);
}

function changeStatusRunning(element) {
	element.className = "running";
}

function changeStatus(element, status) {
	element.textContent = status;
}

function showProgress(element, loaded, total) {
	element.value = loaded / total * 100;
}

open.onerror = showError;

open.onsuccess = function() {
	openDone = true;
}

document.getElementById("file").onchange = function() {
	var file = this;
	file.disabled = true;

	var reader = new FileReader();

	reader.onerror = showError;

	var readerProgress = document.getElementById("reader-progress");
	var readerStatus = document.getElementById("reader-status");

	reader.onloadstart = function() {
		changeStatusRunning(readerStatus);
	}

	reader.onprogress = function(event) {
		if (event.lengthComputable) {
			changeStatus(readerStatus,
				"Reading (" + event.loaded + "/" + event.total + " bytes)");

			showProgress(readerProgress, event.loaded, event.total);
		}
	}

	reader.onload = function(event) {
		reader.onprogress(event);

		var parseProgress = document.getElementById("parse-progress");
		var parseStatus = document.getElementById("parse-status");
		changeStatusRunning(parseStatus);

		var entry = "";
		var rows = [];
		var row = [];
		for (var i = 0; i < this.result.length;) {
			switch (this.result[i]) {
			case ",":
				row.push(entry);
				entry = "";
				i++;
				break;

			case "\n":
				row.push(entry);
				rows.push(row);
				entry = "";
				row = [];
				i++;
				break;

			case "\"":
				while (true) {
					i++;
					if (this.result[i] == "\"") {
						i++;
						if (this.result[i] == "\"") {
							entry += "\"";
						} else {
							break;
						}
					} else {
						entry += this.result[i];
					}
				}

				break;

			default:
				entry += this.result[i];
				i++;
				break;
			}

			changeStatus(parseStatus, "Parsing ("
				+ i + "/" + this.result.length + " bytes, "
				+ rows.length + " entries)");

			showProgress(parseProgress, i, this.result.length);
		}

		open.onsuccess = function() {
			var storeProgress = document.getElementById("store-progress");
			var storeStatus = document.getElementById("store-status");
			changeStatusRunning(storeStatus);

			var store = open.result
				.transaction("tweets", "readwrite")
				.objectStore("tweets");
			var text = document.createElement("textarea");

			stored = 1;
			for (i = 1; i < rows.length; i++) {
				var object = { };
				for (var j = 0; j < rows[i].length; j++) {
					text.innerHTML = rows[i][j];
					object[rows[0][j]] = text.value;
					}

				var request = store.add(object);
				request.onerror = showError;
				request.onsuccess = function() {
					stored++;
					if (stored >= rows.length) {
						var doneStatus = document.getElementById("done-status");
						changeStatusRunning(doneStatus);
						changeStatus(doneStatus,
						"Done (Type \"tweets\" in the omnibox and press tab to search tweets)");
					}
				}

				changeStatus(storeStatus, "Storing ("
					+ i + "/" + (rows.length - 1)
					+ " tweets)");

				showProgress(storeProgress, i, rows.length);
			}
		}

		if (openDone)
			open.onsuccess();
	}

	reader.readAsText(this.files[0]);
}
<|endoftext|>


<commit_before>"use strict";

var crx = require('crx');
var path = require('path');

var required_properties = ['manifest_version', 'name', 'version'];
var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
var filename_template = "<%= pkg.name %>-<%= manifest.version %>.crx";

/**
 * Resolve the home directory of a supposed-path value
 *
 * @param {String} value
 * @returns {String}
 */
function resolveHomeDirectory(value){
  if (homeDir && typeof value === 'string' && value[0] === '~'){
    value = value.replace(/^~/, homeDir);
  }

  return value;
}

/**
 * Initializes the grunt helper
 *
 * @param {grunt} grunt
 * @returns {{build: Function, expandConfiguration: Function, getTaskConfiguration: Function, resolveHomeDirectory: Function}}
 */
exports.init = function(grunt){
  /**
   * Builds a pre-configured chrome extension in 3 steps
   *
   * @api
   * @param {crx} ChromeExtension
   * @param {Function} callback
   * @return null
   */
  function build(ChromeExtension, callback) {
    grunt.file.mkdir(path.dirname(ChromeExtension.dest));

    grunt.util.async.series([
      function loadFilesInTemporaryFolder(next){
        ChromeExtension.load(next);
      },
      function removeExcludedFiles(next){
        if (!Array.isArray(ChromeExtension.exclude) || !ChromeExtension.exclude.length){
          return next();
        }

        var files = grunt.file.expand(ChromeExtension.exclude.map(function(pattern){
          return path.join(ChromeExtension.path, '/', pattern);
        }));

        // deletes all the file in parallel
        grunt.util.async.forEach(files, function(filepath, done){
          grunt.file.delete(filepath, {force: true});

          done();
        }, next);
      },
      function finallyPackFiles(next){
        ChromeExtension.pack(function(err, data){
          if (err){
            throw new grunt.task.taskError(err);
          }

          grunt.file.write(this.dest, data);

          next();
        });
      }
    ], callback);
  }

  function createObject(taskConfig, defaults){
    taskConfig = expandConfiguration(taskConfig, defaults);

    return new crx(taskConfig);
  }

  /**
   * Refines a task configuration (expand settings etc.)
   *
   * @param {Object} taskConfig
   * @param {Object=} defaults
   * @return {Object}
   */
  function expandConfiguration(taskConfig, defaults){
    defaults = defaults || getTaskConfiguration();
    var config = grunt.util._.defaults({}, taskConfig,  defaults);

    ['dest', 'src'].forEach(function(key){
      if ((Array.isArray(config[key]) && config[key].length === 0) || !config[key]){
        grunt.fail.fatal("You can't specify an empty '"+key+"' configuration value.");
      }
    });

    // XXX (alexeykuzmin): Is there a better way to get source folder path?
    var sourceDir = Array.isArray(config.src) ? config.src[0] : config.src;

    // Eventually expanding `~` in config paths
    ['privateKey', 'src', 'dest'].forEach(function(key){
      config[key] = resolveHomeDirectory(config[key]);
    });

    // Checking availability
    if (!grunt.file.exists(sourceDir)){
      grunt.fail.fatal('Unable to locate source directory.');
    }

    if (!grunt.file.exists(config.privateKey)){
      grunt.fail.fatal('Unable to locate your private key.');
    }
    else{
      config.privateKey = grunt.file.read(config.privateKey);
    }

    // Check extension manifest
    config.manifest = grunt.file.readJSON(path.join(sourceDir, 'manifest.json'));
    required_properties.forEach(function(prop) {
      if ('undefined' === typeof config.manifest[prop]) {
        grunt.fail.fatal('Invalid manifest: property "' + prop + '" is missing.');
      }
    });

    // Expanding destination
    if (grunt.file.isDir(config.dest)){
      var filename = config.filename || filename_template;

      config.dest = path.join(config.dest, filename);
    }

    ['dest'].forEach(function(key){
      config[key] = grunt.template.process(config[key], {
        "data": {
          "manifest": config.manifest,
          "pkg": grunt.file.readJSON('package.json')
        }
      });
    });

    // Codebase generation (@todo cleanup that with clean separation of grunt and chrome extension config)
    config.codebase = config.baseURL || config.codebase || null;

    if (config.codebase && !/.crx$/.test(config.codebase)){
      config.codebase = config.codebase.replace(/\/$/, '');
      config.codebase += '/' + path.basename(config.dest);
    }

    // @todo remove that to better separate grunt config and Chrome Extension config
    // rootDirectory should be a String, not Array
    config.rootDirectory = sourceDir;
    config.maxBuffer = config.options.maxBuffer || config.maxBuffer || undefined;

    return config;
  }

  /**
   * Returns a task configuration profile
   *
   * @param {String=} profile
   * @return {Object}
   */
  function getTaskConfiguration(profile){
    var config;

    profile = profile || 'default';

    config = grunt.file.readJSON(__dirname + '/../data/config-'+ profile +'.json');

    return config;
  }

  /*
   * Blending
   */
  return {
    "build": build,
    "createObject": createObject,
    "expandConfiguration": expandConfiguration,
    "filename": filename_template,
    "getTaskConfiguration": getTaskConfiguration,
    "resolveHomeDirectory": resolveHomeDirectory
  };
};
<commit_msg>`grunt.task.taskError` -> `grunt.fail.fatal`<commit_after>"use strict";

var crx = require('crx');
var path = require('path');

var required_properties = ['manifest_version', 'name', 'version'];
var homeDir = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
var filename_template = "<%= pkg.name %>-<%= manifest.version %>.crx";

/**
 * Resolve the home directory of a supposed-path value
 *
 * @param {String} value
 * @returns {String}
 */
function resolveHomeDirectory(value){
  if (homeDir && typeof value === 'string' && value[0] === '~'){
    value = value.replace(/^~/, homeDir);
  }

  return value;
}

/**
 * Initializes the grunt helper
 *
 * @param {grunt} grunt
 * @returns {{build: Function, expandConfiguration: Function, getTaskConfiguration: Function, resolveHomeDirectory: Function}}
 */
exports.init = function(grunt){
  /**
   * Builds a pre-configured chrome extension in 3 steps
   *
   * @api
   * @param {crx} ChromeExtension
   * @param {Function} callback
   * @return null
   */
  function build(ChromeExtension, callback) {
    grunt.file.mkdir(path.dirname(ChromeExtension.dest));

    grunt.util.async.series([
      function loadFilesInTemporaryFolder(next){
        ChromeExtension.load(next);
      },
      function removeExcludedFiles(next){
        if (!Array.isArray(ChromeExtension.exclude) || !ChromeExtension.exclude.length){
          return next();
        }

        var files = grunt.file.expand(ChromeExtension.exclude.map(function(pattern){
          return path.join(ChromeExtension.path, '/', pattern);
        }));

        // deletes all the file in parallel
        grunt.util.async.forEach(files, function(filepath, done){
          grunt.file.delete(filepath, {force: true});

          done();
        }, next);
      },
      function finallyPackFiles(next){
        ChromeExtension.pack(function(err, data){
          if (err){
            throw new grunt.fail.fatal(err);
          }

          grunt.file.write(this.dest, data);

          next();
        });
      }
    ], callback);
  }

  function createObject(taskConfig, defaults){
    taskConfig = expandConfiguration(taskConfig, defaults);

    return new crx(taskConfig);
  }

  /**
   * Refines a task configuration (expand settings etc.)
   *
   * @param {Object} taskConfig
   * @param {Object=} defaults
   * @return {Object}
   */
  function expandConfiguration(taskConfig, defaults){
    defaults = defaults || getTaskConfiguration();
    var config = grunt.util._.defaults({}, taskConfig,  defaults);

    ['dest', 'src'].forEach(function(key){
      if ((Array.isArray(config[key]) && config[key].length === 0) || !config[key]){
        grunt.fail.fatal("You can't specify an empty '"+key+"' configuration value.");
      }
    });

    // XXX (alexeykuzmin): Is there a better way to get source folder path?
    var sourceDir = Array.isArray(config.src) ? config.src[0] : config.src;

    // Eventually expanding `~` in config paths
    ['privateKey', 'src', 'dest'].forEach(function(key){
      config[key] = resolveHomeDirectory(config[key]);
    });

    // Checking availability
    if (!grunt.file.exists(sourceDir)){
      grunt.fail.fatal('Unable to locate source directory.');
    }

    if (!grunt.file.exists(config.privateKey)){
      grunt.fail.fatal('Unable to locate your private key.');
    }
    else{
      config.privateKey = grunt.file.read(config.privateKey);
    }

    // Check extension manifest
    config.manifest = grunt.file.readJSON(path.join(sourceDir, 'manifest.json'));
    required_properties.forEach(function(prop) {
      if ('undefined' === typeof config.manifest[prop]) {
        grunt.fail.fatal('Invalid manifest: property "' + prop + '" is missing.');
      }
    });

    // Expanding destination
    if (grunt.file.isDir(config.dest)){
      var filename = config.filename || filename_template;

      config.dest = path.join(config.dest, filename);
    }

    ['dest'].forEach(function(key){
      config[key] = grunt.template.process(config[key], {
        "data": {
          "manifest": config.manifest,
          "pkg": grunt.file.readJSON('package.json')
        }
      });
    });

    // Codebase generation (@todo cleanup that with clean separation of grunt and chrome extension config)
    config.codebase = config.baseURL || config.codebase || null;

    if (config.codebase && !/.crx$/.test(config.codebase)){
      config.codebase = config.codebase.replace(/\/$/, '');
      config.codebase += '/' + path.basename(config.dest);
    }

    // @todo remove that to better separate grunt config and Chrome Extension config
    // rootDirectory should be a String, not Array
    config.rootDirectory = sourceDir;
    config.maxBuffer = config.options.maxBuffer || config.maxBuffer || undefined;

    return config;
  }

  /**
   * Returns a task configuration profile
   *
   * @param {String=} profile
   * @return {Object}
   */
  function getTaskConfiguration(profile){
    var config;

    profile = profile || 'default';

    config = grunt.file.readJSON(__dirname + '/../data/config-'+ profile +'.json');

    return config;
  }

  /*
   * Blending
   */
  return {
    "build": build,
    "createObject": createObject,
    "expandConfiguration": expandConfiguration,
    "filename": filename_template,
    "getTaskConfiguration": getTaskConfiguration,
    "resolveHomeDirectory": resolveHomeDirectory
  };
};
<|endoftext|>


<commit_before>var Path = require('path');
var FS = require('fs');

function Ctx() {
  this.reset();
  this.template = this.basePath = null;
}

Ctx.cache = {};

var CtxProto = Ctx.prototype;

/*
  Prepare ctx for next template rendering
*/
CtxProto.reset = function() {
  this._contents = {};
  this.res = '';
  this.stack = [];
  this.m = null;
};

/*
  Pop stack to sp
*/
CtxProto.pop = function(sp) {
  var l = this.stack.length;
  var filename = this.filename;
  while(sp < l--) {
    var path = this._resolvePath(this.stack.pop());
    var fn = this._load(path);
    this.filename = path;
    fn.call(this.m, this);
  }
  this.filename = filename;
  return this.res;
};

CtxProto.partial = function(path, model, cb) {
  if (cb) {
    this.res = cb.call(this.m, this);
  }

  path = this._resolvePath(path);

  var f = this._load(path), oldModel = this.m, filename = this.filename;
  this.filename = path;
  var res = this.rt.safe(f.call(this.m = model, this));
  this.m = oldModel;
  this.filename = filename;
  return res;
};

CtxProto.extend = function(path) {
  this.stack.push(path);
};

CtxProto.content = function() {
  switch(arguments.length) {
    case 0:
      return this.rt.safe(this.res);
    case 1:
      return this._contents[arguments[0]] || '';
    case 2:
      var name = arguments[0], cb = arguments[1];
      if (name) {
        // capturing block
        this._contents[name] = cb.call(this.m);
        return '';
      } else {
        return cb.call(this.m);
      }
  }
};

CtxProto._loadWithCache = function(path) {
  var fn = Ctx.cache[path];
  if (fn) {
    return fn;
  }

  return Ctx.cache[path] = this._loadWithoutCache(path);
};

CtxProto._loadWithoutCache = function(path) {
  var src = FS.readFileSync(path, 'utf8');
  return this.template.exec(src, {}, this);
};

CtxProto._load = CtxProto._loadWithCache;

CtxProto._resolvePath = function(path) {
  var dirname  = Path.dirname,
      basename = Path.basename,
      join = Path.join;

  if (path[0] !== '/' && !this.filename)
    throw new Error('the "filename" option is required to use with "relative" paths');

  if (path[0] === '/' && !this.basePath)
    throw new Error('the "basePath" option is required to use with "absolute" paths');

  path = join(path[0] === '/' ? this.basePath : dirname(this.filename), path);

  if (basename(path).indexOf('.') === -1) {
    path += '.slm';
  }

  return path;
};

module.exports = Ctx;
<commit_msg>Code cleanup<commit_after>var Path = require('path');
var FS = require('fs');

function Ctx() {
  this.reset();
  this.template = this.basePath = null;
}

Ctx.cache = {};

var CtxProto = Ctx.prototype;

/*
  Prepare ctx for next template rendering
*/
CtxProto.reset = function() {
  this._contents = {};
  this.res = '';
  this.stack = [];
  this.m = null;
};

/*
  Pop stack to sp
*/
CtxProto.pop = function(sp) {
  var l = this.stack.length;
  var filename = this.filename;
  while(sp < l--) {
    var path = this._resolvePath(this.stack.pop());
    var fn = this._load(path);
    this.filename = path;
    fn.call(this.m, this);
  }
  this.filename = filename;
  return this.res;
};

CtxProto.partial = function(path, model, cb) {
  if (cb) {
    this.res = cb.call(this.m, this);
  }

  path = this._resolvePath(path);

  var f = this._load(path), oldModel = this.m, filename = this.filename;
  this.filename = path;
  var res = this.rt.safe(f.call(this.m = model, this));
  this.m = oldModel;
  this.filename = filename;
  return res;
};

CtxProto.extend = function(path) {
  this.stack.push(path);
};

CtxProto.content = function() {
  switch(arguments.length) {
    case 0:
      return this.rt.safe(this.res);
    case 1:
      return this._contents[arguments[0]] || '';
    case 2:
      var name = arguments[0], cb = arguments[1];
      if (name) {
        // capturing block
        this._contents[name] = cb.call(this.m);
        return '';
      } else {
        return cb.call(this.m);
      }
  }
};

CtxProto._loadWithCache = function(path) {
  var fn = Ctx.cache[path];
  if (fn) {
    return fn;
  }

  return Ctx.cache[path] = this._loadWithoutCache(path);
};

CtxProto._loadWithoutCache = function(path) {
  var src = FS.readFileSync(path, 'utf8');
  return this.template.exec(src, {}, this);
};

CtxProto._load = CtxProto._loadWithCache;

CtxProto._resolvePath = function(path) {
  var dirname  = Path.dirname,
      basename = Path.basename,
      join = Path.join;

  if (path[0] !== '/' && !this.filename) {
    throw new Error('the "filename" option is required to use with "relative" paths');
  }

  if (path[0] === '/' && !this.basePath) {
    throw new Error('the "basePath" option is required to use with "absolute" paths');
  }

  path = join(path[0] === '/' ? this.basePath : dirname(this.filename), path);

  if (basename(path).indexOf('.') === -1) {
    path += '.slm';
  }

  return path;
};

module.exports = Ctx;
<|endoftext|>


<commit_before>import React from 'react'
import { mount } from 'enzyme'

import withControl from './withControl'

test('withControl()', () => {

  class Base extends React.Component {
    render() {
      return <div />;
    }
  }

  const Controlled = withControl('base')(Base);

  const wrapper = mount(
    <Controlled />,
    {
      context: {
        animatronics: {
          registerComponent: () => {},
          unregisterComponent: () => {},
        }
      }
    }
  );

  expect(wrapper.find('ControlledComponent').length).toBe(1);
});
<commit_msg>:white_check_mark: [withControl] Use id instead of implicit component name<commit_after>import React from 'react'
import { mount } from 'enzyme'

import withControl from './withControl'

test('withControl()', () => {

  class Base extends React.Component {
    render() {
      return <div id='test' />;
    }
  }

  const Controlled = withControl('base')(Base);

  const wrapper = mount(
    <Controlled />,
    {
      context: {
        animatronics: {
          registerComponent: () => {},
          unregisterComponent: () => {},
        }
      }
    }
  );

  expect(wrapper.find('#test').length).toBe(1);
});
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>AboutObjects test 6 done.<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>//= require "dom/selection"
//= require "events/field_change"

/** section: wysihat
 *  mixin WysiHat.Commands
 *
 *  Methods will be mixed into the editor element. Most of these
 *  methods will be used to bind to button clicks or key presses.
 *
 *  var editor = WysiHat.Editor.attach(textarea);
 *  $('bold_button').observe('click', function(event) {
 *    editor.boldSelection();
 *    Event.stop(event);
 *  });
 *
 *  In this example, it is important to stop the click event so you don't
 *  lose your current selection.
**/
WysiHat.Commands = (function(window) {
  /**
   *  WysiHat.Commands#boldSelection() -> undefined
   *
   *  Bolds the current selection.
  **/
  function boldSelection() {
    this.execCommand('bold', false, null);
  }

  /**
   *  WysiHat.Commands#boldSelected() -> boolean
   *
   *  Check if current selection is bold or strong.
  **/
  function boldSelected() {
    return this.queryCommandState('bold');
  }

  /**
   *  WysiHat.Commands#underlineSelection() -> undefined
   *
   *  Underlines the current selection.
  **/
  function underlineSelection() {
    this.execCommand('underline', false, null);
  }

  /**
   *  WysiHat.Commands#underlineSelected() -> boolean
   *
   *  Check if current selection is underlined.
  **/
  function underlineSelected() {
    return this.queryCommandState('underline');
  }

  /**
   *  WysiHat.Commands#italicSelection() -> undefined
   *
   *  Italicizes the current selection.
  **/
  function italicSelection() {
    this.execCommand('italic', false, null);
  }

  /**
   *  WysiHat.Commands#italicSelected() -> boolean
   *
   *  Check if current selection is italic or emphasized.
  **/
  function italicSelected() {
    return this.queryCommandState('italic');
  }

  /**
   *  WysiHat.Commands#italicSelection() -> undefined
   *
   *  Strikethroughs the current selection.
  **/
  function strikethroughSelection() {
    this.execCommand('strikethrough', false, null);
  }

  /**
   *  WysiHat.Commands#blockquoteSelection() -> undefined
   *
   *  Blockquotes the current selection.
  **/
  function blockquoteSelection() {
    this.execCommand('blockquote', false, null);
  }

  /**
   * WysiHat.Commands#fontSelection(font) -> undefined
   *
   * Sets the font for the current selection
  **/
  function fontSelection(font) {
    this.execCommand('fontname', false, font);
  }

  /**
   * WysiHat.Commands#fontSizeSelection(fontSize) -> undefined
   * - font size (int) : font size for selection
   *
   * Sets the font size for the current selection
  **/
  function fontSizeSelection(fontSize) {
    this.execCommand('fontsize', false, fontSize);
  }

  /**
   *  WysiHat.Commands#colorSelection(color) -> undefined
   *  - color (String): a color name or hexadecimal value
   *
   *  Sets the foreground color of the current selection.
  **/
  function colorSelection(color) {
    this.execCommand('forecolor', false, color);
  }

  /**
   *  WysiHat.Commands#backgroundColorSelection(color) -> undefined
   *  - color (string) - a color or hexadecimal value
   *
   * Sets the background color.  Firefox will fill in the background
   * color of the entire iframe unless hilitecolor is used.
  **/
  function backgroundColorSelection(color) {
    if(Prototype.Browser.Gecko) {
      this.execCommand('hilitecolor', false, color);
    } else {
      this.execCommand('backcolor', false, color);
    }
  }

  /**
   *  WysiHat.Commands#alignSelection(color) -> undefined
   *  - alignment (string) - how the text should be aligned (left, center, right)
   *
  **/
  function alignSelection(alignment) {
    this.execCommand('justify' + alignment);
  }

  /**
   *  WysiHat.Commands#backgroundColorSelected() -> alignment
   *
   *  Returns the alignment of the selected text area
  **/
  function alignSelected() {
    var node = window.getSelection().getNode();
    return Element.getStyle(node, 'textAlign');
  }

  /**
   *  WysiHat.Commands#linkSelection(url) -> undefined
   *  - url (String): value for href
   *
   *  Wraps the current selection in a link.
  **/
  function linkSelection(url) {
    this.execCommand('createLink', false, url);
  }

  /**
   *  WysiHat.Commands#unlinkSelection() -> undefined
   *
   *  Selects the entire link at the cursor and removes it
  **/
  function unlinkSelection() {
    var node = window.getSelection().getNode();
    if (this.linkSelected())
      window.getSelection().selectNode(node);

    this.execCommand('unlink', false, null);
  }

  /**
   *  WysiHat.Commands#linkSelected() -> boolean
   *
   *  Check if current selection is link.
  **/
  function linkSelected() {
    var node = window.getSelection().getNode();
    return node ? node.tagName.toUpperCase() == 'A' : false;
  }

  /**
   *  WysiHat.Commands#formatblockSelection(element) -> undefined
   *  - element (String): the type of element you want to wrap your selection
   *    with (like 'h1' or 'p').
   *
   *  Wraps the current selection in a header or paragraph.
  **/
  function formatblockSelection(element){
    this.execCommand('formatblock', false, element);
  }

  /**
   *  WysiHat.Commands#toggleOrderedList() -> undefined
   *
   *  Formats current selection as an ordered list. If the selection is empty
   *  a new list is inserted.
  **/
  function toggleOrderedList() {
    this.execCommand('insertorderedlist', false, null);
  }

  /**
   *  WysiHat.Commands#insertOrderedList() -> undefined
   *
   *  Alias for WysiHat.Commands#toggleOrderedList
  **/
  function insertOrderedList() {
    this.toggleOrderedList();
  }

  /**
   *  WysiHat.Commands#orderedListSelected() -> boolean
   *
   *  Check if current selection is within an ordered list.
  **/
  function orderedListSelected() {
    var element = window.getSelection().getNode();
    if (element) return element.match('*[contenteditable=""] ol, *[contenteditable=true] ol, *[contenteditable=""] ol *, *[contenteditable=true] ol *');
    return false;
  }

  /**
   *  WysiHat.Commands#toggleUnorderedList() -> undefined
   *
   *  Formats current selection as an unordered list. If the selection is empty
   *  a new list is inserted.
  **/
  function toggleUnorderedList() {
    this.execCommand('insertunorderedlist', false, null);
  }

  /**
   *  WysiHat.Commands#insertUnorderedList() -> undefined
   *
   *  Alias for WysiHat.Commands#toggleUnorderedList()
  **/
  function insertUnorderedList() {
    this.toggleUnorderedList();
  }

  /**
   *  WysiHat.Commands#unorderedListSelected() -> boolean
   *
   *  Check if current selection is within an unordered list.
  **/
  function unorderedListSelected() {
    var element = window.getSelection().getNode();
    if (element) return element.match('*[contenteditable=""] ul, *[contenteditable=true] ul, *[contenteditable=""] ul *, *[contenteditable=true] ul *');
    return false;
  }

  /**
   *  WysiHat.Commands#insertImage(url) -> undefined
   *
   *  - url (String): value for src
   *  Insert an image at the insertion point with the given url.
  **/
  function insertImage(url) {
    this.execCommand('insertImage', false, url);
  }

  /**
   *  WysiHat.Commands#insertHTML(html) -> undefined
   *
   *  - html (String): HTML or plain text
   *  Insert HTML at the insertion point.
  **/
  function insertHTML(html) {
    if (Prototype.Browser.IE) {
      var range = window.document.selection.createRange();
      range.pasteHTML(html);
      range.collapse(false);
      range.select();
    } else {
      this.execCommand('insertHTML', false, html);
    }
  }

  /**
   *  WysiHat.Commands#execCommand(command[, ui = false][, value = null]) -> undefined
   *  - command (String): Command to execute
   *  - ui (Boolean): Boolean flag for showing UI. Currenty this not
   *    implemented by any browser. Just use false.
   *  - value (String): Value to pass to command
   *
   *  A simple delegation method to the documents execCommand method.
  **/
  function execCommand(command, ui, value) {
    var handler = this.commands.get(command);
    if (handler) {
      handler.bind(this)(value);
    } else {
      try {
        window.document.execCommand(command, ui, value);
      } catch(e) { return null; }
    }

    document.activeElement.fire("field:change");
  }

  /**
   *  WysiHat.Commands#queryCommandState(state) -> Boolean
   *  - state (String): bold, italic, underline, etc
   *
   *  A delegation method to the document's queryCommandState method.
   *
   *  Custom states handlers can be added to the queryCommands hash,
   *  which will be checked before calling the native queryCommandState
   *  command.
   *
   *  editor.queryCommands.set("link", editor.linkSelected);
  **/
  function queryCommandState(state) {
    var handler = this.queryCommands.get(state);
    if (handler) {
      return handler.bind(this)();
    } else {
      try {
        return window.document.queryCommandState(state);
      } catch(e) { return null; }
    }
  }

  /**
   *  WysiHat.Commands#getSelectedStyles() -> Hash
   *
   *  Fetches the styles (from the styleSelectors hash) from the current
   *  selection and returns it as a hash
  **/
  function getSelectedStyles() {
    var styles = $H({});
    var editor = this;
    editor.styleSelectors.each(function(style){
      var node = editor.selection.getNode();
      styles.set(style.first(), Element.getStyle(node, style.last()));
    });
    return styles;
  }

  return {
     boldSelection:            boldSelection,
     boldSelected:             boldSelected,
     underlineSelection:       underlineSelection,
     underlineSelected:        underlineSelected,
     italicSelection:          italicSelection,
     italicSelected:           italicSelected,
     strikethroughSelection:   strikethroughSelection,
     blockquoteSelection:      blockquoteSelection,
     fontSelection:            fontSelection,
     fontSizeSelection:        fontSizeSelection,
     colorSelection:           colorSelection,
     backgroundColorSelection: backgroundColorSelection,
     alignSelection:           alignSelection,
     alignSelected:            alignSelected,
     linkSelection:            linkSelection,
     unlinkSelection:          unlinkSelection,
     linkSelected:             linkSelected,
     formatblockSelection:     formatblockSelection,
     toggleOrderedList:        toggleOrderedList,
     insertOrderedList:        insertOrderedList,
     orderedListSelected:      orderedListSelected,
     toggleUnorderedList:      toggleUnorderedList,
     insertUnorderedList:      insertUnorderedList,
     unorderedListSelected:    unorderedListSelected,
     insertImage:              insertImage,
     insertHTML:               insertHTML,
     execCommand:              execCommand,
     queryCommandState:        queryCommandState,
     getSelectedStyles:        getSelectedStyles,

    commands: $H({}),

    queryCommands: $H({
      link:          linkSelected,
      orderedlist:   orderedListSelected,
      unorderedlist: unorderedListSelected
    }),

    styleSelectors: $H({
      fontname:    'fontFamily',
      fontsize:    'fontSize',
      forecolor:   'color',
      hilitecolor: 'backgroundColor',
      backcolor:   'backgroundColor'
    })
  };
})(window);
<commit_msg>toggle un/ordered list will effect the entire list<commit_after>//= require "dom/selection"
//= require "events/field_change"

/** section: wysihat
 *  mixin WysiHat.Commands
 *
 *  Methods will be mixed into the editor element. Most of these
 *  methods will be used to bind to button clicks or key presses.
 *
 *  var editor = WysiHat.Editor.attach(textarea);
 *  $('bold_button').observe('click', function(event) {
 *    editor.boldSelection();
 *    Event.stop(event);
 *  });
 *
 *  In this example, it is important to stop the click event so you don't
 *  lose your current selection.
**/
WysiHat.Commands = (function(window) {
  /**
   *  WysiHat.Commands#boldSelection() -> undefined
   *
   *  Bolds the current selection.
  **/
  function boldSelection() {
    this.execCommand('bold', false, null);
  }

  /**
   *  WysiHat.Commands#boldSelected() -> boolean
   *
   *  Check if current selection is bold or strong.
  **/
  function boldSelected() {
    return this.queryCommandState('bold');
  }

  /**
   *  WysiHat.Commands#underlineSelection() -> undefined
   *
   *  Underlines the current selection.
  **/
  function underlineSelection() {
    this.execCommand('underline', false, null);
  }

  /**
   *  WysiHat.Commands#underlineSelected() -> boolean
   *
   *  Check if current selection is underlined.
  **/
  function underlineSelected() {
    return this.queryCommandState('underline');
  }

  /**
   *  WysiHat.Commands#italicSelection() -> undefined
   *
   *  Italicizes the current selection.
  **/
  function italicSelection() {
    this.execCommand('italic', false, null);
  }

  /**
   *  WysiHat.Commands#italicSelected() -> boolean
   *
   *  Check if current selection is italic or emphasized.
  **/
  function italicSelected() {
    return this.queryCommandState('italic');
  }

  /**
   *  WysiHat.Commands#italicSelection() -> undefined
   *
   *  Strikethroughs the current selection.
  **/
  function strikethroughSelection() {
    this.execCommand('strikethrough', false, null);
  }

  /**
   *  WysiHat.Commands#blockquoteSelection() -> undefined
   *
   *  Blockquotes the current selection.
  **/
  function blockquoteSelection() {
    this.execCommand('blockquote', false, null);
  }

  /**
   * WysiHat.Commands#fontSelection(font) -> undefined
   *
   * Sets the font for the current selection
  **/
  function fontSelection(font) {
    this.execCommand('fontname', false, font);
  }

  /**
   * WysiHat.Commands#fontSizeSelection(fontSize) -> undefined
   * - font size (int) : font size for selection
   *
   * Sets the font size for the current selection
  **/
  function fontSizeSelection(fontSize) {
    this.execCommand('fontsize', false, fontSize);
  }

  /**
   *  WysiHat.Commands#colorSelection(color) -> undefined
   *  - color (String): a color name or hexadecimal value
   *
   *  Sets the foreground color of the current selection.
  **/
  function colorSelection(color) {
    this.execCommand('forecolor', false, color);
  }

  /**
   *  WysiHat.Commands#backgroundColorSelection(color) -> undefined
   *  - color (string) - a color or hexadecimal value
   *
   * Sets the background color.  Firefox will fill in the background
   * color of the entire iframe unless hilitecolor is used.
  **/
  function backgroundColorSelection(color) {
    if(Prototype.Browser.Gecko) {
      this.execCommand('hilitecolor', false, color);
    } else {
      this.execCommand('backcolor', false, color);
    }
  }

  /**
   *  WysiHat.Commands#alignSelection(color) -> undefined
   *  - alignment (string) - how the text should be aligned (left, center, right)
   *
  **/
  function alignSelection(alignment) {
    this.execCommand('justify' + alignment);
  }

  /**
   *  WysiHat.Commands#backgroundColorSelected() -> alignment
   *
   *  Returns the alignment of the selected text area
  **/
  function alignSelected() {
    var node = window.getSelection().getNode();
    return Element.getStyle(node, 'textAlign');
  }

  /**
   *  WysiHat.Commands#linkSelection(url) -> undefined
   *  - url (String): value for href
   *
   *  Wraps the current selection in a link.
  **/
  function linkSelection(url) {
    this.execCommand('createLink', false, url);
  }

  /**
   *  WysiHat.Commands#unlinkSelection() -> undefined
   *
   *  Selects the entire link at the cursor and removes it
  **/
  function unlinkSelection() {
    var node = window.getSelection().getNode();
    if (this.linkSelected())
      window.getSelection().selectNode(node);

    this.execCommand('unlink', false, null);
  }

  /**
   *  WysiHat.Commands#linkSelected() -> boolean
   *
   *  Check if current selection is link.
  **/
  function linkSelected() {
    var node = window.getSelection().getNode();
    return node ? node.tagName.toUpperCase() == 'A' : false;
  }

  /**
   *  WysiHat.Commands#formatblockSelection(element) -> undefined
   *  - element (String): the type of element you want to wrap your selection
   *    with (like 'h1' or 'p').
   *
   *  Wraps the current selection in a header or paragraph.
  **/
  function formatblockSelection(element){
    this.execCommand('formatblock', false, element);
  }

  /**
   *  WysiHat.Commands#toggleOrderedList() -> undefined
   *
   *  Formats current selection as an ordered list. If the selection is empty
   *  a new list is inserted.
   *
   *  If the selection is already a ordered list, the entire list
   *  will be toggled. However, toggling the last item of the list
   *  will only affect that item, not the entire list.
  **/
  function toggleOrderedList() {
    var selection, node;

    selection = window.getSelection();
    node      = selection.getNode();

    if (this.orderedListSelected() && !node.match("ol li:last-child, ol li:last-child *")) {
      selection.selectNode(node.up("ol"));
    } else if (this.unorderedListSelected()) {
      // Toggle list type
      selection.selectNode(node.up("ul"));
    }

    this.execCommand('insertorderedlist', false, null);
  }

  /**
   *  WysiHat.Commands#insertOrderedList() -> undefined
   *
   *  Alias for WysiHat.Commands#toggleOrderedList
  **/
  function insertOrderedList() {
    this.toggleOrderedList();
  }

  /**
   *  WysiHat.Commands#orderedListSelected() -> boolean
   *
   *  Check if current selection is within an ordered list.
  **/
  function orderedListSelected() {
    var element = window.getSelection().getNode();
    if (element) return element.match('*[contenteditable=""] ol, *[contenteditable=true] ol, *[contenteditable=""] ol *, *[contenteditable=true] ol *');
    return false;
  }

  /**
   *  WysiHat.Commands#toggleUnorderedList() -> undefined
   *
   *  Formats current selection as an unordered list. If the selection is empty
   *  a new list is inserted.
   *
   *  If the selection is already a unordered list, the entire list
   *  will be toggled. However, toggling the last item of the list
   *  will only affect that item, not the entire list.
  **/
  function toggleUnorderedList() {
    var selection, node;

    selection = window.getSelection();
    node      = selection.getNode();

    if (this.unorderedListSelected() && !node.match("ul li:last-child, ul li:last-child *")) {
      selection.selectNode(node.up("ul"));
    } else if (this.orderedListSelected()) {
      // Toggle list type
      selection.selectNode(node.up("ol"));
    }

    this.execCommand('insertunorderedlist', false, null);
  }

  /**
   *  WysiHat.Commands#insertUnorderedList() -> undefined
   *
   *  Alias for WysiHat.Commands#toggleUnorderedList()
  **/
  function insertUnorderedList() {
    this.toggleUnorderedList();
  }

  /**
   *  WysiHat.Commands#unorderedListSelected() -> boolean
   *
   *  Check if current selection is within an unordered list.
  **/
  function unorderedListSelected() {
    var element = window.getSelection().getNode();
    if (element) return element.match('*[contenteditable=""] ul, *[contenteditable=true] ul, *[contenteditable=""] ul *, *[contenteditable=true] ul *');
    return false;
  }

  /**
   *  WysiHat.Commands#insertImage(url) -> undefined
   *
   *  - url (String): value for src
   *  Insert an image at the insertion point with the given url.
  **/
  function insertImage(url) {
    this.execCommand('insertImage', false, url);
  }

  /**
   *  WysiHat.Commands#insertHTML(html) -> undefined
   *
   *  - html (String): HTML or plain text
   *  Insert HTML at the insertion point.
  **/
  function insertHTML(html) {
    if (Prototype.Browser.IE) {
      var range = window.document.selection.createRange();
      range.pasteHTML(html);
      range.collapse(false);
      range.select();
    } else {
      this.execCommand('insertHTML', false, html);
    }
  }

  /**
   *  WysiHat.Commands#execCommand(command[, ui = false][, value = null]) -> undefined
   *  - command (String): Command to execute
   *  - ui (Boolean): Boolean flag for showing UI. Currenty this not
   *    implemented by any browser. Just use false.
   *  - value (String): Value to pass to command
   *
   *  A simple delegation method to the documents execCommand method.
  **/
  function execCommand(command, ui, value) {
    var handler = this.commands.get(command);
    if (handler) {
      handler.bind(this)(value);
    } else {
      try {
        window.document.execCommand(command, ui, value);
      } catch(e) { return null; }
    }

    document.activeElement.fire("field:change");
  }

  /**
   *  WysiHat.Commands#queryCommandState(state) -> Boolean
   *  - state (String): bold, italic, underline, etc
   *
   *  A delegation method to the document's queryCommandState method.
   *
   *  Custom states handlers can be added to the queryCommands hash,
   *  which will be checked before calling the native queryCommandState
   *  command.
   *
   *  editor.queryCommands.set("link", editor.linkSelected);
  **/
  function queryCommandState(state) {
    var handler = this.queryCommands.get(state);
    if (handler) {
      return handler.bind(this)();
    } else {
      try {
        return window.document.queryCommandState(state);
      } catch(e) { return null; }
    }
  }

  /**
   *  WysiHat.Commands#getSelectedStyles() -> Hash
   *
   *  Fetches the styles (from the styleSelectors hash) from the current
   *  selection and returns it as a hash
  **/
  function getSelectedStyles() {
    var styles = $H({});
    var editor = this;
    editor.styleSelectors.each(function(style){
      var node = editor.selection.getNode();
      styles.set(style.first(), Element.getStyle(node, style.last()));
    });
    return styles;
  }

  return {
     boldSelection:            boldSelection,
     boldSelected:             boldSelected,
     underlineSelection:       underlineSelection,
     underlineSelected:        underlineSelected,
     italicSelection:          italicSelection,
     italicSelected:           italicSelected,
     strikethroughSelection:   strikethroughSelection,
     blockquoteSelection:      blockquoteSelection,
     fontSelection:            fontSelection,
     fontSizeSelection:        fontSizeSelection,
     colorSelection:           colorSelection,
     backgroundColorSelection: backgroundColorSelection,
     alignSelection:           alignSelection,
     alignSelected:            alignSelected,
     linkSelection:            linkSelection,
     unlinkSelection:          unlinkSelection,
     linkSelected:             linkSelected,
     formatblockSelection:     formatblockSelection,
     toggleOrderedList:        toggleOrderedList,
     insertOrderedList:        insertOrderedList,
     orderedListSelected:      orderedListSelected,
     toggleUnorderedList:      toggleUnorderedList,
     insertUnorderedList:      insertUnorderedList,
     unorderedListSelected:    unorderedListSelected,
     insertImage:              insertImage,
     insertHTML:               insertHTML,
     execCommand:              execCommand,
     queryCommandState:        queryCommandState,
     getSelectedStyles:        getSelectedStyles,

    commands: $H({}),

    queryCommands: $H({
      link:          linkSelected,
      orderedlist:   orderedListSelected,
      unorderedlist: unorderedListSelected
    }),

    styleSelectors: $H({
      fontname:    'fontFamily',
      fontsize:    'fontSize',
      forecolor:   'color',
      hilitecolor: 'backgroundColor',
      backcolor:   'backgroundColor'
    })
  };
})(window);
<|endoftext|>


<commit_before>const Discord = require("discord.js");
var mysql = require('mysql');
var fs = require("fs");
var config = JSON.parse(fs.readFileSync("config.json", "utf8"));
var sqlConnection = mysql.createConnection(config.mysql);
var discordClient = null;
sqlConnection.connect();

var kue = require('kue'),
    queue = kue.createQueue({
        prefix: 'q',
        redis: {
            port: 6379,
            host: '127.0.0.1'
        }
    });
var triggerWords = {

};
var clientState = {
    "online": false,
    "loginName": null,
    "onlineSince": null
};
queue.on( 'error', function( err ) {
    console.log( 'Oops... ', err );
});
function biotmp(token) {
    queue.process('message_send', function (job, done) {
        console.log(job.data.channel_id);
        discordClient.channels.get(job.data.channel_id).send(job.data.message, function(error, message) {
            if (!error) {
                done();
            } else {
                done(error);
            }
        });
    });
    function queueMSG(msg) {
        console.log(msg);
        var elMSGObj = {
            "message": msg.content,
            "channel": {
                "type": msg.channel.type,
                "id": String(msg.channel.id),
                "name": msg.channel.name
            },
            "server": {
                "id": msg.channel.guild.id,
                "name": msg.channel.guild.name
            },
            "author": msg.author,
            "tts": msg.tts,
            "system": msg.system,
            "nonce": msg.nonce,
            "mentions": {
                "everyone": msg.mentions.everyone,
                "users": JSON.stringify(msg.mentions.users),
                "roles": JSON.stringify(msg.mentions.roles)

            }
        };
        elMSGObj.author.lastMessage = undefined;
        for (var i in elMSGObj.mentions.users) {
            elMSGObj.mentions.users[i].lastMessage = undefined;
        }
        var job = queue.create('cmd_process', {
            "title": "Discord Message Processing",
            "message-obj": JSON.stringify(elMSGObj)

        }).priority("low").save( function(err){
            if( !err ) console.log( job.id );
        });
    }
    discordClient = new Discord.Client();
    discordClient.on('ready', function () {
        console.log("Logged in as " + discordClient.user.tag);
        console.log("https://discordapp.com/oauth2/authorize?client_id=" + config.clientID + "&scope=bot&permissions=0")
        clientState.online = true;
        clientState.loginName = discordClient.user.tag;
        clientState.online = Date.now();
    });

    discordClient.on('message', function (msg) {
        if (triggerWords[msg.channel.guild.id] === undefined && msg.content.indexOf("biotmp ") === 0) {
            // triggered - default
            // add triggerword to msg object for further processing
            console.log("Triggered");
            msg.triggerWord = "biotmp ";
            //and queue processing
            queueMSG(msg);
        } else if (triggerWords[msg.channel.guild.id] !== undefined) {
            if (msg.content.indexOf(triggerWords[msg.channel.guild.id] + " ") === 0) {
                // triggered - custom triggerword
                // add triggerword to msg object for further processing
                msg.triggerWord = triggerWords[msg.channel.guild.id] + " ";
                //and queue processing
                queueMSG(msg);

            }
        }

    });

    discordClient.login(token);
}
function updateTriggerWords() {
    sqlConnection.query("SELECT id, server_id, triggerword FROM triggerword", function (err, results) {
       if (err) throw err;
       triggerWords = {};
       results.forEach(function (currentEntry) {
           triggerWords[currentEntry.server_id] = currentEntry.triggerword;
       });
    });
}
setInterval(updateTriggerWords, 1000);
biotmp(config.token);<commit_msg>kirschn dumm<commit_after>const Discord = require("discord.js");
var mysql = require('mysql');
var fs = require("fs");
var config = JSON.parse(fs.readFileSync("config.json", "utf8"));
var sqlConnection = mysql.createConnection(config.mysql);
var discordClient = null;
sqlConnection.connect();

var kue = require('kue'),
    queue = kue.createQueue({
        prefix: 'q',
        redis: {
            port: 6379,
            host: '127.0.0.1'
        }
    });
var triggerWords = {

};
var clientState = {
    "online": false,
    "loginName": null,
    "onlineSince": null
};
queue.on( 'error', function( err ) {
    console.log( 'Oops... ', err );
});
function biotmp(token) {
    queue.process('message_send', function (job, done) {
        console.log(job.data.channel_id);
        discordClient.channels.get(job.data.channel_id).send(job.data.message).then(done);
    });
    function queueMSG(msg) {
        console.log(msg);
        var elMSGObj = {
            "message": msg.content,
            "channel": {
                "type": msg.channel.type,
                "id": String(msg.channel.id),
                "name": msg.channel.name
            },
            "server": {
                "id": msg.channel.guild.id,
                "name": msg.channel.guild.name
            },
            "author": msg.author,
            "tts": msg.tts,
            "system": msg.system,
            "nonce": msg.nonce,
            "mentions": {
                "everyone": msg.mentions.everyone,
                "users": JSON.stringify(msg.mentions.users),
                "roles": JSON.stringify(msg.mentions.roles)

            }
        };
        elMSGObj.author.lastMessage = undefined;
        for (var i in elMSGObj.mentions.users) {
            elMSGObj.mentions.users[i].lastMessage = undefined;
        }
        var job = queue.create('cmd_process', {
            "title": "Discord Message Processing",
            "message-obj": JSON.stringify(elMSGObj)

        }).priority("low").save( function(err){
            if( !err ) console.log( job.id );
        });
    }
    discordClient = new Discord.Client();
    discordClient.on('ready', function () {
        console.log("Logged in as " + discordClient.user.tag);
        console.log("https://discordapp.com/oauth2/authorize?client_id=" + config.clientID + "&scope=bot&permissions=0")
        clientState.online = true;
        clientState.loginName = discordClient.user.tag;
        clientState.online = Date.now();
    });

    discordClient.on('message', function (msg) {
        if (triggerWords[msg.channel.guild.id] === undefined && msg.content.indexOf("biotmp ") === 0) {
            // triggered - default
            // add triggerword to msg object for further processing
            console.log("Triggered");
            msg.triggerWord = "biotmp ";
            //and queue processing
            queueMSG(msg);
        } else if (triggerWords[msg.channel.guild.id] !== undefined) {
            if (msg.content.indexOf(triggerWords[msg.channel.guild.id] + " ") === 0) {
                // triggered - custom triggerword
                // add triggerword to msg object for further processing
                msg.triggerWord = triggerWords[msg.channel.guild.id] + " ";
                //and queue processing
                queueMSG(msg);

            }
        }

    });

    discordClient.login(token);
}
function updateTriggerWords() {
    sqlConnection.query("SELECT id, server_id, triggerword FROM triggerword", function (err, results) {
       if (err) throw err;
       triggerWords = {};
       results.forEach(function (currentEntry) {
           triggerWords[currentEntry.server_id] = currentEntry.triggerword;
       });
    });
}
setInterval(updateTriggerWords, 1000);
biotmp(config.token);<|endoftext|>