<commit_before>// There's no reason that this file is in JavaScript instead of CoffeeScript.
// We should convert it and update the brunch config.

// If we wanted to be more robust, we could use this: https://github.com/padolsey/operative/blob/master/src/operative.js
if(typeof window !== 'undefined' || !self.importScripts)
    throw "Attempt to load worker_world into main window instead of web worker.";

// Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
// This is here for running simuations in enviroments lacking function.bind (PhantomJS mostly)
if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== "function") {
            // closest thing possible to the ECMAScript 5 internal IsCallable function
            throw new TypeError("Function.prototype.bind (Shim) - target is not callable");
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {},
            fBound = function () {
                return fToBind.apply(this instanceof fNOP && oThis
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();

        return fBound;
    };
}

// assign global window so that Brunch's require (in world.js) can go into it
self.window = self;
self.workerID = "DebugWorker";

self.logLimit = 2000;
self.logsLogged = 0;
var console = {
    log: function() {
        if(self.logsLogged++ == self.logLimit)
            self.postMessage({type: 'console-log', args: ["Log limit " + self.logLimit + " reached; shutting up."], id: self.workerID});
        else if(self.logsLogged < self.logLimit) {
            args = [].slice.call(arguments);
            for(var i = 0; i < args.length; ++i) {
                if(args[i] && args[i].constructor) {
                    if(args[i].constructor.className === "Thang" || args[i].isComponent)
                        args[i] = args[i].toString();
                }
            }
            try {
                self.postMessage({type: 'console-log', args: args, id: self.workerID});
            }
            catch(error) {
                self.postMessage({type: 'console-log', args: ["Could not post log: " + args, error.toString(), error.stack, error.stackTrace], id: self.workerID});
            }
        }
    }};  // so that we don't crash when debugging statements happen
console.error = console.info = console.log;
self.console = console;

// We could do way more from this: http://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment
Object.defineProperty(self, "XMLHttpRequest", {
    get: function() { throw new Error("Access to XMLHttpRequest is forbidden."); },
    configurable: false
});

if (!Array.prototype.last){
    Array.prototype.last = function(){
        return this[this.length - 1];
    };
}

self.transferableSupported = function transferableSupported() {
    // Not in IE, even in IE 11
    try {
        var ab = new ArrayBuffer(1);
        worker.postMessage(ab, [ab]);
        return ab.byteLength == 0;
    } catch(error) {
        return false;
    }
    return false;
}
importScripts('/javascripts/world.js');

var World = self.require('lib/world/world');
var GoalManager = self.require('lib/world/GoalManager');
serializedClasses = {
    "Thang": self.require('lib/world/thang'),
    "Vector": self.require('lib/world/vector'),
    "Rectangle": self.require('lib/world/rectangle')
}

self.getCurrentFrame = function getCurrentFrame(args) { return self.world.frames.length; };

//optimize this later
self.currentUserCodeMapCopy = {};
self.currentWorldFrame = 0;

self.maxSerializationDepth = 3;

self.stringifyValue = function(value, depth) {
    var brackets, i, isArray, isObject, key, prefix, s, sep, size, v, values, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3;
    if (!value || _.isString(value)) {
        return value;
    }
    if (_.isFunction(value)) {
        if (depth === 2) {
            return void 0;
        } else {
            return "<Function>";
        }
    }
    if (value === this.thang && depth) {
        return "<this " + value.id + ">";
    }
    if (depth === 2) {
        if (((_ref = value.constructor) != null ? _ref.className : void 0) === "Thang") {
            value = "<" + (value.type || value.spriteName) + " - " + value.id + ", " + (value.pos ? value.pos.toString() : 'non-physical') + ">";
        } else {
            value = value.toString();
        }
        return value;
    }
    isArray = _.isArray(value);
    isObject = _.isObject(value);
    if (!(isArray || isObject)) {
        return value.toString();
    }
    brackets = isArray ? ["[", "]"] : ["{", "}"];
    size = _.size(value);
    if (!size) {
        return brackets.join("");
    }
    values = [];
    if (isArray) {
        for (_i = 0, _len = value.length; _i < _len; _i++) {
            v = value[_i];
            s = this.stringifyValue(v, depth + 1);
            if (s !== void 0) {
                values.push("" + s);
            }
        }
    } else {
        _ref2 = (_ref1 = value.apiProperties) != null ? _ref1 : _.keys(value);
        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
            key = _ref2[_j];
            s = this.stringifyValue(value[key], depth + 1);
            if (s !== void 0) {
                values.push(key + ": " + s);
            }
        }
    }
    sep = '\n' + ((function() {
        var _k, _results;
        _results = [];
        for (i = _k = 0; 0 <= depth ? _k < depth : _k > depth; i = 0 <= depth ? ++_k : --_k) {
            _results.push("  ");
        }
        return _results;
    })()).join('');
    prefix = (_ref3 = value.constructor) != null ? _ref3.className : void 0;
    if (isArray) {
        if (prefix == null) {
            prefix = "Array";
        }
    }
    if (isObject) {
        if (prefix == null) {
            prefix = "Object";
        }
    }
    prefix = prefix ? prefix + " " : "";
    return "" + prefix + brackets[0] + sep + "  " + (values.join(sep + '  ')) + sep + brackets[1];
};

self.retrieveValueFromFrame = function retrieveValueFromFrame(args) {
    var retrieveProperty = function retrieveProperty(currentThangID, currentSpellID, variableChain)
    {
        var prop;
        var value;
        var keys = [];
        for (var i = 0, len = variableChain.length; i < len; i++)
            {
                prop = variableChain[i];
                if (prop === "this")
                {
                    value = self.world.thangMap[currentThangID];

                }
                else if (i === 0)
                {
                    try
                    {
                        value = self.world.userCodeMap[currentThangID][currentSpellID].flow.states.last().statements.last().variables[prop];
                    }
                    catch (e)
                    {
                        value = undefined;
                    }

                }
                else
                {
                    value = value[prop];
                }
                keys.push(prop);
                if (!value) break;
                var classOfValue;
                if (classOfValue = serializedClasses[value.CN])
                {
                    if (value.CN === "Thang")
                    {
                        var thang = self.world.thangMap[value.id];
                        value = thang || "<Thang " + value.id + " (non-existent)>"
                    }
                    else
                    {
                        value = classOfValue.deserializeFromAether(value);
                    }
                }
            }
        var serializedProperty = {
            "key": keys.join("."),
            "value": self.stringifyValue(value,0)
        };
        self.postMessage({type: 'debug-value-return', serialized: serializedProperty});
    };
    self.enableFlowOnThangSpell(args.currentThangID, args.currentSpellID, args.userCodeMap);
    self.setupWorldToRunUntilFrame(args);
    self.world.loadFramesUntilFrame(
        args.frame,
        retrieveProperty.bind({},args.currentThangID, args.currentSpellID, args.variableChain),
        self.onWorldError,
        self.onWorldLoadProgress
    );
};

self.enableFlowOnThangSpell = function enableFlowOnThang(thangID, spellID, userCodeMap) {
    try {
        if (userCodeMap[thangID][spellID].originalOptions.includeFlow === true &&
            userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow)
            return;
        else
        {
            userCodeMap[thangID][spellID].originalOptions.includeFlow = true;
            userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow = true;
            var temporaryAether = Aether.deserialize(userCodeMap[thangID][spellID]);
            temporaryAether.transpile(temporaryAether.raw);
            console.log("Transpiled!");
            userCodeMap[thangID][spellID] = temporaryAether.serialize();
        }

    }
    catch (e) {
        console.log("there was an error enabling flow on thang spell:" + e)
    }
};

self.setupWorldToRunUntilFrame = function setupWorldToRunUntilFrame(args) {
    self.postedErrors = {};
    self.t0 = new Date();
    self.firstWorld = args.firstWorld;
    self.postedErrors = false;
    self.logsLogged = 0;

    var stringifiedUserCodeMap = JSON.stringify(args.userCodeMap);
    var userCodeMapHasChanged = ! _.isEqual(self.currentUserCodeMapCopy, stringifiedUserCodeMap);

    self.currentUserCodeMapCopy = stringifiedUserCodeMap;
    try {
        self.world = new World(args.worldName, args.userCodeMap);
        if(args.level)
            self.world.loadFromLevel(args.level, true);
        self.goalManager = new GoalManager(self.world);
        self.goalManager.setGoals(args.goals);
        self.goalManager.setCode(args.userCodeMap);
        self.goalManager.worldGenerationWillBegin();
        self.world.setGoalManager(self.goalManager);
    }
    catch (error) {
        self.onWorldError(error);
        return;
    }
    Math.random = self.world.rand.randf;  // so user code is predictable

    self.world.totalFrames = args.frame; //hack to work around error checking
    self.currentWorldFrame = args.frame;
};
self.runWorldUntilFrame = function runWorldUntilFrame(args) {
    self.setupWorldToRunUntilFrame(args);
    self.world.loadFramesUntilFrame(args.frame, self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);

};

self.onWorldLoaded = function onWorldLoaded() {
    console.log("World loaded!");
};

self.onWorldError = function onWorldError(error) {
    if(error instanceof Aether.problems.UserCodeProblem) {
        if(!self.postedErrors[error.key]) {
            var problem = error.serialize();
            self.postMessage({type: 'user-code-problem', problem: problem});
            self.postedErrors[error.key] = problem;
        }
    }
    else {
        console.log("Non-UserCodeError:", error.toString() + "\n" + error.stack || error.stackTrace);
    }
    /*  We don't actually have the recoverable property any more; hmm
     if(!self.firstWorld && !error.recoverable) {
     self.abort();
     return false;
     }
     */
    return true;
};

self.onWorldLoadProgress = function onWorldLoadProgress(progress) {
    self.postMessage({type: 'world-load-progress-changed', progress: progress});
};

self.abort = function abort() {
    if(self.world && self.world.name) {
        console.log("About to abort:", self.world.name, typeof self.world.abort);
        if(typeof self.world !== "undefined")
            self.world.abort();
        self.world = null;
    }
    self.postMessage({type: 'abort'});
};

self.reportIn = function reportIn() {
    self.postMessage({type: 'reportIn'});
}

self.addEventListener('message', function(event) {
    console.log("received message!")
    self[event.data.func](event.data.args);
});

self.postMessage({type: 'worker-initialized'});
<commit_msg>Implemented caching and fixed off by one error<commit_after>// There's no reason that this file is in JavaScript instead of CoffeeScript.
// We should convert it and update the brunch config.

// If we wanted to be more robust, we could use this: https://github.com/padolsey/operative/blob/master/src/operative.js
if(typeof window !== 'undefined' || !self.importScripts)
    throw "Attempt to load worker_world into main window instead of web worker.";

// Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
// This is here for running simuations in enviroments lacking function.bind (PhantomJS mostly)
if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== "function") {
            // closest thing possible to the ECMAScript 5 internal IsCallable function
            throw new TypeError("Function.prototype.bind (Shim) - target is not callable");
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {},
            fBound = function () {
                return fToBind.apply(this instanceof fNOP && oThis
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP();

        return fBound;
    };
}

// assign global window so that Brunch's require (in world.js) can go into it
self.window = self;
self.workerID = "DebugWorker";

self.logLimit = 2000;
self.logsLogged = 0;
var console = {
    log: function() {
        if(self.logsLogged++ == self.logLimit)
            self.postMessage({type: 'console-log', args: ["Log limit " + self.logLimit + " reached; shutting up."], id: self.workerID});
        else if(self.logsLogged < self.logLimit) {
            args = [].slice.call(arguments);
            for(var i = 0; i < args.length; ++i) {
                if(args[i] && args[i].constructor) {
                    if(args[i].constructor.className === "Thang" || args[i].isComponent)
                        args[i] = args[i].toString();
                }
            }
            try {
                self.postMessage({type: 'console-log', args: args, id: self.workerID});
            }
            catch(error) {
                self.postMessage({type: 'console-log', args: ["Could not post log: " + args, error.toString(), error.stack, error.stackTrace], id: self.workerID});
            }
        }
    }};  // so that we don't crash when debugging statements happen
console.error = console.info = console.log;
self.console = console;

// We could do way more from this: http://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment
Object.defineProperty(self, "XMLHttpRequest", {
    get: function() { throw new Error("Access to XMLHttpRequest is forbidden."); },
    configurable: false
});

if (!Array.prototype.last){
    Array.prototype.last = function(){
        return this[this.length - 1];
    };
}

self.transferableSupported = function transferableSupported() {
    // Not in IE, even in IE 11
    try {
        var ab = new ArrayBuffer(1);
        worker.postMessage(ab, [ab]);
        return ab.byteLength == 0;
    } catch(error) {
        return false;
    }
    return false;
}
importScripts('/javascripts/world.js');

var World = self.require('lib/world/world');
var GoalManager = self.require('lib/world/GoalManager');
serializedClasses = {
    "Thang": self.require('lib/world/thang'),
    "Vector": self.require('lib/world/vector'),
    "Rectangle": self.require('lib/world/rectangle')
}

self.getCurrentFrame = function getCurrentFrame(args) { return self.world.frames.length; };

//optimize this later
self.currentUserCodeMapCopy = {};
self.currentWorldFrame = 0;

self.maxSerializationDepth = 3;

self.stringifyValue = function(value, depth) {
    var brackets, i, isArray, isObject, key, prefix, s, sep, size, v, values, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3;
    if (!value || _.isString(value)) {
        return value;
    }
    if (_.isFunction(value)) {
        if (depth === 2) {
            return void 0;
        } else {
            return "<Function>";
        }
    }
    if (value === this.thang && depth) {
        return "<this " + value.id + ">";
    }
    if (depth === 2) {
        if (((_ref = value.constructor) != null ? _ref.className : void 0) === "Thang") {
            value = "<" + (value.type || value.spriteName) + " - " + value.id + ", " + (value.pos ? value.pos.toString() : 'non-physical') + ">";
        } else {
            value = value.toString();
        }
        return value;
    }
    isArray = _.isArray(value);
    isObject = _.isObject(value);
    if (!(isArray || isObject)) {
        return value.toString();
    }
    brackets = isArray ? ["[", "]"] : ["{", "}"];
    size = _.size(value);
    if (!size) {
        return brackets.join("");
    }
    values = [];
    if (isArray) {
        for (_i = 0, _len = value.length; _i < _len; _i++) {
            v = value[_i];
            s = this.stringifyValue(v, depth + 1);
            if (s !== void 0) {
                values.push("" + s);
            }
        }
    } else {
        _ref2 = (_ref1 = value.apiProperties) != null ? _ref1 : _.keys(value);
        for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
            key = _ref2[_j];
            s = this.stringifyValue(value[key], depth + 1);
            if (s !== void 0) {
                values.push(key + ": " + s);
            }
        }
    }
    sep = '\n' + ((function() {
        var _k, _results;
        _results = [];
        for (i = _k = 0; 0 <= depth ? _k < depth : _k > depth; i = 0 <= depth ? ++_k : --_k) {
            _results.push("  ");
        }
        return _results;
    })()).join('');
    prefix = (_ref3 = value.constructor) != null ? _ref3.className : void 0;
    if (isArray) {
        if (prefix == null) {
            prefix = "Array";
        }
    }
    if (isObject) {
        if (prefix == null) {
            prefix = "Object";
        }
    }
    prefix = prefix ? prefix + " " : "";
    return "" + prefix + brackets[0] + sep + "  " + (values.join(sep + '  ')) + sep + brackets[1];
};

var cache = {};

self.invalidateCache = function () {
    cache = {};
};

self.retrieveValueFromCache = function (thangID, spellID, variableChain, frame) {
    var frameCache, thangCache, spellCache;
    if ((frameCache = cache[frame]) && (thangCache = frameCache[thangID]) && (spellCache = thangCache[spellID]))
        return spellCache[variableChain.join()];
    return undefined;
};

self.updateCache = function (thangID, spellID, variableChain, frame, value) {
    var key, keys, currentObject;
    keys = [frame,thangID, spellID, variableChain.join()];
    currentObject = cache;

    for (var i = 0, len = keys.length - 1; i < len; i++)
    {
        key = keys[i];
        if (!(key in currentObject))
            currentObject[key] = {};
        currentObject = currentObject[key];
    }
    currentObject[keys[keys.length - 1]] = value;
};

self.retrieveValueFromFrame = function retrieveValueFromFrame(args) {
    var cacheValue;
    if (cacheValue = self.retrieveValueFromCache(args.currentThangID, args.currentSpellID, args.variableChain, args.frame))
        return self.postMessage({type: 'debug-value-return', serialized: {"key": args.variableChain.join(), "value": cacheValue}});

    var retrieveProperty = function retrieveProperty(currentThangID, currentSpellID, variableChain)
    {
        var prop;
        var value;
        var keys = [];
        for (var i = 0, len = variableChain.length; i < len; i++)
            {
                prop = variableChain[i];
                if (prop === "this")
                {
                    value = self.world.thangMap[currentThangID];

                }
                else if (i === 0)
                {
                    try
                    {
                        value = self.world.userCodeMap[currentThangID][currentSpellID].flow.states.last().statements.last().variables[prop];
                    }
                    catch (e)
                    {
                        value = undefined;
                    }

                }
                else
                {
                    value = value[prop];
                }
                keys.push(prop);
                if (!value) break;
                var classOfValue;
                if (classOfValue = serializedClasses[value.CN])
                {
                    if (value.CN === "Thang")
                    {
                        var thang = self.world.thangMap[value.id];
                        value = thang || "<Thang " + value.id + " (non-existent)>"
                    }
                    else
                    {
                        value = classOfValue.deserializeFromAether(value);
                    }
                }
            }
        var serializedProperty = {
            "key": keys.join("."),
            "value": self.stringifyValue(value,0)
        };
        self.updateCache(currentThangID,currentSpellID,variableChain, args.frame, serializedProperty.value);
        self.postMessage({type: 'debug-value-return', serialized: serializedProperty});
    };
    self.enableFlowOnThangSpell(args.currentThangID, args.currentSpellID, args.userCodeMap);
    self.setupWorldToRunUntilFrame(args);
    //You need to load until the very next frame, as the state is gathered at the next frame, this might be a source of bugs!
    self.world.loadFramesUntilFrame(
        args.frame + 1,
        retrieveProperty.bind({},args.currentThangID, args.currentSpellID, args.variableChain),
        self.onWorldError,
        self.onWorldLoadProgress
    );
};

self.enableFlowOnThangSpell = function enableFlowOnThang(thangID, spellID, userCodeMap) {
    try {
        if (userCodeMap[thangID][spellID].originalOptions.includeFlow === true &&
            userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow === true)
            return;
        else
        {
            userCodeMap[thangID][spellID].originalOptions.includeFlow = true;
            userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow = true;
            var temporaryAether = Aether.deserialize(userCodeMap[thangID][spellID]);
            temporaryAether.transpile(temporaryAether.raw);
            console.log("Transpiled!");
            userCodeMap[thangID][spellID] = temporaryAether.serialize();
        }

    }
    catch (e) {
        console.log("there was an error enabling flow on thang spell:" + e)
    }
};

self.setupWorldToRunUntilFrame = function setupWorldToRunUntilFrame(args) {
    self.postedErrors = {};
    self.t0 = new Date();
    self.firstWorld = args.firstWorld;
    self.postedErrors = false;
    self.logsLogged = 0;

    var stringifiedUserCodeMap = JSON.stringify(args.userCodeMap);
    var userCodeMapHasChanged = ! _.isEqual(self.currentUserCodeMapCopy, stringifiedUserCodeMap);
    if (userCodeMapHasChanged) self.invalidateCache();
    self.currentUserCodeMapCopy = stringifiedUserCodeMap;
    try {
        self.world = new World(args.worldName, args.userCodeMap);
        if(args.level)
            self.world.loadFromLevel(args.level, true);
        self.goalManager = new GoalManager(self.world);
        self.goalManager.setGoals(args.goals);
        self.goalManager.setCode(args.userCodeMap);
        self.goalManager.worldGenerationWillBegin();
        self.world.setGoalManager(self.goalManager);
    }
    catch (error) {
        self.onWorldError(error);
        return;
    }
    Math.random = self.world.rand.randf;  // so user code is predictable

    self.world.totalFrames = args.frame; //hack to work around error checking
    self.currentWorldFrame = args.frame;
};
self.runWorldUntilFrame = function runWorldUntilFrame(args) {
    self.setupWorldToRunUntilFrame(args);

    self.world.loadFramesUntilFrame(args.frame, self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);

};

self.onWorldLoaded = function onWorldLoaded() {
    console.log("World loaded!");
};

self.onWorldError = function onWorldError(error) {
    if(error instanceof Aether.problems.UserCodeProblem) {
        if(!self.postedErrors[error.key]) {
            var problem = error.serialize();
            self.postMessage({type: 'user-code-problem', problem: problem});
            self.postedErrors[error.key] = problem;
        }
    }
    else {
        console.log("Non-UserCodeError:", error.toString() + "\n" + error.stack || error.stackTrace);
    }
    /*  We don't actually have the recoverable property any more; hmm
     if(!self.firstWorld && !error.recoverable) {
     self.abort();
     return false;
     }
     */
    return true;
};

self.onWorldLoadProgress = function onWorldLoadProgress(progress) {
    self.postMessage({type: 'world-load-progress-changed', progress: progress});
};

self.abort = function abort() {
    if(self.world && self.world.name) {
        console.log("About to abort:", self.world.name, typeof self.world.abort);
        if(typeof self.world !== "undefined")
            self.world.abort();
        self.world = null;
    }
    self.postMessage({type: 'abort'});
};

self.reportIn = function reportIn() {
    self.postMessage({type: 'reportIn'});
}

self.addEventListener('message', function(event) {
    console.log("received message!")
    self[event.data.func](event.data.args);
});

self.postMessage({type: 'worker-initialized'});
<|endoftext|>


<commit_before>import React from 'react';
import {Card, CardActions, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

const CardExampleWithAvatar = (props) => (
  <Card>
    <CardMedia>

    </CardMedia>
    <CardTitle title={props.name} subtitle="Card subtitle" />
    <CardText>{ props.description }</CardText>
    <CardActions>
      $ {props.price}
      <FlatButton label="Buy" />
    </CardActions>
  </Card>
);

export default CardExampleWithAvatar;<commit_msg>refactor(product card): remove description<commit_after>import React from 'react';
import {Card, CardActions, CardMedia, CardTitle, CardText} from 'material-ui/Card';
import FlatButton from 'material-ui/FlatButton';

const CardExampleWithAvatar = (props) => (
  <Card>
    <CardMedia>

    </CardMedia>
    <CardTitle title={props.name} subtitle="Card subtitle" />
    <CardActions>
      $ {props.price}
      <FlatButton label="Buy" />
    </CardActions>
  </Card>
);

export default CardExampleWithAvatar;<|endoftext|>


<commit_before>// @flow

import invariant from 'assert'
import {
  createJobTransformer,
  getChunk,
  getFileKey,
  getChunkKey,
  type ImportResolved,
  type ImportTransformed,
} from '@pundle/api'

import manifest from '../package.json'

function fileToImport(file: ImportTransformed): ImportResolved {
  return { filePath: file.filePath, format: file.format, meta: file.meta }
}

function createComponent({
  name = '_common_',
  processNonRootChunks = false,
}: { name: string, processNonRootChunks: boolean } = {}) {
  return createJobTransformer({
    name: manifest.name,
    version: manifest.version,
    async callback({ job, context }) {
      if (context.config.target === 'node') {
        // Unlike the browser, node.js does NOT have a "index.html"
        // file where we can push a new script tag.
        // We could ideally push a require for the commons chunk but
        // it's not a top priority.
        return
      }

      const chunkToFiles = new Map()

      job.chunks.forEach(chunk => {
        if ((!chunk.root && !processNonRootChunks) || chunk.flat) return

        const relevantFiles = new Set()

        function iterateImports(fileImport: ImportResolved, topLevelOnly: boolean) {
          const file = job.files.get(getFileKey(fileImport))
          invariant(file, `File referenced in chunk ('${fileImport.filePath}') not found in local cache!?`)
          if (relevantFiles.has(file)) return

          relevantFiles.add(file)
          if (!topLevelOnly) {
            file.imports.forEach(item => iterateImports(item, false))
          }
        }

        if (chunk.filePath) {
          iterateImports(
            {
              meta: chunk.meta,
              format: chunk.format,
              filePath: chunk.filePath,
            },
            false,
          )
        }
        chunk.imports.forEach(item => iterateImports(item, true))
        chunkToFiles.set(chunk, Array.from(relevantFiles))
      })

      let commonFiles = []
      chunkToFiles.forEach((files, chunk) => {
        if (chunk.format === 'js') {
          commonFiles = commonFiles.concat(files)
        }
      })
      const duplicateFiles = commonFiles.filter((file, index) => {
        const lastIndex = commonFiles.lastIndexOf(file)
        if (index !== lastIndex) {
          const firstIndex = commonFiles.indexOf(file)
          if (firstIndex === index) return true
        }
        return false
      })

      if (!duplicateFiles.length) return null

      const clonedJob = job.clone()
      const clonedChunks = new Map()
      const commonChunk = getChunk('js', name, null, duplicateFiles.map(fileToImport), true, true)

      chunkToFiles.forEach((files, chunk) => {
        let hadOne = false
        duplicateFiles.forEach(file => {
          const index = files.indexOf(file)
          if (index !== -1) {
            hadOne = true
            files.splice(index, 1)
          }
        })

        let clonedChunk = chunk
        if (hadOne) {
          clonedChunk = { ...clonedChunk, imports: files.map(fileToImport), flat: true }
        }
        clonedChunks.set(getChunkKey(clonedChunk), clonedChunk)
      })

      clonedChunks.set(getChunkKey(commonChunk), commonChunk)

      clonedJob.chunks = clonedChunks

      return { job: clonedJob }
    },
  })
}

module.exports = createComponent
<commit_msg>:bug: Fix inconsistent return in commons transformer<commit_after>// @flow

import invariant from 'assert'
import {
  createJobTransformer,
  getChunk,
  getFileKey,
  getChunkKey,
  type ImportResolved,
  type ImportTransformed,
} from '@pundle/api'

import manifest from '../package.json'

function fileToImport(file: ImportTransformed): ImportResolved {
  return { filePath: file.filePath, format: file.format, meta: file.meta }
}

function createComponent({
  name = '_common_',
  processNonRootChunks = false,
}: { name: string, processNonRootChunks: boolean } = {}) {
  return createJobTransformer({
    name: manifest.name,
    version: manifest.version,
    async callback({ job, context }) {
      if (context.config.target === 'node') {
        // Unlike the browser, node.js does NOT have a "index.html"
        // file where we can push a new script tag.
        // We could ideally push a require for the commons chunk but
        // it's not a top priority.
        return null
      }

      const chunkToFiles = new Map()

      job.chunks.forEach(chunk => {
        if ((!chunk.root && !processNonRootChunks) || chunk.flat) return

        const relevantFiles = new Set()

        function iterateImports(fileImport: ImportResolved, topLevelOnly: boolean) {
          const file = job.files.get(getFileKey(fileImport))
          invariant(file, `File referenced in chunk ('${fileImport.filePath}') not found in local cache!?`)
          if (relevantFiles.has(file)) return

          relevantFiles.add(file)
          if (!topLevelOnly) {
            file.imports.forEach(item => iterateImports(item, false))
          }
        }

        if (chunk.filePath) {
          iterateImports(
            {
              meta: chunk.meta,
              format: chunk.format,
              filePath: chunk.filePath,
            },
            false,
          )
        }
        chunk.imports.forEach(item => iterateImports(item, true))
        chunkToFiles.set(chunk, Array.from(relevantFiles))
      })

      let commonFiles = []
      chunkToFiles.forEach((files, chunk) => {
        if (chunk.format === 'js') {
          commonFiles = commonFiles.concat(files)
        }
      })
      const duplicateFiles = commonFiles.filter((file, index) => {
        const lastIndex = commonFiles.lastIndexOf(file)
        if (index !== lastIndex) {
          const firstIndex = commonFiles.indexOf(file)
          if (firstIndex === index) return true
        }
        return false
      })

      if (!duplicateFiles.length) return null

      const clonedJob = job.clone()
      const clonedChunks = new Map()
      const commonChunk = getChunk('js', name, null, duplicateFiles.map(fileToImport), true, true)

      chunkToFiles.forEach((files, chunk) => {
        let hadOne = false
        duplicateFiles.forEach(file => {
          const index = files.indexOf(file)
          if (index !== -1) {
            hadOne = true
            files.splice(index, 1)
          }
        })

        let clonedChunk = chunk
        if (hadOne) {
          clonedChunk = { ...clonedChunk, imports: files.map(fileToImport), flat: true }
        }
        clonedChunks.set(getChunkKey(clonedChunk), clonedChunk)
      })

      clonedChunks.set(getChunkKey(commonChunk), commonChunk)

      clonedJob.chunks = clonedChunks

      return { job: clonedJob }
    },
  })
}

module.exports = createComponent
<|endoftext|>


<commit_before>/* test/state_routes_test.js -- test State routes
 * Copyright 2014 Sergei Ianovich
 *
 * Licensed under AGPL-3.0 or later, see LICENSE
 * Process Control Service Web Interface
 */
'use strict';

var expect = require('expect.js');

var State = require('../models/state');
var Routes = require('../routes/state');
var router = require('./support/router');

describe('State routes', function () {
  var device;
  before(function(done) {
    Factory.create('device', function (d) { device = d; done(); });
  });

  describe("#index", function() {
    it("should deny access to non-signed-in users", function(done) {
      var req = { session: {} },
      res = { redirect: function(url) {
        expect(url).to.eql("/signin");
        done();
      }};
      router(Routes.index, req, res);
    });
  });

  describe("#create", function() {
    var req, res;

    beforeEach(function () {
      req = { method: 'PUT', headers: {'content-type': 'application/x-device-data' } };
      res = {};
    });

    it("should check HTTP PUT method", function(done) {
      req.method = 'POST';
      Routes.create(req, res, done);
    });

    it("should check content type", function(done) {
      req.method = 'PUT';
      req.headers = { 'content-type': 'text/html' }
      Routes.create(req, res, done);
    });

    describe('with correct request params', function () {
      var listeners;
      beforeEach(function () {
        listeners = {};
        req.on = function (key, value) {
          if (!listeners[key])
            listeners[key] = value;
          else
            throw 'redefinition of ' + key;
        };
        req.once = req.on;
        req.removeListener = function (key, value) {
          expect(listeners[key]).to.eql(value);
          delete listeners[key];
        };
        Routes.create(req, res, null);
      });

      it('should add listeners', function () {
        expect(listeners.data).to.be.ok;
        expect(listeners.end).to.be.ok;
        expect(listeners.error).to.be.ok;
        expect(listeners.close).to.be.ok;
      });

      describe('adds onData which', function () {
        describe('before receiveing device', function () {
          it('should ignore newlines', function () {
            listeners.data('\n');
          });

          it('should abort when bad JSON', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ device: 3');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });

          it('should abort when no device', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ "a": 3 }');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });

          it('should abort when bad device', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ "device": 3 }');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });
        });

        describe('after receiveing device', function () {
          var code, response;
          beforeEach(function (done) {
            res.writeHead = function (c) { code = c; };
            res.write = function (r) { response = r; done(); };
            listeners.data('{ "device": "' + device._id + '" }');
          });

          it('should report success', function () {
            expect(code).to.be(200);
            expect(response).to.be('ok');
          });

          it('should respond to newline', function (done) {
            res.write = function (response) {
              expect(response).to.be('\n');
              done();
            };
            listeners.data('\n');
          });

          it('should abort on bad JSON', function () {
            var end;
            res.end = function () { end = true; };
            listeners.data('{ "device');
            expect(listeners).to.be.empty;
          });

          it('should save state on good JSON', function (done) {
            State.count({ device: device._id }, function (err, count) {
              var interval, timer;
              function recount () {
                State.count({ device: device._id }, function (err, newCount) {
                  expect(err).not.to.be.ok;
                  if (newCount > count) {
                    clearInterval(interval);
                    clearTimeout(timer);
                    done();
                  }
                });
              };
              expect(err).not.to.be.ok;
              timer = setTimeout(function () {
                clearInterval(interval);
                expect(count).not.to.be(count);
                done();
              }, 300);
              interval = setInterval(recount, 25);
              listeners.data('{ "a": 1, "b": 2 }');
            });
          });
        });
      });
    });
  });
});

// vim:ts=2 sts=2 sw=2 et:
<commit_msg>tests: routes: create state reports setpoints<commit_after>/* test/state_routes_test.js -- test State routes
 * Copyright 2014 Sergei Ianovich
 *
 * Licensed under AGPL-3.0 or later, see LICENSE
 * Process Control Service Web Interface
 */
'use strict';

var expect = require('expect.js');

var State = require('../models/state');
var Routes = require('../routes/state');
var router = require('./support/router');

describe('State routes', function () {
  var device;
  before(function(done) {
    Factory.create('device', function (d) { device = d; done(); });
  });

  var device1;
  before(function(done) {
    Factory.create('device', function (d) { device1 = d; done(); });
  });

  var site;
  before(function(done) {
    Factory.create('site', function (s) { site = s; done(); });
  });

  before(function(done) {
    Factory.create('system',
        { site: site._id, device: device1._id, setpoints: { a: 1 } },
        function () { done(); });
  });

  before(function(done) {
    Factory.create('system',
        { site: site._id, device: device1._id, setpoints: { b: 2 } },
        function () { done(); });
  });

  describe("#index", function() {
    it("should deny access to non-signed-in users", function(done) {
      var req = { session: {} },
      res = { redirect: function(url) {
        expect(url).to.eql("/signin");
        done();
      }};
      router(Routes.index, req, res);
    });
  });

  describe("#create", function() {
    var req, res;

    beforeEach(function () {
      req = { method: 'PUT', headers: {'content-type': 'application/x-device-data' } };
      res = {};
    });

    it("should check HTTP PUT method", function(done) {
      req.method = 'POST';
      Routes.create(req, res, done);
    });

    it("should check content type", function(done) {
      req.method = 'PUT';
      req.headers = { 'content-type': 'text/html' }
      Routes.create(req, res, done);
    });

    describe('with correct request params', function () {
      var listeners;
      beforeEach(function () {
        listeners = {};
        req.on = function (key, value) {
          if (!listeners[key])
            listeners[key] = value;
          else
            throw 'redefinition of ' + key;
        };
        req.once = req.on;
        req.removeListener = function (key, value) {
          expect(listeners[key]).to.eql(value);
          delete listeners[key];
        };
        Routes.create(req, res, null);
      });

      it('should add listeners', function () {
        expect(listeners.data).to.be.ok;
        expect(listeners.end).to.be.ok;
        expect(listeners.error).to.be.ok;
        expect(listeners.close).to.be.ok;
      });

      describe('adds onData which', function () {
        describe('before receiveing device', function () {
          it('should ignore newlines', function () {
            listeners.data('\n');
          });

          it('should abort when bad JSON', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ device: 3');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });

          it('should abort when no device', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ "a": 3 }');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });

          it('should abort when bad device', function () {
            var c;
            res.send = function (code) {
              c = code;
            };
            listeners.data('{ "device": 3 }');
            expect(c).to.be(500);
            expect(listeners).to.be.empty;
          });
        });

        describe('after receiveing device', function () {
          var code, response;
          beforeEach(function (done) {
            res.writeHead = function (c) { code = c; };
            res.write = function (r) { response = r; done(); };
            listeners.data('{ "device": "' + device._id + '" }');
          });

          it('should report success', function () {
            expect(code).to.be(200);
            expect(response).to.be('ok');
          });

          it('should respond to newline', function (done) {
            res.write = function (response) {
              expect(response).to.be('\n');
              done();
            };
            listeners.data('\n');
          });

          it('should abort on bad JSON', function () {
            var end;
            res.end = function () { end = true; };
            listeners.data('{ "device');
            expect(listeners).to.be.empty;
          });

          it('should save state on good JSON', function (done) {
            State.count({ device: device._id }, function (err, count) {
              var interval, timer;
              function recount () {
                State.count({ device: device._id }, function (err, newCount) {
                  expect(err).not.to.be.ok;
                  if (newCount > count) {
                    clearInterval(interval);
                    clearTimeout(timer);
                    done();
                  }
                });
              };
              expect(err).not.to.be.ok;
              timer = setTimeout(function () {
                clearInterval(interval);
                expect(count).not.to.be(count);
                done();
              }, 300);
              interval = setInterval(recount, 25);
              listeners.data('{ "a": 1, "b": 2 }');
            });
          });
        });

        describe('after receiveing device with setpoints', function () {
          var code, response;
          beforeEach(function (done) {
            res.writeHead = function (c) { code = c; };
            res.write = function (r) { response = r; done(); };
            listeners.data('{ "device": "' + device1._id + '" }');
          });

          it('should report setpoints', function (done) {
            res.write = function (r) {
              expect(r).to.eql(JSON.stringify({a: 1, b: 2}));
              done();
            };
            listeners.data('{ "c": 3 }');
          });
        });
      });
    });
  });
});

// vim:ts=2 sts=2 sw=2 et:
<|endoftext|>


<commit_before>/* jshint node:true */
'use strict';

var gulp = require('gulp');
var browserify = require('browserify');
var transform = require('vinyl-transform');
var $ = require('gulp-load-plugins')();

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

gulp.task('styles', function () {
  return gulp.src(['app/styles/main.css'])
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/styles'));
});

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jshint.reporter('fail'));
});

gulp.task('javascript', function () {
  // transform regular node stream to gulp (buffered vinyl) stream
  var browserified = transform(function(filename) {
    var b = browserify({entries: filename, debug: true});
    return b.bundle();
  });

  return gulp.src('app/scripts/edit.js')
    .pipe(browserified)
    .pipe($.sourcemaps.init({loadMaps: true}))
        // Add transformation tasks to the pipeline here.
       .pipe($.uglify())
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest('.tmp/js'));
});

gulp.task('html', ['styles', 'javascript'], function () {
  var assets = $.useref.assets({searchPath: ['.tmp','app','.']});
  //var assets = $.useref.assets();

  return gulp.src('app/*.html')
    .pipe(assets)
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    //.pipe($.if('*.html', $.minifyHtml({conditionals: true, loose: true})))
    .pipe(gulp.dest('dist'));
});

//Optimize images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images')).pipe($.size({title: 'images'}));
});

gulp.task('fonts', function () {
  return gulp.src(require('main-bower-files')().concat('app/fonts/**/*'))
    .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
    .pipe($.flatten())
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('extras', function () {
  return gulp.src([
    'app/*.*',
    '!app/*.html',
    '!app/**/*~',
    '!app/**/*swp',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

gulp.task('clean', require('del').bind(null, ['.tmp', 'dist']));

gulp.task('connect', function () {
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var app = require('connect')()
    .use(require('connect-livereload')({port: 35729}))
    .use(serveStatic('.tmp'))
    .use(serveStatic('app'))
    .use(serveStatic('dist'))
    // paths to bower_components should be relative to the current file
    // e.g. in app/index.html you should use ../bower_components
    .use('/bower_components', serveStatic('bower_components'))
    .use(serveIndex('app'));

  require('http').createServer(app)
    .listen(9000)
    .on('listening', function () {
      console.log('Started connect web server on http://localhost:9000');
    });
});

gulp.task('serve', ['connect', 'watch'], function () {
  require('opn')('http://localhost:9000');
});

// serve from build to ensure everything is there
gulp.task('serve-build', ['clean'], function () {
  gulp.start('build');
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var app = require('connect')().use(serveStatic('dist')).use(serveIndex('dist'));
  require('http').createServer(app).listen(9000).on('listening', function () {
    console.log('Serving distribution at http://localhost:9000');
  });
});

// inject bower components
gulp.task('wiredep', function () {
  var wiredep = require('wiredep').stream;

  gulp.src('app/*.html')
    .pipe(wiredep())
    .pipe(gulp.dest('app'));
});

gulp.task('watch', ['connect'], function () {
  $.livereload.listen();

  // watch for changes
  gulp.watch([
    'app/*.html',
    '.tmp/styles/**/*.css',
    '.tmp/js/**/*.js',
    'app/images/**/*'
  ]).on('change', $.livereload.changed);

  gulp.watch('app/styles/**/*.css', ['styles']);
  gulp.watch('app/scripts/**/*.js', ['javascript']);
  gulp.watch('bower.json', ['wiredep']);
});

gulp.task('test', function () {
  var jasmine = require("gulp-jasmine");
  gulp.src('specs/**.js')
    .pipe(jasmine());
});

gulp.task('test-watch', function () {
    gulp.watch([
      'specs/**.js',
      'app/scripts/**.js'
    ], ['test']);
});

gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () {
  gulp.src([
      'bower_components/ace-builds/src-min-noconflict/theme-tomorrow_night_eighties.js',
      'bower_components/ace-builds/src-min-noconflict/worker-json.js',
      'bower_components/ace-builds/src-min-noconflict/mode-json.js'
    ])
    .pipe($.size({title: 'copy ace js'}))
    .pipe(gulp.dest('dist/js/ace/'));
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('default', ['clean'], function () {
  gulp.start('build');
});
<commit_msg>Only put a small set of images in the dist<commit_after>/* jshint node:true */
'use strict';

var gulp = require('gulp');
var browserify = require('browserify');
var transform = require('vinyl-transform');
var $ = require('gulp-load-plugins')();

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

gulp.task('styles', function () {
  return gulp.src(['app/styles/main.css'])
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp/styles'));
});

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.jshint.reporter('fail'));
});

gulp.task('javascript', function () {
  // transform regular node stream to gulp (buffered vinyl) stream
  var browserified = transform(function(filename) {
    var b = browserify({entries: filename, debug: true});
    return b.bundle();
  });

  return gulp.src('app/scripts/edit.js')
    .pipe(browserified)
    .pipe($.sourcemaps.init({loadMaps: true}))
        // Add transformation tasks to the pipeline here.
       .pipe($.uglify())
    .pipe($.sourcemaps.write('./'))
    .pipe(gulp.dest('.tmp/js'));
});

gulp.task('html', ['styles', 'javascript'], function () {
  var assets = $.useref.assets({searchPath: ['.tmp','app','.']});
  //var assets = $.useref.assets();

  return gulp.src('app/*.html')
    .pipe(assets)
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    //.pipe($.if('*.html', $.minifyHtml({conditionals: true, loose: true})))
    .pipe(gulp.dest('dist'));
});

//Optimize images
gulp.task('images', function () {
  return gulp.src([
      'app/images/**/aws*.png',
      'app/images/**/unknown.png'
    ])
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images')).pipe($.size({title: 'images'}));
});

gulp.task('fonts', function () {
  return gulp.src(require('main-bower-files')().concat('app/fonts/**/*'))
    .pipe($.filter('**/*.{eot,svg,ttf,woff}'))
    .pipe($.flatten())
    .pipe(gulp.dest('dist/fonts'));
});

gulp.task('extras', function () {
  return gulp.src([
    'app/*.*',
    '!app/*.html',
    '!app/**/*~',
    '!app/**/*swp',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

gulp.task('clean', require('del').bind(null, ['.tmp', 'dist']));

gulp.task('connect', function () {
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var app = require('connect')()
    .use(require('connect-livereload')({port: 35729}))
    .use(serveStatic('.tmp'))
    .use(serveStatic('app'))
    .use(serveStatic('dist'))
    // paths to bower_components should be relative to the current file
    // e.g. in app/index.html you should use ../bower_components
    .use('/bower_components', serveStatic('bower_components'))
    .use(serveIndex('app'));

  require('http').createServer(app)
    .listen(9000)
    .on('listening', function () {
      console.log('Started connect web server on http://localhost:9000');
    });
});

gulp.task('serve', ['connect', 'watch'], function () {
  require('opn')('http://localhost:9000');
});

// serve from build to ensure everything is there
gulp.task('serve-build', ['clean'], function () {
  gulp.start('build');
  var serveStatic = require('serve-static');
  var serveIndex = require('serve-index');
  var app = require('connect')().use(serveStatic('dist')).use(serveIndex('dist'));
  require('http').createServer(app).listen(9000).on('listening', function () {
    console.log('Serving distribution at http://localhost:9000');
  });
});

// inject bower components
gulp.task('wiredep', function () {
  var wiredep = require('wiredep').stream;

  gulp.src('app/*.html')
    .pipe(wiredep())
    .pipe(gulp.dest('app'));
});

gulp.task('watch', ['connect'], function () {
  $.livereload.listen();

  // watch for changes
  gulp.watch([
    'app/*.html',
    '.tmp/styles/**/*.css',
    '.tmp/js/**/*.js',
    'app/images/**/*'
  ]).on('change', $.livereload.changed);

  gulp.watch('app/styles/**/*.css', ['styles']);
  gulp.watch('app/scripts/**/*.js', ['javascript']);
  gulp.watch('bower.json', ['wiredep']);
});

gulp.task('test', function () {
  var jasmine = require("gulp-jasmine");
  gulp.src('specs/**.js')
    .pipe(jasmine());
});

gulp.task('test-watch', function () {
    gulp.watch([
      'specs/**.js',
      'app/scripts/**.js'
    ], ['test']);
});

gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () {
  gulp.src([
      'bower_components/ace-builds/src-min-noconflict/theme-tomorrow_night_eighties.js',
      'bower_components/ace-builds/src-min-noconflict/worker-json.js',
      'bower_components/ace-builds/src-min-noconflict/mode-json.js'
    ])
    .pipe($.size({title: 'copy ace js'}))
    .pipe(gulp.dest('dist/js/ace/'));
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('default', ['clean'], function () {
  gulp.start('build');
});
<|endoftext|>


<commit_before>import './bootstrap-datepicker.js'

!function (a) {
    a.fn.datepicker.dates.de = {
        days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
        daysShort: ["Nie", "Pon", "Wto", "Śro", "Czw", "Pią", "Sob"],
        daysMin: ["Nd", "Pn", "Wt", "Śr", "Cz", "Pt", "Sb"],
        months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
        monthsShort: ["Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"],
        today: "Dziś",
        monthsTitle: "Miesiące",
        clear: "Wyczyść",
        weekStart: 1,
        format: "dd.mm.yyyy"
    }
}(jQuery)<commit_msg>fix polnish translation bug #170<commit_after>import './bootstrap-datepicker.js'

!function (a) {
    a.fn.datepicker.dates.pl = {
        days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"],
        daysShort: ["Nie", "Pon", "Wto", "Śro", "Czw", "Pią", "Sob"],
        daysMin: ["Nd", "Pn", "Wt", "Śr", "Cz", "Pt", "Sb"],
        months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"],
        monthsShort: ["Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"],
        today: "Dziś",
        monthsTitle: "Miesiące",
        clear: "Wyczyść",
        weekStart: 1,
        format: "dd.mm.yyyy"
    }
}(jQuery)
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var version = process.env.VERSION || require('../../package.json').version;
var content = { '1.0.9': '1.0', '1.1.6': '1.1', '1.2.9': '1.2' };
if (!content[version]) content[version] = '1.3';
fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content));
<commit_msg>update version.js<commit_after>var fs = require('fs');
var path = require('path');
var version = process.env.VERSION || require('../../package.json').version;
var content = { '1.0.9': '1.0', '1.1.6': '1.1', '1.2.9': '1.2', '1.3.7': '1.3' };
if (!content[version]) content[version] = '1.4';
fs.writeFileSync(path.resolve(__dirname, '../../examples/versions.json'), JSON.stringify(content));
<|endoftext|>


<commit_before>'use strict';

var Q = require('q');
var gulpUtil = require('gulp-util');
var childProcess = require('child_process');
var jetpack = require('fs-jetpack');
var utils = require('./utils');

var projectDir;
var tmpDir;
var releasesDir;
var readyAppDir;
var codeDir;
var manifest;

var init = function () {
    projectDir = jetpack;
    tmpDir = projectDir.dir('./tmp', { empty: true });
    releasesDir = projectDir.dir('./releases');
    manifest = projectDir.read('app/package.json', 'json');
    readyAppDir = tmpDir.cwd(manifest.name);
    codeDir = readyAppDir.cwd('resources/app');

    return Q();
};

var copyRuntime = function () {
    return projectDir.copyAsync('node_modules/electron-prebuilt/dist', readyAppDir.path(), { overwrite: true });
};

var copyBuiltApp = function () {
    return projectDir.copyAsync('build', codeDir.path(), { overwrite: true });
};

var finalize = function () {
    var deferred = Q.defer();

    var rcedit = require('rcedit');
    rcedit(readyAppDir.path('electron.exe'), {
        icon: projectDir.path('resources/windows/icon.ico')
    }, function (err) {
        if (!err) {
            deferred.resolve();
        }
    });

    return deferred.promise;
};

var createInstaller = function () {
    var deferred = Q.defer();

    var finalPackageName = manifest.name + '_' + manifest.version + '.exe';
    var installScript = projectDir.read('resources/windows/installer.nsi');
    installScript = utils.replace(installScript, {
        name: manifest.name,
        productName: manifest.productName,
        version: manifest.version,
        src: readyAppDir.path(),
        dest: releasesDir.path(finalPackageName),
        icon: readyAppDir.path('icon.ico'),
        setupIcon: projectDir.path('resources/windows/setup-icon.ico'),
        banner: projectDir.path('resources/windows/setup-banner.bmp'),
    });
    tmpDir.write('installer.nsi', installScript);

    gulpUtil.log('Building installer with NSIS...');

    // Remove destination file if already exists.
    releasesDir.remove(finalPackageName);

    // Note: NSIS have to be added to PATH (environment variables).
    var nsis = childProcess.spawn('makensis', [tmpDir.path('installer.nsi')]);
    nsis.stdout.pipe(process.stdout);
    nsis.stderr.pipe(process.stderr);
    nsis.on('close', function () {
        gulpUtil.log('Installer ready!', releasesDir.path(finalPackageName));
        deferred.resolve();
    });

    return deferred.promise;
};

var cleanClutter = function () {
    return tmpDir.removeAsync('.');
};

module.exports = function () {
    return init()
    .then(copyRuntime)
    .then(copyBuiltApp)
    .then(finalize)
    .then(createInstaller)
    .then(cleanClutter);
};
<commit_msg>Still must copy icon<commit_after>'use strict';

var Q = require('q');
var gulpUtil = require('gulp-util');
var childProcess = require('child_process');
var jetpack = require('fs-jetpack');
var utils = require('./utils');

var projectDir;
var tmpDir;
var releasesDir;
var readyAppDir;
var codeDir;
var manifest;

var init = function () {
    projectDir = jetpack;
    tmpDir = projectDir.dir('./tmp', { empty: true });
    releasesDir = projectDir.dir('./releases');
    manifest = projectDir.read('app/package.json', 'json');
    readyAppDir = tmpDir.cwd(manifest.name);
    codeDir = readyAppDir.cwd('resources/app');

    return Q();
};

var copyRuntime = function () {
    return projectDir.copyAsync('node_modules/electron-prebuilt/dist', readyAppDir.path(), { overwrite: true });
};

var copyBuiltApp = function () {
    return projectDir.copyAsync('build', codeDir.path(), { overwrite: true });
};

var finalize = function () {
    var deferred = Q.defer();

    return projectDir.copy('resources/windows/icon.ico', readyAppDir.path('icon.ico'));

    // Replace Electron icon for your own.
    var rcedit = require('rcedit');
    rcedit(readyAppDir.path('electron.exe'), {
        icon: projectDir.path('resources/windows/icon.ico')
    }, function (err) {
        if (!err) {
            deferred.resolve();
        }
    });

    return deferred.promise;
};

var createInstaller = function () {
    var deferred = Q.defer();

    var finalPackageName = manifest.name + '_' + manifest.version + '.exe';
    var installScript = projectDir.read('resources/windows/installer.nsi');
    installScript = utils.replace(installScript, {
        name: manifest.name,
        productName: manifest.productName,
        version: manifest.version,
        src: readyAppDir.path(),
        dest: releasesDir.path(finalPackageName),
        icon: readyAppDir.path('icon.ico'),
        setupIcon: projectDir.path('resources/windows/setup-icon.ico'),
        banner: projectDir.path('resources/windows/setup-banner.bmp'),
    });
    tmpDir.write('installer.nsi', installScript);

    gulpUtil.log('Building installer with NSIS...');

    // Remove destination file if already exists.
    releasesDir.remove(finalPackageName);

    // Note: NSIS have to be added to PATH (environment variables).
    var nsis = childProcess.spawn('makensis', [tmpDir.path('installer.nsi')]);
    nsis.stdout.pipe(process.stdout);
    nsis.stderr.pipe(process.stderr);
    nsis.on('close', function () {
        gulpUtil.log('Installer ready!', releasesDir.path(finalPackageName));
        deferred.resolve();
    });

    return deferred.promise;
};

var cleanClutter = function () {
    return tmpDir.removeAsync('.');
};

module.exports = function () {
    return init()
    .then(copyRuntime)
    .then(copyBuiltApp)
    .then(finalize)
    .then(createInstaller)
    .then(cleanClutter);
};
<|endoftext|>


<commit_before>import * as props from './props.js';
import Symbol from './Symbol.js';

const deltaXSymbol = Symbol('deltaX');
const deltaYSymbol = Symbol('deltaY');
const multiTouchSymbol = Symbol('multiTouch');
const previousXSymbol = Symbol('previousX');
const previousYSymbol = Symbol('previousY');
const startXSymbol = Symbol('startX');

export default function TouchSwipeMixin(Base) {
  return class TouchSwipe extends Base {

    constructor() {
      super();

      // In all touch events, only handle single touches. We don't want to
      // inadvertently do work when the user's trying to pinch-zoom for example.
      // TODO: Even better approach than below would be to ignore touches after
      // the first if the user has already begun a swipe.
      // TODO: Touch events should probably be factored out into its own mixin.
      if (window.PointerEvent) {
        // Prefer listening to standard pointer events.
        this.addEventListener('pointerdown', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            gestureStart(this, event.clientX, event.clientY);
          }
        });
        this.addEventListener('pointermove', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            const handled = gestureContinue(this, event.clientX, event.clientY);
            if (handled) {
              event.preventDefault();
            }
          }
        });
        this.addEventListener('pointerup', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            gestureEnd(this, event.clientX, event.clientY);
          }
        });
      } else {
        // Pointer events not supported -- listen to older touch events.
        this.addEventListener('touchstart', event => {
          if (this[multiTouchSymbol]) {
            return;
          } else if (event.touches.length === 1) {
            const clientX = event.changedTouches[0].clientX;
            const clientY = event.changedTouches[0].clientY;
            gestureStart(this, clientX, clientY);
          } else {
            this[multiTouchSymbol] = true;
          }
        });
        this.addEventListener('touchmove', event => {
          if (!this[multiTouchSymbol] && event.touches.length === 1) {
            const clientX = event.changedTouches[0].clientX;
            const clientY = event.changedTouches[0].clientY;
            const handled = gestureContinue(this, clientX, clientY);
            if (handled) {
              event.preventDefault();
            }
          }
        });
        this.addEventListener('touchend', event => {
          if (event.touches.length === 0) {
            // All touches removed; gesture is complete.
            if (!this[multiTouchSymbol]) {
              // Single-touch swipe has finished.
              const clientX = event.changedTouches[0].clientX;
              const clientY = event.changedTouches[0].clientY;
              gestureEnd(this, clientX, clientY);
            }
            this[multiTouchSymbol] = false;
          }
        });
      }
    }

    get defaultState() {
      return Object.assign({}, super.defaultState, {
        swipeFraction: null,
        touchAction: 'none'
      });
    }

    get props() {
      return props.merge(super.props, {
        style: {
          'touch-action': this.state.touchAction
        }
      })
    }

    get swipeTarget() {
      return super.swipeTarget || this;
    }

    updateSwipeFraction(swipeFraction) {
      // TODO: Rationalize or clean this out.
      // const changed = this.state.swipeFraction !== swipeFraction;
      // if (changed) {
      //   if (this.props.onSwipeFractionChanged) {
      //     this.props.onSwipeFractionChanged(swipeFraction);
      //   } else {
          this.setState({ swipeFraction });
      //   }
      // }
      // return changed;
    }

  }
}

// Return true if the pointer event is for the pen, or the primary touch point.
function isEventForPenOrPrimaryTouch(event) {
  return event.pointerType === 'pen' ||
    (event.pointerType === 'touch' && event.isPrimary);
}

/*
 * Invoked when the user has moved during a touch operation.
 */
function gestureContinue(element, clientX, clientY) {
  element[deltaXSymbol] = clientX - element[previousXSymbol];
  element[deltaYSymbol] = clientY - element[previousYSymbol];
  element[previousXSymbol] = clientX;
  element[previousYSymbol] = clientY;
  if (Math.abs(element[deltaXSymbol]) > Math.abs(element[deltaYSymbol])) {
    // Move was mostly horizontal.
    const swipeFraction = getSwipeFraction(element, clientX);
    element.updateSwipeFraction(swipeFraction);
    // Indicate that the event was handled. It'd be nicer if we didn't have
    // to do this so that, e.g., a user could be swiping left and right
    // while simultaneously scrolling up and down. (Native touch apps can do
    // that.) However, Mobile Safari wants to handle swipe events near the
    // page and interpret them as navigations. To avoid having a horiziontal
    // swipe misintepreted as a navigation, we indicate that we've handled
    // the event, and prevent default behavior.
    return true;
  } else {
    // Move was mostly vertical.
    return false; // Not handled
  }
}

/*
 * Invoked when the user has finished a touch operation.
 */
/* eslint-disable no-unused-vars */
function gestureEnd(component, clientX, clientY) {

  let gesture;
  // TODO: Make flick gesture use timing instead of just distance so that it
  // works better on Android.
  if (component[deltaXSymbol] >= 20) {
    // Finished going right at high speed.
    gesture = 'swipeRight';
  } else if (component[deltaXSymbol] <= -20) {
    // Finished going left at high speed.
    gesture = 'swipeLeft';
  } else {
    // Finished at low speed.
    const swipeFraction = getSwipeFraction(component, clientX);
    if (swipeFraction <= -0.5) {
      gesture = 'swipeLeft';
    } else if (swipeFraction >= 0.5) {
      gesture = 'swipeRight';
    }
  }

  component[deltaXSymbol] = null;
  component[deltaYSymbol] = null;

  // If component has method for indicated gesture, invoke it.
  if (gesture && component[gesture]) {
    component[gesture]();
  }

  component.updateSwipeFraction(null);
}

/*
 * Invoked when the user has begun a touch operation.
 */
function gestureStart(element, clientX, clientY) {
  element[startXSymbol] = clientX;
  element[previousXSymbol] = clientX;
  element[previousYSymbol] = clientY;
  element[deltaXSymbol] = 0;
  element[deltaYSymbol] = 0;
  element.updateSwipeFraction(0);
}

function getSwipeFraction(element, x) {
  const dragDistance = x - element[startXSymbol];
  const width = element.swipeTarget.offsetWidth;
  const fraction = width > 0 ?
    dragDistance / width :
    0;
  return fraction;
}
<commit_msg>Use speed (not distance) of last touch movement to determine flick gesture, for better interaction on Chrome Android.<commit_after>import * as props from './props.js';
import Symbol from './Symbol.js';

const multiTouchKey = Symbol('multiTouch');
const previousTimeKey = Symbol('previousTime');
const previousVelocityKey = Symbol('previousVelocity');
const previousXKey = Symbol('previousX');
const previousYKey = Symbol('previousY');
const startXKey = Symbol('startX');

export default function TouchSwipeMixin(Base) {
  return class TouchSwipe extends Base {

    constructor() {
      super();

      // In all touch events, only handle single touches. We don't want to
      // inadvertently do work when the user's trying to pinch-zoom for example.
      // TODO: Even better approach than below would be to ignore touches after
      // the first if the user has already begun a swipe.
      // TODO: Touch events should probably be factored out into its own mixin.
      if (window.PointerEvent) {
        // Prefer listening to standard pointer events.
        this.addEventListener('pointerdown', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            gestureStart(this, event.clientX, event.clientY);
          }
        });
        this.addEventListener('pointermove', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            const handled = gestureContinue(this, event.clientX, event.clientY);
            if (handled) {
              event.preventDefault();
            }
          }
        });
        this.addEventListener('pointerup', event => {
          if (isEventForPenOrPrimaryTouch(event)) {
            gestureEnd(this, event.clientX, event.clientY);
          }
        });
      } else {
        // Pointer events not supported -- listen to older touch events.
        this.addEventListener('touchstart', event => {
          if (this[multiTouchKey]) {
            return;
          } else if (event.touches.length === 1) {
            const clientX = event.changedTouches[0].clientX;
            const clientY = event.changedTouches[0].clientY;
            gestureStart(this, clientX, clientY);
          } else {
            this[multiTouchKey] = true;
          }
        });
        this.addEventListener('touchmove', event => {
          if (!this[multiTouchKey] && event.touches.length === 1) {
            const clientX = event.changedTouches[0].clientX;
            const clientY = event.changedTouches[0].clientY;
            const handled = gestureContinue(this, clientX, clientY);
            if (handled) {
              event.preventDefault();
            }
          }
        });
        this.addEventListener('touchend', event => {
          if (event.touches.length === 0) {
            // All touches removed; gesture is complete.
            if (!this[multiTouchKey]) {
              // Single-touch swipe has finished.
              const clientX = event.changedTouches[0].clientX;
              const clientY = event.changedTouches[0].clientY;
              gestureEnd(this, clientX, clientY);
            }
            this[multiTouchKey] = false;
          }
        });
      }
    }

    get defaultState() {
      return Object.assign({}, super.defaultState, {
        swipeFraction: null,
        touchAction: 'none'
      });
    }

    get props() {
      return props.merge(super.props, {
        style: {
          'touch-action': this.state.touchAction
        }
      })
    }

    get swipeTarget() {
      return super.swipeTarget || this;
    }

    updateSwipeFraction(swipeFraction) {
      // TODO: Rationalize or clean this out.
      // const changed = this.state.swipeFraction !== swipeFraction;
      // if (changed) {
      //   if (this.props.onSwipeFractionChanged) {
      //     this.props.onSwipeFractionChanged(swipeFraction);
      //   } else {
          this.setState({ swipeFraction });
      //   }
      // }
      // return changed;
    }

  }
}

// Return true if the pointer event is for the pen, or the primary touch point.
function isEventForPenOrPrimaryTouch(event) {
  return event.pointerType === 'pen' ||
    (event.pointerType === 'touch' && event.isPrimary);
}

/*
 * Invoked when the user has moved during a touch operation.
 */
function gestureContinue(component, clientX, clientY) {

  // Calculate and save the velocity since the last event. If this is the last
  // movement of the gesture, this velocity will be used to determine whether
  // the user is trying to flick.
  const deltaX = clientX - component[previousXKey];
  const deltaY = clientY - component[previousYKey];
  const now = Date.now();
  const deltaTime = now - component[previousTimeKey];
  const velocity = deltaX / deltaTime * 1000;

  component[previousXKey] = clientX;
  component[previousYKey] = clientY;
  component[previousTimeKey] = now;
  component[previousVelocityKey] = velocity;

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    // Move was mostly horizontal.
    const swipeFraction = getSwipeFraction(component, clientX);
    component.updateSwipeFraction(swipeFraction);
    // Indicate that the event was handled. It'd be nicer if we didn't have
    // to do this so that, e.g., a user could be swiping left and right
    // while simultaneously scrolling up and down. (Native touch apps can do
    // that.) However, Mobile Safari wants to handle swipe events near the
    // page and interpret them as navigations. To avoid having a horiziontal
    // swipe misintepreted as a navigation, we indicate that we've handled
    // the event, and prevent default behavior.
    return true;
  } else {
    // Move was mostly vertical.
    return false; // Not handled
  }
}

/*
 * Invoked when the user has finished a touch operation.
 */
/* eslint-disable no-unused-vars */
function gestureEnd(component, clientX, clientY) {

  let gesture;
  // Examine velocity of last movement to see if user is flicking.
  const velocity = component[previousVelocityKey];
  const flickThresholdVelocity = 800; // speed in pixels/second
  if (velocity >= flickThresholdVelocity) {
    // Flicked right at high speed.
    gesture = 'swipeRight';
  } else if (velocity <= -flickThresholdVelocity) {
    // Flicked left at high speed.
    gesture = 'swipeLeft';
  } else {
    // Finished at low speed.
    const swipeFraction = getSwipeFraction(component, clientX);
    if (swipeFraction <= -0.5) {
      gesture = 'swipeLeft';
    } else if (swipeFraction >= 0.5) {
      gesture = 'swipeRight';
    }
  }

  // If component has method for indicated gesture, invoke it.
  if (gesture && component[gesture]) {
    component[gesture]();
  }

  component.updateSwipeFraction(null);
}

/*
 * Invoked when the user has begun a touch operation.
 */
function gestureStart(component, clientX, clientY) {
  component[startXKey] = clientX;
  component[previousXKey] = clientX;
  component[previousYKey] = clientY;
  component[previousTimeKey] = Date.now();
  component[previousVelocityKey] = 0;
  component.updateSwipeFraction(0);
}

function getSwipeFraction(component, x) {
  const dragDistance = x - component[startXKey];
  const width = component.swipeTarget.offsetWidth;
  const fraction = width > 0 ?
    dragDistance / width :
    0;
  return fraction;
}
<|endoftext|>