<commit_before>import React from 'react';
import { render } from 'react-dom';
import endpoint from './endpoint';
import Logo from './react-components/logo.jsx';
import Footer from './react-components/footer.jsx';
import { oauthLogin } from '../common/appId';
import { isEuCountry, showHideEuElements } from '../common/footer-checks';
import GTM from '../common/gtm';
import { load as loadLang, showBanner } from '../common/lang';
import { moveToDeriv } from '../common/utils/utility';
import { get as getStorage, set as setStorage, remove, getTokenList } from '../common/utils/storageManager';
import { createUrl, parseQueryString, serialize } from '../common/utils/tools';
import '../common/binary-ui/dropdown';
import BotLanding from './react-components/bot-landing';
import BinaryLanding from './react-components/binary-landing';

const today = new Date().getTime();
// eslint-disable-next-line one-var
const oneMilliSec = 1000;
// will uncomment before production release
// const sevenDays = 7;
// const oneMinute = 60;
// const oneDay = 24;

export const elements = ['#notification-banner', '#main', '#footer', '#header', '#topbar'];
// eslint-disable-next-line one-var
export const bannerToken = getStorage('setDueDateForBanner');

// eslint-disable-next-line arrow-body-style
export const expirationDate = () => {
    return today + oneMilliSec * 600;
};

export const calcSetTimeoutValueBanner = expirationDate() - new Date().getTime();

// eslint-disable-next-line import/no-mutable-exports
export let timerForBanner;

const checkifBotRunning = () => {
    if (document.getElementById('runButton').style.display === 'none') {
        return true;
    }
    return false;
};
let Component, dynamicVar;
export const getComponent = () => {
    if (window.location.pathname === '/movetoderiv.html') {
        Component = <BinaryLanding />;
        dynamicVar = 'movetoderiv';
    } else {
        Component = <BotLanding />;
        dynamicVar = 'bot-landing';
    }
};
export const setTimeOutBanner = route => {
    let bannerDisplayed;
    const qs = parseQueryString();
    // eslint-disable-next-line consistent-return
    timerForBanner = setTimeout(() => {
        if (
            (route === 'index' && !!bannerDisplayed === false) ||
            (route === 'views' && checkifBotRunning() === false)
        ) {
            const getDefaultPath = window.location.href.replace('/bot.html', serialize(qs));
            window.location.replace(getDefaultPath);
            renderBanner();
        } else if (
            (route === 'index' && !!bannerDisplayed === true) ||
            (route === 'views' && checkifBotRunning() === true)
        ) {
            remove('setDueDateForBanner');
            setStorage('setDueDateForBanner', expirationDate());
            return false;
        }
    }, calcSetTimeoutValueBanner);
};

const renderBanner = () => {
    if (window.location.href.indexOf('bot.html') === -1) {
        getComponent();
        render(Component, document.getElementById(dynamicVar));
        setStorage('setDueDateForBanner', expirationDate());
        elements.map(elem => document.querySelector(elem).classList.add('hidden'));
        document.getElementById(dynamicVar).classList.remove('hidden');
        document.getElementById('bot-main').classList.remove('hidden');
        document.getElementById('topbar').classList.remove('hidden');
        $('.barspinner').hide();
    }
};

// eslint-disable-next-line consistent-return
const renderElements = () => {
    // eslint-disable-next-line one-var, no-unused-vars
    getComponent();
    setTimeOutBanner('index');
    $('.barspinner').show();

    if (!bannerToken) {
        if (window.location.href.indexOf('bot.html') === -1) {
            renderBanner();
        }
    } else {
        if (today > bannerToken) {
            remove('setDueDateForBanner');
            renderBanner();
            return false;
        }
        if (window.location.href.indexOf('bot.html') === -1) {
            render(<Logo />, document.getElementById('binary-logo'));
            render(<Footer />, document.getElementById('footer'));
            isEuCountry().then(isEu => showHideEuElements(isEu));
            showBanner();
            $('#shop-url').attr(
                'href',
                createUrl({ subdomain: 'shop', path: 'collections/strategies', isNonBotPage: true })
            );
            elements.map(elem => document.querySelector(elem).classList.remove('hidden'));
            document.getElementById(dynamicVar).classList.add('hidden');
        }
        document.getElementById('bot-main').classList.remove('hidden');
        setTimeout(() => {
            $('.barspinner').hide();
        }, 2000);
    }
};

const loginCheck = () => {
    if (endpoint()) return;
    moveToDeriv();
    if (window.location.href.indexOf('bot.html') === -1) {
        loadLang();
    }
    $('.show-on-load').show();
    if (bannerToken) {
        if (getTokenList().length) {
            if (!window.location.pathname.includes('/bot.html')) {
                window.location.pathname = `${window.location.pathname.replace(/\/+$/, '')}/bot.html`;
            }
            document.getElementById('bot-main').classList.remove('hidden');
        } else {
            oauthLogin(() => {
                $('.barspinner').hide();
                renderElements();
                GTM.init();
            });
        }
    } else {
        setTimeout(() => {
            renderBanner();
        }, 0);
    }
};

loginCheck();
<commit_msg>resolved merge confict and fixed the routing issue for move to deriv page<commit_after>import React from 'react';
import { render } from 'react-dom';
import endpoint from './endpoint';
import Logo from './react-components/logo.jsx';
import Footer from './react-components/footer.jsx';
import { oauthLogin } from '../common/appId';
import { isEuCountry, showHideEuElements } from '../common/footer-checks';
import GTM from '../common/gtm';
import { load as loadLang, showBanner } from '../common/lang';
import { moveToDeriv } from '../common/utils/utility';
import { get as getStorage, set as setStorage, remove, getTokenList } from '../common/utils/storageManager';
import { createUrl, parseQueryString, serialize } from '../common/utils/tools';
import '../common/binary-ui/dropdown';
import BotLanding from './react-components/bot-landing';
import BinaryLanding from './react-components/binary-landing';

const today = new Date().getTime();
// eslint-disable-next-line one-var
const oneMilliSec = 1000;
const sevenDays = 7;
const oneMinute = 60;
const oneDay = 24;

export const elements = ['#notification-banner', '#main', '#footer', '#header', '#topbar'];
// eslint-disable-next-line one-var
export const bannerToken = getStorage('setDueDateForBanner');

// eslint-disable-next-line arrow-body-style
export const expirationDate = () => {
    return today + oneMilliSec * oneMinute * oneMinute * oneDay * sevenDays;
};

export const calcSetTimeoutValueBanner = expirationDate() - new Date().getTime();

// eslint-disable-next-line import/no-mutable-exports
export let timerForBanner;

const checkifBotRunning = () => {
    if (document.getElementById('runButton').style.display === 'none') {
        return true;
    }
    return false;
};
let Component, dynamicRoutePathanme;
export const getComponent = () => {
    if (window.location.pathname === '/movetoderiv.html') {
        Component = <BinaryLanding />;
        dynamicRoutePathanme = 'movetoderiv';
    } else {
        Component = <BotLanding />;
        dynamicRoutePathanme = 'bot-landing';
    }
    return {
        Component,
        dynamicRoutePathanme,
    };
};
export const setTimeOutBanner = route => {
    let bannerDisplayed;
    const qs = parseQueryString();
    // eslint-disable-next-line consistent-return
    timerForBanner = setTimeout(() => {
        if (
            (route === 'index' && !!bannerDisplayed === false) ||
            (route === 'views' && checkifBotRunning() === false)
        ) {
            const getDefaultPath = window.location.href.replace('/bot.html', serialize(qs));
            window.location.replace(getDefaultPath);
            renderBanner();
        } else if (
            (route === 'index' && !!bannerDisplayed === true) ||
            (route === 'views' && checkifBotRunning() === true)
        ) {
            remove('setDueDateForBanner');
            setStorage('setDueDateForBanner', expirationDate());
            return false;
        }
    }, calcSetTimeoutValueBanner);
};

export const renderBanner = () => {
    if (window.location.href.indexOf('bot.html') === -1 || window.location.pathname === '/movetoderiv.html') {
        getComponent();
        render(Component, document.getElementById(dynamicRoutePathanme));
        if (dynamicRoutePathanme === 'bot-landing') {
            setStorage('setDueDateForBanner', expirationDate());
        }
        elements.map(elem => document.querySelector(elem).classList.add('hidden'));
        document.getElementById(dynamicRoutePathanme).classList.remove('hidden');
        document.getElementById('bot-main').classList.remove('hidden');
        document.getElementById('topbar').classList.remove('hidden');
        $('.barspinner').hide();
    }
};

// eslint-disable-next-line consistent-return
const renderElements = () => {
    // eslint-disable-next-line one-var, no-unused-vars
    getComponent();
    setTimeOutBanner('index');
    $('.barspinner').show();

    if (!bannerToken) {
        if (window.location.href.indexOf('bot.html') === -1) {
            renderBanner();
        }
    } else {
        if (today > bannerToken) {
            remove('setDueDateForBanner');
            renderBanner();
            return false;
        }
        if (window.location.href.indexOf('bot.html') === -1) {
            render(<Logo />, document.getElementById('binary-logo'));
            render(<Footer />, document.getElementById('footer'));
            isEuCountry().then(isEu => showHideEuElements(isEu));
            showBanner();
            $('#shop-url').attr(
                'href',
                createUrl({ subdomain: 'shop', path: 'collections/strategies', isNonBotPage: true })
            );
            elements.map(elem => document.querySelector(elem).classList.remove('hidden'));
            document.getElementById(dynamicRoutePathanme).classList.add('hidden');
        }
        document.getElementById('bot-main').classList.remove('hidden');
        setTimeout(() => {
            $('.barspinner').hide();
        }, 2000);
    }
};

const loginCheck = () => {
    if (endpoint()) return;
    moveToDeriv();
    if (window.location.href.indexOf('bot.html') === -1) {
        loadLang();
    }
    $('.show-on-load').show();
    if (bannerToken && window.location.pathname !== '/movetoderiv.html') {
        if (getTokenList().length) {
            if (!window.location.pathname.includes('/bot.html')) {
                window.location.pathname = `${window.location.pathname.replace(/\/+$/, '')}/bot.html`;
            }
            document.getElementById('bot-main').classList.remove('hidden');
        } else {
            oauthLogin(() => {
                $('.barspinner').hide();
                renderElements();
                GTM.init();
            });
        }
    } else {
        setTimeout(() => {
            renderBanner();
        }, 0);
    }
};

loginCheck();
<|endoftext|>


<commit_before>var SYSTEM = require("system");
var FILE = require("file");
var OS = require("os");
var UTIL = require("util");
var stream = require("term").stream;

var requiresSudo = false;

SYSTEM.args.slice(1).forEach(function(arg){
    if (arg === "sudo-install")
        requiresSudo = true;
});

function ensurePackageUpToDate(packageName, requiredVersion, options)
{
    options = options || {};

    var packageInfo = require("packages").catalog[packageName];
    if (!packageInfo)
    {
        if (options.optional)
            return;

        print("You are missing package \"" + packageName + "\", version " + requiredVersion + " or later. Please install using \"tusk install "+packageName+"\" and re-run jake");
        OS.exit(1);
    }

    var version = packageInfo.version;
    if (typeof version === "string")
        version = version.split(".");

    if (typeof requiredVersion === "string")
        requiredVersion = requiredVersion.split(".");

    if (version && UTIL.compare(version, requiredVersion) !== -1)
        return;

    print("Your copy of " + packageName + " is out of date (" + (version||["0"]).join(".") + " installed, " + requiredVersion.join(".") + " required).");

    if (!options.noupdate)
    {
        print("Update? yes or no:");
        if (!SYSTEM.env["CAPP_AUTO_UPGRADE"] && system.stdin.readLine() !== "yes\n")
        {
            print("Jake aborted.");
            OS.exit(1);
        }

        if (requiresSudo)
        {
            if (OS.system(["sudo", "tusk", "install", "--force", packageName]))
            {
                // Attempt a hackish work-around for sudo compiled with the --with-secure-path option
                if (OS.system("sudo bash -c 'source " + getShellConfigFile() + "; tusk install --force "+packageName))
                    OS.exit(1); //rake abort if ($? != 0)
            }
        }
        else
            OS.system(["tusk", "install", "--force", packageName]);
    }

    if (options.message)
    {
        print(options.message)
        OS.exit(1);
    }
}

// UPDATE THESE TO PICK UP CORRESPONDING CHANGES IN DEPENDENCIES
ensurePackageUpToDate("jake",           "0.1.5");
ensurePackageUpToDate("browserjs",      "0.1.1");
ensurePackageUpToDate("shrinksafe",     "0.2");
ensurePackageUpToDate("narwhal",        "0.2.2", {
    noupdate : true,
    message : "Update Narwhal to 0.2.1 by running bootstrap.sh, or pulling the latest from git (see: http://github.com/280north/narwhal)."
});
ensurePackageUpToDate("narwhal-jsc",    "0.1.1", {
    optional : true,
    message : "Rebuild narwhal-jsc by changing to the narwhal-jsc package directory and running \"make webkit\"."
});

var JAKE = require("jake");

// Set up development environment variables.

// record the initial SYSTEM.env so we know which need to be serialized later
var envInitial = Object.freeze(UTIL.copy(SYSTEM.env));

SYSTEM.env["BUILD_PATH"] = FILE.absolute(
    SYSTEM.env["BUILD_PATH"] ||
    SYSTEM.env["CAPP_BUILD"] || // Global Cappuccino build directory.
    SYSTEM.env["STEAM_BUILD"] || // Maintain backwards compatibility with steam.
    FILE.join(FILE.dirname(module.path), "Build") // Just build here.
);

if (!SYSTEM.env["CAPP_BUILD"] && SYSTEM.env["STEAM_BUILD"])
    system.stderr.print("STEAM_BUILD environment variable is deprecated; Please use CAPP_BUILD instead.");

if (!SYSTEM.env["CONFIG"])
    SYSTEM.env["CONFIG"] = "Release";

global.ENV  = SYSTEM.env;
global.ARGV = SYSTEM.args
global.FILE = FILE;
global.OS   = OS;

global.task = JAKE.task;
global.directory = JAKE.directory;
global.file = JAKE.file;
global.filedir = JAKE.filedir;
global.FileList = JAKE.FileList;

global.$CONFIGURATION                   = SYSTEM.env['CONFIG'];
global.$BUILD_DIR                       = SYSTEM.env['BUILD_PATH'];
global.$BUILD_CONFIGURATION_DIR         = FILE.join($BUILD_DIR, $CONFIGURATION);

global.$BUILD_CJS_OBJECTIVE_J           = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "objective-j");

global.$BUILD_CJS_CAPPUCCINO            = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino");
global.$BUILD_CJS_CAPPUCCINO_BIN        = FILE.join($BUILD_CJS_CAPPUCCINO, "bin");
global.$BUILD_CJS_CAPPUCCINO_LIB        = FILE.join($BUILD_CJS_CAPPUCCINO, "lib");
global.$BUILD_CJS_CAPPUCCINO_FRAMEWORKS = FILE.join($BUILD_CJS_CAPPUCCINO, "Frameworks");

global.CLEAN = require("jake/clean").CLEAN;
global.CLOBBER = require("jake/clean").CLOBBER;
global.CLEAN.push(global.$BUILD_DIR);
global.CLOBBER.push(global.$BUILD_DIR);

global.$HOME_DIR        = FILE.absolute(FILE.dirname(module.path));
global.$LICENSE_FILE    = FILE.absolute(FILE.join(FILE.dirname(module.path), 'LICENSE'));

global.FIXME_fileDependency = function(destinationPath, sourcePath)
{
    file(destinationPath, [sourcePath], function(){
        FILE.touch(destinationPath);
    });
};

// logic to determine which packages should be loaded but are not.
// used in serializedENV()
function additionalPackages()
{
    var builtObjectiveJPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "objective-j", "");
    var builtCappuccinoPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "cappuccino", "");

    var packages = [];

    // load built objective-j if exists, otherwise unbuilt
    if (builtObjectiveJPackage.join("package.json").exists()) {
        if (!packageInCatalog(builtObjectiveJPackage))
            packages.push(builtObjectiveJPackage);
    }

    // load built cappuccino if it exists
    if (builtCappuccinoPackage.join("package.json").exists()) {
        if (!packageInCatalog(builtCappuccinoPackage))
            packages.push(builtCappuccinoPackage);
    }

    return packages;
}

// checks to see if a path is in the package catalog
function packageInCatalog(path)
{
    var catalog = require("packages").catalog;
    for (var name in catalog)
        if (String(catalog[name].directory) === String(path))
            return true;
    return false;
}

serializedENV = function()
{
    var envNew = {};

    // add changed keys to the new ENV
    Object.keys(SYSTEM.env).forEach(function(key) {
        if (SYSTEM.env[key] !== envInitial[key])
            envNew[key] = SYSTEM.env[key];
    });

    // pseudo-HACK: add NARWHALOPT with packages we should ensure are loaded
    var packages = additionalPackages();
    if (packages.length) {
        envNew["NARWHALOPT"] = packages.map(function(p) { return "-p " + OS.enquote(p); }).join(" ");
        envNew["PATH"] = packages.map(function(p) { return FILE.join(p, "bin"); }).concat(SYSTEM.env["PATH"]).join(":");
    }

    return Object.keys(envNew).map(function(key) {
        return key + "=" + OS.enquote(envNew[key]);
    }).join(" ");
}

function reforkWithPackages()
{
    if (additionalPackages().length > 0) {
        var cmd = serializedENV() + " " + system.args.map(OS.enquote).join(" ");
        //print("REFORKING: " + cmd);
        OS.exit(OS.system(cmd));
    }
}

reforkWithPackages();

function handleSetupEnvironmentError(e) {
    if (String(e).indexOf("require error")==-1) {
        print("setupEnvironment warning: " + e);
        //throw e;
    }
}

function setupEnvironment()
{
    try {
        require("objective-j").OBJJ_INCLUDE_PATHS.push(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino", "Frameworks"));
    } catch (e) {
        handleSetupEnvironmentError(e);
    }
}

setupEnvironment();

global.rm_rf = function(/*String*/ aFilename)
{
    try { FILE.rmtree(aFilename); }
    catch (anException) { }
}

global.cp_r = function(/*String*/ from, /*String*/ to)
{
    if (FILE.exists(to))
        rm_rf(to);

    if (FILE.isDirectory(from))
        FILE.copyTree(from, to);
    else{try{
        FILE.copy(from, to);}catch(e) { print(e + FILE.exists(from) + " " + FILE.exists(FILE.dirname(to))); }}
}

global.cp = function(/*String*/ from, /*String*/ to)
{
    FILE.copy(from, to);
//    FILE.chmod(to, FILE.mod(from));
}

global.mv = function(/*String*/ from, /*String*/ to)
{
    FILE.move(from, to);
}

global.subjake = function(/*Array<String>*/ directories, /*String*/ aTaskName)
{
    if (!Array.isArray(directories))
        directories = [directories];

    directories.forEach(function(/*String*/ aDirectory)
    {
        if (FILE.isDirectory(aDirectory) && FILE.isFile(FILE.join(aDirectory, "Jakefile")))
        {
            var cmd = "cd " + OS.enquote(aDirectory) + " && " + serializedENV() + " " + OS.enquote(SYSTEM.args[0]) + " " + OS.enquote(aTaskName);
            var returnCode = OS.system(cmd);
            if (returnCode)
                OS.exit(returnCode);
        }
        else
            print("warning: subjake missing: " + aDirectory + " (this is not necessarily an error, " + aDirectory + " may be optional)");
    });
}

global.executableExists = function(/*String*/ executableName)
{
    var paths = SYSTEM.env["PATH"].split(':');
    for (var i = 0; i < paths.length; i++) {
        var path = FILE.join(paths[i], executableName);
        if (FILE.exists(path))
            return path;
    }
    return null;
}

$OBJJ_TEMPLATE_EXECUTABLE = FILE.join($HOME_DIR, "Objective-J", "CommonJS", "objj-executable");

global.make_objj_executable = function(aPath)
{
    cp($OBJJ_TEMPLATE_EXECUTABLE, aPath);
    FILE.chmod(aPath, 0755);
}

global.symlink_executable = function(source)
{
    relative = FILE.relative($ENVIRONMENT_NARWHAL_BIN_DIR, source);
    destination = FILE.join($ENVIRONMENT_NARWHAL_BIN_DIR, FILE.basename(source));
    FILE.symlink(relative, destination);
}

global.getCappuccinoVersion = function() {
    var versionFile = FILE.path(module.path).dirname().join("version.json");
    return JSON.parse(versionFile.read({ charset : "UTF-8" })).version;
}

global.setPackageMetadata = function(packagePath) {
    var pkg = JSON.parse(FILE.read(packagePath, { charset : "UTF-8" }));

    var p = OS.popen(["git", "rev-parse", "--verify", "HEAD"]);
    if (p.wait() === 0) {
        var sha = p.stdout.read().split("\n")[0];
        if (sha.length === 40)
            pkg["cappuccino-revision"] = sha;
    }

    pkg["cappuccino-timestamp"] = new Date().getTime();
    pkg["version"] = getCappuccinoVersion();

    stream.print("    Version:   \0purple(" + pkg["version"] + "\0)");
    stream.print("    Revision:  \0purple(" + pkg["cappuccino-revision"] + "\0)");
    stream.print("    Timestamp: \0purple(" + pkg["cappuccino-timestamp"] + "\0)");

    FILE.write(packagePath, JSON.stringify(pkg, null, 4), { charset : "UTF-8" });
}

global.subtasks = function(subprojects, taskNames)
{
    taskNames.forEach(function(aTaskName)
    {
        var subtaskName = aTaskName + "_subprojects";

        task (aTaskName, [subtaskName]);

        task (subtaskName, function()
        {
            subjake(subprojects, aTaskName);
        });
    });
}

function spawnJake(/*String*/ aTaskName)
{
    if (OS.system(serializedENV() + " " + SYSTEM.args[0] + " " + aTaskName))
        OS.exit(1);//rake abort if ($? != 0)
}

// built in tasks

task ("build");
task ("default", "build");

task ("release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("build");
});

task ("debug", function()
{
    SYSTEM.env["CONFIG"] = "Debug";
    spawnJake("build");
});

task ("all", ["debug", "release"]);

task ("clean-debug", function()
{
    SYSTEM.env['CONFIG'] = 'Debug'
    spawnJake("clean");
});

task ("cleandebug", ["clean-debug"]);

task ("clean-release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("clean");
});

task ("cleanrelease", ["clean-release"]);

task ("clean-all", ["clean-debug", "clean-release"]);
task ("cleanall", ["clean-all"]);

task ("clobber-debug", function()
{
    SYSTEM.env["CONFIG"] = "Debug";
    spawnJake("clobber");
});

task ("clobberdebug", ["clobber-debug"]);

task ("clobber-release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("clobber");
});

task ("clobberrelease", ['clobber-release']);

task ("clobber-all", ["clobber-debug", "clobber-release"]);
task ("clobberall", ["clobber-all"]);
<commit_msg>Use include instead of push to increase performance of jake.<commit_after>var SYSTEM = require("system");
var FILE = require("file");
var OS = require("os");
var UTIL = require("util");
var stream = require("term").stream;

var requiresSudo = false;

SYSTEM.args.slice(1).forEach(function(arg){
    if (arg === "sudo-install")
        requiresSudo = true;
});

function ensurePackageUpToDate(packageName, requiredVersion, options)
{
    options = options || {};

    var packageInfo = require("packages").catalog[packageName];
    if (!packageInfo)
    {
        if (options.optional)
            return;

        print("You are missing package \"" + packageName + "\", version " + requiredVersion + " or later. Please install using \"tusk install "+packageName+"\" and re-run jake");
        OS.exit(1);
    }

    var version = packageInfo.version;
    if (typeof version === "string")
        version = version.split(".");

    if (typeof requiredVersion === "string")
        requiredVersion = requiredVersion.split(".");

    if (version && UTIL.compare(version, requiredVersion) !== -1)
        return;

    print("Your copy of " + packageName + " is out of date (" + (version||["0"]).join(".") + " installed, " + requiredVersion.join(".") + " required).");

    if (!options.noupdate)
    {
        print("Update? yes or no:");
        if (!SYSTEM.env["CAPP_AUTO_UPGRADE"] && system.stdin.readLine() !== "yes\n")
        {
            print("Jake aborted.");
            OS.exit(1);
        }

        if (requiresSudo)
        {
            if (OS.system(["sudo", "tusk", "install", "--force", packageName]))
            {
                // Attempt a hackish work-around for sudo compiled with the --with-secure-path option
                if (OS.system("sudo bash -c 'source " + getShellConfigFile() + "; tusk install --force "+packageName))
                    OS.exit(1); //rake abort if ($? != 0)
            }
        }
        else
            OS.system(["tusk", "install", "--force", packageName]);
    }

    if (options.message)
    {
        print(options.message)
        OS.exit(1);
    }
}

// UPDATE THESE TO PICK UP CORRESPONDING CHANGES IN DEPENDENCIES
ensurePackageUpToDate("jake",           "0.1.5");
ensurePackageUpToDate("browserjs",      "0.1.1");
ensurePackageUpToDate("shrinksafe",     "0.2");
ensurePackageUpToDate("narwhal",        "0.2.2", {
    noupdate : true,
    message : "Update Narwhal to 0.2.1 by running bootstrap.sh, or pulling the latest from git (see: http://github.com/280north/narwhal)."
});
ensurePackageUpToDate("narwhal-jsc",    "0.1.1", {
    optional : true,
    message : "Rebuild narwhal-jsc by changing to the narwhal-jsc package directory and running \"make webkit\"."
});

var JAKE = require("jake");

// Set up development environment variables.

// record the initial SYSTEM.env so we know which need to be serialized later
var envInitial = Object.freeze(UTIL.copy(SYSTEM.env));

SYSTEM.env["BUILD_PATH"] = FILE.absolute(
    SYSTEM.env["BUILD_PATH"] ||
    SYSTEM.env["CAPP_BUILD"] || // Global Cappuccino build directory.
    SYSTEM.env["STEAM_BUILD"] || // Maintain backwards compatibility with steam.
    FILE.join(FILE.dirname(module.path), "Build") // Just build here.
);

if (!SYSTEM.env["CAPP_BUILD"] && SYSTEM.env["STEAM_BUILD"])
    system.stderr.print("STEAM_BUILD environment variable is deprecated; Please use CAPP_BUILD instead.");

if (!SYSTEM.env["CONFIG"])
    SYSTEM.env["CONFIG"] = "Release";

global.ENV  = SYSTEM.env;
global.ARGV = SYSTEM.args
global.FILE = FILE;
global.OS   = OS;

global.task = JAKE.task;
global.directory = JAKE.directory;
global.file = JAKE.file;
global.filedir = JAKE.filedir;
global.FileList = JAKE.FileList;

global.$CONFIGURATION                   = SYSTEM.env['CONFIG'];
global.$BUILD_DIR                       = SYSTEM.env['BUILD_PATH'];
global.$BUILD_CONFIGURATION_DIR         = FILE.join($BUILD_DIR, $CONFIGURATION);

global.$BUILD_CJS_OBJECTIVE_J           = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "objective-j");

global.$BUILD_CJS_CAPPUCCINO            = FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino");
global.$BUILD_CJS_CAPPUCCINO_BIN        = FILE.join($BUILD_CJS_CAPPUCCINO, "bin");
global.$BUILD_CJS_CAPPUCCINO_LIB        = FILE.join($BUILD_CJS_CAPPUCCINO, "lib");
global.$BUILD_CJS_CAPPUCCINO_FRAMEWORKS = FILE.join($BUILD_CJS_CAPPUCCINO, "Frameworks");

global.CLEAN = require("jake/clean").CLEAN;
global.CLOBBER = require("jake/clean").CLOBBER;
global.CLEAN.include(global.$BUILD_DIR);
global.CLOBBER.include(global.$BUILD_DIR);

global.$HOME_DIR        = FILE.absolute(FILE.dirname(module.path));
global.$LICENSE_FILE    = FILE.absolute(FILE.join(FILE.dirname(module.path), 'LICENSE'));

global.FIXME_fileDependency = function(destinationPath, sourcePath)
{
    file(destinationPath, [sourcePath], function(){
        FILE.touch(destinationPath);
    });
};

// logic to determine which packages should be loaded but are not.
// used in serializedENV()
function additionalPackages()
{
    var builtObjectiveJPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "objective-j", "");
    var builtCappuccinoPackage = FILE.path($BUILD_CONFIGURATION_DIR).join("CommonJS", "cappuccino", "");

    var packages = [];

    // load built objective-j if exists, otherwise unbuilt
    if (builtObjectiveJPackage.join("package.json").exists()) {
        if (!packageInCatalog(builtObjectiveJPackage))
            packages.push(builtObjectiveJPackage);
    }

    // load built cappuccino if it exists
    if (builtCappuccinoPackage.join("package.json").exists()) {
        if (!packageInCatalog(builtCappuccinoPackage))
            packages.push(builtCappuccinoPackage);
    }

    return packages;
}

// checks to see if a path is in the package catalog
function packageInCatalog(path)
{
    var catalog = require("packages").catalog;
    for (var name in catalog)
        if (String(catalog[name].directory) === String(path))
            return true;
    return false;
}

serializedENV = function()
{
    var envNew = {};

    // add changed keys to the new ENV
    Object.keys(SYSTEM.env).forEach(function(key) {
        if (SYSTEM.env[key] !== envInitial[key])
            envNew[key] = SYSTEM.env[key];
    });

    // pseudo-HACK: add NARWHALOPT with packages we should ensure are loaded
    var packages = additionalPackages();
    if (packages.length) {
        envNew["NARWHALOPT"] = packages.map(function(p) { return "-p " + OS.enquote(p); }).join(" ");
        envNew["PATH"] = packages.map(function(p) { return FILE.join(p, "bin"); }).concat(SYSTEM.env["PATH"]).join(":");
    }

    return Object.keys(envNew).map(function(key) {
        return key + "=" + OS.enquote(envNew[key]);
    }).join(" ");
}

function reforkWithPackages()
{
    if (additionalPackages().length > 0) {
        var cmd = serializedENV() + " " + system.args.map(OS.enquote).join(" ");
        //print("REFORKING: " + cmd);
        OS.exit(OS.system(cmd));
    }
}

reforkWithPackages();

function handleSetupEnvironmentError(e) {
    if (String(e).indexOf("require error")==-1) {
        print("setupEnvironment warning: " + e);
        //throw e;
    }
}

function setupEnvironment()
{
    try {
        require("objective-j").OBJJ_INCLUDE_PATHS.push(FILE.join($BUILD_CONFIGURATION_DIR, "CommonJS", "cappuccino", "Frameworks"));
    } catch (e) {
        handleSetupEnvironmentError(e);
    }
}

setupEnvironment();

global.rm_rf = function(/*String*/ aFilename)
{
    try { FILE.rmtree(aFilename); }
    catch (anException) { }
}

global.cp_r = function(/*String*/ from, /*String*/ to)
{
    if (FILE.exists(to))
        rm_rf(to);

    if (FILE.isDirectory(from))
        FILE.copyTree(from, to);
    else{try{
        FILE.copy(from, to);}catch(e) { print(e + FILE.exists(from) + " " + FILE.exists(FILE.dirname(to))); }}
}

global.cp = function(/*String*/ from, /*String*/ to)
{
    FILE.copy(from, to);
//    FILE.chmod(to, FILE.mod(from));
}

global.mv = function(/*String*/ from, /*String*/ to)
{
    FILE.move(from, to);
}

global.subjake = function(/*Array<String>*/ directories, /*String*/ aTaskName)
{
    if (!Array.isArray(directories))
        directories = [directories];

    directories.forEach(function(/*String*/ aDirectory)
    {
        if (FILE.isDirectory(aDirectory) && FILE.isFile(FILE.join(aDirectory, "Jakefile")))
        {
            var cmd = "cd " + OS.enquote(aDirectory) + " && " + serializedENV() + " " + OS.enquote(SYSTEM.args[0]) + " " + OS.enquote(aTaskName);
            var returnCode = OS.system(cmd);
            if (returnCode)
                OS.exit(returnCode);
        }
        else
            print("warning: subjake missing: " + aDirectory + " (this is not necessarily an error, " + aDirectory + " may be optional)");
    });
}

global.executableExists = function(/*String*/ executableName)
{
    var paths = SYSTEM.env["PATH"].split(':');
    for (var i = 0; i < paths.length; i++) {
        var path = FILE.join(paths[i], executableName);
        if (FILE.exists(path))
            return path;
    }
    return null;
}

$OBJJ_TEMPLATE_EXECUTABLE = FILE.join($HOME_DIR, "Objective-J", "CommonJS", "objj-executable");

global.make_objj_executable = function(aPath)
{
    cp($OBJJ_TEMPLATE_EXECUTABLE, aPath);
    FILE.chmod(aPath, 0755);
}

global.symlink_executable = function(source)
{
    relative = FILE.relative($ENVIRONMENT_NARWHAL_BIN_DIR, source);
    destination = FILE.join($ENVIRONMENT_NARWHAL_BIN_DIR, FILE.basename(source));
    FILE.symlink(relative, destination);
}

global.getCappuccinoVersion = function() {
    var versionFile = FILE.path(module.path).dirname().join("version.json");
    return JSON.parse(versionFile.read({ charset : "UTF-8" })).version;
}

global.setPackageMetadata = function(packagePath) {
    var pkg = JSON.parse(FILE.read(packagePath, { charset : "UTF-8" }));

    var p = OS.popen(["git", "rev-parse", "--verify", "HEAD"]);
    if (p.wait() === 0) {
        var sha = p.stdout.read().split("\n")[0];
        if (sha.length === 40)
            pkg["cappuccino-revision"] = sha;
    }

    pkg["cappuccino-timestamp"] = new Date().getTime();
    pkg["version"] = getCappuccinoVersion();

    stream.print("    Version:   \0purple(" + pkg["version"] + "\0)");
    stream.print("    Revision:  \0purple(" + pkg["cappuccino-revision"] + "\0)");
    stream.print("    Timestamp: \0purple(" + pkg["cappuccino-timestamp"] + "\0)");

    FILE.write(packagePath, JSON.stringify(pkg, null, 4), { charset : "UTF-8" });
}

global.subtasks = function(subprojects, taskNames)
{
    taskNames.forEach(function(aTaskName)
    {
        var subtaskName = aTaskName + "_subprojects";

        task (aTaskName, [subtaskName]);

        task (subtaskName, function()
        {
            subjake(subprojects, aTaskName);
        });
    });
}

function spawnJake(/*String*/ aTaskName)
{
    if (OS.system(serializedENV() + " " + SYSTEM.args[0] + " " + aTaskName))
        OS.exit(1);//rake abort if ($? != 0)
}

// built in tasks

task ("build");
task ("default", "build");

task ("release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("build");
});

task ("debug", function()
{
    SYSTEM.env["CONFIG"] = "Debug";
    spawnJake("build");
});

task ("all", ["debug", "release"]);

task ("clean-debug", function()
{
    SYSTEM.env['CONFIG'] = 'Debug'
    spawnJake("clean");
});

task ("cleandebug", ["clean-debug"]);

task ("clean-release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("clean");
});

task ("cleanrelease", ["clean-release"]);

task ("clean-all", ["clean-debug", "clean-release"]);
task ("cleanall", ["clean-all"]);

task ("clobber-debug", function()
{
    SYSTEM.env["CONFIG"] = "Debug";
    spawnJake("clobber");
});

task ("clobberdebug", ["clobber-debug"]);

task ("clobber-release", function()
{
    SYSTEM.env["CONFIG"] = "Release";
    spawnJake("clobber");
});

task ("clobberrelease", ['clobber-release']);

task ("clobber-all", ["clobber-debug", "clobber-release"]);
task ("clobberall", ["clobber-all"]);
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var capture = require('./lib/capture');

module.exports = Compiler;

function Compiler(node, opts) {
  this.opts = opts = opts || {};
  this.node = node;
}

Compiler.prototype.compile = function() {
  var ast = this.visit(this.node);
  return 'return ' + JSON.stringify(ast) + ';';
};

Compiler.prototype.visit = function(node, parent) {
  if (!node || !node.type) return undefined;
  return this['visit' + node.type](node, parent);
};

Compiler.prototype.visitCase = function(node) {
  return {
    type: 'switch',
    expression: node.expr,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitWhen = function(node) {
  return {
    type: node.expr === 'default' ? 'default' : 'case',
    expression: node.expr !== 'default' ? node.expr : undefined,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitLiteral = function(node) {
  return {
    type: 'expression',
    expression: node.str,
    buffer: node.buffer,
    escape: node.escape,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlock = function(node) {
  var length = node.nodes.length;

  var ast = [];

  for (var i = 0; i < length; ++i) {
    var out = this.visit(node.nodes[i]);
    this.mergeChildren(ast, out);
  }

  if (!node.name || node.name.indexOf('!') !== 0 || node.isSubBlock) return ast;

  return {
    type: 'named_block',
    name: node.name,
    children: ast,
    line: node.line,
    filename: node.filename,
    args: node.args
  };
};

Compiler.prototype.mergeChildren = function(acc, child) {
  if (!child) return acc;
  if (Array.isArray(child)) acc.push.apply(acc, child);
  else acc.push(child);
  return acc;
};

Compiler.prototype.visitMixinBlock = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitDoctype = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Doctypes are not supported at this time'));
};

Compiler.prototype.visitMixin = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitTag = function(node) {
  var self = this;
  var name = node.name;

  if (node.selfClosing &&
      node.block &&
      !(node.block.type === 'Block' && node.block.nodes.length === 0) &&
      node.block.nodes.some(function(tag) {
        return tag.type !== 'Text' || !/^\s*$/.test(tag.val);
      })) {
    throw errorAtNode(node, new Error(name + ' is self closing and should not have content.'));
  }

  if (name === 't') return self.visitTranslation(node);
  if (name === 'import') return self.visitImport(node);
  if (name === 'var') return self.visitVar(node);
  if (name === 'const') return self.visitConst(node);
  if (name === 'export') return self.visitExport(node);
  if (name === 'function') return self.visitFunction(node);

  var attrs = node.attrs.slice();

  var children = this.visitChildren(node, attrs);

  return {
    type: 'tag',
    name: name,
    props: this.visitAttributes(attrs, node.attributeBlocks),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitChildren = function(node, attrs) {
  var self = this;
  var parent = node.name;
  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : []));
  return children.reduce(function(acc, child) {
    var name = child.args && child.name;
    var c = self.visit(addParentClass(parent, name, child));
    if (child.type !== 'Block' || !child.name) self.mergeChildren(acc, c);
    else attrs.push({name: child.name, val: c, block: true, args: child.args});
    return acc;
  }, []);
};

Compiler.prototype.visitImport = function(node) {
  return {
    type: 'import',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitExport = function(node) {
  return {
    type: 'export',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFunction = function(node) {
  var nodes = node.block.nodes;
  var first = nodes[0];

  var children = nodes.slice(1);

  return {
    type: 'function',
    expression: first.val,
    children: this.visitBlock({nodes: children}),
    buffer: false
  };
};

Compiler.prototype.visitVar = function(node) {
  return {
    type: 'var',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitConst = function(node) {
  return {
    type: 'const',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFilter = function(filter) {
  if (filter.name === 'capture') return capture(filter, this);
  var text = filter.block.nodes.map(
    function(node){ return node.val; }
  ).join('\n');

  return {
    type: 'filter',
    name: filter.name,
    attrs: filter.attrs,
    content: text,
    line: filter.line,
    filename: filter.filename
  };
};

Compiler.prototype.visitText = function(node) {
  if (!node.val) return false;
  // TODO interpolation
  // TODO unescape html expressions
  return {
    type: 'text',
    expression: JSON.stringify(node.val),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitTranslation = function(node) {
  var self = this;
  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).map(function(child) {
    if (child.type !== 'Block') throw errorAtNode(node, new Error('Invalid child for translation'));
    var name = child.name;
    if (!name) throw errorAtNode(node, new Error('Block missing name'));

    var visited = self.visit(child);

    if (visited.length === 1) visited[0].props.key = {name: name, expression: JSON.stringify(name)};

    attrs.push({
      name: name,
      val: visited,
      block: true
    });
  });

  var el = {
    type: 'tag',
    name: 't',
    props: this.visitAttributes(attrs, node.attributeBlocks, true),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };

  return el;
};

Compiler.prototype.visitComment = function(node) {
  return {
    type: node.buffer ? 'comment' : 'js_comment',
    value: node.val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlockComment = function(node) {
  var value = node.block.nodes.map(function(comment) {
    return comment.val;
  }).join('\n');
  return {
    type: node.buffer ? 'comment' : 'js_comment',
    value: value,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitCode = function(node) {
  var self = this;
  var val = node.val;
  var type = val.slice(0, 3);
  var expr = val.slice(3);

  var children = self.visit(node.block);

  switch(type) {
  case 'IFF':
    return {
      type: 'if',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'NIF':
    return {
      type: 'unless',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'ELF':
    return {
      type: 'elseif',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'ELS':
    return {
      type: 'else',
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'EXP':
    return {
      type: 'expression',
      buffer: node.buffer,
      expression: expr,
      escape: node.escape,
      line: node.line,
      filename: node.filename
    };
  }
  throw node;
};

Compiler.prototype.visitEach = function(node) {
  var parts = node.val.split(/ +in +/);

  if (parts.length === 1) return {
    type: 'for',
    expression: node.val.replace(/^ *\(/, '').replace(/\) *$/, ''),
    children: node.block && this.visit(node.block),
    buffer: true
  };

  var kv = parts[0].split(/ *\, */);

  return {
    type: 'each',
    key: (kv[1] || node.key).trim(),
    value: kv[0].trim(),
    expression: parts[1].trim(),
    children: node.block && this.visit(node.block),
    buffer: true
  };
};

Compiler.prototype.visitYield = function(node) {
  return {
    type: 'yield',
    line: node.line,
    filename: node.filename,
    name: node.val,
    args: node.args
  };
};

Compiler.prototype.visitAttributes = function(attrs, blocks, isTranslate) {
  var styles = [];
  var classes = [];

  var out = attrs.reduce(function(acc, attr, i) {
    if (attr.name === 'class' || attr.name === 'className') {
      classes.push(attr.val);
    } else if (attr.name === 'style') {
      styles.push(attr.val);
    } else if (isTranslate && i == 0 && attr.val === true) {
      acc.path = {
        expression: JSON.stringify(attr.name),
        escaped: attr.escaped,
        args: attr.args
      };
    } else {
      acc[attr.name] = {
        expression: attr.val,
        escaped: attr.escaped,
        args: attr.args
      };
    }
    return acc;
  }, {});

  if (styles.length) {
    out.style = {
      expressions: styles
    };
  }

  if (classes.length) {
    out['class'] = {
      expressions: classes
    };
  }

  if (blocks && blocks.length) {
    out['&props'] = {
      expressions: blocks
    };
  }

  return out;
};

function errorAtNode(node, error) {
  error.line = node.line;
  error.filename = node.filename;
  return error;
}

function nodesToExpr(node) {
  return node.block.nodes.map(function(n) {
    return n.val;
  }).join('\n');
}

function addParentClass(parent, block, child) {
  if (child && child.nodes) {
    child.nodes = addParentClassToChildren(parent, child.name, child.nodes);
    return child;
  }
  if ((child.type === 'Code' || child.type === 'Each') && child.block && child.block.nodes) {
    child.block.nodes = addParentClassToChildren(parent, block, child.block.nodes);
    return child;
  }

  // only apply block classes to PascalCase tags
  var first = parent.charAt(0);
  if (first !== first.toUpperCase()) return child;

  // wrap text nodes in a span
  if (child.type === 'Text') child = {
    type: 'Tag',
    name: 'span',
    attributeNames: [],
    attrs: [],
    attributeBlocks: [],
    block: {nodes: [child]},
    selfClosing: false,
    line: child.line,
    filename: child.filename
  };

  if (!child || !Array.isArray(child.attrs)) return child;

  var name = parent + '-block';
  if (block) name += '-' + block;
  child.attrs.push({
    name: 'class',
    val: JSON.stringify(name)
  });
  return child;
}

function addParentClassToChildren(parent, block, children) {
  return (children || []).map(addParentClass.bind(null, parent, block));
}
<commit_msg>fix arguments on t tags<commit_after>/**
 * Module dependencies
 */

var capture = require('./lib/capture');

module.exports = Compiler;

function Compiler(node, opts) {
  this.opts = opts = opts || {};
  this.node = node;
}

Compiler.prototype.compile = function() {
  var ast = this.visit(this.node);
  return 'return ' + JSON.stringify(ast) + ';';
};

Compiler.prototype.visit = function(node, parent) {
  if (!node || !node.type) return undefined;
  return this['visit' + node.type](node, parent);
};

Compiler.prototype.visitCase = function(node) {
  return {
    type: 'switch',
    expression: node.expr,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitWhen = function(node) {
  return {
    type: node.expr === 'default' ? 'default' : 'case',
    expression: node.expr !== 'default' ? node.expr : undefined,
    children: this.visit(node.block),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitLiteral = function(node) {
  return {
    type: 'expression',
    expression: node.str,
    buffer: node.buffer,
    escape: node.escape,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlock = function(node) {
  var length = node.nodes.length;

  var ast = [];

  for (var i = 0; i < length; ++i) {
    var out = this.visit(node.nodes[i]);
    this.mergeChildren(ast, out);
  }

  if (!node.name || node.name.indexOf('!') !== 0 || node.isSubBlock) return ast;

  return {
    type: 'named_block',
    name: node.name,
    children: ast,
    line: node.line,
    filename: node.filename,
    args: node.args
  };
};

Compiler.prototype.mergeChildren = function(acc, child) {
  if (!child) return acc;
  if (Array.isArray(child)) acc.push.apply(acc, child);
  else acc.push(child);
  return acc;
};

Compiler.prototype.visitMixinBlock = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitDoctype = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Doctypes are not supported at this time'));
};

Compiler.prototype.visitMixin = function(node) {
  // TODO
  throw errorAtNode(node, new Error('Mixins are not supported at this time'));
};

Compiler.prototype.visitTag = function(node) {
  var self = this;
  var name = node.name;

  if (node.selfClosing &&
      node.block &&
      !(node.block.type === 'Block' && node.block.nodes.length === 0) &&
      node.block.nodes.some(function(tag) {
        return tag.type !== 'Text' || !/^\s*$/.test(tag.val);
      })) {
    throw errorAtNode(node, new Error(name + ' is self closing and should not have content.'));
  }

  if (name === 't') return self.visitTranslation(node);
  if (name === 'import') return self.visitImport(node);
  if (name === 'var') return self.visitVar(node);
  if (name === 'const') return self.visitConst(node);
  if (name === 'export') return self.visitExport(node);
  if (name === 'function') return self.visitFunction(node);

  var attrs = node.attrs.slice();

  var children = this.visitChildren(node, attrs);

  return {
    type: 'tag',
    name: name,
    props: this.visitAttributes(attrs, node.attributeBlocks),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitChildren = function(node, attrs) {
  var self = this;
  var parent = node.name;
  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : []));
  return children.reduce(function(acc, child) {
    var name = child.args && child.name;
    var c = self.visit(addParentClass(parent, name, child));
    if (child.type !== 'Block' || !child.name) self.mergeChildren(acc, c);
    else attrs.push({name: child.name, val: c, block: true, args: child.args});
    return acc;
  }, []);
};

Compiler.prototype.visitImport = function(node) {
  return {
    type: 'import',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitExport = function(node) {
  return {
    type: 'export',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFunction = function(node) {
  var nodes = node.block.nodes;
  var first = nodes[0];

  var children = nodes.slice(1);

  return {
    type: 'function',
    expression: first.val,
    children: this.visitBlock({nodes: children}),
    buffer: false
  };
};

Compiler.prototype.visitVar = function(node) {
  return {
    type: 'var',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitConst = function(node) {
  return {
    type: 'const',
    expression: nodesToExpr(node),
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitFilter = function(filter) {
  if (filter.name === 'capture') return capture(filter, this);
  var text = filter.block.nodes.map(
    function(node){ return node.val; }
  ).join('\n');

  return {
    type: 'filter',
    name: filter.name,
    attrs: filter.attrs,
    content: text,
    line: filter.line,
    filename: filter.filename
  };
};

Compiler.prototype.visitText = function(node) {
  if (!node.val) return false;
  // TODO interpolation
  // TODO unescape html expressions
  return {
    type: 'text',
    expression: JSON.stringify(node.val),
    line: node.line,
    filename: node.filename,
    buffer: true
  };
};

Compiler.prototype.visitTranslation = function(node) {
  var self = this;
  var attrs = node.attrs.slice();

  var children = (node.block && node.block.nodes.length && node.block.nodes || (node.code ? [node.code] : [])).map(function(child) {
    if (child.type !== 'Block') throw errorAtNode(node, new Error('Invalid child for translation'));
    var name = child.name;
    if (!name) throw errorAtNode(node, new Error('Block missing name'));

    var visited = self.visit(child);

    if (visited.length === 1) visited[0].props.key = {name: name, expression: JSON.stringify(name)};

    attrs.push({
      name: name,
      val: visited,
      block: true,
      args: child.args
    });
  });

  var el = {
    type: 'tag',
    name: 't',
    props: this.visitAttributes(attrs, node.attributeBlocks, true),
    children: children,
    line: node.line,
    filename: node.filename,
    buffer: true
  };

  return el;
};

Compiler.prototype.visitComment = function(node) {
  return {
    type: node.buffer ? 'comment' : 'js_comment',
    value: node.val,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitBlockComment = function(node) {
  var value = node.block.nodes.map(function(comment) {
    return comment.val;
  }).join('\n');
  return {
    type: node.buffer ? 'comment' : 'js_comment',
    value: value,
    line: node.line,
    filename: node.filename
  };
};

Compiler.prototype.visitCode = function(node) {
  var self = this;
  var val = node.val;
  var type = val.slice(0, 3);
  var expr = val.slice(3);

  var children = self.visit(node.block);

  switch(type) {
  case 'IFF':
    return {
      type: 'if',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'NIF':
    return {
      type: 'unless',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'ELF':
    return {
      type: 'elseif',
      expression: expr,
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'ELS':
    return {
      type: 'else',
      children: children,
      line: node.line,
      filename: node.filename
    };
  case 'EXP':
    return {
      type: 'expression',
      buffer: node.buffer,
      expression: expr,
      escape: node.escape,
      line: node.line,
      filename: node.filename
    };
  }
  throw node;
};

Compiler.prototype.visitEach = function(node) {
  var parts = node.val.split(/ +in +/);

  if (parts.length === 1) return {
    type: 'for',
    expression: node.val.replace(/^ *\(/, '').replace(/\) *$/, ''),
    children: node.block && this.visit(node.block),
    buffer: true
  };

  var kv = parts[0].split(/ *\, */);

  return {
    type: 'each',
    key: (kv[1] || node.key).trim(),
    value: kv[0].trim(),
    expression: parts[1].trim(),
    children: node.block && this.visit(node.block),
    buffer: true
  };
};

Compiler.prototype.visitYield = function(node) {
  return {
    type: 'yield',
    line: node.line,
    filename: node.filename,
    name: node.val,
    args: node.args
  };
};

Compiler.prototype.visitAttributes = function(attrs, blocks, isTranslate) {
  var styles = [];
  var classes = [];

  var out = attrs.reduce(function(acc, attr, i) {
    if (attr.name === 'class' || attr.name === 'className') {
      classes.push(attr.val);
    } else if (attr.name === 'style') {
      styles.push(attr.val);
    } else if (isTranslate && i == 0 && attr.val === true) {
      acc.path = {
        expression: JSON.stringify(attr.name),
        escaped: attr.escaped,
        args: attr.args
      };
    } else {
      acc[attr.name] = {
        expression: attr.val,
        escaped: attr.escaped,
        args: attr.args
      };
    }
    return acc;
  }, {});

  if (styles.length) {
    out.style = {
      expressions: styles
    };
  }

  if (classes.length) {
    out['class'] = {
      expressions: classes
    };
  }

  if (blocks && blocks.length) {
    out['&props'] = {
      expressions: blocks
    };
  }

  return out;
};

function errorAtNode(node, error) {
  error.line = node.line;
  error.filename = node.filename;
  return error;
}

function nodesToExpr(node) {
  return node.block.nodes.map(function(n) {
    return n.val;
  }).join('\n');
}

function addParentClass(parent, block, child) {
  if (child && child.nodes) {
    child.nodes = addParentClassToChildren(parent, child.name, child.nodes);
    return child;
  }
  if ((child.type === 'Code' || child.type === 'Each') && child.block && child.block.nodes) {
    child.block.nodes = addParentClassToChildren(parent, block, child.block.nodes);
    return child;
  }

  // only apply block classes to PascalCase tags
  var first = parent.charAt(0);
  if (first !== first.toUpperCase()) return child;

  // wrap text nodes in a span
  if (child.type === 'Text') child = {
    type: 'Tag',
    name: 'span',
    attributeNames: [],
    attrs: [],
    attributeBlocks: [],
    block: {nodes: [child]},
    selfClosing: false,
    line: child.line,
    filename: child.filename
  };

  if (!child || !Array.isArray(child.attrs)) return child;

  var name = parent + '-block';
  if (block) name += '-' + block;
  child.attrs.push({
    name: 'class',
    val: JSON.stringify(name)
  });
  return child;
}

function addParentClassToChildren(parent, block, children) {
  return (children || []).map(addParentClass.bind(null, parent, block));
}
<|endoftext|>


<commit_before>var fs = require('fs'),
	path = require('path'),
	util = require('./lib/util')

module.exports = {
	compile: compileFile,
	compileHTML: compileHTMLFile,
	compileCode: compileCode,
	dontAddClosureForModule: dontAddClosureForModule,
	dontIncludeModule: dontIncludeModule,
	addPath: addPath,
	addFile: addFile,
	addReplacement: addReplacement
}

var _ignoreClosuresFor = []
function dontAddClosureForModule(searchFor) {
	_ignoreClosuresFor.push(searchFor)
	return module.exports
}

var _ignoreModules = []
function dontIncludeModule(module) {
	_ignoreModules.push(module)
	return module.exports
}

function addReplacement(searchFor, replaceWith) {
	util.addReplacement.apply(util, arguments)
	return module.exports
}

function addPath() {
	util.addPath.apply(util, arguments)
	return module.exports
}

function addFile() {
	util.addFile.apply(util, arguments)
	return module.exports
}

/* api
 *****/
function compileFile(filePath, opts) {
	filePath = path.resolve(filePath)
	opts = util.extend(opts, { basePath:path.dirname(filePath), toplevel:true })
	var code = util.getCode(filePath)
	return _compile(code, opts, filePath)
}

function compileCode(code, opts) {
	opts = util.extend(opts, { basePath:process.cwd(), toplevel:true })
	return _compile(code, opts, '<code passed into compiler.compile()>')
}

function compileHTMLFile(filePath, opts) {
	var html = fs.readFileSync(filePath).toString()
	while (match = html.match(/<script src="\/require\/([\/\w\.]+)"><\/script>/)) {
		var js = compileFile(match[1].toString(), opts)

		var BACKREFERENCE_WORKAROUND = '____________backreference_workaround________'
		js = js.replace('\$\&', BACKREFERENCE_WORKAROUND)
		html = html.replace(match[0], '<script>'+js+'</script>')
		html = html.replace(BACKREFERENCE_WORKAROUND, '\$\&')
	}
	return html
}

var _compile = function(code, opts, mainModule) {
	var code = 'var __require__ = {}, require=function(){}\n' + _compileModule(code, opts.basePath, mainModule)
	if (opts.minify === false) { return code } // TODO use uglifyjs' beautifier?

	if (opts.max_line_length == null) {
		opts.max_line_length = 120
	}

	var uglifyJS = require('uglify-js')

	var ast = uglifyJS.parser.parse(code, opts.strict_semicolons),
	ast = uglifyJS.uglify.ast_mangle(ast, opts)
	ast = uglifyJS.uglify.ast_squeeze(ast, opts)

	var result = uglifyJS.uglify.gen_code(ast, opts)
	if (opts.max_line_length) {
		result = uglifyJS.uglify.split_lines(result, opts.max_line_length)
	}
	return result
}

/* util
 ******/
var _compileModule = function(code, pathBase, mainModule) {
	var modules = [mainModule]
	_replaceRequireStatements(mainModule, code, modules, pathBase)
	code = _concatModules(modules)
	code = _minifyRequireStatements(code, modules)
	return code
}

var _minifyRequireStatements = function(code, modules) {
	for (var i=0, modulePath; modulePath = modules[i]; i++) {
		var escapedPath = modulePath.replace(/\//g, '\\/').replace('(','\\(').replace(')','\\)'),
			regex = new RegExp('__require__\\["'+ escapedPath +'"\\]', 'g')

		code = code.replace(regex, '__require__["_'+ i +'"]')
	}
	return code
}

var _pathnameGroupingRegex = /require\s*\(['"]([\w\/\.-]*)['"]\)/

var _replaceRequireStatements = function(modulePath, code, modules, pathBase) {
	var requireStatements = util.getRequireStatements(code)

	if (!requireStatements.length) {
		modules[modulePath] = code
		return
	}

	for (var i=0, requireStatement; requireStatement = requireStatements[i]; i++) {
		var rawModulePath = requireStatement.match(_pathnameGroupingRegex)[1],
			subModulePath = util.resolve(rawModulePath, pathBase).replace(/\.js$/, '')

		if (!subModulePath) {
			throw new Error("Require Compiler Error: Cannot find module '"+ rawModulePath +"' (in '"+ modulePath +"')")
		}

		code = code.replace(requireStatement, '__require__["' + subModulePath + '"].exports')

		if (!modules[subModulePath]) {
			modules[subModulePath] = true
			var newPathBase = path.dirname(subModulePath),
				newModuleCode = util.getCode(subModulePath + '.js')
			_replaceRequireStatements(subModulePath, newModuleCode, modules, newPathBase)
			modules.push(subModulePath)
		}
	}

	modules[modulePath] = code
}

var _concatModules = function(modules) {
	var code = function(modulePath) {
		for (var i=0; i<_ignoreModules.length; i++) {
			if (modulePath.match(_ignoreModules[i])) {
				return ''
			}
		}

		var ignoreClosure = false
		for (var i=0; i<_ignoreClosuresFor.length; i++) {
			if (modulePath.match(_ignoreClosuresFor[i])) {
				ignoreClosure = true
				break
			}
		}

		return [
			ignoreClosure ? '' : ';(function() {',
			'	// ' + modulePath,
			'	var module = __require__["'+modulePath+'"] = {exports:{}}, exports = module.exports;',
			modules[modulePath],
			ignoreClosure ? '' : '})()'
		].join('\n')
	}

	var moduleDefinitions = []
	for (var i=1, modulePath; modulePath = modules[i]; i++) {
		moduleDefinitions.push(code(modulePath))
	}
	moduleDefinitions.push(code(modules[0])) // __main__

	return moduleDefinitions.join('\n\n')
}

var _repeat = function(str, times) {
	if (times < 0) { return '' }
	return new Array(times + 1).join(str)
}
<commit_msg>make the compiler respect the NODE_PATH environment variable<commit_after>var fs = require('fs'),
	path = require('path'),
	util = require('./lib/util')

module.exports = {
	compile: compileFile,
	compileHTML: compileHTMLFile,
	compileCode: compileCode,
	dontAddClosureForModule: dontAddClosureForModule,
	dontIncludeModule: dontIncludeModule,
	addPath: addPath,
	addFile: addFile,
	addReplacement: addReplacement
}

var _ignoreClosuresFor = []
function dontAddClosureForModule(searchFor) {
	_ignoreClosuresFor.push(searchFor)
	return module.exports
}

var _ignoreModules = []
function dontIncludeModule(module) {
	_ignoreModules.push(module)
	return module.exports
}

function addReplacement(searchFor, replaceWith) {
	util.addReplacement.apply(util, arguments)
	return module.exports
}

function addPath() {
	util.addPath.apply(util, arguments)
	return module.exports
}

function addFile() {
	util.addFile.apply(util, arguments)
	return module.exports
}

/* api
 *****/
function compileFile(filePath, opts) {
	filePath = path.resolve(filePath)
	opts = util.extend(opts, { basePath:path.dirname(filePath), toplevel:true })
	var code = util.getCode(filePath)
	return _compile(code, opts, filePath)
}

function compileCode(code, opts) {
	opts = util.extend(opts, { basePath:process.cwd(), toplevel:true })
	return _compile(code, opts, '<code passed into compiler.compile()>')
}

function compileHTMLFile(filePath, opts) {
	var html = fs.readFileSync(filePath).toString()
	while (match = html.match(/<script src="\/require\/([\/\w\.]+)"><\/script>/)) {
		var js = compileFile(match[1].toString(), opts)

		var BACKREFERENCE_WORKAROUND = '____________backreference_workaround________'
		js = js.replace('\$\&', BACKREFERENCE_WORKAROUND)
		html = html.replace(match[0], '<script>'+js+'</script>')
		html = html.replace(BACKREFERENCE_WORKAROUND, '\$\&')
	}
	return html
}

var _compile = function(code, opts, mainModule) {
	var code = 'var __require__ = {}, require=function(){}\n' + _compileModule(code, opts.basePath, mainModule)
	if (opts.minify === false) { return code } // TODO use uglifyjs' beautifier?

	if (opts.max_line_length == null) {
		opts.max_line_length = 120
	}

	var uglifyJS = require('uglify-js')

	var ast = uglifyJS.parser.parse(code, opts.strict_semicolons),
	ast = uglifyJS.uglify.ast_mangle(ast, opts)
	ast = uglifyJS.uglify.ast_squeeze(ast, opts)

	var result = uglifyJS.uglify.gen_code(ast, opts)
	if (opts.max_line_length) {
		result = uglifyJS.uglify.split_lines(result, opts.max_line_length)
	}
	return result
}

/* util
 ******/
var _compileModule = function(code, pathBase, mainModule) {
	var modules = [mainModule]
	_replaceRequireStatements(mainModule, code, modules, pathBase)
	code = _concatModules(modules)
	code = _minifyRequireStatements(code, modules)
	return code
}

var _minifyRequireStatements = function(code, modules) {
	for (var i=0, modulePath; modulePath = modules[i]; i++) {
		var escapedPath = modulePath.replace(/\//g, '\\/').replace('(','\\(').replace(')','\\)'),
			regex = new RegExp('__require__\\["'+ escapedPath +'"\\]', 'g')

		code = code.replace(regex, '__require__["_'+ i +'"]')
	}
	return code
}

var _nodePaths = process.env.NODE_PATH.split(':')
var _pathnameGroupingRegex = /require\s*\(['"]([\w\/\.-]*)['"]\)/
var _replaceRequireStatements = function(modulePath, code, modules, pathBase) {
	var requireStatements = util.getRequireStatements(code)

	if (!requireStatements.length) {
		modules[modulePath] = code
		return
	}

	for (var i=0, requireStatement; requireStatement = requireStatements[i]; i++) {
		var subModulePath = util.resolveRequireStatement(requireStatement, modulePath)

		if (!subModulePath) {
			throw new Error("Require Compiler Error: Cannot find module '"+ rawModulePath +"' (in '"+ modulePath +"')")
		}

		code = code.replace(requireStatement, '__require__["' + subModulePath + '"].exports')

		if (!modules[subModulePath]) {
			modules[subModulePath] = true
			var newPathBase = path.dirname(subModulePath),
				newModuleCode = util.getCode(subModulePath)
			_replaceRequireStatements(subModulePath, newModuleCode, modules, newPathBase)
			modules.push(subModulePath)
		}
	}

	modules[modulePath] = code
}

var _concatModules = function(modules) {
	var code = function(modulePath) {
		for (var i=0; i<_ignoreModules.length; i++) {
			if (modulePath.match(_ignoreModules[i])) {
				return ''
			}
		}

		var ignoreClosure = false
		for (var i=0; i<_ignoreClosuresFor.length; i++) {
			if (modulePath.match(_ignoreClosuresFor[i])) {
				ignoreClosure = true
				break
			}
		}

		return [
			ignoreClosure ? '' : ';(function() {',
			'	// ' + modulePath,
			'	var module = __require__["'+modulePath+'"] = {exports:{}}, exports = module.exports;',
			modules[modulePath],
			ignoreClosure ? '' : '})()'
		].join('\n')
	}

	var moduleDefinitions = []
	for (var i=1, modulePath; modulePath = modules[i]; i++) {
		moduleDefinitions.push(code(modulePath))
	}
	moduleDefinitions.push(code(modules[0])) // __main__

	return moduleDefinitions.join('\n\n')
}

var _repeat = function(str, times) {
	if (times < 0) { return '' }
	return new Array(times + 1).join(str)
}
<|endoftext|>


<commit_before>/* eslint-disable prefer-arrow-callback, func-names, class-methods-use-this */
import loader from 'graphql-tag/loader';

export default class GraphQLCompiler {
  processFilesForTarget(files) {
    // Fake webpack context
    // @see https://github.com/apollographql/graphql-tag/blob/master/loader.js#L43
    const context = {
      cacheable() {},
    };

    files
    .forEach(file => {
      const path = `${file.getPathInPackage()}.js`;
      const content = file.getContentsAsString().trim();

      try {
        const data = loader.call(context, content);

        file.addJavaScript({
          data,
          path,
        });
      } catch (e) {
        if (e.locations) {
          file.error({
            message: e.message,
            line: e.locations[0].line,
            column: e.locations[0].column,
          });
          return null;
        }
        throw e;
      }
    });
  }
}
<commit_msg>Make link to webpack context explanation permanent<commit_after>/* eslint-disable prefer-arrow-callback, func-names, class-methods-use-this */
import loader from 'graphql-tag/loader';

export default class GraphQLCompiler {
  processFilesForTarget(files) {
    // Fake webpack context
    // @see https://github.com/apollographql/graphql-tag/blob/57a258713acecde5ebef0c5771a975d6446703c7/loader.js#L43
    const context = {
      cacheable() {},
    };

    files
    .forEach(file => {
      const path = `${file.getPathInPackage()}.js`;
      const content = file.getContentsAsString().trim();

      try {
        const data = loader.call(context, content);

        file.addJavaScript({
          data,
          path,
        });
      } catch (e) {
        if (e.locations) {
          file.error({
            message: e.message,
            line: e.locations[0].line,
            column: e.locations[0].column,
          });
          return null;
        }
        throw e;
      }
    });
  }
}
<|endoftext|>


<commit_before>// Create the ConkerChrome object
var ConkerC = function(opts) {

    // Default options
    var defaults = {
	line: 40,        // Number of pixels to scroll up and down
	column: 20,      // Number of pixels to scroll left and right
	ctrl: "ctrl",    // Default key mappings
	meta: "meta",    // Users can change these
	shift: "shift"   // If they want
    };

    // Load the user provided options
    var options = jQuery.extend({}, defaults, opts);

    // Lots of pixels jump to the top or bottom of a page
    // The user shouldn't be able to set this
    var BIG = 10000000000;

    // HTML Selectors for ConkerChrome elements
    var selectors = {
	conker: "#conkerchrome",
	commandbar: "#commandbar",
	commandinput: "#conkerchrome input",
	number: ".conkerchrome_number",
	links: "a:in-view"
    }

    // CSS Selectors for ConkerChrome elements
    var css = {
	highlight: "conkerchrome_highlight",
	selected: "conkerchrome_selected",
	number: "conkerchrome_number"
    }

    var baseMode = {
	enter: function(){},
	leave: function(){},
	update: function(e, bar){}
    }

    // Module to hold all the keybindings
    // I wrote this a while ago, not sure how it works
    var hotkeys = function() {
	var matched = false;
	var current = "";
	var combo = "";
	var partialKeyMap = {};
	var fullKeyMap = {};
	var keyMap = {};
	var unrecognized = function(){};

	var keyPress = function() {
	    if (partialKeyMap[combo]) {
		current = combo;
		matched = true;
	    } else if (fullKeyMap[combo]) {
		matched = true;
		current = "";
		fullKeyMap[combo]();
	    }
	};

	var keyFn = function(kk){
	    return function() {
		combo = current + kk;
		keyPress();
	    }
	};

	jQuery(document).keydown(function() {
	    matched = false;
	    command = false;
	});

	jQuery(document).keyup(function() {
	    if(!matched) {
		unrecognized();
		current = "";
	    }
	});

	// Return the hotkeys object
	return {
	    setUnrecognized: function(fn){ unrecognized = fn; },
	    add: function(k, fn){

		var keys = k.toLowerCase().split(" ");
		var seq = "";

		for ( var i = 0, l = keys.length; i < l; i++ ) {

		    //Create a partial mapping
		    seq += keys[i];
		    if (i < (l - 1)) {
			partialKeyMap[seq] = true;
		    } else {
			fullKeyMap[seq] = fn;
		    }

		    //Only maps keys we haven't seen before
		    if (!keyMap[ keys[i] ]) {
			keyMap[ keys[i] ] = true;
			$(document).bind('keydown', keys[i], keyFn(keys[i]));
		    }
		}
	    }
	}
    }();

    // Call this function when an unknown command is entered
    hotkeys.setUnrecognized(function(){});

    // Create conkerbar
    var conkerBar = function(){

	var currentMode  = baseMode;

	jQuery(document.body).append("

<input type=\"text\">
");
	var bar = jQuery(selectors.conker);
	var title = jQuery(selectors.commandbar);
	var input = jQuery(selectors.commandinput);

	var change = function(mode) {
	    currentMode = mode;
	}

	var hideBar = function(){
	    bar.hide();
	    input.val("").blur();
	    currentMode.leave();
	    currentMode = baseMode;
	}

	input.keyup(function(e) {
	    if(e.keyCode == 71 && e.ctrlKey){
		hideBar();
	    }
	    currentMode.update(e, input);
	});

	return {
	    hide: hideBar,
	    show: function(mode){
		currentMode = mode
		title.text(mode.title());
		input.val(mode.placeholder());
		bar.show();
		input.css({"left": title.width() + 10}).focus();
		mode.enter();
	    }
	};
    }();

    // Unfocus selected area (such as a textbox)
    hotkeys.add("esc", function(){
	$(":focus").blur();
    });

    // Cancel current command
    hotkeys.add("ctrl+g", conkerBar.hide);

    // Move back one page in the history
    hotkeys.add("shift+b", function() {
	window.history.back();
    });

    // Move forward one page in the history
    hotkeys.add("shift+f", function() {
	window.history.forward();
    });

    // Reload the current page
    hotkeys.add("ctrl+r", function() {
	window.location.reload(true);
    });

    // Movement around the page

    // Scroll the page all the way to the right
    hotkeys.add("ctrl+a", function(){
	window.scrollBy(-BIG, 0);
    });

    // Scroll the page all the way to the left
    hotkeys.add("ctrl+e", function(){
	window.scrollBy(BIG, 0);
    });

    // Scroll the page forward a column
    hotkeys.add("ctrl+f", function(){
	window.scrollBy(options.column, 0);
    });

    // Scroll the page back a column
    hotkeys.add("ctrl+b", function(){
	window.scrollBy(-options.column, 0);
    });

    // Scroll the page down a line
    hotkeys.add("ctrl+n", function(){
	window.scrollBy(0, options.line);
    });

    // Scroll the page up a line
    hotkeys.add("ctrl+p", function(){
	window.scrollBy(0, -options.line);
    });

    // Jump down a page length
    hotkeys.add("ctrl+v", function(){
	window.scrollBy(0, window.innerHeight - options.line);
    });

    // Jump up a page length
    hotkeys.add("meta+v", function(){
	window.scrollBy(0, -(window.innerHeight - options.line));
    });

    // Jump to the end of the page
    hotkeys.add("meta+shift+.", function(){
	window.scrollBy(0, BIG);
    });

    // Jump to the top of the page
    hotkeys.add("meta+shift+,", function(){
	window.scrollBy(0, -BIG);
    });

    // Close the current tab
    hotkeys.add('ctrl+x k', function() {
	chrome.extension.sendRequest({action: "close-tab"});
    });

    hotkeys.add('f', function (evt){
	conkerBar.show(followMode);
    });

    // Follow a link on the page
    var followMode = function() {

	var links;
	var current = 0;

	return {
	    title: function(){ return "Enter Link ID" },
	    placeholder: function() { return "" },
	    enter: function(){
		links = jQuery(selectors.links);
		links.each(function(i, elem) {
		    jQuery(this).append(jQuery("
", {
			"class": css.number, "text": i}))
			.addClass(css.highlight);
		});
		links.first().addClass(css.selected);
	    },
	    update: function(e, bar) {
		// If ctrl+n, move to next link
		if(e.keyCode == 78 && e.ctrlKey){
		    jQuery("a." + css.selected).removeClass(css.selected);
		    current = (current + 1) % links.length;
		    jQuery(links.get(current)).addClass(css.selected);
		    bar.val(current);
		} // If ctrl+p, move back a link
		else if(e.keyCode == 80 && e.ctrlKey){
		    jQuery("a." + css.selected).removeClass(css.selected);
		    current = (current - 1) % links.length;
		    jQuery(links.get(current)).addClass(css.selected);
		    bar.val(current);
		} else {
		    jQuery("a." + css.selected).removeClass(css.selected);

		    current = bar.val() || current;
		    link = jQuery(links.get(current));

		    // If the return was pressed,
		    if (e.keyCode == 13) {
			if (link && link.attr("href")) {
			    // If shift+return, open new tab
			    if (e.shiftKey) {
				chrome.extension.sendRequest({
				    action: "new-tab",
				    url: link.attr("href")
				});
			    } else {
				window.location.href = link.attr("href");
			    }
			}
		    } else {
			link.addClass(css.selected);
		    }
		}
	    },
	    leave: function(){
		links.removeClass(css.highlight)
		    .removeClass(css.selected);
		jQuery(selectors.number).remove();
	    }
	}
    }();

    // Edit Url
    var editUrlMode = {
	title: function(){ return "Edit Url"; },
	placeholder: function() { return document.URL; },
	enter: function(){
	},
	update: function(e, bar) {
	    v = bar.val();
	    if (!v) return;
	    // If the return was pressed,
	    if (e.keyCode == 13) {
		window.location.href = v;
	    }
	},
	leave: function(){
	}
    }

    // Open a new tab mode
    var newTabMode = {
	title: function(){ return "Enter Url"; },
	placeholder: function() { return ""; },
	enter: function(){
	},
	update: function(e, bar) {
	    v = bar.val();
	    if (!v) return;
	    // If the return was pressed,
	    if (e.keyCode == 13) {
		chrome.extension.sendRequest({
		    action: "new-tab",
		    url: v,
		    selected: true
		});
	    }
	},
	leave: function(){
	}
    }
}({}); //This object will later be a user stored settings file<commit_msg>More general selector syntax<commit_after>// Create the ConkerChrome object
var ConkerC = function(opts) {

    // Default options
    var defaults = {
	line: 40,        // Number of pixels to scroll up and down
	column: 20,      // Number of pixels to scroll left and right
	ctrl: "ctrl",    // Default key mappings
	meta: "meta",    // Users can change these
	shift: "shift"   // If they want
    };

    // Load the user provided options
    var options = jQuery.extend({}, defaults, opts);

    // Lots of pixels jump to the top or bottom of a page
    // The user shouldn't be able to set this
    var BIG = 10000000000;

    // HTML Selectors for ConkerChrome elements
    var selectors = {
	conker: "#conkerchrome",
	commandbar: "#commandbar",
	commandinput: "#conkerchrome input",
	number: ".conkerchrome_number",
	links: "a:in-view"
    }

    // CSS Selectors for ConkerChrome elements
    var css = {
	highlight: "conkerchrome_highlight",
	selected: "conkerchrome_selected",
	number: "conkerchrome_number"
    }

    var baseMode = {
	enter: function(){},
	leave: function(){},
	update: function(e, bar){}
    }

    // Module to hold all the keybindings
    // I wrote this a while ago, not sure how it works
    var hotkeys = function() {
	var matched = false;
	var current = "";
	var combo = "";
	var partialKeyMap = {};
	var fullKeyMap = {};
	var keyMap = {};
	var unrecognized = function(){};

	var keyPress = function() {
	    if (partialKeyMap[combo]) {
		current = combo;
		matched = true;
	    } else if (fullKeyMap[combo]) {
		matched = true;
		current = "";
		fullKeyMap[combo]();
	    }
	};

	var keyFn = function(kk){
	    return function() {
		combo = current + kk;
		keyPress();
	    }
	};

	jQuery(document).keydown(function() {
	    matched = false;
	    command = false;
	});

	jQuery(document).keyup(function() {
	    if(!matched) {
		unrecognized();
		current = "";
	    }
	});

	// Return the hotkeys object
	return {
	    setUnrecognized: function(fn){ unrecognized = fn; },
	    add: function(k, fn){

		var keys = k.toLowerCase().split(" ");
		var seq = "";

		for ( var i = 0, l = keys.length; i < l; i++ ) {

		    //Create a partial mapping
		    seq += keys[i];
		    if (i < (l - 1)) {
			partialKeyMap[seq] = true;
		    } else {
			fullKeyMap[seq] = fn;
		    }

		    //Only maps keys we haven't seen before
		    if (!keyMap[ keys[i] ]) {
			keyMap[ keys[i] ] = true;
			$(document).bind('keydown', keys[i], keyFn(keys[i]));
		    }
		}
	    }
	}
    }();

    // Call this function when an unknown command is entered
    hotkeys.setUnrecognized(function(){});

    // Create conkerbar
    var conkerBar = function(){

	var currentMode  = baseMode;

	jQuery(document.body).append("

<input type=\"text\">
");
	var bar = jQuery(selectors.conker);
	var title = jQuery(selectors.commandbar);
	var input = jQuery(selectors.commandinput);

	var change = function(mode) {
	    currentMode = mode;
	}

	var hideBar = function(){
	    bar.hide();
	    input.val("").blur();
	    currentMode.leave();
	    currentMode = baseMode;
	}

	input.keyup(function(e) {
	    if(e.keyCode == 71 && e.ctrlKey){
		hideBar();
	    }
	    currentMode.update(e, input);
	});

	return {
	    hide: hideBar,
	    show: function(mode){
		currentMode = mode
		title.text(mode.title());
		input.val(mode.placeholder());
		bar.show();
		input.css({"left": title.width() + 10}).focus();
		mode.enter();
	    }
	};
    }();

    // Unfocus selected area (such as a textbox)
    hotkeys.add("esc", function(){
	$(":focus").blur();
    });

    // Cancel current command
    hotkeys.add("ctrl+g", conkerBar.hide);

    // Move back one page in the history
    hotkeys.add("shift+b", function() {
	window.history.back();
    });

    // Move forward one page in the history
    hotkeys.add("shift+f", function() {
	window.history.forward();
    });

    // Reload the current page
    hotkeys.add("ctrl+r", function() {
	window.location.reload(true);
    });

    // Movement around the page

    // Scroll the page all the way to the right
    hotkeys.add("ctrl+a", function(){
	window.scrollBy(-BIG, 0);
    });

    // Scroll the page all the way to the left
    hotkeys.add("ctrl+e", function(){
	window.scrollBy(BIG, 0);
    });

    // Scroll the page forward a column
    hotkeys.add("ctrl+f", function(){
	window.scrollBy(options.column, 0);
    });

    // Scroll the page back a column
    hotkeys.add("ctrl+b", function(){
	window.scrollBy(-options.column, 0);
    });

    // Scroll the page down a line
    hotkeys.add("ctrl+n", function(){
	window.scrollBy(0, options.line);
    });

    // Scroll the page up a line
    hotkeys.add("ctrl+p", function(){
	window.scrollBy(0, -options.line);
    });

    // Jump down a page length
    hotkeys.add("ctrl+v", function(){
	window.scrollBy(0, window.innerHeight - options.line);
    });

    // Jump up a page length
    hotkeys.add("meta+v", function(){
	window.scrollBy(0, -(window.innerHeight - options.line));
    });

    // Jump to the end of the page
    hotkeys.add("meta+shift+.", function(){
	window.scrollBy(0, BIG);
    });

    // Jump to the top of the page
    hotkeys.add("meta+shift+,", function(){
	window.scrollBy(0, -BIG);
    });

    // Close the current tab
    hotkeys.add('ctrl+x k', function() {
	chrome.extension.sendRequest({action: "close-tab"});
    });

    hotkeys.add('f', function (evt){
	conkerBar.show(followMode);
    });

    // Follow a link on the page
    var followMode = function() {

	var links;
	var current = 0;

	return {
	    title: function(){ return "Enter Link ID" },
	    placeholder: function() { return "" },
	    enter: function(){
		links = jQuery(selectors.links);
		links.each(function(i, elem) {
		    jQuery(this).append(jQuery("
", {
			"class": css.number, "text": i}))
			.addClass(css.highlight);
		});
		links.first().addClass(css.selected);
	    },
	    update: function(e, bar) {
		// If ctrl+n, move to next link
		if(e.keyCode == 78 && e.ctrlKey){
		    jQuery("." + css.selected).removeClass(css.selected);
		    current = (current + 1) % links.length;
		    jQuery(links.get(current)).addClass(css.selected);
		    bar.val(current);
		} // If ctrl+p, move back a link
		else if(e.keyCode == 80 && e.ctrlKey){
		    jQuery("." + css.selected).removeClass(css.selected);
		    current = (current - 1) % links.length;
		    jQuery(links.get(current)).addClass(css.selected);
		    bar.val(current);
		} else {
		    jQuery("." + css.selected).removeClass(css.selected);

		    current = parseInt(bar.val()) || current;
		    link = jQuery(links.get(current));

		    // If the return was pressed,
		    if (e.keyCode == 13) {
			if (link && link.attr("href")) {
			    // If shift+return, open new tab
			    if (e.shiftKey) {
				chrome.extension.sendRequest({
				    action: "new-tab",
				    url: link.attr("href")
				});
			    } else {
				window.location.href = link.attr("href");
			    }
			}
		    } else {
			link.addClass(css.selected);
		    }
		}
	    },
	    leave: function(){
		links.removeClass(css.highlight)
		    .removeClass(css.selected);
		jQuery(selectors.number).remove();
	    }
	}
    }();

    // Edit Url
    var editUrlMode = {
	title: function(){ return "Edit Url"; },
	placeholder: function() { return document.URL; },
	enter: function(){
	},
	update: function(e, bar) {
	    v = bar.val();
	    if (!v) return;
	    // If the return was pressed,
	    if (e.keyCode == 13) {
		window.location.href = v;
	    }
	},
	leave: function(){
	}
    }

    // Open a new tab mode
    var newTabMode = {
	title: function(){ return "Enter Url"; },
	placeholder: function() { return ""; },
	enter: function(){
	},
	update: function(e, bar) {
	    v = bar.val();
	    if (!v) return;
	    // If the return was pressed,
	    if (e.keyCode == 13) {
		chrome.extension.sendRequest({
		    action: "new-tab",
		    url: v,
		    selected: true
		});
	    }
	},
	leave: function(){
	}
    }
}({}); //This object will later be a user stored settings file<|endoftext|>