<commit_before>#!/usr/bin/env node

var exec = require("child_process").exec;
var path = require("path");
var fs = require("fs");
var util = require("util");

var Promise = require("./lib/promise");

var DEBUG = true;

// Some standard helpers

function debug() {
    var args;
    if(DEBUG) {
        args = Array.prototype.slice.call(arguments, 0);
        args.unshift("DEBUG:");

        console.log.apply(this, args);
    }
}

function die(message, exception) {
    if(exception) {
        message += ": " + exception.message;
    }

    console.log(message);

    process.exit(1);
}

function help() {
    console.log("usage: git aux <command> [<args>]");
    console.log();
    console.log("Commands:");
    console.log("init <basedir>   Initialise git aux to use the chosen directory");
    console.log("add <file(s)>    Add the chosen file (from basedir) to the repository");
    console.log("sync             Import changes to tracked files in basedir into the repository");
    console.log("apply            Apply changes from the repository into the basedir");
    console.log();
}

function get_git_root() {
    var promise = new Promise();

    exec("git rev-parse --show-toplevel", function(err, stdout, stderr) {
        if(err) {
            console.log("Not a git repository");
            process.exit(1);
        }

        home = stdout.trim();

        promise.fulfill(home);
    });

    return promise;
}

function get_config(git_root) {
    var promise = new Promise();

    fs.readFile(path.join(git_root, ".git", "aux", "config.json"), "utf8", function(err, data) {
        if(err) {
            promise.fulfill(null);
            debug("No config");
        } else {
            try {
                data = JSON.parse(data);
                promise.fulfill(data);
            } catch(e) {
                die("Unable to parse git aux config", e);
            }
        }
    });

    return promise;
}

function save_config(git_root, config) {
    var promise = new Promise();

    fs.writeFile(path.join(git_root, ".git", "aux", "config.json"), JSON.stringify(config, null, 2), function(err) {
        if(err) {
            die("Unable to save config", err);
        }

        promise.fulfill();
    });

    return promise;
}

function mkdir(dir) {
    var promise = new Promise();

    debug("Making dir:", dir);

    fs.mkdir(dir, function(err) {
        if(err) {
            if(err.code === "ENOENT") {
                mkdir(path.dirname(dir)).then(function() {
                    mkdir(dir).then(promise.fulfill);
                });
            } else if(err.code === "EEXIST") {
                promise.fulfill();
            } else {
                die("Error creating directory", err);
            }
        } else {
            promise.fulfill();
        }
    });

    return promise;
}

// Git aux commands

function init(git_root, basedir) {
    // Make git aux directory
    fs.mkdir(path.join(git_root, ".git", "aux"), function(err) {
        if(err) {
            die("Couldn't create git aux directory", err);
        }

        save_config(git_root, {
            basedir: path.resolve(process.cwd(), basedir)
        }).then(function() {
            console.log("Initialised git aux repository");
        });
    });
}

function add(git_root, config, files) {
    files.forEach(function(file) {
        var relative_path = path.resolve(process.cwd(), file);

        // FIXME: Make this a recursive copy

        if(new RegExp("^" + config.basedir + path.sep).test(relative_path)) {
            relative_path = path.relative(config.basedir, relative_path);

            debug("Adding:", relative_path);

            mkdir(path.dirname(path.join(git_root, relative_path))).then(function() {
                var is = fs.createReadStream(path.join(config.basedir, relative_path));
                os = fs.createWriteStream(path.join(git_root, relative_path));

                util.pump(is, os, function(err) {
                    if(err) {
                        die("Failed copying file", err);
                    }

                    exec("git add " + path.join(git_root, relative_path), function(err) {
                        if(err) {
                            die("Failed adding file to git", err);
                        }
                    });
                });
            });
        } else {
            die(file + " is not within this git aux repo's basedir (" + config.basedir + ")");
        }
    });
}

function get_files(dir) {
    var promise = new Promise();

    var count = 0;

    var output = [];

    fs.readdir(dir, function(err, files) {
        if(err) {
            die("Error reading dir", err);
        }

        count = files.length;

        files.forEach(function(file) {
            fs.stat(path.join(dir, file), function(err, stats) {
                if(err) {
                    die("Failed getting file info", err);
                }

                if(stats.isFile()) {
                    count--;

                    output.push(path.join(dir, file));

                    if(count === 0) {
                        console.log("File");
                        promise.fulfill(output);
                    }
                } else if(stats.isDirectory()) {
                    get_files(path.join(dir, file)).then(function(sub_dir) {
                        //output = output.concat(sub_dir);

                        output.push(sub_dir);

                        count--;

                        if(count === 0) {
                            promise.fulfill(output);
                        }
                    });
                } else {
                    count--;

                    if(count === 0) {
                        console.log("Bum");
                        promise.fulfill(output);
                    }
                }
            });
        });
    });

    return promise;
}

get_files("/home/steve/code/git-aux").then(function(files) {
    console.log(files);
});

function sync(git_root, config) {
    // First stash
    exec("git stash", function(err) {
        var count;

        if(err) {
            die("Failed to stash", err);
        }
    });

    // Get file list

    // Stash pop

    // Copy contents from basedir
}

// Check the parameters

if(process.argv.length < 3) {
    help();
    process.exit();
}

// Get the config
/*
get_git_root().then(function(git_root) {
    get_config(git_root).then(function(config) {
        var command = process.argv[2];
        var args = process.argv.slice(3);

        debug("Config:", config);

        debug("Command:", command);
        debug("Args:", args);

        if(!config && command !== "init") {
            die("Not a git aux repository");
        }

        if(command === "init") {
            if(config) {
                die("Already a git aux repository");
            }

            if(args.length !== 1) {
                help();
                process.exit(1);
            }

            init(git_root, args[0]);
        } else if(command === "add") {
            if(args.length === 0) {
                help();
                process.exit(1);
            }

            add(git_root, config, args);
        } else if(command === "sync") {
        } else if(command === "apply") {
        } else {
            console.log("unknown command:", command);
            help();
            process.exit(1);
        }
    });
});
*/
<commit_msg>Add sync command<commit_after>#!/usr/bin/env node

var exec = require("child_process").exec;
var spawn = require("child_process").spawn;
var path = require("path");
var fs = require("fs");
var util = require("util");

var Promise = require("./lib/promise");

var DEBUG = true;

// Some standard helpers

function debug() {
    var args;
    if(DEBUG) {
        args = Array.prototype.slice.call(arguments, 0);
        args.unshift("DEBUG:");

        console.log.apply(this, args);
    }
}

function die(message, exception) {
    if(exception) {
        message += ": " + exception.message;
    }

    console.log(message);

    if(DEBUG) {
        throw exception;
    }

    process.exit(1);
}

function help() {
    console.log("usage: git aux <command> [<args>]");
    console.log();
    console.log("Commands:");
    console.log("init <basedir>   Initialise git aux to use the chosen directory");
    console.log("add <file(s)>    Add the chosen file (from basedir) to the repository");
    console.log("sync             Import changes to tracked files in basedir into the repository");
    console.log("apply            Apply changes from the repository into the basedir");
    console.log();
}

function get_git_root() {
    var promise = new Promise();

    exec("git rev-parse --show-toplevel", function(err, stdout, stderr) {
        if(err) {
            console.log("Not a git repository");
            process.exit(1);
        }

        home = stdout.trim();

        promise.fulfill(home);
    });

    return promise;
}

function get_config(git_root) {
    var promise = new Promise();

    fs.readFile(path.join(git_root, ".git", "aux", "config.json"), "utf8", function(err, data) {
        if(err) {
            promise.fulfill(null);
            debug("No config");
        } else {
            try {
                data = JSON.parse(data);
                promise.fulfill(data);
            } catch(e) {
                die("Unable to parse git aux config", e);
            }
        }
    });

    return promise;
}

function save_config(git_root, config) {
    var promise = new Promise();

    fs.writeFile(path.join(git_root, ".git", "aux", "config.json"), JSON.stringify(config, null, 2), function(err) {
        if(err) {
            die("Unable to save config", err);
        }

        promise.fulfill();
    });

    return promise;
}

function mkdir(dir) {
    var promise = new Promise();

    debug("Making dir:", dir);

    fs.mkdir(dir, function(err) {
        if(err) {
            if(err.code === "ENOENT") {
                mkdir(path.dirname(dir)).then(function() {
                    mkdir(dir).then(promise.fulfill);
                });
            } else if(err.code === "EEXIST") {
                promise.fulfill();
            } else {
                die("Error creating directory", err);
            }
        } else {
            promise.fulfill();
        }
    });

    return promise;
}

// Git aux commands

function init(git_root, basedir) {
    // Make git aux directory
    fs.mkdir(path.join(git_root, ".git", "aux"), function(err) {
        if(err) {
            die("Couldn't create git aux directory", err);
        }

        save_config(git_root, {
            basedir: path.resolve(process.cwd(), basedir)
        }).then(function() {
            console.log("Initialised git aux repository");
        });
    });
}

function rm(file) {
    var promise = new Promise();

    fs.stat(file, function(err, stats) {
        if(err) {
            if(err.code === "ENOENT") {
                return promise.fulfill();
            } else {
                die("Unable to stat file", err);
            }
        }

        if(stats.isDirectory()) {
            fs.readdir(file, function(err, files) {
                var count = files.length;

                function finish() {
                    fs.rmdir(file, function(err) {
                        if(err) {
                            die("Unable to remove dir", err);
                        }

                        promise.fulfill();
                    });
                }

                if(count === 0) {
                    finish();
                } else {
                    files.forEach(function(f) {
                        rm(path.join(file, f)).then(function() {
                            count--;

                            if(count === 0) {
                                finish();
                            }
                        });
                    });
                }
            });
        } else {
            fs.unlink(file, function(err) {
                if(err) {
                    die("Unable to delete file", err);
                }

                promise.fulfill();
            });
        }
    });

    return promise;
}

function copy(src, dest) {
    var promise = new Promise();

    rm(dest).then(function() {
        fs.stat(src, function(err, stats) {
            var is, os;

            if(err) {
                if(err.code === "ENOENT") {
                    promise.fulfill();
                } else {
                    die("Unable to stat file", err);
                }
            }

            if(stats.isDirectory()) {
                fs.mkdir(dest, function(err) {
                    if(err) {
                        die("Unable to create directory", err);
                    }

                    fs.readdir(src, function(err, files) {
                        var count = files.length;

                        if(count === 0) {
                            promise.fulfill();
                        }

                        files.forEach(function(file) {
                            copy(path.join(src, file), path.join(dest, file)).then(function() {
                                count--;

                                if(count === 0) {
                                    promise.fulfill();
                                }
                            });
                        });
                    });
                });
            } else {
                is = fs.createReadStream(src);
                os = fs.createWriteStream(dest);

                util.pump(is, os, function(err) {
                    if(err) {
                        die("Failed copying file", err);
                    }

                    promise.fulfill();
                });
            }
        });
    });

    return promise;
}

function add(git_root, config, files) {
    files.forEach(function(file) {
        var relative_path = path.resolve(process.cwd(), file);

        // FIXME: Make this a recursive copy

        if(new RegExp("^" + config.basedir + path.sep).test(relative_path)) {
            relative_path = path.relative(config.basedir, relative_path);

            debug("Adding:", relative_path);

            copy(path.join(config.basedir, relative_path), path.join(git_root, relative_path)).then(function() {
                exec("git add " + path.join(git_root, relative_path), function(err) {
                    if(err) {
                        die("Failed adding file to git", err);
                    }
                });
            });
        } else {
            die(file + " is not within this git aux repo's basedir (" + config.basedir + ")");
        }
    });
}

function get_files(dir) {
    var promise = new Promise();

    var count = 0;

    var output = [];

    fs.readdir(dir, function(err, files) {
        if(err) {
            die("Error reading dir", err);
        }

        count = files.length;

        if(count === 0) {
            promise.fulfill(output);
        }

        files.forEach(function(file) {
            fs.stat(path.join(dir, file), function(err, stats) {
                if(err) {
                    die("Failed getting file info", err);
                }

                if(stats.isFile()) {
                    count--;

                    output.push(path.join(dir, file));

                    if(count === 0) {
                        promise.fulfill(output);
                    }
                } else if(stats.isDirectory()) {
                    get_files(path.join(dir, file)).then(function(sub_dir) {
                        count--;

                        output = output.concat(sub_dir);

                        if(count === 0) {
                            promise.fulfill(output);
                        }
                    });
                } else {
                    count--;

                    if(count === 0) {
                        promise.fulfill(output);
                    }
                }
            });
        });
    });

    return promise;
}

get_files("/home/steve/code/git-aux/test/repo").then(function(files) {
    console.log(files);
});

function sync(git_root, config) {
    fs.readdir(git_root, function(err, files) {
        var count = files.length - 1;

        function finish() {
            spawn("git", ["add", "-p"], {stdio: "inherit"});
        }

        if(count === 0) {
            finish();
        }

        files.forEach(function(file) {
            if(file !== ".git") {
                debug("Syncing: " + file);

                file = path.relative(git_root, path.join(git_root, file));

                copy(path.join(config.basedir, file), path.join(git_root, file)).then(function() {
                    count--;

                    if(count === 0) {
                        finish();
                    }
                });
            }
        });
    });
}

// Check the parameters

if(process.argv.length < 3) {
    help();
    process.exit();
}

// Get the config
get_git_root().then(function(git_root) {
    get_config(git_root).then(function(config) {
        var command = process.argv[2];
        var args = process.argv.slice(3);

        debug("Config:", config);

        debug("Command:", command);
        debug("Args:", args);

        if(!config && command !== "init") {
            die("Not a git aux repository");
        }

        if(command === "init") {
            if(config) {
                die("Already a git aux repository");
            }

            if(args.length !== 1) {
                help();
                process.exit(1);
            }

            init(git_root, args[0]);
        } else if(command === "add") {
            if(args.length === 0) {
                help();
                process.exit(1);
            }

            add(git_root, config, args);
        } else if(command === "sync") {
            if(args.length !== 0) {
                help();
                process.exit(1);
            }

            sync(git_root, config);
        } else if(command === "apply") {
        } else {
            console.log("unknown command:", command);
            help();
            process.exit(1);
        }
    });
});
<|endoftext|>


<commit_before>const webpack = require('webpack');
const path = require("path");
const ManifestPlugin = require('webpack-manifest-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const autoprefixer = require("autoprefixer");

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /css$/,
          chunks: 'all',
          enforce: true
        },
        vendors: {
          filename: 'js/[name].[chunkhash].js'
        }
      }
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css'
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        postcss: [
          autoprefixer()
        ]
      }
    }),
    new webpack.ProvidePlugin({
      moment: "moment",
      axios: "axios"
    }),
    new ManifestPlugin({
      fileName: '../../_data/asset-manifest.json'
    }),
    new WebpackCleanupPlugin()
  ],
  entry: {
    about: "./assets/js/about.js",
    archive: "./assets/js/archive.js",
    index: "./assets/js/index.js",
    post: "./assets/js/post.js",
    commons: "./assets/js/commons.js",
    library: "./assets/js/library.js",
    logBook: "./assets/js/logBook.js",
    getInvolved: "./assets/js/get-involved.js",
    trad: "./assets/js/trad.js",
    trip: "./assets/js/trip.js",
    tripArchive: "./assets/js/trip-archive.js",
    weather: "./assets/js/weather.js"
  },
  output: {
    path: path.resolve(__dirname, 'assets/dist/'),
    filename: "js/[name].[chunkhash].js"
  },
  module: {
    rules: [
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        use: 'url-loader?limit=100000'
      },
      {
        test: /\.hbs$/,
        loader: 'handlebars-loader',
        query: {
          helperDirs: [
            __dirname + "/assets/js/helpers"
          ]
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      }
    ]
  }
};<commit_msg>improve handlebars-loader syntax<commit_after>const webpack = require('webpack');
const path = require("path");
const ManifestPlugin = require('webpack-manifest-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const autoprefixer = require("autoprefixer");

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /css$/,
          chunks: 'all',
          enforce: true
        },
        vendors: {
          filename: 'js/[name].[chunkhash].js'
        }
      }
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css'
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
        postcss: [
          autoprefixer()
        ]
      }
    }),
    new webpack.ProvidePlugin({
      moment: "moment",
      axios: "axios"
    }),
    new webpack.LoaderOptionsPlugin({
      options: {
          handlebarsLoader: {}
      }
    }),
    new ManifestPlugin({
      fileName: '../../_data/asset-manifest.json'
    }),
    new WebpackCleanupPlugin()
  ],
  entry: {
    about: "./assets/js/about.js",
    archive: "./assets/js/archive.js",
    index: "./assets/js/index.js",
    post: "./assets/js/post.js",
    commons: "./assets/js/commons.js",
    library: "./assets/js/library.js",
    logBook: "./assets/js/logBook.js",
    getInvolved: "./assets/js/get-involved.js",
    trad: "./assets/js/trad.js",
    trip: "./assets/js/trip.js",
    tripArchive: "./assets/js/trip-archive.js",
    weather: "./assets/js/weather.js"
  },
  output: {
    path: path.resolve(__dirname, 'assets/dist/'),
    filename: "js/[name].[chunkhash].js"
  },
  module: {
    rules: [
      {
        test: /\.(png|woff|woff2|eot|ttf|svg)$/,
        use: 'url-loader?limit=100000'
      },
      {
        test: /\.hbs$/,
        loader: 'handlebars-loader'
      },
      {
        test: /\.js$/,
        exclude: /node_modules$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      }
    ]
  }
};<|endoftext|>


<commit_before>// Toggle main sections
$(".docs-sidebar-section-title").click(function () {
    $('.docs-sidebar-section').not(this).closest('.docs-sidebar-section').removeClass('active');
    $(this).closest('.docs-sidebar-section').toggleClass('active');
});

// Bootstrap stuff
$('.docs-actions i').tooltip();
$('.docs-sidebar-home').tooltip();

/* BB 150310
   openstackdocstheme provides three types of admonitions, important, note
   and warning. We decorate their title paragraphs with Font Awesome icons
   by adding the appropriate FA classes.                               */

$('div.important > p.admonition-title').prepend('

');
$('div.note > p.admonition-title').prepend('

');
$('div.seealso > p.admonition-title').prepend('

');
$('div.warning > p.admonition-title').prepend('

');
$('div.versionadded > p').prepend('

');
$('div.versionchanged > p').prepend('

');
$('div.deprecated > p').prepend('

');

/* BB 150310
   We also insert a space between the icon and the admonition title
   ("Note", "Warning", "Important" or their i18n equivalents).

   This could be done with a single clause $('p.admonition-title')....,
   affecting all types of admonitions. I play it safe here and explicitly
   work on the three openstackdocstheme admonitions.

   The first parameter of the text() callback is not needed here (it's
   the index of the HTML element that we are modifying)                 */

// Gives the log a bug icon the information it needs to generate the bug in
// Launchpad with pre-filled information such as git SHA, opendev.org
// source URL, published document URL and tag.
function logABug(bugTitle, bugProject, fieldComment, fieldTags, repositoryName, useStoryboard) {

    var lineFeed = "%0A";

    var bugChecklist = "This bug tracker is for errors with the documentation, " +
        "use the following as a template and remove or add fields as " +
        "you see fit. Convert [ ] into [x] to check boxes:" + lineFeed + lineFeed +
        "- [ ] This doc is inaccurate in this way: ______" + lineFeed +
        "- [ ] This is a doc addition request." + lineFeed +
        "- [ ] I have a fix to the document that I can paste below including example: " +
        "input and output. " + lineFeed + lineFeed +
        "If you have a troubleshooting or support issue, use the following " +
        " resources:" + lineFeed + lineFeed +
        " - Ask OpenStack: http://ask.openstack.org" + lineFeed +
        " - The mailing list: http://lists.openstack.org" + lineFeed +
        " - IRC: 'openstack' channel on Freenode"+ lineFeed;

    var urlBase = "https://bugs.launchpad.net/" + bugProject + "/+filebug?field.title=";
    var currentURL = "URL: " + window.location.href;
    var bugLink = "";
    if (useStoryboard) {
        var urlBase = "https://storyboard.openstack.org/#!/project/";
        bugLink = urlBase + repositoryName;
    } else {
        bugLink = urlBase  + encodeURIComponent(bugTitle) +
        "&field.tags=" + fieldTags +
        "&field.comment=" + lineFeed + lineFeed +  lineFeed +
        bugChecklist + lineFeed + "-----------------------------------" + lineFeed + fieldComment +
        lineFeed + currentURL;
    }
    document.getElementById("logABugLink1").href=bugLink;
    document.getElementById("logABugLink2").href=bugLink;
    document.getElementById("logABugLink3").href=bugLink;
}
<commit_msg>js: Fix some comments<commit_after>// Toggle main sections
$(".docs-sidebar-section-title").click(function () {
    $('.docs-sidebar-section').not(this).closest('.docs-sidebar-section').removeClass('active');
    $(this).closest('.docs-sidebar-section').toggleClass('active');
});

// Bootstrap stuff
$('.docs-actions i').tooltip();
$('.docs-sidebar-home').tooltip();

/* BB 150310
 *
 * openstackdocstheme provides three types of admonitions, important, note
 * and warning. We decorate their title paragraphs with Font Awesome icons
 * by adding the appropriate FA classes.
 *
 * We also insert a space between the icon and the admonition title
 * ("Note", "Warning", "Important" or their i18n equivalents). This could be
 * done with a single clause - $('p.admonition-title').... - affecting all
 * types of admonitions. I play it safe here and explicitly work on the three
 * openstackdocstheme admonitions.
 */
$('div.important > p.admonition-title').prepend('

');
$('div.note > p.admonition-title').prepend('

');
$('div.seealso > p.admonition-title').prepend('

');
$('div.warning > p.admonition-title').prepend('

');
$('div.versionadded > p').prepend('

');
$('div.versionchanged > p').prepend('

');
$('div.deprecated > p').prepend('

');

function logABug(bugTitle, bugProject, fieldComment, fieldTags, repositoryName, useStoryboard) {
    /* Gives the log a bug icon the information it needs to generate the bug in
     * Launchpad with pre-filled information such as git SHA, opendev.org
     * source URL, published document URL and tag.
     */
    var lineFeed = "%0A";

    var bugChecklist = "This bug tracker is for errors with the documentation, " +
        "use the following as a template and remove or add fields as " +
        "you see fit. Convert [ ] into [x] to check boxes:" + lineFeed + lineFeed +
        "- [ ] This doc is inaccurate in this way: ______" + lineFeed +
        "- [ ] This is a doc addition request." + lineFeed +
        "- [ ] I have a fix to the document that I can paste below including example: " +
        "input and output. " + lineFeed + lineFeed +
        "If you have a troubleshooting or support issue, use the following " +
        " resources:" + lineFeed + lineFeed +
        " - Ask OpenStack: http://ask.openstack.org" + lineFeed +
        " - The mailing list: http://lists.openstack.org" + lineFeed +
        " - IRC: 'openstack' channel on Freenode"+ lineFeed;

    var urlBase = "https://bugs.launchpad.net/" + bugProject + "/+filebug?field.title=";
    var currentURL = "URL: " + window.location.href;
    var bugLink = "";
    if (useStoryboard) {
        var urlBase = "https://storyboard.openstack.org/#!/project/";
        bugLink = urlBase + repositoryName;
    } else {
        bugLink = urlBase  + encodeURIComponent(bugTitle) +
        "&field.tags=" + fieldTags +
        "&field.comment=" + lineFeed + lineFeed +  lineFeed +
        bugChecklist + lineFeed + "-----------------------------------" + lineFeed + fieldComment +
        lineFeed + currentURL;
    }
    document.getElementById("logABugLink1").href=bugLink;
    document.getElementById("logABugLink2").href=bugLink;
    document.getElementById("logABugLink3").href=bugLink;
}
<|endoftext|>


<commit_before>module.exports = {
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended',
  ],
  parserOptions: {
    project: './tsconfig.json',
    tsconfigRootDir: '.',
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  rules: {
    'prettier/prettier': [
      'error',
      {
        bracketSpacing: true,
        trailingComma: 'all',
        singleQuote: true,
        semi: true,
        useTabs: false,
        tabWidth: 2,
        printWidth: 120,
      },
    ],
    eqeqeq: 'error',
    curly: 'error',
    'no-trailing-spaces': 'error',
    'eol-last': ['error', 'always'],
    'prefer-template': 'error',
    '@typescript-eslint/no-use-before-define': 'off',
    '@typescript-eslint/no-misused-promises': 'warn',
    '@typescript-eslint/require-await': 'off',
    '@typescript-eslint/unbound-method': 'off',
    '@typescript-eslint/no-empty-interface': 'off',
    '@typescript-eslint/explicit-function-return-type': ['warn', { allowExpressions: true }],
    '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
    '@typescript-eslint/array-type': ['error', { array: true }],

    '@typescript-eslint/explicit-module-boundary-types': [
      'warn',
      {
        allowTypedFunctionExpressions: true,
        allowHigherOrderFunctions: true,
        allowDirectConstAssertionInArrowFunctions: true,
        shouldTrackReferences: true,
      },
    ],
    '@typescript-eslint/naming-convention': [
      'warn',
      { selector: 'default', format: ['camelCase'] },

      { selector: 'variableLike', format: ['camelCase'] },
      {
        selector: 'variable',
        format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
        leadingUnderscore: 'allow',
      },
      {
        selector: 'function',
        format: ['camelCase', 'PascalCase'],
      },
      {
        selector: 'parameter',
        format: ['camelCase', 'PascalCase'],
        leadingUnderscore: 'allow',
      },
      { selector: 'enumMember', format: ['UPPER_CASE'] },
      { selector: 'memberLike', format: ['camelCase'] },
      {
        selector: 'memberLike',
        modifiers: ['private'],
        format: ['camelCase'],
        leadingUnderscore: 'allow',
      },
      { selector: 'typeParameter', format: ['PascalCase'], prefix: ['T'] },
      {
        selector: 'typeLike',
        format: ['PascalCase'],
        custom: { regex: '^[IT][A-Z]', match: false },
      },
      {
        selector: 'interface',
        format: ['PascalCase'],
        custom: { regex: '^[IT][A-Z]', match: false },
      },
    ],

    '@typescript-eslint/restrict-template-expressions': [
      'warn',
      {
        allowNumber: true,
        allowBoolean: false,
        allowAny: false,
        allowNullish: false,
      },
    ],
    '@typescript-eslint/prefer-optional-chain': ['warn'],

    '@typescript-eslint/prefer-ts-expect-error': ['error'],
    '@typescript-eslint/promise-function-async': ['warn'],
    '@typescript-eslint/prefer-string-starts-ends-with': ['error'],
    '@typescript-eslint/prefer-reduce-type-parameter': ['warn'],
    '@typescript-eslint/prefer-includes': ['error'],
    '@typescript-eslint/prefer-for-of': ['error'],
    '@typescript-eslint/prefer-enum-initializers': ['warn'],
    '@typescript-eslint/no-loop-func': ['warn'],
  },
};
<commit_msg>feat: allow const and component members<commit_after>module.exports = {
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended',
  ],
  parserOptions: {
    project: './tsconfig.json',
    tsconfigRootDir: '.',
    ecmaVersion: 2020,
    sourceType: 'module',
  },
  rules: {
    'prettier/prettier': [
      'error',
      {
        bracketSpacing: true,
        trailingComma: 'all',
        singleQuote: true,
        semi: true,
        useTabs: false,
        tabWidth: 2,
        printWidth: 120,
      },
    ],
    eqeqeq: 'error',
    curly: 'error',
    'no-trailing-spaces': 'error',
    'eol-last': ['error', 'always'],
    'prefer-template': 'error',
    '@typescript-eslint/no-use-before-define': 'off',
    '@typescript-eslint/no-misused-promises': 'warn',
    '@typescript-eslint/require-await': 'off',
    '@typescript-eslint/unbound-method': 'off',
    '@typescript-eslint/no-empty-interface': 'off',
    '@typescript-eslint/explicit-function-return-type': ['warn', { allowExpressions: true }],
    '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
    '@typescript-eslint/array-type': ['error', { array: true }],

    '@typescript-eslint/explicit-module-boundary-types': [
      'warn',
      {
        allowTypedFunctionExpressions: true,
        allowHigherOrderFunctions: true,
        allowDirectConstAssertionInArrowFunctions: true,
        shouldTrackReferences: true,
      },
    ],
    '@typescript-eslint/naming-convention': [
      'warn',
      { selector: 'default', format: ['camelCase'] },

      { selector: 'variableLike', format: ['camelCase'] },
      {
        selector: 'variable',
        format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
        leadingUnderscore: 'allow',
      },
      {
        selector: 'function',
        format: ['camelCase', 'PascalCase'],
      },
      {
        selector: 'parameter',
        format: ['camelCase', 'PascalCase'],
        leadingUnderscore: 'allow',
      },
      { selector: 'enumMember', format: ['UPPER_CASE'] },
      { selector: 'memberLike', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
      {
        selector: 'memberLike',
        modifiers: ['private'],
        format: ['camelCase'],
        leadingUnderscore: 'allow',
      },
      { selector: 'typeParameter', format: ['PascalCase'], prefix: ['T'] },
      {
        selector: 'typeLike',
        format: ['PascalCase'],
        custom: { regex: '^[IT][A-Z]', match: false },
      },
      {
        selector: 'interface',
        format: ['PascalCase'],
        custom: { regex: '^[IT][A-Z]', match: false },
      },
    ],

    '@typescript-eslint/restrict-template-expressions': [
      'warn',
      {
        allowNumber: true,
        allowBoolean: false,
        allowAny: false,
        allowNullish: false,
      },
    ],
    '@typescript-eslint/prefer-optional-chain': ['warn'],

    '@typescript-eslint/prefer-ts-expect-error': ['error'],
    '@typescript-eslint/promise-function-async': ['warn'],
    '@typescript-eslint/prefer-string-starts-ends-with': ['error'],
    '@typescript-eslint/prefer-reduce-type-parameter': ['warn'],
    '@typescript-eslint/prefer-includes': ['error'],
    '@typescript-eslint/prefer-for-of': ['error'],
    '@typescript-eslint/prefer-enum-initializers': ['warn'],
    '@typescript-eslint/no-loop-func': ['warn'],
  },
};
<|endoftext|>


<commit_before>const fs = require('fs');
const requestLib = require('request');

const SWARFARM_URL = 'https://swarfarm.com/api/v2/';
const pluginName = 'SwarfarmLogger';
let request, acceptedCommands, apiKey, proxy, myConfig;

const getApiKey = wizardId => {
  if (apiKey instanceof Object) {
    return apiKey[wizardId];
  } else {
    return apiKey;
  }
};

const setRequestAuth = (opts, wizardId) => {
  const token = getApiKey(wizardId);
  if (token) {
    opts = Object.assign(opts, {
      headers: {
        Authorization: `Token ${token}`
      }
    });
  }

  return opts;
};

const getApiCommands = () => {
  // Get list of commands from server
  try {
    proxy.log({
      type: 'debug',
      source: 'plugin',
      name: pluginName,
      message: 'Retrieving list of accepted log types from SWARFARM...'
    });

    request.get('data_logs/', (error, response, body) => {
      if (!error && response.statusCode === 200) {
        acceptedCommands = JSON.parse(body);
      }

      proxy.log({
        type: 'success',
        source: 'plugin',
        name: pluginName,
        message: `Looking for the following commands to log: ${Object.keys(acceptedCommands)
          .filter(cmd => cmd != '__version')
          .join(', ')}`
      });
    });
  } catch (error) {
    proxy.log({
      type: 'error',
      source: 'plugin',
      name: pluginName,
      message: 'Unable to retrieve accepted log types. SWARFARM logging is disabled.'
    });
    myConfig.enabled = false;
  }
};

const processLog = (req, resp) => {
  const { command, wizard_id } = req;

  if (!acceptedCommands[command]) {
    // Not listening for this API command
    return;
  }

  const req_options = setRequestAuth(
    {
      json: true,
      body: { data: { request: req, response: resp, __version: acceptedCommands.__version } }
    },
    wizard_id
  );

  // Send it
  request.post('data_logs/', req_options, (error, response, body) => {
    if (error) {
      proxy.log({
        type: 'error',
        source: 'plugin',
        name: pluginName,
        message: `Error: ${error.message}`
      });
      return;
    }

    // Log message to proxy window
    if (response.statusCode === 200) {
      proxy.log({
        type: 'success',
        source: 'plugin',
        name: pluginName,
        message: `${command} logged successfully`
      });
    } else {
      if (response.statusCode == 401) {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `SWARFARM Authentication failure: ${body.detail}`
        });
      } else {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `Error ${response.statusCode}: ${body.detail}`
        });
      }
    }

    // Check if server indicates accepted API commands is out of date
    if (body && body.reinit) {
      getApiCommands();
    }
  });
};

const uploadProfile = (req, resp) => {
  const { command } = req;
  const { wizard_id } = resp;

  if (command === 'HubUserLogin') {
    // Check that API key is filled in
    if (!apiKey) {
      proxy.log({
        type: 'error',
        source: 'plugin',
        name: pluginName,
        message: `Profile upload is enabled, but missing API key. Check ${pluginName} settings.`
      });

      return;
    }

    proxy.log({
      type: 'info',
      source: 'plugin',
      name: pluginName,
      message: 'Uploading profile to SWARFARM...'
    });

    const req_options = setRequestAuth(
      {
        json: true,
        body: resp
      },
      wizard_id
    );

    request.post('profiles/upload/', req_options, (error, response, body) => {
      if (error) {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `Error: ${error.message}`
        });
        return;
      }

      if (response.statusCode === 200) {
        proxy.log({
          type: 'debug',
          source: 'plugin',
          name: pluginName,
          message: 'SWARFARM profile successfully uploaded - awaiting import queue.'
        });

        const jobId = body.job_id;
        let resultCheckTimer;

        // 5 minute failsafe to stop checking job status
        const failsafeCheckTimer = setTimeout(() => {
          proxy.log({
            type: 'error',
            source: 'plugin',
            name: pluginName,
            message: 'Timed out retrieving import status.'
          });
          clearInterval(resultCheckTimer);
        }, 300000);

        resultCheckTimer = setInterval(() => {
          request.get(
            `profiles/upload/${jobId}/`,
            setRequestAuth(
              {
                json: true
              },
              wizard_id
            ),
            (resultError, resultResponse, resultBody) => {
              if (resultBody && resultBody.status === 'SUCCESS') {
                clearTimeout(failsafeCheckTimer);
                clearInterval(resultCheckTimer);

                proxy.log({
                  type: 'success',
                  source: 'plugin',
                  name: pluginName,
                  message: 'SWARFARM profile import complete!'
                });
              }
            }
          );
        }, 2500);
      } else if (response.statusCode === 400) {
        // HTTP 400 Bad Request - malformed upload data or request
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `There were errors importing your SWARFARM profile: ${JSON.stringify(body)}`
        });
      } else if (response.statusCode === 401) {
        // HTTP 401 Unauthorized - Failed to authenticate
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: 'Unable to authenticate to SWARFARM. Check your API key in settings.'
        });
      } else if (response.statusCode === 409) {
        // HTTP 409 Conflict - Validation checks failed
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `${JSON.stringify(body)}. You must manually upload your profile on SWARFARM to resolve this.`
        });
      }
    });
  }
};

module.exports = {
  defaultConfig: {
    enabled: true,
    profileSync: false,
    apiKey: ''
  },
  defaultConfigDetails: {
    profileSync: { label: 'Automatically upload profile to SWARFARM' },
    apiKey: { label: 'SWARFARM API key', type: 'textarea' }
  },
  pluginName,
  pluginDescription: 'Syncs your SWARFARM profile automatically and logs data for your account.',
  init(proxyInstance, config) {
    myConfig = config.Config.Plugins[pluginName];

    if (myConfig.enabled) {
      proxy = proxyInstance;
      request = requestLib.defaults({ baseUrl: SWARFARM_URL });
      apiKey = myConfig.apiKey;

      if (!apiKey) {
        // Warning message to user to prompt to set API key.
        proxy.log({
          type: 'warning',
          source: 'plugin',
          name: pluginName,
          message:
            'You have not configured a SWARFARM API key in Settings. Logs will attempt to be associated to your SWARFARM account via in-game account ID, but this is not guaranteed to work.'
        });
      }

      getApiCommands();
      setInterval(getApiCommands, 60 * 60 * 1000); // Refresh API commands every hour

      proxy.on('apiCommand', (req, resp) => {
        processLog(req, resp);

        // Profile sync if enabled
        if (myConfig.profileSync) {
          uploadProfile(req, resp);
        }
      });
    }
  }
};
<commit_msg>Update swarfarm-logger for better behavior, not require restart on settings change, and API key trimming/validation and appropriate error messages<commit_after>const requestLib = require('request');

const SWARFARM_URL = 'https://swarfarm.com/api/v2/';
const pluginName = 'SwarfarmLogger';
let request, acceptedCommands, proxy, apiKey;

const trimApiKey = inputApiObject => {
  // Trims whitespace from input API key. Only works for plain string input.
  if (inputApiObject instanceof Object) {
    // JSON input must be done correctly by the user and is not trimmed.
    return inputApiObject;
  } else {
    return inputApiObject.trim();
  }
};

const apiKeyRegex = RegExp('^[a-z0-9]{40}$'); // Exactly 40 hex characters
const apiKeyIsValid = key => apiKeyRegex.test(key);

const getApiKey = wizardId => {
  if (apiKey instanceof Object) {
    return apiKey[wizardId];
  } else {
    return apiKey;
  }
};

const setRequestAuth = (opts, wizardId) => {
  const token = getApiKey(wizardId);
  if (apiKeyIsValid(token)) {
    opts = Object.assign(opts, {
      headers: {
        Authorization: `Token ${token}`
      }
    });
  } else {
    // Only raise error message if some text is present
    if (token) {
      proxy.log({
        type: 'warning',
        source: 'plugin',
        name: pluginName,
        message: 'Invalid API key. Copy/paste it from SWARFARM profile settings. Logging without API key until it is updated.'
      });
    }
  }

  return opts;
};

const getApiCommands = () => {
  // Get list of commands from server

  proxy.log({
    type: 'debug',
    source: 'plugin',
    name: pluginName,
    message: 'Retrieving list of accepted log types from SWARFARM...'
  });

  request.get('data_logs/', (error, response, body) => {
    if (!error && response.statusCode === 200) {
      acceptedCommands = JSON.parse(body);
    }

    proxy.log({
      type: 'success',
      source: 'plugin',
      name: pluginName,
      message: `Looking for the following commands to log: ${Object.keys(acceptedCommands)
        .filter(cmd => cmd != '__version')
        .join(', ')}`
    });
  });
};

const processLog = (req, resp) => {
  const { command, wizard_id } = req;

  if (!acceptedCommands[command]) {
    // Not listening for this API command
    return;
  }

  const req_options = setRequestAuth(
    {
      json: true,
      body: { data: { request: req, response: resp, __version: acceptedCommands.__version } }
    },
    wizard_id
  );

  // Send it
  request.post('data_logs/', req_options, (error, response, body) => {
    if (error) {
      proxy.log({
        type: 'error',
        source: 'plugin',
        name: pluginName,
        message: `Error: ${error.message}`
      });
      return;
    }

    // Log message to proxy window
    if (response.statusCode === 200) {
      proxy.log({
        type: 'success',
        source: 'plugin',
        name: pluginName,
        message: `${command} logged successfully`
      });
    } else {
      if (response.statusCode == 401) {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `SWARFARM Authentication failure: ${body.detail}`
        });
      } else {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `Error ${response.statusCode}: ${body.detail}`
        });
      }
    }

    // Check if server indicates accepted API commands is out of date
    if (body && body.reinit) {
      getApiCommands();
    }
  });
};

const uploadProfile = (req, resp) => {
  const { command } = req;
  const { wizard_id } = resp;

  if (command === 'HubUserLogin') {
    // Check that API key is filled in
    if (!apiKey) {
      proxy.log({
        type: 'error',
        source: 'plugin',
        name: pluginName,
        message: `Profile upload is enabled, but missing API key. Check ${pluginName} settings.`
      });

      return;
    }

    proxy.log({
      type: 'info',
      source: 'plugin',
      name: pluginName,
      message: 'Uploading profile to SWARFARM...'
    });

    const req_options = setRequestAuth(
      {
        json: true,
        body: resp
      },
      wizard_id
    );

    request.post('profiles/upload/', req_options, (error, response, body) => {
      if (error) {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `Error: ${error.message}`
        });
        return;
      }

      if (response.statusCode === 200) {
        proxy.log({
          type: 'debug',
          source: 'plugin',
          name: pluginName,
          message: 'SWARFARM profile successfully uploaded - awaiting import queue.'
        });

        const jobId = body.job_id;
        let resultCheckTimer;

        // 5 minute failsafe to stop checking job status
        const failsafeCheckTimer = setTimeout(() => {
          proxy.log({
            type: 'error',
            source: 'plugin',
            name: pluginName,
            message: 'Timed out retrieving import status.'
          });
          clearInterval(resultCheckTimer);
        }, 300000);

        resultCheckTimer = setInterval(() => {
          request.get(
            `profiles/upload/${jobId}/`,
            setRequestAuth(
              {
                json: true
              },
              wizard_id
            ),
            (resultError, resultResponse, resultBody) => {
              if (resultBody && resultBody.status === 'SUCCESS') {
                clearTimeout(failsafeCheckTimer);
                clearInterval(resultCheckTimer);

                proxy.log({
                  type: 'success',
                  source: 'plugin',
                  name: pluginName,
                  message: 'SWARFARM profile import complete!'
                });
              }
            }
          );
        }, 2500);
      } else if (response.statusCode === 400) {
        // HTTP 400 Bad Request - malformed upload data or request
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `There were errors importing your SWARFARM profile: ${JSON.stringify(body)}`
        });
      } else if (response.statusCode === 401) {
        // HTTP 401 Unauthorized - Failed to authenticate
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: 'Unable to authenticate to SWARFARM. Check your API key in settings.'
        });
      } else if (response.statusCode === 409) {
        // HTTP 409 Conflict - Validation checks failed
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: `${JSON.stringify(body)}. You must manually upload your profile on SWARFARM to resolve this.`
        });
      }
    });
  }
};

module.exports = {
  defaultConfig: {
    enabled: true,
    profileSync: false,
    apiKey: ''
  },
  defaultConfigDetails: {
    profileSync: { label: 'Automatically upload profile to SWARFARM' },
    apiKey: { label: 'SWARFARM API key', type: 'textarea' }
  },
  pluginName,
  pluginDescription: 'Syncs your SWARFARM profile automatically and logs data for your account.',
  init(proxyInstance, config) {
    if (config.Config.Plugins[pluginName].enabled) {
      proxy = proxyInstance;
      request = requestLib.defaults({ baseUrl: SWARFARM_URL });
      config.Config.Plugins[pluginName].apiKey = trimApiKey(config.Config.Plugins[pluginName].apiKey);

      if (!config.Config.Plugins[pluginName].apiKey) {
        if (config.Config.Plugins[pluginName].profileSync) {
          // Error message to user indicating profile sync will not work without API key
          proxy.log({
            type: 'error',
            source: 'plugin',
            name: pluginName,
            message:
              'An API key is required for SWARFARM profile sync and recommended for data logging. Copy it into settings from your SWARFARM Edit Profile page to enable this feature.'
          });
        } else {
          // Warning message to user to prompt to set API key.
          proxy.log({
            type: 'warning',
            source: 'plugin',
            name: pluginName,
            message:
              'You have not configured a SWARFARM API key in Settings. Logs will attempt to be associated to your SWARFARM account via in-game account ID, but this is not guaranteed to work.'
          });
        }
      }

      try {
        getApiCommands();
      } catch (error) {
        proxy.log({
          type: 'error',
          source: 'plugin',
          name: pluginName,
          message: 'Unable to retrieve accepted log types. SWARFARM logging is disabled.'
        });
      }
      setInterval(getApiCommands, 60 * 60 * 1000); // Refresh API commands every hour

      proxy.on('apiCommand', (req, resp) => {
        // Update API key from settings each log event in case it changed
        apiKey = config.Config.Plugins[pluginName].apiKey;

        try {
          processLog(req, resp);
        } catch (error) {
          proxy.log({
            type: 'error',
            source: 'plugin',
            name: pluginName,
            message: 'Error submitting log event to SWARFARM.'
          });
        }

        // Profile sync if enabled
        if (config.Config.Plugins[pluginName].profileSync) {
          uploadProfile(req, resp);
        }
      });
    }
  }
};
<|endoftext|>


<commit_before>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Lib = require('../../lib');
var setConvertCartesian = require('../cartesian/set_convert');

var deg2rad = Lib.deg2rad;
var rad2deg = Lib.rad2deg;
var isFullCircle = Lib.isFullCircle;

/**
 * setConvert for polar axes!
 *
 * @param {object} ax
 *   axis in question (works for both radial and angular axes)
 * @param {object} polarLayout
 *   full polar layout of the subplot associated with 'ax'
 * @param {object} fullLayout
 *   full layout
 *
 * Here, reuse some of the Cartesian setConvert logic,
 * but we must extend some of it, as both radial and angular axes
 * don't have domains and angular axes don't have _true_ ranges.
 *
 * Moreover, we introduce two new coordinate systems:
 * - 'g' for geometric coordinates and
 * - 't' for angular ticks
 *
 * Radial axis coordinate systems flow:
 * - d2c (in calc) just like for cartesian axes
 * - c2g (in plot) translates calcdata about `radialaxis.range[0]`
 *
 * Angular axis coordinate systems flow:
 * + for linear axes:
 *   - d2c (in calc) angles -> 'data' radians
 *   - c2g (in plot) 'data' -> 'geometric' radians (fn of ax rotation & direction)
 *   - t2g (in updateAngularAxis) 'tick' value (in degrees) -> 'geometric' radians
 * + for category axes:
 *   - d2c (in calc) just like for cartesian axes
 *   - c2g (in plot) category indices -> 'geometric' radians
 *   - t2g (in updateAngularAxis) 'tick' value (as category indices) -> 'geometric' radians
 *
 * Then, 'g'eometric data is ready to be converted to (x,y).
 */
module.exports = function setConvert(ax, polarLayout, fullLayout) {
    setConvertCartesian(ax, fullLayout);

    switch(ax._id) {
        case 'x':
        case 'radialaxis':
            setConvertRadial(ax);
            break;
        case 'angularaxis':
            setConvertAngular(ax, polarLayout);
            break;
    }
};

function setConvertRadial(ax) {
    ax.setGeometry = function() {
        var rng = ax.range;

        var rFilter = rng[0] > rng[1] ?
            function(v) { return v <= 0; } :
            function(v) { return v >= 0; };

        ax.c2g = function(v) {
            var r = ax.c2r(v) - rng[0];
            return rFilter(r) ? r : 0;
        };

        ax.g2c = function(v) {
            return ax.r2c(v + rng[0]);
        };
    };
}

function toRadians(v, unit) {
    return unit === 'degrees' ? deg2rad(v) : v;
}

function fromRadians(v, unit) {
    return unit === 'degrees' ? rad2deg(v) : v;
}

function setConvertAngular(ax, polarLayout) {
    var axType = ax.type;

    if(axType === 'linear') {
        var _d2c = ax.d2c;
        var _c2d = ax.c2d;

        ax.d2c = function(v, unit) { return toRadians(_d2c(v), unit); };
        ax.c2d = function(v, unit) { return _c2d(fromRadians(v, unit)); };
    }

    // override makeCalcdata to handle thetaunit and special theta0/dtheta logic
    ax.makeCalcdata = function(trace, coord) {
        var arrayIn = trace[coord];
        var len = trace._length;
        var arrayOut, i;

        var _d2c = function(v) { return ax.d2c(v, trace.thetaunit); };

        if(arrayIn) {
            if(Lib.isTypedArray(arrayIn) && axType === 'linear') {
                if(len === arrayIn.length) {
                    return arrayIn;
                } else if(arrayIn.subarray) {
                    return arrayIn.subarray(0, len);
                }
            }

            arrayOut = new Array(len);
            for(i = 0; i < len; i++) {
                arrayOut[i] = _d2c(arrayIn[i]);
            }
        } else {
            var coord0 = coord + '0';
            var dcoord = 'd' + coord;
            var v0 = (coord0 in trace) ? _d2c(trace[coord0]) : 0;
            var dv = (trace[dcoord]) ? _d2c(trace[dcoord]) : (ax.period || 2 * Math.PI) / len;

            arrayOut = new Array(len);
            for(i = 0; i < len; i++) {
                arrayOut[i] = v0 + i * dv;
            }
        }

        return arrayOut;
    };

    // N.B. we mock the axis 'range' here
    ax.setGeometry = function() {
        var sector = polarLayout.sector;
        var dir = {clockwise: -1, counterclockwise: 1}[ax.direction];
        var rot = deg2rad(ax.rotation);

        ax.rad2g = function(v) { return dir * v + rot; };
        ax.g2rad = function(v) { return (v - rot) / dir; };

        switch(axType) {
            case 'linear':
                ax.c2rad = ax.rad2c = Lib.identity;
                ax.t2rad = deg2rad;
                ax.rad2r = rad2deg;

                // Set the angular range in degrees to make auto-tick computation cleaner,
                // changing rotation/direction should not affect the angular tick value.
                ax.range = isFullCircle(sector) ?
                    sector.slice() :
                    sector.map(deg2rad).map(ax.g2rad).map(rad2deg);
                break;

            case 'category':
                var catLen = ax._categories.length;
                var _period = ax._period = ax.period ? Math.max(ax.period, catLen) : catLen;

                ax.c2rad = ax.t2rad = function(v) { return v * 2 * Math.PI / _period; };
                ax.rad2c = ax.rad2t = function(v) { return v * _period / Math.PI / 2; };

                ax.range = [0, _period];
                break;
        }

        ax.c2g = function(v) { return ax.rad2g(ax.c2rad(v)); };
        ax.g2c = function(v) { return ax.rad2c(ax.g2rad(v)); };

        ax.t2g = function(v) { return ax.rad2g(ax.t2rad(v)); };
        ax.g2t = function(v) { return ax.rad2t(ax.g2rad(v)); };
    };
}
<commit_msg>:hocho: unused keys from angular axis objects<commit_after>/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Lib = require('../../lib');
var setConvertCartesian = require('../cartesian/set_convert');

var deg2rad = Lib.deg2rad;
var rad2deg = Lib.rad2deg;
var isFullCircle = Lib.isFullCircle;

/**
 * setConvert for polar axes!
 *
 * @param {object} ax
 *   axis in question (works for both radial and angular axes)
 * @param {object} polarLayout
 *   full polar layout of the subplot associated with 'ax'
 * @param {object} fullLayout
 *   full layout
 *
 * Here, reuse some of the Cartesian setConvert logic,
 * but we must extend some of it, as both radial and angular axes
 * don't have domains and angular axes don't have _true_ ranges.
 *
 * Moreover, we introduce two new coordinate systems:
 * - 'g' for geometric coordinates and
 * - 't' for angular ticks
 *
 * Radial axis coordinate systems flow:
 * - d2c (in calc) just like for cartesian axes
 * - c2g (in plot) translates calcdata about `radialaxis.range[0]`
 *
 * Angular axis coordinate systems flow:
 * + for linear axes:
 *   - d2c (in calc) angles -> 'data' radians
 *   - c2g (in plot) 'data' -> 'geometric' radians (fn of ax rotation & direction)
 *   - t2g (in updateAngularAxis) 'tick' value (in degrees) -> 'geometric' radians
 * + for category axes:
 *   - d2c (in calc) just like for cartesian axes
 *   - c2g (in plot) category indices -> 'geometric' radians
 *   - t2g (in updateAngularAxis) 'tick' value (as category indices) -> 'geometric' radians
 *
 * Then, 'g'eometric data is ready to be converted to (x,y).
 */
module.exports = function setConvert(ax, polarLayout, fullLayout) {
    setConvertCartesian(ax, fullLayout);

    switch(ax._id) {
        case 'x':
        case 'radialaxis':
            setConvertRadial(ax);
            break;
        case 'angularaxis':
            setConvertAngular(ax, polarLayout);
            break;
    }
};

function setConvertRadial(ax) {
    ax.setGeometry = function() {
        var rng = ax.range;

        var rFilter = rng[0] > rng[1] ?
            function(v) { return v <= 0; } :
            function(v) { return v >= 0; };

        ax.c2g = function(v) {
            var r = ax.c2r(v) - rng[0];
            return rFilter(r) ? r : 0;
        };

        ax.g2c = function(v) {
            return ax.r2c(v + rng[0]);
        };
    };
}

function toRadians(v, unit) {
    return unit === 'degrees' ? deg2rad(v) : v;
}

function fromRadians(v, unit) {
    return unit === 'degrees' ? rad2deg(v) : v;
}

function setConvertAngular(ax, polarLayout) {
    var axType = ax.type;

    if(axType === 'linear') {
        var _d2c = ax.d2c;
        var _c2d = ax.c2d;

        ax.d2c = function(v, unit) { return toRadians(_d2c(v), unit); };
        ax.c2d = function(v, unit) { return _c2d(fromRadians(v, unit)); };
    }

    // override makeCalcdata to handle thetaunit and special theta0/dtheta logic
    ax.makeCalcdata = function(trace, coord) {
        var arrayIn = trace[coord];
        var len = trace._length;
        var arrayOut, i;

        var _d2c = function(v) { return ax.d2c(v, trace.thetaunit); };

        if(arrayIn) {
            if(Lib.isTypedArray(arrayIn) && axType === 'linear') {
                if(len === arrayIn.length) {
                    return arrayIn;
                } else if(arrayIn.subarray) {
                    return arrayIn.subarray(0, len);
                }
            }

            arrayOut = new Array(len);
            for(i = 0; i < len; i++) {
                arrayOut[i] = _d2c(arrayIn[i]);
            }
        } else {
            var coord0 = coord + '0';
            var dcoord = 'd' + coord;
            var v0 = (coord0 in trace) ? _d2c(trace[coord0]) : 0;
            var dv = (trace[dcoord]) ? _d2c(trace[dcoord]) : (ax.period || 2 * Math.PI) / len;

            arrayOut = new Array(len);
            for(i = 0; i < len; i++) {
                arrayOut[i] = v0 + i * dv;
            }
        }

        return arrayOut;
    };

    // N.B. we mock the axis 'range' here
    ax.setGeometry = function() {
        var sector = polarLayout.sector;
        var dir = {clockwise: -1, counterclockwise: 1}[ax.direction];
        var rot = deg2rad(ax.rotation);

        var rad2g = function(v) { return dir * v + rot; };
        var g2rad = function(v) { return (v - rot) / dir; };

        var rad2c, c2rad;
        var rad2t, t2rad;

        switch(axType) {
            case 'linear':
                c2rad = rad2c = Lib.identity;
                t2rad = deg2rad;
                rad2t = rad2deg;

                // Set the angular range in degrees to make auto-tick computation cleaner,
                // changing rotation/direction should not affect the angular tick value.
                ax.range = isFullCircle(sector) ?
                    sector.slice() :
                    sector.map(deg2rad).map(g2rad).map(rad2deg);
                break;

            case 'category':
                var catLen = ax._categories.length;
                var _period = ax.period ? Math.max(ax.period, catLen) : catLen;

                c2rad = t2rad = function(v) { return v * 2 * Math.PI / _period; };
                rad2c = rad2t = function(v) { return v * _period / Math.PI / 2; };

                ax.range = [0, _period];
                break;
        }

        ax.c2g = function(v) { return rad2g(c2rad(v)); };
        ax.g2c = function(v) { return rad2c(g2rad(v)); };

        ax.t2g = function(v) { return rad2g(t2rad(v)); };
        ax.g2t = function(v) { return rad2t(g2rad(v)); };
    };
}
<|endoftext|>


<commit_before>/*
* ngSocket.js
* https://github.com/chrisenytc/ng-socket
*
* Copyright (c) 2013 Christopher EnyTC, David Prothero
* Licensed under the MIT license.
*/

// Module Copyright (c) 2013 Michael Benford

// Module for provide Socket.io support

define(["socket.io"], function (io) {
	"use strict";

	angular.module("ngSocket", [])
	.provider("$socket", socketProvider);

	function socketProvider() {
		var url;
		var token;

		this.setUrl = setUrl;
		this.getUrl = getUrl;
		this.setToken = setToken;
		this.$get = ["$rootScope", socketFactory];

		function setUrl(value) {
			url = value;
		}

		function getUrl() {
			return url;
		}

		function setToken(value) {
			token = value;
		}

		function socketFactory($rootScope) {
			var socket;

			var service = {
				addListener: addListener,
				on: addListener,
				once: addListenerOnce,
				removeListener: removeListener,
				removeAllListeners: removeAllListeners,
				emit: emit
			};

			return service;
			////////////////////////////////

			function initializeSocket() {
				//Check if socket is undefined
				if (typeof socket === "undefined") {
					if (url !== "undefined") {
						socket = io.connect(url);
					} else {
						socket = io.connect();
					}
					socket.on("connect", function() {
						socket.emit("authenticate", {
							token: token
						});
					});
				}
			}

			function angularCallback(callback) {
				return function () {
					if (callback) {
						var args = arguments;
						$rootScope.$apply(function () {
							callback.apply(socket, args);
						});
					}
				};
			}

			function addListener(name, scope, callback) {
				initializeSocket();

				if (arguments.length === 2) {
				scope = null;
				callback = arguments[1];
				}

				socket.on(name, angularCallback(callback));

				if (scope !== null) {
					scope.$on("$destroy", function () {
						removeListener(name, callback);
					});
				}
			}

			function addListenerOnce(name, callback) {
				initializeSocket();
				socket.once(name, angularCallback(callback));
			}

			function removeListener(name, callback) {
				initializeSocket();
				socket.removeListener(name, angularCallback(callback));
			}

			function removeAllListeners(name) {
				initializeSocket();
				socket.removeAllListeners(name);
			}

			function emit(name, data, callback) {
				initializeSocket();
				socket.emit(name, data, angularCallback(callback));
			}
		}
	}
});
<commit_msg>check token and run callback<commit_after>/*
* ngSocket.js
* https://github.com/chrisenytc/ng-socket
*
* Copyright (c) 2013 Christopher EnyTC, David Prothero
* Licensed under the MIT license.
*/

// Module Copyright (c) 2013 Michael Benford
// Edited by Daniel Melchior

// Module for provide Socket.io support

define(["socket.io"], function (io) {
	"use strict";

	angular.module("ngSocket", [])
	.provider("$socket", socketProvider);

	function socketProvider() {
		var url;
		var token;

		this.setUrl = setUrl;
		this.getUrl = getUrl;
		this.setToken = setToken;
		this.$get = ["$rootScope", socketFactory];

		function setUrl(value) {
			url = value;
		}

		function getUrl() {
			return url;
		}

		function setToken(value) {
			token = value;
		}

		function socketFactory($rootScope) {
			var socket;

			var service = {
				checkToken: checkToken,
				addListener: addListener,
				on: addListener,
				once: addListenerOnce,
				removeListener: removeListener,
				removeAllListeners: removeAllListeners,
				emit: emit
			};

			return service;
			////////////////////////////////

			function initializeSocket(cb) {
				//Check if socket is undefined
				if (typeof socket === "undefined") {
					if (url !== "undefined") {
						socket = io.connect(url);
					} else {
						socket = io.connect();
					}

					socket.on("connect", function() {
						socket.emit("authenticate", {
							token: token
						});
						socket.on("tokenCorrect", function() {
							angularCallback(cb(true));
						});
						socket.on("tokenWrong", function() {
							angularCallback(cb(false));
						});
					});
				}
			}

			function checkToken(cb) {
				initializeSocket(cb);
			}

			function angularCallback(callback) {
				return function () {
					if (callback) {
						var args = arguments;
						$rootScope.$apply(function () {
							callback.apply(socket, args);
						});
					}
				};
			}

			function addListener(name, scope, callback) {
				initializeSocket();

				if (arguments.length === 2) {
					scope = null;
					callback = arguments[1];
				}

				socket.on(name, angularCallback(callback));

				if (scope !== null) {
					scope.$on("$destroy", function () {
						removeListener(name, callback);
					});
				}
			}

			function addListenerOnce(name, callback) {
				initializeSocket();
				socket.once(name, angularCallback(callback));
			}

			function removeListener(name, callback) {
				initializeSocket();
				socket.removeListener(name, angularCallback(callback));
			}

			function removeAllListeners(name) {
				initializeSocket();
				socket.removeAllListeners(name);
			}

			function emit(name, data, callback) {
				initializeSocket();
				socket.emit(name, data, angularCallback(callback));
			}
		}
	}
});
<|endoftext|>


<commit_before>QUnit.module('getWindowRect');

QUnit.test('Returns correct object if no offset is set', function(assert){
  assert.expect(4);
  var done = assert.async();
  ventana.queue(function() {
    var result = ventana.getWindowRect();
    assert.equal(result.top, 0, 'top should equal scrolled Y position');
    assert.equal(result.left, 0, 'left should equal scrolled x position');
    assert.equal(result.width, window.innerWidth, 'width should equal innerWidth');
    assert.equal(result.height, window.innerHeight, 'height should equal innerHeight');
    done();
  });
});

QUnit.test('Returns correct object when offset is set', function(assert){
  var result = ventana.getWindowRect({
    top: 5
  });
  assert.equal(result.top, 5, 'top should equal scrollY + offset');
});
<commit_msg>Make test synchronous<commit_after>QUnit.module('getWindowRect');

QUnit.test('Returns correct object if no offset is set', function(assert){
  var result = ventana.getWindowRect();
  assert.equal(result.top, 0, 'top should equal scrolled Y position');
  assert.equal(result.left, 0, 'left should equal scrolled x position');
  assert.equal(result.width, window.innerWidth, 'width should equal innerWidth');
  assert.equal(result.height, window.innerHeight, 'height should equal innerHeight');
});

QUnit.test('Returns correct object when offset is set', function(assert){
  var result = ventana.getWindowRect({
    top: 5
  });
  assert.equal(result.top, 5, 'top should equal scrollY + offset');
});
<|endoftext|>


<commit_before>let mocha = require('mocha'),
    chai = require('chai'),
    sinon = require('sinon'),
    Router = require('../../src/Router'),
    ControllerDispatcher = require('../../src/Router/ControllerDispatcher');

chai.should();

describe('Router', function () {
    let router, response;

    beforeEach(function () {
        router = new Router();

        response = {
            end: function (text) {
                return text;
            },
            setHeader: function (key, value) {
                return {};
            },
            writeHead: function (value) {
                return value;
            }
        };

    });

    afterEach(function () {
        if (JSON.stringify['restore'])
            JSON.stringify.restore();
    });

    it('should register get route', function () {
        router.get('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register post route', function () {
        router.post('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register put route', function () {
        router.put('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register delete route', function () {
        router.delete('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register multiple routes', function () {
        router.get('/home/1', function () {
            return 1;
        });

        router.get('/home/2', function () {
            return 2;
        });

        router.post('/home/3', function () {
            return 3;
        });

        router.routesList.should.have.property('length').that.equals(3);

        let route1 = router.findMatchingRoute('GET', '/home/1');
        route1.should.have.all.keys('handler', 'params', 'splat', 'src');
        route1.handler.closure().should.equal(1);

        let route2 = router.findMatchingRoute('GET', '/home/2');
        route2.should.have.all.keys('handler', 'params', 'splat', 'src');
        route2.handler.closure().should.equal(2);

        let route3 = router.findMatchingRoute('POST', '/home/3');
        route3.should.have.all.keys('handler', 'params', 'splat', 'src');
        route3.handler.closure().should.equal(3);
    });

    it('cant resolve missing route', function () {
        router.findMatchingRoute('GET', 'missingroute')
            .should.have.all.keys('handler', 'params', 'splat', 'src')
            .and.deep.equals({
                handler: null,
                params: {},
                splat: null,
                src: null
            });
    });

    it('extract parameters from route', function () {
        router.get('/:id', function () {
            return 1;
        });
        router.findMatchingRoute('GET', '/34')
            .should.have.property('params')
            .that.deep.equals({
                id: '34'
            });
    });

    it('resolve a route with casting', function () {
        router.get('/test', function () {
            return 1;
        });

        router.resolveRoute({method: 'GET', url: '/test'}, response).should.equal('1');
    });

    it('respond with string right away', function () {
        router.get('/test/string', function () {
            return "ok";
        });

        router.resolveRoute({method: 'GET', url: '/test/string'}, response).should.equal('ok');
    });

    it('should return Route not found if theres no route', function () {
        router.resolveRoute({method: 'GET', url: '404'}, response).should.equal('Route not found');
    });

    it('parse object to string', function () {
        router.get('/test/parsed', function () {
            return {
                "test": "test"
            };
        });

        router.resolveRoute({method: 'GET', url: '/test/parsed'}, response).should.equal('{\n    "test": "test"\n}');
    });

    it('adds string as handler', function () {
        router.get('/test/string', 'Controller');

        router.routesList[0].should.have.property('closure').that.equals('Controller');
    });

    it('returns a 500 error if json cannot be parsed to string', () => {
        sinon.stub(JSON, 'stringify').throws("Error");

        router.get('/test/errors', function () {
            return {
                "test": "test"
            };
        });
        router.resolveRoute({method: 'GET', url: '/test/errors'}, response).should.equal('Server error.');
    });

    it('goes through the controller', () => {
        let dispatch = sinon.stub(ControllerDispatcher, 'dispatchRoute').returns(true);
        let responder = sinon.stub(Router, 'respondToRoute').returns(true);
        let route = {
            handler: { closure: "TestController" },
            params: {}
        };

        Router.dispatchRoute(route, response);
        dispatch.restore();
        responder.restore();
        sinon.assert.calledOnce(dispatch);
        sinon.assert.calledOnce(responder);
    });

});<commit_msg>test added<commit_after>let mocha = require('mocha'),
    chai = require('chai'),
    sinon = require('sinon'),
    Router = require('../../src/Router'),
    ControllerDispatcher = require('../../src/Router/ControllerDispatcher');

chai.should();

describe('Router', function () {
    let router, response;

    beforeEach(function () {
        router = new Router();

        response = {
            end: function (text) {
                return text;
            },
            setHeader: function (key, value) {
                return {};
            },
            writeHead: function (value) {
                return value;
            }
        };

    });

    afterEach(function () {
        if (JSON.stringify['restore'])
            JSON.stringify.restore();
    });

    it('should register get route', function () {
        router.get('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register post route', function () {
        router.post('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register put route', function () {
        router.put('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register delete route', function () {
        router.delete('/home', function (req, res) {
            res.end();
        });
        router.routesList.should.have.property('length').that.equals(1);
        router.routesList[0].should.have.all.keys('method', 'path', 'options', 'closure');
    });

    it('should register multiple routes', function () {
        router.get('/home/1', function () {
            return 1;
        });

        router.get('/home/2', function () {
            return 2;
        });

        router.post('/home/3', function () {
            return 3;
        });

        router.routesList.should.have.property('length').that.equals(3);

        let route1 = router.findMatchingRoute('GET', '/home/1');
        route1.should.have.all.keys('handler', 'params', 'splat', 'src');
        route1.handler.closure().should.equal(1);

        let route2 = router.findMatchingRoute('GET', '/home/2');
        route2.should.have.all.keys('handler', 'params', 'splat', 'src');
        route2.handler.closure().should.equal(2);

        let route3 = router.findMatchingRoute('POST', '/home/3');
        route3.should.have.all.keys('handler', 'params', 'splat', 'src');
        route3.handler.closure().should.equal(3);
    });

    it('cant resolve missing route', function () {
        router.findMatchingRoute('GET', 'missingroute')
            .should.have.all.keys('handler', 'params', 'splat', 'src')
            .and.deep.equals({
                handler: null,
                params: {},
                splat: null,
                src: null
            });
    });

    it('extract parameters from route', function () {
        router.get('/:id', function () {
            return 1;
        });
        router.findMatchingRoute('GET', '/34')
            .should.have.property('params')
            .that.deep.equals({
                id: '34'
            });
    });

    it('resolve a route with casting', function () {
        router.get('/test', function () {
            return 1;
        });

        router.resolveRoute({method: 'GET', url: '/test'}, response).should.equal('1');
    });

    it('respond with string right away', function () {
        router.get('/test/string', function () {
            return "ok";
        });

        router.resolveRoute({method: 'GET', url: '/test/string'}, response).should.equal('ok');
    });

    it('should return Route not found if theres no route', function () {
        router.resolveRoute({method: 'GET', url: '404'}, response).should.equal('Route not found');
    });

    it('parse object to string', function () {
        router.get('/test/parsed', function () {
            return {
                "test": "test"
            };
        });

        router.resolveRoute({method: 'GET', url: '/test/parsed'}, response).should.equal('{\n    "test": "test"\n}');
    });

    it('adds string as handler', function () {
        router.get('/test/string', 'Controller');

        router.routesList[0].should.have.property('closure').that.equals('Controller');
    });

    it('returns a 500 error if json cannot be parsed to string', () => {
        sinon.stub(JSON, 'stringify').throws("Error");

        router.get('/test/errors', function () {
            return {
                "test": "test"
            };
        });
        router.resolveRoute({method: 'GET', url: '/test/errors'}, response).should.equal('Server error.');
    });

    it('nothing to return', () => {
        router.get('/test/nothing', function () {
        });
        router.resolveRoute({method: 'GET', url: '/test/nothing'}, response);
    });

    it('goes through the controller', () => {
        let dispatch = sinon.stub(ControllerDispatcher, 'dispatchRoute').returns(true);
        let responder = sinon.stub(Router, 'respondToRoute').returns(true);
        let route = {
            handler: { closure: "TestController" },
            params: {}
        };

        Router.dispatchRoute(route, response);
        dispatch.restore();
        responder.restore();
        sinon.assert.calledOnce(dispatch);
        sinon.assert.calledOnce(responder);
    });

});<|endoftext|>


<commit_before>var _ = require('underscore'),
    bower = require('bower'),
    childProcess = require('child_process'),
    fs = require('fs'),
    request = require('request'),
    util = require('util'),
    semver = require('semver'),
    yeoman = require('yeoman-generator');

var CollectVersions = module.exports = function CollectVersions(args, options, config) {

  yeoman.generators.Base.apply(this, arguments);

  this.argument('type', {desc: 'Version type. May be one of {scotsman, bower, hapi, npm}', required: true});

  if (this.type === 'scotsman' || this.type === 'hapi') {
    this.argument('url', {desc: 'Remote version list url', required: true});
  } else if (this.type !== 'bower' && this.type !== 'npm') {
    throw new Error('First argument must be one of {scotsman, bower, hapi, npm}');
  }
};

util.inherits(CollectVersions, yeoman.generators.Base);

CollectVersions.prototype.exec = function() {
  if (this.type === 'scotsman') {
    this._scotsman();
  } else if (this.type === 'hapi') {
    this._hapi();
  } else if (this.type === 'bower') {
    this._bowerLS();
  } else if (this.type === 'npm') {
    this._npmLS();
  }
};

CollectVersions.prototype._scotsman = function() {
  var done = this.async(),
      self = this;

  function process(err, response, body) {
    if (err) {
      throw new Error('Failed to load scotsman url "' + self.url + '" ' + err);
    }

    var ls = (/<pre>((?:\n|.)*?)<\/pre>/.exec(body) || [])[1];
    self.versions = parseVersions(ls);
    self.versions[0].bowerRoot = true;

    done();
  }

  if (this.url.indexOf('//') >= 0) {
    request(this.url, process);
  } else {
    fs.readFile(this.url, function(err, data) {
      process(err, undefined, data.toString());
    });
  }
};

CollectVersions.prototype._bowerLS = function() {
  var done = this.async(),
      self = this;
  childProcess.exec('bower ls --offline', function(err, stdout, stderr) {
    self.versions = parseVersions(stdout);
    self.versions[0].bowerRoot = true;

    done();
  });
};

CollectVersions.prototype._npmLS = function() {
  var done = this.async(),
      self = this;
  childProcess.exec('npm ls --json', function(err, stdout, stderr) {
    var versions = [];

    function deepPluck(name, obj, root) {
      versions.push({
        name: name,
        version: obj.version
      });

      if (obj.dependencies) {
        _.each(obj.dependencies, function(info, child) {
          return deepPluck((root ? '' : name + '/') + child, info);
        });
      }
    }

    var list = JSON.parse(stdout);
    deepPluck(list.name, list, true);
    versions[0].npmRoot = true;

    self.versions = versions;

    done();
  });

};

CollectVersions.prototype.output = function() {
  if (!this.quiet) {
    console.log(JSON.stringify(this.versions, undefined, 2));
  }
};

function parseVersions(ls) {
  /*jshint boss:true */
  var versions = [],
      matcher = /(\S+)#(\S+)/g,
      match;
  while (match = matcher.exec(ls)) {
    versions.push({
      name: match[1],
      version: match[2]
    });
  }
  return versions;
}
<commit_msg>Add error logging to npm and bower collectors<commit_after>var _ = require('underscore'),
    bower = require('bower'),
    childProcess = require('child_process'),
    fs = require('fs'),
    request = require('request'),
    util = require('util'),
    semver = require('semver'),
    yeoman = require('yeoman-generator');

var CollectVersions = module.exports = function CollectVersions(args, options, config) {

  yeoman.generators.Base.apply(this, arguments);

  this.argument('type', {desc: 'Version type. May be one of {scotsman, bower, hapi, npm}', required: true});

  if (this.type === 'scotsman' || this.type === 'hapi') {
    this.argument('url', {desc: 'Remote version list url', required: true});
  } else if (this.type !== 'bower' && this.type !== 'npm') {
    throw new Error('First argument must be one of {scotsman, bower, hapi, npm}');
  }
};

util.inherits(CollectVersions, yeoman.generators.Base);

CollectVersions.prototype.exec = function() {
  if (this.type === 'scotsman') {
    this._scotsman();
  } else if (this.type === 'hapi') {
    this._hapi();
  } else if (this.type === 'bower') {
    this._bowerLS();
  } else if (this.type === 'npm') {
    this._npmLS();
  }
};

CollectVersions.prototype._scotsman = function() {
  var done = this.async(),
      self = this;

  function process(err, response, body) {
    if (err) {
      throw new Error('Failed to load scotsman url "' + self.url + '" ' + err);
    }

    var ls = (/<pre>((?:\n|.)*?)<\/pre>/.exec(body) || [])[1];
    self.versions = parseVersions(ls);
    self.versions[0].bowerRoot = true;

    done();
  }

  if (this.url.indexOf('//') >= 0) {
    request(this.url, process);
  } else {
    fs.readFile(this.url, function(err, data) {
      process(err, undefined, data.toString());
    });
  }
};

CollectVersions.prototype._bowerLS = function() {
  var done = this.async(),
      self = this;
  childProcess.exec('bower ls --offline', function(err, stdout, stderr) {
    if (err) {
      throw err;
    }

    self.versions = parseVersions(stdout);
    self.versions[0].bowerRoot = true;

    done();
  });
};

CollectVersions.prototype._npmLS = function() {
  var done = this.async(),
      self = this;
  childProcess.exec('npm ls --json', function(err, stdout, stderr) {
    if (err) {
      throw err;
    }

    var versions = [];

    function deepPluck(name, obj, root) {
      versions.push({
        name: name,
        version: obj.version
      });

      if (obj.dependencies) {
        _.each(obj.dependencies, function(info, child) {
          return deepPluck((root ? '' : name + '/') + child, info);
        });
      }
    }

    var list = JSON.parse(stdout);
    deepPluck(list.name, list, true);
    versions[0].npmRoot = true;

    self.versions = versions;

    done();
  });

};

CollectVersions.prototype.output = function() {
  if (!this.quiet) {
    console.log(JSON.stringify(this.versions, undefined, 2));
  }
};

function parseVersions(ls) {
  /*jshint boss:true */
  var versions = [],
      matcher = /(\S+)#(\S+)/g,
      match;
  while (match = matcher.exec(ls)) {
    versions.push({
      name: match[1],
      version: match[2]
    });
  }
  return versions;
}
<|endoftext|>


<commit_before>var fs = require('fs');
var Logger = require('./util/logger.js');
var fileUtil = require('./util/file-util.js');
var Constants = require('./util/constants.js');
var $ = require('jquery');

fs.readdir(Constants.STANDARD_FILE_PATH, (error, files) => {
  updateFileList(files);
});

fs.watch(Constants.STANDARD_FILE_PATH, (event, filename) => {
  fs.readdir(Constants.STANDARD_FILE_PATH, (error, files) => {
    updateFileList(files);
  });
});

$(document).ready(function() {
  $(".fileList").on('click', "*", function(event) {
    var fileName = $(this).text();
    var file = fileUtil.openFile(Constants.STANDARD_FILE_PATH + fileName);
    $(".editorFrame").text(file);
  });
});

function updateFileList(files) {
  var htmlToAppend = "";
  files.forEach(function(file, index, array) {
    htmlToAppend += "
" + file + "
";
  });
  $(".fileList").html(htmlToAppend);
}
<commit_msg>fixed small bug<commit_after>var fs = require('fs');
var Logger = require('./util/logger.js');
var fileUtil = require('./util/file-util.js');
var Constants = require('./util/constants.js');
var $ = require('jquery');

fs.readdir(Constants.STANDARD_FILE_PATH, (error, files) => {
  updateFileList(files);
});

fs.watch(Constants.STANDARD_FILE_PATH, (event, filename) => {
  fs.readdir(Constants.STANDARD_FILE_PATH, (error, files) => {
    updateFileList(files);
  });
});

$(document).ready(function() {
  $(".fileList").on('click', "*", function(event) {
    var fileName = $(this).text();
    var file = fileUtil.openFile(Constants.STANDARD_FILE_PATH + fileName);
    $(".editorFrame").text(file);
  });
});

function updateFileList(files) {
  if (files === undefined) {
    return;
  }
  var htmlToAppend = "";
  files.forEach(function(file, index, array) {
    htmlToAppend += "
" + file + "
";
  });
  $(".fileList").html(htmlToAppend);
}
<|endoftext|>


<commit_before>/*global d3 */

var params = d3.select("#api_key");

if (!params.empty()) {
  var api_key = params.attr('data-api-key');
  var page = params.attr('data-page');
  if (page == null) { page = 1; }
  var per_page = params.attr('data-per-page');
  var q = params.attr('data-q');
  var source_id = params.attr('data-source-id');
  var state = params.attr('data-state');

  var query = encodeURI("/api/deposits?page=" + page);
  if (per_page !== null) { query += "&per_page=" + per_page; }
  if (q !== null) { query += "&q=" + q; }
  if (source_id !== null) { query += "&source_id=" + source_id; }
  if (state !== null) { query += "&state=" + state; }
}

// asynchronously load data from the Lagotto API
queue()
  .defer(d3.json, encodeURI("/api/sources"))
  .defer(d3.json, encodeURI("/api/relation_types"))
  .defer(d3.json, query)
  .await(function(error, s, r, d) {
    if (error) { return console.warn(error); }
    eventsViz(d, s.sources, r.relation_types);
    paginate(d, "#content");
});

// add data to page
function eventsViz(json, sources, relation_types) {
  data = json.deposits;

  json.href = "?page={{number}}";
  if (q !== null) { json.href += "&q=" + q; }
  if (state !== null) { json.href += "&state=" + state; }
  if (source_id !== null) { json.href += "&source_id=" + source_id; }

  d3.select("#loading-results").remove();

  if (typeof data === "undefined" || data.length === 0) {
    d3.select("#content").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("There are currently no deposits");
    return;
  }

  if (json.meta.total > 1) {
    d3.select("#content").insert("h4")
      .attr("class", "results")
      .text(numberWithDelimiter(json.meta.total) + " Deposits");
  }

  for (var i=0; i<data.length; i++) {
    var deposit = data[i];
    var source = sources.filter(function(d) { return d.id === deposit.source_id; })[0];
    var relation_type = relation_types.filter(function(d) { return d.id === deposit.relation_type_id; })[0];

    d3.select("#content").insert("div")
      .attr("class", "panel panel-default")
      .attr("id", "panel-" + i).insert("div")
      .attr("class", "panel-body")
      .attr("id", "panel-body-" + i);

    d3.select("#panel-body-" + i).append("h4")
      .attr("class", "work")
      .html(deposit.id);

    d3.select("#panel-body-" + i).append("span")
      .attr("class", "pull-right")
      .text(deposit.state);

    if (typeof Object.keys(deposit.subj).length > 0) {
      d3.select("#panel-body-" + i).append("h5")
        .text("Subj");
      d3.select("#panel-body-" + i).append("p")
        .html(function() { return deposit.subj; });
    }

    if (typeof Object.keys(deposit.obj).length > 0) {
      d3.select("#panel-body-" + i).append("h5")
        .text("Obj");
      d3.select("#panel-body-" + i).append("p")
        .html(function() { return deposit.obj; });
    }

    d3.select("#panel-body-" + i).append("p")
      .text(relation_type.title + " ").append("a")
      .attr("href", function() { return pathForWork(deposit.obj_id); })
      .html(deposit.obj_id);

    if (typeof deposit.errors !== "undefined") {
      var error_key = Object.keys(deposit.errors);

      d3.select("#panel-body-" + i).append("h5")
        .text("Errors in " + error_key);
      d3.select("#panel-body-" + i).append("p")
        .html(deposit.errors[error_key]);
    }

    d3.select("#panel-" + i).insert("div")
      .attr("class", "panel-footer")
      .attr("id", "panel-footer-" + i).append("a")
      .attr("href", function() { return deposit.subj_id; })
      .html('<i class="fa fa-external-link"/>').append('span')
      .text(deposit.subj_id);
    d3.select("#panel-footer-" + i).append("a")
      .attr("class", "pull-right")
      .attr("href", function() { return "/deposits?source_id=" + deposit.source_id; })
      .text(source.title);
  }
}
<commit_msg>handle missing source_id in deposits<commit_after>/*global d3 */

var params = d3.select("#api_key");

if (!params.empty()) {
  var api_key = params.attr('data-api-key');
  var page = params.attr('data-page');
  if (page == null) { page = 1; }
  var per_page = params.attr('data-per-page');
  var q = params.attr('data-q');
  var source_id = params.attr('data-source-id');
  var state = params.attr('data-state');

  var query = encodeURI("/api/deposits?page=" + page);
  if (per_page !== null) { query += "&per_page=" + per_page; }
  if (q !== null) { query += "&q=" + q; }
  if (source_id !== null) { query += "&source_id=" + source_id; }
  if (state !== null) { query += "&state=" + state; }
}

// asynchronously load data from the Lagotto API
queue()
  .defer(d3.json, encodeURI("/api/sources"))
  .defer(d3.json, encodeURI("/api/relation_types"))
  .defer(d3.json, query)
  .await(function(error, s, r, d) {
    if (error) { return console.warn(error); }
    eventsViz(d, s.sources, r.relation_types);
    paginate(d, "#content");
});

// add data to page
function eventsViz(json, sources, relation_types) {
  data = json.deposits;

  json.href = "?page={{number}}";
  if (q !== null) { json.href += "&q=" + q; }
  if (state !== null) { json.href += "&state=" + state; }
  if (source_id !== null) { json.href += "&source_id=" + source_id; }

  d3.select("#loading-results").remove();

  if (typeof data === "undefined" || data.length === 0) {
    d3.select("#content").text("")
      .insert("div")
      .attr("class", "alert alert-info")
      .text("There are currently no deposits");
    return;
  }

  if (json.meta.total > 1) {
    d3.select("#content").insert("h4")
      .attr("class", "results")
      .text(numberWithDelimiter(json.meta.total) + " Deposits");
  }

  for (var i=0; i<data.length; i++) {
    var deposit = data[i];
    var source = sources.filter(function(d) { return d.id === deposit.source_id; })[0];
    var relation_type = relation_types.filter(function(d) { return d.id === deposit.relation_type_id; })[0];

    d3.select("#content").insert("div")
      .attr("class", "panel panel-default")
      .attr("id", "panel-" + i).insert("div")
      .attr("class", "panel-body")
      .attr("id", "panel-body-" + i);

    d3.select("#panel-body-" + i).append("h4")
      .attr("class", "work")
      .html(deposit.id);

    d3.select("#panel-body-" + i).append("span")
      .attr("class", "pull-right")
      .text(deposit.state);

    if (typeof Object.keys(deposit.subj).length > 0) {
      d3.select("#panel-body-" + i).append("h5")
        .text("Subj");
      d3.select("#panel-body-" + i).append("p")
        .html(function() { return deposit.subj; });
    }

    if (typeof Object.keys(deposit.obj).length > 0) {
      d3.select("#panel-body-" + i).append("h5")
        .text("Obj");
      d3.select("#panel-body-" + i).append("p")
        .html(function() { return deposit.obj; });
    }

    d3.select("#panel-body-" + i).append("p")
      .text(relation_type.title + " ").append("a")
      .attr("href", function() { return pathForWork(deposit.obj_id); })
      .html(deposit.obj_id);

    if (typeof deposit.errors !== "undefined") {
      var error_key = Object.keys(deposit.errors);

      d3.select("#panel-body-" + i).append("h5")
        .text("Errors in " + error_key);
      d3.select("#panel-body-" + i).append("p")
        .html(deposit.errors[error_key]);
    }

    d3.select("#panel-" + i).insert("div")
      .attr("class", "panel-footer")
      .attr("id", "panel-footer-" + i).append("a")
      .attr("href", function() { return deposit.subj_id; })
      .html('<i class="fa fa-external-link"/>').append('span')
      .text(deposit.subj_id);
    if (typeof source !== "undefined") {
      d3.select("#panel-footer-" + i).append("a")
        .attr("class", "pull-right")
        .attr("href", function() { return "/deposits?source_id=" + deposit.source_id; })
        .text(source.title);
    }
  }
}
<|endoftext|>