<commit_before>var project = require('../package.json');
var settings = require("./settings");

module.exports = {
  help: function () {
    console.log("Usage: magellan [options]");
    console.log("");
    console.log("By default, magellan will run all available tests in parallel with phantomjs.");
    console.log("");
    console.log(" Parallelism, Workflow and Filtering:");
    console.log("  --serial                     Run tests one at a time with detailed output.");
    console.log("  --max_workers=N              Set maximum number of parallel works to (see defaults below).");
    console.log("  --max_test_attempts=N        Retry tests N times (default: 3).");
    console.log("  --bail_early                 Kill builds that have failed at least 10% of tests, after 10 or more test runs.");
    console.log("  --bail_fast                  Kill builds that fail any test.");
    console.log("  --bail_time                  Set test kill time in milliseconds. *CAN* be used without bail_early/bail_fast.")
    console.log("  --debug                      Enable debugging magellan messages (dev mode).");
    console.log("");
    console.log(" Configuration:");
    console.log("  --config=config-path         Specify Magellan configuration location.");
    console.log("  --temp_dir=path              Specify temporary file directory for Magellan (default: temp/).");
    console.log("");
    console.log(" Reporting and CI Integration:");
    console.log("  --aggregate_screenshots      Activate harvesting of screenshots for uploading to a screenshot service.");
    console.log("  --screenshot_aggregator_url  Specify the URL to the screenshot service endpoint.");
    console.log("  --external_build_id          Use an external build id, i.e. from CI. Must be filename and URL-safe.");
    console.log("");
    console.log(" Browser and SauceLabs Support:");
    console.log("  --sauce                      Run tests on SauceLabs cloud.");
    console.log("  --list_browsers              List the available browsers configured.");
    console.log("  --browser=browsername        Run tests in chrome, firefox, etc (default: phantomjs).");
    console.log("  --browsers=b1,b2,..          Run multiple browsers in parallel.");
    console.log("  --browsers=all               Run all available browsers (sauce only).");
    console.log("  --create_tunnels             Create secure tunnels in sauce mode (for use with --sauce only)");
    console.log("  --profile=p1,p2,..           Specify lists of browsers to use defined in profiles in magellan.json config.")
    console.log("  --profile=http://abc/p#p1,p2 Use profiles p1 and p2 hosted at JSON file http://abc/p (see README for details).")

    var help;

    if (settings.testFramework && settings.testFramework.help) {
      help = settings.testFramework.help;
    }

    if (help) {
      console.log("");
      console.log(" Framework-specific (" + settings.framework + "):");
      var maxWidth = 31;

      Object.keys(help).forEach(function (key) {
        var str = "  --" + key;
        var example = "=" + help[key].example || "";
        // pad
        while (str.length < maxWidth) {
          str += " ";
        }
        // truncate just in case the example was too long to begin with
        str = str.substr(0, maxWidth);
        str += help[key].description;
        console.log(str);
      });
    }

    console.log("");
    console.log("  +------------------------------------------+-----------+-------------------+");
    console.log("  | Workflow / Output Examples               | # workers | output style      |");
    console.log("  +------------------------------------------+-----------+-------------------+");
    console.log("  |--browser=phantomjs                       | 8         | summary, failures |");
    console.log("  |--browser=<not phantom> --sauce           | 3         | summary, failures |");
    console.log("  |--browser=<not phantom>                   | 3         | summary, failures |");
    console.log("  |--sauce --browser=<xxxx> --serial         | 1         | detail, all tests |");
    console.log("  |--sauce --browser=<not phantom> --serial  | 1         | detail, all tests |");
    console.log("  |--browser=<any> --serial                  | 1         | detail, all tests |");
    console.log("  +------------------------------------------+-----------+-------------------+");

    console.log("");
    console.log("magellan v" + project.version);
  }
};
<commit_msg>fix example values in CLI help<commit_after>var project = require('../package.json');
var settings = require("./settings");

module.exports = {
  help: function () {
    console.log("Usage: magellan [options]");
    console.log("");
    console.log("By default, magellan will run all available tests in parallel with phantomjs.");
    console.log("");
    console.log(" Parallelism, Workflow and Filtering:");
    console.log("  --serial                     Run tests one at a time with detailed output.");
    console.log("  --max_workers=N              Set maximum number of parallel works to (see defaults below).");
    console.log("  --max_test_attempts=N        Retry tests N times (default: 3).");
    console.log("  --bail_early                 Kill builds that have failed at least 10% of tests, after 10 or more test runs.");
    console.log("  --bail_fast                  Kill builds that fail any test.");
    console.log("  --bail_time                  Set test kill time in milliseconds. *CAN* be used without bail_early/bail_fast.")
    console.log("  --debug                      Enable debugging magellan messages (dev mode).");
    console.log("");
    console.log(" Configuration:");
    console.log("  --config=config-path         Specify Magellan configuration location.");
    console.log("  --temp_dir=path              Specify temporary file directory for Magellan (default: temp/).");
    console.log("");
    console.log(" Reporting and CI Integration:");
    console.log("  --aggregate_screenshots      Activate harvesting of screenshots for uploading to a screenshot service.");
    console.log("  --screenshot_aggregator_url  Specify the URL to the screenshot service endpoint.");
    console.log("  --external_build_id          Use an external build id, i.e. from CI. Must be filename and URL-safe.");
    console.log("");
    console.log(" Browser and SauceLabs Support:");
    console.log("  --sauce                      Run tests on SauceLabs cloud.");
    console.log("  --list_browsers              List the available browsers configured.");
    console.log("  --browser=browsername        Run tests in chrome, firefox, etc (default: phantomjs).");
    console.log("  --browsers=b1,b2,..          Run multiple browsers in parallel.");
    console.log("  --browsers=all               Run all available browsers (sauce only).");
    console.log("  --create_tunnels             Create secure tunnels in sauce mode (for use with --sauce only)");
    console.log("  --profile=p1,p2,..           Specify lists of browsers to use defined in profiles in magellan.json config.")
    console.log("  --profile=http://abc/p#p1,p2 Use profiles p1 and p2 hosted at JSON file http://abc/p (see README for details).")

    var help;

    if (settings.testFramework && settings.testFramework.help) {
      help = settings.testFramework.help;
    }

    if (help) {
      console.log("");
      console.log(" Framework-specific (" + settings.framework + "):");
      var maxWidth = 31;

      Object.keys(help).forEach(function (key) {
        var str = "  --" + key;
        if (help[key].example) {
          str += "=" + help[key].example;
        }
        // pad
        while (str.length < maxWidth) {
          str += " ";
        }
        // truncate just in case the example was too long to begin with
        str = str.substr(0, maxWidth);
        str += help[key].description;
        console.log(str);
      });
    }

    console.log("");
    console.log("  +------------------------------------------+-----------+-------------------+");
    console.log("  | Workflow / Output Examples               | # workers | output style      |");
    console.log("  +------------------------------------------+-----------+-------------------+");
    console.log("  |--browser=phantomjs                       | 8         | summary, failures |");
    console.log("  |--browser=<not phantom> --sauce           | 3         | summary, failures |");
    console.log("  |--browser=<not phantom>                   | 3         | summary, failures |");
    console.log("  |--sauce --browser=<xxxx> --serial         | 1         | detail, all tests |");
    console.log("  |--sauce --browser=<not phantom> --serial  | 1         | detail, all tests |");
    console.log("  |--browser=<any> --serial                  | 1         | detail, all tests |");
    console.log("  +------------------------------------------+-----------+-------------------+");

    console.log("");
    console.log("magellan v" + project.version);
  }
};
<|endoftext|>


<commit_before>var Queue = require('bull');
var Job = require('./node_modules/bull/lib/job');
var Promise = require('bluebird');

/**
  Adds a job to the queue.
  @method add
  @param data: {} Custom data to store for this job. Should be JSON serializable.
  @param opts: JobOptions Options for this job.
*/
Queue.prototype.add = function(data, opts) {
    var _this = this;
    opts = opts || {};

    // If we fail after incrementing the job id we may end having an unused
    // id, but this should not be so harmful
    return _this.client.incrAsync(this.toKey('id')).then(function(jobId) {
        return Job.create(_this, jobId, data, opts).then(function(job) {
            var key = _this.toKey('wait');
            var channel = _this.toKey("jobs");
            var multi = _this.client.multi();
            multi[(opts.lifo ? 'r' : 'l') + 'push'](key, jobId);
            multi.publish(channel, jobId);
            // if queue is LIFO use rpushAsync
            return multi.execAsync().then(function() {
                return job;
            });
        });
    });
};

var messageQueue = new Queue("test-control-messages", 6379, "localhost");

messageQueue.process(function(job, cb) {
    var q = new Queue(job.data.queueName, 6379, "localhost");
    var times = parseInt(job.data.times);
    console.log("adding " + times + " job to queue " + job.data.queuName);
    var promisses = [];
    for (var i = 0; i < times; i++) {
        promisses.push(q.add({ value: "test" }));
    }
    Promise.all(promisses).then(function () {
        q.count().then(function (c) {
            console.log("q length: " + c);
            cb();
        });
    });
});

console.log("test-control-message-queue started");<commit_msg>clean up<commit_after>var Queue = require('bull');
var Job = require('./node_modules/bull/lib/job');
var Promise = require('bluebird');

/**
  Adds a job to the queue.
  @method add
  @param data: {} Custom data to store for this job. Should be JSON serializable.
  @param opts: JobOptions Options for this job.
*/
Queue.prototype.add = function(data, opts) {
    var _this = this;
    opts = opts || {};

    // If we fail after incrementing the job id we may end having an unused
    // id, but this should not be so harmful
    return _this.client.incrAsync(this.toKey('id')).then(function(jobId) {
        return Job.create(_this, jobId, data, opts).then(function(job) {
            var key = _this.toKey('wait');
            var channel = _this.toKey("jobs");
            process.stdout.write(".");
            var multi = _this.client.multi();
            multi[(opts.lifo ? 'r' : 'l') + 'push'](key, jobId);
            multi.publish(channel, jobId);
            // if queue is LIFO use rpushAsync
            return multi.execAsync().then(function() {
                return job;
            });
        });
    });
};

var messageQueue = new Queue("test-control-messages", 6379, "localhost");

messageQueue.process(function(job, cb) {
    var q = new Queue(job.data.queueName, 6379, "localhost");
    var times = parseInt(job.data.times);
    console.log("adding " + times + " job to queue " + job.data.queueName);
    var promisses = [];
    for (var i = 0; i < times; i++) {
        promisses.push(q.add({ value: "test" }));
    }
    Promise.all(promisses).then(function () {
        q.count().then(function (c) {
            console.log("q length: " + c);
            cb();
        });
    });
});

console.log("test-control-message-queue started");<|endoftext|>


<commit_before>/*
MagJS v0.20
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  'use strict';

  var hookins = {
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = [].concat(id2)[0]
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id)
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    setTimeout(function() {

      mag.redraw(node, idInstance, 1);

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);
    })

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, props)
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  mag.redraw = function(node, idInstance, force) {
    if (!node || typeof idInstance == 'undefined') {
      throw Error('Mag.JS - Id or node invalid: ' + node, idInstance);
    }

    // verify idInstance
    if (!isValidId(node.id, idInstance)) {
      return
    }

    // clear existing configs ?
    // TODO: per idInstance / id ?
    mag.fill.configs.splice(0, mag.fill.configs.length)

    if (force) mag.mod.clear(idInstance)

    var fun = makeRedrawFun(node, idInstance, force)

    // check for existing frame id then clear it if exists
    fastdom.clear(mag.mod.getFrameId(idInstance))
      //ENQUEUE
    var fid = fastdom.write(fun);
    //save frame id with the instance
    mag.mod.setFrameId(idInstance, fid)
      // then if instance already has frame id create new discard old or just retain old
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }

  var makeClone = function(idInstance, node, mod, props) {
    var a = function(id, node, mod, props, index) {

      var cloner = node.cloneNode(1)
      cloner.id = node.id + (props.key ? '.' + props.key : '') + '.' + index;

      // if clone already exists return ?
      if (mag.utils.items.isItem(cloner.id)) {
        // return
      }

      var idInstance2 = mag.utils.getItemInstanceId(cloner.id)

      // get unqiue instance ID's module
      mag.mod.submodule(cloner.id, idInstance2, mod, props)

      observer(idInstance2, cloner.id)

      // DRAW
      mag.redraw(cloner, idInstance2, 1)
      return cloner
    }.bind({}, idInstance, node, mod, props)

    //BOUND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return idInstance
    }.bind({}, idInstance)
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids) {
      return [].concat(mag.mod.getState(ids))[0]
    }.bind({}, idInstance)

    // a.toJSON = function(ids) {}.bind({}, idInstance)

    return a
  }
  var nodeCache = []

  function getNode(id) {
    //cache nodes?
    if (nodeCache[id]) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {
      // throw Error('invalid node id: ' + id);
    }
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id, change) {
      if (getNode(id)) {
        mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(nodeId)) {
        fastdom.clear(mag.mod.getFrameId(index))
          // remove from indexes
        mag.utils.items.removeItem(index)
          //mag.mod.remove(index)
        mag.mod.clear(index)
          //observer index
        mag.props.cached.splice(index, 1)
          //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.props.setup(idInstance, mag.debounce(callback))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      var props = mag.mod.getProps(idInstance)

      var data = mag.utils.merge(mag.utils.copy(state), mag.utils.copy(props))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      var display = node.style.display || ''
      node.style.display = 'none'
      var node = mag.fill.run(node, state)
      node.style.display = display
        // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node)

    }.bind({}, node1, idInstance1, force1)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  window.mag = mag

})(window.mag || {}, document);
<commit_msg>Update mag.js<commit_after>/*
MagJS v0.20
http://github.com/magnumjs/mag.js
(c) Michael Glazer
License: MIT
*/
(function(mag, document, undefined) {

  'use strict';

  var hookins = {
    attributes: [],
    elementMatcher: []
  }

  mag.create = function(id, module, props) {
    return function(id2, props2) {
      if (typeof id2 !== 'string') {
        props2 = [].concat(id2)[0]
        id2 = 0
      }
      return mag.module(id2 || id, module, mag.utils.merge(props || {}, props2 || {}))
    }
  }

  mag.module = function(id, mod, props) {

    props = props || {}

    // already here before?
    if (mag.utils.items.isItem(id)) {
      if (reloader(mag.utils.items.getItem(id), getNode(id))) return;
    }

    // get unique instance ID if not exists or with props.key
    var idInstance;
    // get unique instance ID if not exists or with props.key
    if (props.key && mag.utils.items.isItem(id + '.' + props.key)) {
      idInstance = mag.utils.items.getItem(id + '.' + props.key)
    } else {
      idInstance = mag.utils.getItemInstanceId(props.key ? id + '.' + props.key : id)
    }

    // TODO: cache/ clearable
    // clear cache if exists
    if (!props.retain) mag.mod.clear(idInstance)

    // get unqiue instance ID's module
    mag.mod.submodule(id, idInstance, mod, props)

    // NODE
    var node = getNode(id)

    //WATCH
    observer(idInstance, id)

    // LIFE CYCLE EVENT
    if (mag.utils.callLCEvent('willload', mag.mod.getState(idInstance), node, idInstance, 1)) return;

    // unloader handlers in controller
    addControllerUnloaders(idInstance)

    // DRAW async
    mag.redraw(node, idInstance, 1);

    // LIFE CYCLE EVENT
    mag.utils.callLCEvent('didload', mag.mod.getState(idInstance), node, idInstance, 1);

    // return function to clone create new clone instances ;)
    return makeClone(idInstance, node, mod, props)
  }

  var isValidId = function(nodeId, idInstance) {

    // verify idInstance
    if (idInstance < 0 || idInstance != mag.utils.items.getItem(nodeId)) {
      // if original id is a match
      if (nodeId == mag.mod.getId(idInstance)) return true;
      return false
    }
    return true
  }

  mag.redraw = function(node, idInstance, force) {
    if (!node || typeof idInstance == 'undefined') {
      throw Error('Mag.JS - Id or node invalid: ' + node, idInstance);
    }

    // verify idInstance
    if (!isValidId(node.id, idInstance)) {
      return
    }

    // clear existing configs ?
    // TODO: per idInstance / id ?
    // CHANGED: since the observer will be called and cache changed
    if(force)mag.fill.configs.splice(0, mag.fill.configs.length)

    if (force) mag.mod.clear(idInstance)

    var fun = makeRedrawFun(node, idInstance, force)

    // check for existing frame id then clear it if exists
    fastdom.clear(mag.mod.getFrameId(idInstance))
      //ENQUEUE
    var fid = fastdom.write(fun);
    //save frame id with the instance
    mag.mod.setFrameId(idInstance, fid)
    // then if instance already has frame id create new discard old or just retain old
  }

  mag.hookin = function(name, key, handler) {
    hookins[name].push({
      context: {},
      handler: handler,
      key: key
    })
  }

  mag.hook = function(name, key, data) {
    for (var i = 0, size = hookins[name].length; i < size; i++) {
      mag.utils.callHook(hookins, key, name, i, data)
    }
  }

  var makeClone = function(idInstance, node, mod, props) {
    var a = function(id, node, mod, props, index) {

      var cloner = node.cloneNode(1)
      cloner.id = node.id + (props.key ? '.' + props.key : '') + '.' + index;

      // if clone already exists return ?
      if (mag.utils.items.isItem(cloner.id)) {
        // return
      }

      var idInstance2 = mag.utils.getItemInstanceId(cloner.id)

      // get unqiue instance ID's module
      mag.mod.submodule(cloner.id, idInstance2, mod, props)

      observer(idInstance2, cloner.id)

      // DRAW
      mag.redraw(cloner, idInstance2, 1)

      return cloner
    }.bind({}, idInstance, node, mod, props)

    //BOUND CLONE INSTANCE METHODS
    a.getId = function(ids) {
      return idInstance
    }.bind({}, idInstance)
    a.draw = function(node, ids, force) {
      mag.redraw(node, ids, force)
    }.bind({}, node, idInstance)
    a.getState = function(ids) {
      return [].concat(mag.mod.getState(ids))[0]
    }.bind({}, idInstance)

    return a
  }
  var nodeCache = []

  function getNode(id) {
    //cache nodes?
    if (nodeCache[id]) return nodeCache[id]
    var node = document.getElementById(id);
    if (node) nodeCache[id] = node
    if (!node) {
      // throw Error('invalid node id: ' + id);
    }
    return node;
  }

  var observer = function(idInstance, nodeId) {
    var callback = function(index, id, change) {
      if (getNode(id)) {
          mag.redraw(getNode(id), index)
      } else if (mag.utils.items.isItem(nodeId)) {
        fastdom.clear(mag.mod.getFrameId(index))
          // remove from indexes
        mag.utils.items.removeItem(index)
          //mag.mod.remove(index)
        mag.mod.clear(index)
          //observer index
        mag.props.cached.splice(index, 1)
        //throw Error('invalid node id ' + id + ' index ' + index)
      }
    }.bind({}, idInstance, nodeId)
    mag.props.setup(idInstance, mag.debounce(callback))
  }

  var makeRedrawFun = function(node1, idInstance1, force1) {
    return function(node, idInstance, force) {

      // verify idInstance
      if (!isValidId(node.id, idInstance) || !node) {
        return
      }

      // get state
      var state = mag.mod.getState(idInstance)

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('isupdate', state, node, idInstance)) return;

      //get props
      var props = mag.mod.getProps(idInstance)

      // merge state & props
      var data = mag.utils.merge(mag.utils.copy(state), mag.utils.copy(props))

      // CACHED?
      if (mag.mod.iscached(idInstance, data) && !force) {
        return 0;
      };

      // LIFE CYCLE EVENT
      if (mag.utils.callLCEvent('willupdate', state, node, idInstance)) return;

      //RUN VIEW FUN
      mag.mod.callView(node, idInstance);

      //START DOM
      mag.fill.run(node, state)
      // END DOM

      //CONFIGS
      callConfigs(node.id, mag.fill.configs)

      // add configs unloaders
      addConfigUnloaders(node.id, idInstance)

      // LIFE CYCLE EVENT
      mag.utils.callLCEvent('didupdate', state, node)

    }.bind({}, node1, idInstance1, force1)
  }

  var callConfigs = function(id, configs) {
    for (var k in configs) {
      if (k.indexOf('id("' + id + '")/') > -1) {
        configs[k]()
      }
    }
  }

  var addControllerUnloaders = function(idInstance) {
    // TODO: controller unloaders
    var state = mag.mod.getState(idInstance)
    mag.utils.unloaders[idInstance] = mag.utils.unloaders[idInstance] || []
    if (state.onunload) mag.utils.unloaders[idInstance].push({
      controller: state,
      handler: state.onunload
    })
  }

  var addConfigUnloaders = function(id, index) {

    for (var k in mag.fill.cached) {
      if (k.indexOf('id("' + id + '")/') > -1 && k.indexOf('-config') > -1 && mag.fill.cached[k].configContext) {

        mag.utils.unloaders[index] = mag.utils.unloaders[index] || []

        mag.utils.unloaders[index].push({
          controller: mag.fill.cached[k].configContext,
          handler: mag.fill.cached[k].configContext.onunload
        })

      }
    }
  }

  var reloader = function(idInstance, node) {
    return mag.utils.callLCEvent('onreload', mag.mod.getState(idInstance), node, idInstance)
  }

  window.mag = mag

})(window.mag || {}, document);
<|endoftext|>


<commit_before>const fs = require('fs');
const data = require('./data/raw-data.json');

const allowedCities = [
  'breckerfeld',
  'ennepetal',
  'gevelsberg',
  'herdecke',
  'schwelm',
  'sprockhövel',
  'wetter (ruhr)',
  'witten',
  'werne',
  'unna',
  'selm',
  'schwerte',
  'lünen',
  'kamen',
  'holzwickede',
  'fröndenberg/ruhr',
  'bönen',
  'bergkamen',
  'waltrop',
  'recklinghausen',
  'oer-erkenschwick',
  'marl',
  'herten',
  'haltern am see',
  'gladbeck',
  'dorsten',
  'datteln',
  'castrop-rauxel',
  'hattingen',
  'alpen',
  'dinslaken',
  'hamminkeln',
  'xanten',
  'wesel',
  'voerde (niederrhein)',
  'sonsbeck',
  'schermbeck',
  'rheinberg',
  'neukirchen-vluyn',
  'moers',
  'kamp-lintfort',
  'hünxe',
  'oberhausen',
  'mülheim an der ruhr',
  'herne',
  'hamm',
  'hagen',
  'bochum',
  'bottrop',
  'dortmund',
  'duisburg',
  'essen',
  'gelsenkirchen'
];

data.features = data.features.filter((city) => {
  let lowerCaseCity = city.properties.GN.toLowerCase();
  let includesCity = allowedCities.indexOf(lowerCaseCity) > -1;

  return includesCity;
})

let newJson = JSON.stringify(data, null, 4);

fs.writeFileSync('./data/map-data.json', newJson);
<commit_msg>Fixed the Converter. It now changes "null" to "Nein"<commit_after>const fs = require('fs');
const data = require('./data/raw-data.json');

const allowedCities = [
  'breckerfeld',
  'ennepetal',
  'gevelsberg',
  'herdecke',
  'schwelm',
  'sprockhövel',
  'wetter (ruhr)',
  'witten',
  'werne',
  'unna',
  'selm',
  'schwerte',
  'lünen',
  'kamen',
  'holzwickede',
  'fröndenberg/ruhr',
  'bönen',
  'bergkamen',
  'waltrop',
  'recklinghausen',
  'oer-erkenschwick',
  'marl',
  'herten',
  'haltern am see',
  'gladbeck',
  'dorsten',
  'datteln',
  'castrop-rauxel',
  'hattingen',
  'alpen',
  'dinslaken',
  'hamminkeln',
  'xanten',
  'wesel',
  'voerde (niederrhein)',
  'sonsbeck',
  'schermbeck',
  'rheinberg',
  'neukirchen-vluyn',
  'moers',
  'kamp-lintfort',
  'hünxe',
  'oberhausen',
  'mülheim an der ruhr',
  'herne',
  'hamm',
  'hagen',
  'bochum',
  'bottrop',
  'dortmund',
  'duisburg',
  'essen',
  'gelsenkirchen'
];

data.features = data.features.filter((city) => {
  let lowerCaseCity = city.properties.GN.toLowerCase();

  for(var key in city.properties) {
    if(city.properties[key] == null) {
      city.properties[key] = "Nein";
    }
  }

  return allowedCities.indexOf(lowerCaseCity) > -1;
});

let newJson = JSON.stringify(data, null, 4);

fs.writeFileSync('./data/map-data.json', newJson);
<|endoftext|>


<commit_before>import initStoryshots from '@storybook/addon-storyshots';
import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';
import path from 'path';

initStoryshots( {
	suite: 'Puppeteer storyshots',
	test: puppeteerTest( {
		// eslint-disable-next-line sitekit/acronym-case
		storybookUrl: `file://${ path.resolve( __dirname, '../dist' ) }`,
		setupTimeout: 5000,
		testTimeout: 5000,
	} ),
} );
<commit_msg>Add file header.<commit_after>/**
 * Failing stories test runner.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Node dependencies
 */
import path from 'path';

/**
 * External dependencies
 */
import initStoryshots from '@storybook/addon-storyshots';
import { puppeteerTest } from '@storybook/addon-storyshots-puppeteer';

initStoryshots( {
	suite: 'Puppeteer storyshots',
	test: puppeteerTest( {
		// eslint-disable-next-line sitekit/acronym-case
		storybookUrl: `file://${ path.resolve( __dirname, '../dist' ) }`,
		setupTimeout: 5000,
		testTimeout: 5000,
	} ),
} );
<|endoftext|>


<commit_before>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';

import { constants } from 'commons/utils/constants';
import loadEntities from 'commons/redux/util/loadEntities';
import i18n from 'commons/utils/i18n';

const Home = React.createClass({
  propTypes: {
    activeLocale: PropTypes.string,
    categories: PropTypes.object.isRequired,
    main_categories: PropTypes.array,
    products: PropTypes.array,
  },
  contextTypes: {
    activeLocale: PropTypes.string,
  },
  getInitialState() {
    return {};
  },
  componentDidMount() {
    /*
    $('.main-banner').owlCarousel({ autoPlay: 10000, items: 1 });
    $('.center-slide').owlCarousel({ autoPlay: 10000, items: 1 });
    */
  },
  render() {
    const { activeLocale } = this.props;
    const renderCategories = () => {
      if (!this.props.main_categories) {
        return (

);
      }
      const categories = this.props.main_categories;
      const renderCategory = (c, index) => {
        const onMouseEnter = () => {
          this.setState({ hoverCategory: c });
        };
        let className = 'item';
        const { cursor, hoverCategory } = this.state;
        if (cursor === 'categoryHover' && hoverCategory && c.id === hoverCategory.id) {
          className += ' active';
        }
        return (
          <Link key={`${c.id}-${index}`} to={`/categories/${c.id}`}>

              {c.name[activeLocale]}

          </Link>
        );
      };
      let categoryHoverBox = null;
      const hoverItems = [];
      if (this.state.hoverCategory) {
        (this.state.hoverCategory.children || []).forEach((child, index) => {
          if (index >= 2) {
            return;
          }
          hoverItems.push(
            <Link key={child.id} to={`/categories/${child.id}`}><div key={`depth1-${child.id}`} className="title-item">{child.name[activeLocale]}
</Link> // eslint-disable-line
          );
          (child.children || []).forEach((child2, index2) => {
            if (index2 >= 3) {
              return;
            }
            hoverItems.push(
              <Link key={child2.id} to={`/categories/${child2.id}`}><div key={`depth2-${child2.id}`} className="sub-item">{child2.name[activeLocale]}
</Link> // eslint-disable-line
            );
          });
        });
        categoryHoverBox = (

 this.setState({ cursor: 'categoryHover' })}
            onMouseLeave={() => this.setState({ cursor: 'none' })}
          >
            {hoverItems}

        );
      };
      return (

            {i18n.get('word.categories')}
            <Link to="/categories/4">
{i18n.get('word.seeAll')}
</Link>

            {categories.map(renderCategory)}

          {categoryHoverBox}

      );
    };
    const trendPicks = [
      { img: `${constants.resourceRoot}/banner/trandpick1.jpg`, link: '/products/100442' },
      { img: `${constants.resourceRoot}/banner/trandpick2.jpg`, link: '/products/87299' },
      { img: `${constants.resourceRoot}/banner/trandpick3.jpg`, link: '/products/84874' },
      { img: `${constants.resourceRoot}/banner/trandpick4.jpg`, link: '/products/91472' },
      { img: `${constants.resourceRoot}/banner/trandpick5.jpg`, link: '/products/90831' },
      { img: `${constants.resourceRoot}/banner/trandpick6.jpg`, link: '/products/89069' },
      { img: `${constants.resourceRoot}/banner/trandpick7.jpg`, link: '/products/93900' },
      { img: `${constants.resourceRoot}/banner/trandpick8.jpg`, link: '/products/90827' },
    ];
    const renderTrendPickItem = (trend, index) => {
      const className = index < 4 ? 'trend-top' : 'trend-bottom';
      return (
        <Link to={trend.link} key={`trend${index}`} className={className}>

        </Link>
      );
    };
    return (

            {renderCategories()}

              <img src={`${constants.resourceRoot}/banner/main_20160426.jpg`} />

              스타일 픽
              COMING
              SOON

            <Link to="/service/info/service_info" className="right-banner">
              <img src={`${constants.resourceRoot}/banner/main_right_20160426.png`} />
            </Link>

              상가별 매장정보

<img src={`${constants.resourceRoot}/banner/build_apm.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_apmluxe.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_belpost.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_designerclub.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_theot.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_nuzzon.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_techno.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_cph.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_uus.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_queens.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_shose.jpg`} />

                    시장별 상가

                    더보기

                  <img src={`${constants.resourceRoot}/main/ico_right4_w.gif`} />

              트렌드 톡

                <img src={`${constants.resourceRoot}/banner/trandpick.jpg`} />

                {trendPicks.map(renderTrendPickItem)}

            <Link to="/service/info/service_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico01.png`} />

서비스 소개

                  믿고 거래하는

                  No.1 온라인 도매시장

            </Link>
            <Link to="/service/info/signup_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico02.png`} />

회원가입 안내

                  고객 우선 원칙

                  회원 시스템

            </Link>
            <Link to="/service/info/order_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico03.png`} />

주문 배송

                  원하는 브랜드 및 상품

                  사입 요청 가능

            </Link>
            <Link to="/service/info/customer_center" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico04.png`} />

고객지원 센터

                  편리한 소통을 위한

                  언어별 고객지원 센터

            </Link>

        {/*

<Link to="/service/info/intro">회사소개</Link>

<Link to="/user/terms">이용약관</Link>

<Link to="/user/policies">개인정보 취급방침</Link>

<Link to="/service/info/signup">회원가입 안내</Link>

         */}

    );
  },
});

export default connect((state) => ({
  categories: state.categories,
  activeLocale: state.i18n.activeLocale,
  main_categories: state.cms.main_categories,
  ...loadEntities(state, 'products', 'products'),
}))(Home);
<commit_msg>remove trend talk<commit_after>// Copyright (C) 2016 Goom Inc. All rights reserved.

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router';

import { constants } from 'commons/utils/constants';
import loadEntities from 'commons/redux/util/loadEntities';
import i18n from 'commons/utils/i18n';

const Home = React.createClass({
  propTypes: {
    activeLocale: PropTypes.string,
    categories: PropTypes.object.isRequired,
    main_categories: PropTypes.array,
    products: PropTypes.array,
  },
  contextTypes: {
    activeLocale: PropTypes.string,
  },
  getInitialState() {
    return {};
  },
  componentDidMount() {
    /*
    $('.main-banner').owlCarousel({ autoPlay: 10000, items: 1 });
    $('.center-slide').owlCarousel({ autoPlay: 10000, items: 1 });
    */
  },
  render() {
    const { activeLocale } = this.props;
    const renderCategories = () => {
      if (!this.props.main_categories) {
        return (

);
      }
      const categories = this.props.main_categories;
      const renderCategory = (c, index) => {
        const onMouseEnter = () => {
          this.setState({ hoverCategory: c });
        };
        let className = 'item';
        const { cursor, hoverCategory } = this.state;
        if (cursor === 'categoryHover' && hoverCategory && c.id === hoverCategory.id) {
          className += ' active';
        }
        return (
          <Link key={`${c.id}-${index}`} to={`/categories/${c.id}`}>

              {c.name[activeLocale]}

          </Link>
        );
      };
      let categoryHoverBox = null;
      const hoverItems = [];
      if (this.state.hoverCategory) {
        (this.state.hoverCategory.children || []).forEach((child, index) => {
          if (index >= 2) {
            return;
          }
          hoverItems.push(
            <Link key={child.id} to={`/categories/${child.id}`}><div key={`depth1-${child.id}`} className="title-item">{child.name[activeLocale]}
</Link> // eslint-disable-line
          );
          (child.children || []).forEach((child2, index2) => {
            if (index2 >= 3) {
              return;
            }
            hoverItems.push(
              <Link key={child2.id} to={`/categories/${child2.id}`}><div key={`depth2-${child2.id}`} className="sub-item">{child2.name[activeLocale]}
</Link> // eslint-disable-line
            );
          });
        });
        categoryHoverBox = (

 this.setState({ cursor: 'categoryHover' })}
            onMouseLeave={() => this.setState({ cursor: 'none' })}
          >
            {hoverItems}

        );
      };
      return (

            {i18n.get('word.categories')}
            <Link to="/categories/4">
{i18n.get('word.seeAll')}
</Link>

            {categories.map(renderCategory)}

          {categoryHoverBox}

      );
    };
    const trendPicks = [
      { img: `${constants.resourceRoot}/banner/trandpick1.jpg`, link: '/products/100442' },
      { img: `${constants.resourceRoot}/banner/trandpick2.jpg`, link: '/products/87299' },
      { img: `${constants.resourceRoot}/banner/trandpick3.jpg`, link: '/products/84874' },
      { img: `${constants.resourceRoot}/banner/trandpick4.jpg`, link: '/products/91472' },
      { img: `${constants.resourceRoot}/banner/trandpick5.jpg`, link: '/products/90831' },
      { img: `${constants.resourceRoot}/banner/trandpick6.jpg`, link: '/products/89069' },
      { img: `${constants.resourceRoot}/banner/trandpick7.jpg`, link: '/products/93900' },
      { img: `${constants.resourceRoot}/banner/trandpick8.jpg`, link: '/products/90827' },
    ];
    const renderTrendPickItem = (trend, index) => {
      const className = index < 4 ? 'trend-top' : 'trend-bottom';
      return (
        <Link to={trend.link} key={`trend${index}`} className={className}>

        </Link>
      );
    };
    return (

            {renderCategories()}

              <img src={`${constants.resourceRoot}/banner/main_20160426.jpg`} />

              스타일 픽
              COMING
              SOON

            <Link to="/service/info/service_info" className="right-banner">
              <img src={`${constants.resourceRoot}/banner/main_right_20160426.png`} />
            </Link>

              상가별 매장정보

<img src={`${constants.resourceRoot}/banner/build_apm.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_apmluxe.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_belpost.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_designerclub.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_theot.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_nuzzon.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_techno.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_cph.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_uus.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_queens.jpg`} />

<img src={`${constants.resourceRoot}/banner/build_shose.jpg`} />

                    시장별 상가

                    더보기

                  <img src={`${constants.resourceRoot}/main/ico_right4_w.gif`} />

            {/*

              트렌드 톡

                <img src={`${constants.resourceRoot}/banner/trandpick.jpg`} />

                {trendPicks.map(renderTrendPickItem)}

             */}

            <Link to="/service/info/service_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico01.png`} />

서비스 소개

                  믿고 거래하는

                  No.1 온라인 도매시장

            </Link>
            <Link to="/service/info/signup_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico02.png`} />

회원가입 안내

                  고객 우선 원칙

                  회원 시스템

            </Link>
            <Link to="/service/info/order_info" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico03.png`} />

주문 배송

                  원하는 브랜드 및 상품

                  사입 요청 가능

            </Link>
            <Link to="/service/info/customer_center" className="slogan-item">

                <img src={`${constants.resourceRoot}/footer/main/keyword_ico04.png`} />

고객지원 센터

                  편리한 소통을 위한

                  언어별 고객지원 센터

            </Link>

        {/*

<Link to="/service/info/intro">회사소개</Link>

<Link to="/user/terms">이용약관</Link>

<Link to="/user/policies">개인정보 취급방침</Link>

<Link to="/service/info/signup">회원가입 안내</Link>

         */}

    );
  },
});

export default connect((state) => ({
  categories: state.categories,
  activeLocale: state.i18n.activeLocale,
  main_categories: state.cms.main_categories,
  ...loadEntities(state, 'products', 'products'),
}))(Home);
<|endoftext|>


<commit_before>import classNames from 'classnames'

let memoizedIsAndroid
let memoizedIsChrome
let memoizedIsElloAndroid
let memoizedIsFirefox
let memoizedIsIE11
let memoizedIsIOS
let memoizedIsSafari

export function isAndroid() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsAndroid !== 'undefined') { return memoizedIsAndroid }
  memoizedIsAndroid = /Android/gi.test(navigator.userAgent)
  return memoizedIsAndroid
}

export function isChrome() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsChrome !== 'undefined') { return memoizedIsChrome }
  memoizedIsChrome = !!window.chrome && !!window.chrome.webstore
  return memoizedIsChrome
}

export function isElloAndroid() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsElloAndroid !== 'undefined') { return memoizedIsElloAndroid }
  memoizedIsElloAndroid = /Ello Android/gi.test(navigator.userAgent)
  return memoizedIsElloAndroid
}

export function isFirefox() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsFirefox !== 'undefined') { return memoizedIsFirefox }
  memoizedIsFirefox = /Firefox/gi.test(navigator.userAgent)
  return memoizedIsFirefox
}

export function isSafari() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsSafari !== 'undefined') { return memoizedIsSafari }
  memoizedIsSafari = /Safari/gi.test(navigator.userAgent) && !isChrome()
  return memoizedIsSafari
}

export function isIOS() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsIOS !== 'undefined') { return memoizedIsIOS }
  memoizedIsIOS = /iPad|iPhone|iPod/gi.test(navigator.userAgent)
  return memoizedIsIOS
}

export function isIE11() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsIE11 !== 'undefined') { return memoizedIsIE11 }
  const docStyle = document.documentElement.style
  memoizedIsIE11 = '-ms-scroll-limit' in docStyle && '-ms-ime-align' in docStyle
  return memoizedIsIE11
}

export function getElloPlatform() {
  return isElloAndroid() ? 'ello-android-app' : 'ello-webapp'
}

// -------------------------------------

export function addFeatureDetection() {
  const cl = document.documentElement.classList
  if (!('ontouchstart' in document.documentElement)) {
    cl.add('no-touch')
  }
  const onTouchStart = () => {
    document.removeEventListener('touchstart', onTouchStart)
    cl.remove('no-touch')
    cl.add('has-touch')
  }
  if (isChrome()) { cl.add('isChrome') }
  if (isSafari()) { cl.add('isSafari') }
  if (isFirefox()) { cl.add('isFirefox') }
  if (isIE11()) { cl.add('isIE11') }
  document.addEventListener('touchstart', onTouchStart)
}

export function hideSoftKeyboard() {
  if (document.activeElement) {
    document.activeElement.blur()
  }
}

<commit_msg>Fix a linter error<commit_after>let memoizedIsAndroid
let memoizedIsChrome
let memoizedIsElloAndroid
let memoizedIsFirefox
let memoizedIsIE11
let memoizedIsIOS
let memoizedIsSafari

export function isAndroid() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsAndroid !== 'undefined') { return memoizedIsAndroid }
  memoizedIsAndroid = /Android/gi.test(navigator.userAgent)
  return memoizedIsAndroid
}

export function isChrome() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsChrome !== 'undefined') { return memoizedIsChrome }
  memoizedIsChrome = !!window.chrome && !!window.chrome.webstore
  return memoizedIsChrome
}

export function isElloAndroid() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsElloAndroid !== 'undefined') { return memoizedIsElloAndroid }
  memoizedIsElloAndroid = /Ello Android/gi.test(navigator.userAgent)
  return memoizedIsElloAndroid
}

export function isFirefox() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsFirefox !== 'undefined') { return memoizedIsFirefox }
  memoizedIsFirefox = /Firefox/gi.test(navigator.userAgent)
  return memoizedIsFirefox
}

export function isSafari() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsSafari !== 'undefined') { return memoizedIsSafari }
  memoizedIsSafari = /Safari/gi.test(navigator.userAgent) && !isChrome()
  return memoizedIsSafari
}

export function isIOS() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsIOS !== 'undefined') { return memoizedIsIOS }
  memoizedIsIOS = /iPad|iPhone|iPod/gi.test(navigator.userAgent)
  return memoizedIsIOS
}

export function isIE11() {
  if (typeof window === 'undefined') { return false }
  if (typeof memoizedIsIE11 !== 'undefined') { return memoizedIsIE11 }
  const docStyle = document.documentElement.style
  memoizedIsIE11 = '-ms-scroll-limit' in docStyle && '-ms-ime-align' in docStyle
  return memoizedIsIE11
}

export function getElloPlatform() {
  return isElloAndroid() ? 'ello-android-app' : 'ello-webapp'
}

// -------------------------------------

export function addFeatureDetection() {
  const cl = document.documentElement.classList
  if (!('ontouchstart' in document.documentElement)) {
    cl.add('no-touch')
  }
  const onTouchStart = () => {
    document.removeEventListener('touchstart', onTouchStart)
    cl.remove('no-touch')
    cl.add('has-touch')
  }
  if (isChrome()) { cl.add('isChrome') }
  if (isSafari()) { cl.add('isSafari') }
  if (isFirefox()) { cl.add('isFirefox') }
  if (isIE11()) { cl.add('isIE11') }
  document.addEventListener('touchstart', onTouchStart)
}

export function hideSoftKeyboard() {
  if (document.activeElement) {
    document.activeElement.blur()
  }
}

<|endoftext|>


<commit_before>import shortid from 'shortid';

export default function Image(img = {}) {
  this._id = img._id || undefined;
  this.file = img.file || null;
  this.url = img.url || null;
  this.shortid = img.shortid || shortid.generate();
  this.state = img.state || 0;
  this.progress = img.progress || 0;
  this.ratio = img.ratio || undefined;

  // Methods
  this.getUrl = () => {
    const url = this.file
      ? window.URL.createObjectURL(this.file)
      : this.url || null;
    return url;
  };

  this.getSmallestThumbUrl = () => {
    if (this.thumbnails && Object.keys(this.thumbnails)) {
      return this.thumbnails[Math.min.apply(null, Object.keys(this.thumbnails))];
    }
    return this.getUrl();
  }

  this.getBiggestThumbUrl = () => {
    if (this.thumbnails && Object.keys(this.thumbnails)) {
      return this.thumbnails[Math.max.apply(null, Object.keys(this.thumbnails))];
    }
    return this.getUrl();
  }

  this.getSrcSetString = () => {
    if (!this.thumbnails || this.thumbnails.length === 0) return;
    /* eslint consistent-return:0 */
    return Object.keys(this.thumbnails).reduce((acc, thumbnailSize, index) => {
      const newAcc = `${acc}${!index ? '' : ', '}${this.thumbnails[thumbnailSize]} ${thumbnailSize}w`;
      return newAcc;
    }, '');
  }

  this.getBlobOrSmallestThumb = () => {
    if (this.file) return URL.createObjectURL(this.file);
    return this.getSmallestThumbUrl();
  }

  this.getTitleImageUrl = () => {
    if (this.thumbnails && this.thumbnails[640]) {
      return this.thumbnails[640];
    }
    return this.getSmallestThumbUrl();
  }
}
<commit_msg>Remove obsolete image functions<commit_after>import shortid from 'shortid';
import { constructThumborUrl } from 'src/config/constants';

export default function Image(img = {}) {
  this._id = img._id || undefined;
  this.file = img.file || null;
  this.url = img.url || null;
  this.shortid = img.shortid || shortid.generate();
  this.state = img.state || 0;
  this.progress = img.progress || 0;
  this.ratio = img.ratio || undefined;

  // Methods
  this.getUrl = () => {
    const url = this.file
      ? window.URL.createObjectURL(this.file)
      : this.url || null;
    return url;
  };

  this.getBlobOrSmallestThumb = () => {
    if (this.file) return URL.createObjectURL(this.file);
    return this.getThumbnail(160);
  }

  this.getThumbnail = size => constructThumborUrl(this.url, { width: size });
  this.getBlurryThumb = () => constructThumborUrl(this.url, {
    width: 20,
    filters: {
      blur: 2,
    },
  });
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2012 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Helper functions for generating Python for blocks.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.Python');

goog.require('Blockly.Generator');
goog.require('Blockly.utils.string');

/**
 * Python code generator.
 * @type {!Blockly.Generator}
 */
Blockly.Python = new Blockly.Generator('Python');

/**
 * List of illegal variable names.
 * This is not intended to be a security feature.  Blockly is 100% client-side,
 * so bypassing this list is trivial.  This is intended to prevent users from
 * accidentally clobbering a built-in object or function.
 * @private
 */
Blockly.Python.addReservedWords(
    // import keyword
    // print(','.join(sorted(keyword.kwlist)))
    // https://docs.python.org/3/reference/lexical_analysis.html#keywords
    // https://docs.python.org/2/reference/lexical_analysis.html#keywords
    'False,None,True,and,as,assert,break,class,continue,def,del,elif,else,' +
    'except,exec,finally,for,from,global,if,import,in,is,lambda,nonlocal,not,' +
    'or,pass,print,raise,return,try,while,with,yield,' +
    // https://docs.python.org/3/library/constants.html
    // https://docs.python.org/2/library/constants.html
    'NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' +
    // >>> print(','.join(sorted(dir(__builtins__))))
    // https://docs.python.org/3/library/functions.html
    // https://docs.python.org/2/library/functions.html
    'ArithmeticError,AssertionError,AttributeError,BaseException,' +
    'BlockingIOError,BrokenPipeError,BufferError,BytesWarning,' +
    'ChildProcessError,ConnectionAbortedError,ConnectionError,' +
    'ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,' +
    'Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,' +
    'FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,' +
    'ImportWarning,IndentationError,IndexError,InterruptedError,' +
    'IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,' +
    'ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,' +
    'NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,' +
    'PermissionError,ProcessLookupError,RecursionError,ReferenceError,' +
    'ResourceWarning,RuntimeError,RuntimeWarning,StandardError,' +
    'StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,' +
    'SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,' +
    'UnicodeDecodeError,UnicodeEncodeError,UnicodeError,' +
    'UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,' +
    'ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,' +
    '__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,' +
    'basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,' +
    'coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,' +
    'enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,' +
    'getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,' +
    'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' +
    'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' +
    'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' +
    'sum,super,tuple,type,unichr,unicode,vars,xrange,zip'
);

/**
 * Order of operation ENUMs.
 * http://docs.python.org/reference/expressions.html#summary
 */
Blockly.Python.ORDER_ATOMIC = 0;            // 0 "" ...
Blockly.Python.ORDER_COLLECTION = 1;        // tuples, lists, dictionaries
Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...`
Blockly.Python.ORDER_MEMBER = 2.1;          // . []
Blockly.Python.ORDER_FUNCTION_CALL = 2.2;   // ()
Blockly.Python.ORDER_EXPONENTIATION = 3;    // **
Blockly.Python.ORDER_UNARY_SIGN = 4;        // + -
Blockly.Python.ORDER_BITWISE_NOT = 4;       // ~
Blockly.Python.ORDER_MULTIPLICATIVE = 5;    // * / // %
Blockly.Python.ORDER_ADDITIVE = 6;          // + -
Blockly.Python.ORDER_BITWISE_SHIFT = 7;     // << >>
Blockly.Python.ORDER_BITWISE_AND = 8;       // &
Blockly.Python.ORDER_BITWISE_XOR = 9;       // ^
Blockly.Python.ORDER_BITWISE_OR = 10;       // |
Blockly.Python.ORDER_RELATIONAL = 11;       // in, not in, is, is not,
                                            //     <, <=, >, >=, <>, !=, ==
Blockly.Python.ORDER_LOGICAL_NOT = 12;      // not
Blockly.Python.ORDER_LOGICAL_AND = 13;      // and
Blockly.Python.ORDER_LOGICAL_OR = 14;       // or
Blockly.Python.ORDER_CONDITIONAL = 15;      // if else
Blockly.Python.ORDER_LAMBDA = 16;           // lambda
Blockly.Python.ORDER_NONE = 99;             // (...)

/**
 * List of outer-inner pairings that do NOT require parentheses.
 * @type {!Array.<!Array.<number>>}
 */
Blockly.Python.ORDER_OVERRIDES = [
  // (foo()).bar -> foo().bar
  // (foo())[0] -> foo()[0]
  [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER],
  // (foo())() -> foo()()
  [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_FUNCTION_CALL],
  // (foo.bar).baz -> foo.bar.baz
  // (foo.bar)[0] -> foo.bar[0]
  // (foo[0]).bar -> foo[0].bar
  // (foo[0])[1] -> foo[0][1]
  [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_MEMBER],
  // (foo.bar)() -> foo.bar()
  // (foo[0])() -> foo[0]()
  [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_FUNCTION_CALL],

  // not (not foo) -> not not foo
  [Blockly.Python.ORDER_LOGICAL_NOT, Blockly.Python.ORDER_LOGICAL_NOT],
  // a and (b and c) -> a and b and c
  [Blockly.Python.ORDER_LOGICAL_AND, Blockly.Python.ORDER_LOGICAL_AND],
  // a or (b or c) -> a or b or c
  [Blockly.Python.ORDER_LOGICAL_OR, Blockly.Python.ORDER_LOGICAL_OR]
];

/**
 * Initialise the database of variable names.
 * @param {!Blockly.Workspace} workspace Workspace to generate code from.
 * @this {Blockly.Generator}
 */
Blockly.Python.init = function(workspace) {
  /**
   * Empty loops or conditionals are not allowed in Python.
   */
  Blockly.Python.PASS = this.INDENT + 'pass\n';
  // Create a dictionary of definitions to be printed before the code.
  Blockly.Python.definitions_ = Object.create(null);
  // Create a dictionary mapping desired function names in definitions_
  // to actual function names (to avoid collisions with user functions).
  Blockly.Python.functionNames_ = Object.create(null);

  if (!Blockly.Python.variableDB_) {
    Blockly.Python.variableDB_ =
        new Blockly.Names(Blockly.Python.RESERVED_WORDS_);
  } else {
    Blockly.Python.variableDB_.reset();
  }

  Blockly.Python.variableDB_.setVariableMap(workspace.getVariableMap());

  var defvars = [];
  // Add developer variables (not created or named by the user).
  var devVarList = Blockly.Variables.allDeveloperVariables(workspace);
  for (var i = 0; i < devVarList.length; i++) {
    defvars.push(Blockly.Python.variableDB_.getName(devVarList[i],
        Blockly.Names.DEVELOPER_VARIABLE_TYPE) + ' = None');
  }

  // Add user variables, but only ones that are being used.
  var variables = Blockly.Variables.allUsedVarModels(workspace);
  for (var i = 0; i < variables.length; i++) {
    defvars.push(Blockly.Python.variableDB_.getName(variables[i].getId(),
        Blockly.VARIABLE_CATEGORY_NAME) + ' = None');
  }

  Blockly.Python.definitions_['variables'] = defvars.join('\n');
};

/**
 * Prepend the generated code with the variable definitions.
 * @param {string} code Generated code.
 * @return {string} Completed code.
 */
Blockly.Python.finish = function(code) {
  // Convert the definitions dictionary into a list.
  var imports = [];
  var definitions = [];
  for (var name in Blockly.Python.definitions_) {
    var def = Blockly.Python.definitions_[name];
    if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) {
      imports.push(def);
    } else {
      definitions.push(def);
    }
  }
  // Clean up temporary data.
  delete Blockly.Python.definitions_;
  delete Blockly.Python.functionNames_;
  Blockly.Python.variableDB_.reset();
  var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n');
  return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code;
};

/**
 * Naked values are top-level blocks with outputs that aren't plugged into
 * anything.
 * @param {string} line Line of generated code.
 * @return {string} Legal line of code.
 */
Blockly.Python.scrubNakedValue = function(line) {
  return line + '\n';
};

/**
 * Encode a string as a properly escaped Python string, complete with quotes.
 * @param {string} string Text to encode.
 * @return {string} Python string.
 * @private
 */
Blockly.Python.quote_ = function(string) {
  // Can't use goog.string.quote since % must also be escaped.
  string = string.replace(/\\/g, '\\\\')
                 .replace(/\n/g, '\\\n');

  // Follow the CPython behaviour of repr() for a non-byte string.
  var quote = '\'';
  if (string.indexOf('\'') !== -1) {
    if (string.indexOf('"') === -1) {
      quote = '"';
    } else {
      string = string.replace(/'/g, '\\\'');
    }
  };
  return quote + string + quote;
};

/**
 * Encode a string as a properly escaped multiline Python string, complete
 * with quotes.
 * @param {string} string Text to encode.
 * @return {string} Python string.
 * @private
 */
Blockly.Python.multiline_quote_ = function(string) {
  // Can't use goog.string.quote since % must also be escaped.
  string = string.replace(/'''/g, '\\\'\\\'\\\'');
  return '\'\'\'' + string + '\'\'\'';
};

/**
 * Common tasks for generating Python from blocks.
 * Handles comments for the specified block and any connected value blocks.
 * Calls any statements following this block.
 * @param {!Blockly.Block} block The current block.
 * @param {string} code The Python code created for this block.
 * @param {boolean=} opt_thisOnly True to generate code for only this statement.
 * @return {string} Python code with comments and subsequent blocks added.
 * @private
 */
Blockly.Python.scrub_ = function(block, code, opt_thisOnly) {
  var commentCode = '';
  // Only collect comments for blocks that aren't inline.
  if (!block.outputConnection || !block.outputConnection.targetConnection) {
    // Collect comment for this block.
    var comment = block.getCommentText();
    if (comment) {
      comment = Blockly.utils.string.wrap(comment,
          Blockly.Python.COMMENT_WRAP - 3);
      commentCode += Blockly.Python.prefixLines(comment + '\n', '# ');
    }
    // Collect comments for all value arguments.
    // Don't collect comments for nested statements.
    for (var i = 0; i < block.inputList.length; i++) {
      if (block.inputList[i].type == Blockly.INPUT_VALUE) {
        var childBlock = block.inputList[i].connection.targetBlock();
        if (childBlock) {
          comment = Blockly.Python.allNestedComments(childBlock);
          if (comment) {
            commentCode += Blockly.Python.prefixLines(comment, '# ');
          }
        }
      }
    }
  }
  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
  var nextCode = opt_thisOnly ? '' : Blockly.Python.blockToCode(nextBlock);
  return commentCode + code + nextCode;
};

/**
 * Gets a property and adjusts the value, taking into account indexing, and
 * casts to an integer.
 * @param {!Blockly.Block} block The block.
 * @param {string} atId The property ID of the element to get.
 * @param {number=} opt_delta Value to add.
 * @param {boolean=} opt_negate Whether to negate the value.
 * @return {string|number}
 */
Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
  var delta = opt_delta || 0;
  if (block.workspace.options.oneBasedIndex) {
    delta--;
  }
  var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0';
  var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE :
      Blockly.Python.ORDER_NONE;
  var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex;

  if (Blockly.isNumber(at)) {
    // If the index is a naked number, adjust it right now.
    at = parseInt(at, 10) + delta;
    if (opt_negate) {
      at = -at;
    }
  } else {
    // If the index is dynamic, adjust it in code.
    if (delta > 0) {
      at = 'int(' + at + ' + ' + delta + ')';
    } else if (delta < 0) {
      at = 'int(' + at + ' - ' + -delta + ')';
    } else {
      at = 'int(' + at + ')';
    }
    if (opt_negate) {
      at = '-' + at;
    }
  }
  return at;
};
<commit_msg>Fix python multiline string<commit_after>/**
 * @license
 * Copyright 2012 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Helper functions for generating Python for blocks.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

goog.provide('Blockly.Python');

goog.require('Blockly.Generator');
goog.require('Blockly.utils.string');

/**
 * Python code generator.
 * @type {!Blockly.Generator}
 */
Blockly.Python = new Blockly.Generator('Python');

/**
 * List of illegal variable names.
 * This is not intended to be a security feature.  Blockly is 100% client-side,
 * so bypassing this list is trivial.  This is intended to prevent users from
 * accidentally clobbering a built-in object or function.
 * @private
 */
Blockly.Python.addReservedWords(
    // import keyword
    // print(','.join(sorted(keyword.kwlist)))
    // https://docs.python.org/3/reference/lexical_analysis.html#keywords
    // https://docs.python.org/2/reference/lexical_analysis.html#keywords
    'False,None,True,and,as,assert,break,class,continue,def,del,elif,else,' +
    'except,exec,finally,for,from,global,if,import,in,is,lambda,nonlocal,not,' +
    'or,pass,print,raise,return,try,while,with,yield,' +
    // https://docs.python.org/3/library/constants.html
    // https://docs.python.org/2/library/constants.html
    'NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' +
    // >>> print(','.join(sorted(dir(__builtins__))))
    // https://docs.python.org/3/library/functions.html
    // https://docs.python.org/2/library/functions.html
    'ArithmeticError,AssertionError,AttributeError,BaseException,' +
    'BlockingIOError,BrokenPipeError,BufferError,BytesWarning,' +
    'ChildProcessError,ConnectionAbortedError,ConnectionError,' +
    'ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,' +
    'Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,' +
    'FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,' +
    'ImportWarning,IndentationError,IndexError,InterruptedError,' +
    'IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,' +
    'ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,' +
    'NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,' +
    'PermissionError,ProcessLookupError,RecursionError,ReferenceError,' +
    'ResourceWarning,RuntimeError,RuntimeWarning,StandardError,' +
    'StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,' +
    'SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,' +
    'UnicodeDecodeError,UnicodeEncodeError,UnicodeError,' +
    'UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,' +
    'ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,' +
    '__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,' +
    'basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,' +
    'coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,' +
    'enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,' +
    'getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,' +
    'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' +
    'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' +
    'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' +
    'sum,super,tuple,type,unichr,unicode,vars,xrange,zip'
);

/**
 * Order of operation ENUMs.
 * http://docs.python.org/reference/expressions.html#summary
 */
Blockly.Python.ORDER_ATOMIC = 0;            // 0 "" ...
Blockly.Python.ORDER_COLLECTION = 1;        // tuples, lists, dictionaries
Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...`
Blockly.Python.ORDER_MEMBER = 2.1;          // . []
Blockly.Python.ORDER_FUNCTION_CALL = 2.2;   // ()
Blockly.Python.ORDER_EXPONENTIATION = 3;    // **
Blockly.Python.ORDER_UNARY_SIGN = 4;        // + -
Blockly.Python.ORDER_BITWISE_NOT = 4;       // ~
Blockly.Python.ORDER_MULTIPLICATIVE = 5;    // * / // %
Blockly.Python.ORDER_ADDITIVE = 6;          // + -
Blockly.Python.ORDER_BITWISE_SHIFT = 7;     // << >>
Blockly.Python.ORDER_BITWISE_AND = 8;       // &
Blockly.Python.ORDER_BITWISE_XOR = 9;       // ^
Blockly.Python.ORDER_BITWISE_OR = 10;       // |
Blockly.Python.ORDER_RELATIONAL = 11;       // in, not in, is, is not,
                                            //     <, <=, >, >=, <>, !=, ==
Blockly.Python.ORDER_LOGICAL_NOT = 12;      // not
Blockly.Python.ORDER_LOGICAL_AND = 13;      // and
Blockly.Python.ORDER_LOGICAL_OR = 14;       // or
Blockly.Python.ORDER_CONDITIONAL = 15;      // if else
Blockly.Python.ORDER_LAMBDA = 16;           // lambda
Blockly.Python.ORDER_NONE = 99;             // (...)

/**
 * List of outer-inner pairings that do NOT require parentheses.
 * @type {!Array.<!Array.<number>>}
 */
Blockly.Python.ORDER_OVERRIDES = [
  // (foo()).bar -> foo().bar
  // (foo())[0] -> foo()[0]
  [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER],
  // (foo())() -> foo()()
  [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_FUNCTION_CALL],
  // (foo.bar).baz -> foo.bar.baz
  // (foo.bar)[0] -> foo.bar[0]
  // (foo[0]).bar -> foo[0].bar
  // (foo[0])[1] -> foo[0][1]
  [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_MEMBER],
  // (foo.bar)() -> foo.bar()
  // (foo[0])() -> foo[0]()
  [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_FUNCTION_CALL],

  // not (not foo) -> not not foo
  [Blockly.Python.ORDER_LOGICAL_NOT, Blockly.Python.ORDER_LOGICAL_NOT],
  // a and (b and c) -> a and b and c
  [Blockly.Python.ORDER_LOGICAL_AND, Blockly.Python.ORDER_LOGICAL_AND],
  // a or (b or c) -> a or b or c
  [Blockly.Python.ORDER_LOGICAL_OR, Blockly.Python.ORDER_LOGICAL_OR]
];

/**
 * Initialise the database of variable names.
 * @param {!Blockly.Workspace} workspace Workspace to generate code from.
 * @this {Blockly.Generator}
 */
Blockly.Python.init = function(workspace) {
  /**
   * Empty loops or conditionals are not allowed in Python.
   */
  Blockly.Python.PASS = this.INDENT + 'pass\n';
  // Create a dictionary of definitions to be printed before the code.
  Blockly.Python.definitions_ = Object.create(null);
  // Create a dictionary mapping desired function names in definitions_
  // to actual function names (to avoid collisions with user functions).
  Blockly.Python.functionNames_ = Object.create(null);

  if (!Blockly.Python.variableDB_) {
    Blockly.Python.variableDB_ =
        new Blockly.Names(Blockly.Python.RESERVED_WORDS_);
  } else {
    Blockly.Python.variableDB_.reset();
  }

  Blockly.Python.variableDB_.setVariableMap(workspace.getVariableMap());

  var defvars = [];
  // Add developer variables (not created or named by the user).
  var devVarList = Blockly.Variables.allDeveloperVariables(workspace);
  for (var i = 0; i < devVarList.length; i++) {
    defvars.push(Blockly.Python.variableDB_.getName(devVarList[i],
        Blockly.Names.DEVELOPER_VARIABLE_TYPE) + ' = None');
  }

  // Add user variables, but only ones that are being used.
  var variables = Blockly.Variables.allUsedVarModels(workspace);
  for (var i = 0; i < variables.length; i++) {
    defvars.push(Blockly.Python.variableDB_.getName(variables[i].getId(),
        Blockly.VARIABLE_CATEGORY_NAME) + ' = None');
  }

  Blockly.Python.definitions_['variables'] = defvars.join('\n');
};

/**
 * Prepend the generated code with the variable definitions.
 * @param {string} code Generated code.
 * @return {string} Completed code.
 */
Blockly.Python.finish = function(code) {
  // Convert the definitions dictionary into a list.
  var imports = [];
  var definitions = [];
  for (var name in Blockly.Python.definitions_) {
    var def = Blockly.Python.definitions_[name];
    if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) {
      imports.push(def);
    } else {
      definitions.push(def);
    }
  }
  // Clean up temporary data.
  delete Blockly.Python.definitions_;
  delete Blockly.Python.functionNames_;
  Blockly.Python.variableDB_.reset();
  var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n');
  return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code;
};

/**
 * Naked values are top-level blocks with outputs that aren't plugged into
 * anything.
 * @param {string} line Line of generated code.
 * @return {string} Legal line of code.
 */
Blockly.Python.scrubNakedValue = function(line) {
  return line + '\n';
};

/**
 * Encode a string as a properly escaped Python string, complete with quotes.
 * @param {string} string Text to encode.
 * @return {string} Python string.
 * @private
 */
Blockly.Python.quote_ = function(string) {
  // Can't use goog.string.quote since % must also be escaped.
  string = string.replace(/\\/g, '\\\\')
                 .replace(/\n/g, '\\\n');

  // Follow the CPython behaviour of repr() for a non-byte string.
  var quote = '\'';
  if (string.indexOf('\'') !== -1) {
    if (string.indexOf('"') === -1) {
      quote = '"';
    } else {
      string = string.replace(/'/g, '\\\'');
    }
  };
  return quote + string + quote;
};

/**
 * Encode a string as a properly escaped multiline Python string, complete
 * with quotes.
 * @param {string} string Text to encode.
 * @return {string} Python string.
 * @private
 */
Blockly.Python.multiline_quote_ = function(string) {
  var lines = string.split(/\n/g).map(Blockly.Python.quote_);
  // Join with the following, plus a newline:
  // + '\n' +
  return lines.join(' + \'\\n\' + \n');
};

/**
 * Common tasks for generating Python from blocks.
 * Handles comments for the specified block and any connected value blocks.
 * Calls any statements following this block.
 * @param {!Blockly.Block} block The current block.
 * @param {string} code The Python code created for this block.
 * @param {boolean=} opt_thisOnly True to generate code for only this statement.
 * @return {string} Python code with comments and subsequent blocks added.
 * @private
 */
Blockly.Python.scrub_ = function(block, code, opt_thisOnly) {
  var commentCode = '';
  // Only collect comments for blocks that aren't inline.
  if (!block.outputConnection || !block.outputConnection.targetConnection) {
    // Collect comment for this block.
    var comment = block.getCommentText();
    if (comment) {
      comment = Blockly.utils.string.wrap(comment,
          Blockly.Python.COMMENT_WRAP - 3);
      commentCode += Blockly.Python.prefixLines(comment + '\n', '# ');
    }
    // Collect comments for all value arguments.
    // Don't collect comments for nested statements.
    for (var i = 0; i < block.inputList.length; i++) {
      if (block.inputList[i].type == Blockly.INPUT_VALUE) {
        var childBlock = block.inputList[i].connection.targetBlock();
        if (childBlock) {
          comment = Blockly.Python.allNestedComments(childBlock);
          if (comment) {
            commentCode += Blockly.Python.prefixLines(comment, '# ');
          }
        }
      }
    }
  }
  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
  var nextCode = opt_thisOnly ? '' : Blockly.Python.blockToCode(nextBlock);
  return commentCode + code + nextCode;
};

/**
 * Gets a property and adjusts the value, taking into account indexing, and
 * casts to an integer.
 * @param {!Blockly.Block} block The block.
 * @param {string} atId The property ID of the element to get.
 * @param {number=} opt_delta Value to add.
 * @param {boolean=} opt_negate Whether to negate the value.
 * @return {string|number}
 */
Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) {
  var delta = opt_delta || 0;
  if (block.workspace.options.oneBasedIndex) {
    delta--;
  }
  var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0';
  var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE :
      Blockly.Python.ORDER_NONE;
  var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex;

  if (Blockly.isNumber(at)) {
    // If the index is a naked number, adjust it right now.
    at = parseInt(at, 10) + delta;
    if (opt_negate) {
      at = -at;
    }
  } else {
    // If the index is dynamic, adjust it in code.
    if (delta > 0) {
      at = 'int(' + at + ' + ' + delta + ')';
    } else if (delta < 0) {
      at = 'int(' + at + ' - ' + -delta + ')';
    } else {
      at = 'int(' + at + ')';
    }
    if (opt_negate) {
      at = '-' + at;
    }
  }
  return at;
};
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

// Meter class that generates a number correlated to audio volume.
// The meter class itself displays nothing, but it makes the
// instantaneous and time-decaying volumes available for inspection.
// It also reports on the fraction of samples that were at or near
// the top of the measurement range.
function SoundMeter(context) {
  this.context = context;
  this.instant = 0.0;
  this.slow = 0.0;
  this.clip = 0.0;
  this.script = context.createScriptProcessor(2048, 1, 1);
  var that = this;
  this.script.onaudioprocess = function(event) {
    var input = event.inputBuffer.getChannelData(0);
    var i;
    var sum = 0.0;
    var clipcount = 0;
    for (i = 0; i < input.length; ++i) {
      sum += input[i] * input[i];
      if (Math.abs(input[i]) > 0.99) {
        clipcount += 1;
      }
    }
    that.instant = Math.sqrt(sum / input.length);
    that.slow = 0.95 * that.slow + 0.05 * that.instant;
    that.clip = clipcount / input.length;
  };
}

SoundMeter.prototype.connectToSource = function (stream, callback) {
    console.log('SoundMeter connecting');
    try {
        this.mic = this.context.createMediaStreamSource(stream);
        this.mic.connect(this.script);
        // necessary to make sample run, but should not be.
        this.script.connect(this.context.destination);
        if (typeof callback != 'undefined')
            callback(null);
    } catch (e) {
        console.error(e);
        if (typeof callback != 'undefined')
            callback(e);
    }
};
SoundMeter.prototype.stop = function() {
  this.mic.disconnect();
  this.script.disconnect();
};
<commit_msg>fix the style issues<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

// Meter class that generates a number correlated to audio volume.
// The meter class itself displays nothing, but it makes the
// instantaneous and time-decaying volumes available for inspection.
// It also reports on the fraction of samples that were at or near
// the top of the measurement range.
function SoundMeter(context) {
  this.context = context;
  this.instant = 0.0;
  this.slow = 0.0;
  this.clip = 0.0;
  this.script = context.createScriptProcessor(2048, 1, 1);
  var that = this;
  this.script.onaudioprocess = function(event) {
    var input = event.inputBuffer.getChannelData(0);
    var i;
    var sum = 0.0;
    var clipcount = 0;
    for (i = 0; i < input.length; ++i) {
      sum += input[i] * input[i];
      if (Math.abs(input[i]) > 0.99) {
        clipcount += 1;
      }
    }
    that.instant = Math.sqrt(sum / input.length);
    that.slow = 0.95 * that.slow + 0.05 * that.instant;
    that.clip = clipcount / input.length;
  };
}

SoundMeter.prototype.connectToSource = function(stream, callback) {
  console.log('SoundMeter connecting');
  try {
      this.mic = this.context.createMediaStreamSource(stream);
      this.mic.connect(this.script);
      // necessary to make sample run, but should not be.
      this.script.connect(this.context.destination);
      if (typeof callback !== 'undefined') {
          callback(null);
      }
  } catch (e) {
      console.error(e);
      if (typeof callback !== 'undefined') {
          callback(e);
      }
  }
};
SoundMeter.prototype.stop = function() {
  this.mic.disconnect();
  this.script.disconnect();
};
<|endoftext|>


<commit_before>/*
  Copyright 2015 Google Inc. All Rights Reserved.
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

var assert = require('chai').assert;
var stageLoader = require('../../core/stage-loader');
var stages = require('../../core/stages');
var types = require('../../core/types');
var experiment = require('../../core/experiment');
var stream = require('../../core/stream');
var Promise = require('bluebird');

function testPipeline(stageList, incb) {
  var cb = function(data) { incb(); };
  stageLoader.processStages(stageList, cb, function(e) { throw e; });
};

// TODO: Terminate this with extreme prejudice
function testOutput(expectedResult) {
  return {
    impl: function(data) {
      assert.deepEqual(expectedResult, data.data[0].data);
      return Promise.resolve({command: 'done', stream: data});
    },
    name: 'testOutput',
    input: types.newTypeVar(),
    output: types.unit
  }
}

function fileComparisonPipeline(jsonFile, htmlFile) {
  return [
    stageLoader.stageSpecificationToStage({name: 'input', options: {data: jsonFile}}),
    stageLoader.stageSpecificationToStage('fileToBuffer'),
    stageLoader.stageSpecificationToStage('bufferToString'),
    stageLoader.stageSpecificationToStage('jsonParse'),
    stageLoader.stageSpecificationToStage("HTMLWriter"),
    stageLoader.stageSpecificationToStage({name: 'updateTag', options: {tag: 'data', in: /.*/, out: htmlFile}}),
    stageLoader.stageSpecificationToStage({name: 'compare', options: {tag: 'data'}})
  ];
}

function tokenizeDetokenizePipeline(jsonFile) {
  return [
    stageLoader.stageSpecificationToStage({name: 'input', options: {data: jsonFile}}),
    stageLoader.stageSpecificationToStage('fileToBuffer'),
    stageLoader.stageSpecificationToStage('bufferToString'),
    stageLoader.stageSpecificationToStage('jsonParse'),
    stageLoader.stageSpecificationToStage("StyleTokenizerFilter"),
    stageLoader.stageSpecificationToStage("StyleDetokenizerFilter"),
    stageLoader.stageSpecificationToStage({name: 'compare', options: {tag: 'data'}})
  ]
}

// TODO: glob these so we can automatically test lots of inputs/outputs.

describe('Simple Pipeline', function() {
  it('should generate valid html', function(done) {
    var output = testOutput('<!DOCTYPE html><base href="http://localhost:8000/simple.html">\n\n
This is some text in a div
\n');
    var pipeline = [{name: 'input', options: {data: 'tests/pipeline/simple.json'}}, 'fileToBuffer', 'bufferToString', 'jsonParse', "HTMLWriter"];
    pipeline = pipeline.map(stageLoader.stageSpecificationToStage);
    pipeline.push(output);
    testPipeline(pipeline, done);
  });

  it('simple json dumps should match prerendered html', function(done) {
    testPipeline(fileComparisonPipeline("tests/pipeline/simple.json", "tests/pipeline/simple.html"), done);
  });

  it('slightly more complicated json dumps should match prerendered html', function(done) {
    testPipeline(fileComparisonPipeline("tests/pipeline/inline-style.json", "tests/pipeline/inline-style.html"), done);
  });
});

describe('Style Tokenizer / Detokenizer', function() {
  it('should be idempotent in the absence of inline style', function(done) {
    testPipeline(tokenizeDetokenizePipeline("tests/pipeline/simple.json"), done);
  });

  it('should be idempotent in the presence of inline style', function(done) {
    testPipeline(tokenizeDetokenizePipeline("tests/pipeline/inline-style.json"), done);
  });
});

describe('experiment', function() {
  it('should be able to run', function(done) {
    testPipeline([{name: 'input', options: {data: 'tests/pipeline/simple.exp'}}, 'fileToBuffer', 'bufferToString', 'doExperiment'].map(stageLoader.stageSpecificationToStage), done);
  });
});

<commit_msg>Remove another require of stages<commit_after>/*
  Copyright 2015 Google Inc. All Rights Reserved.
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
      http://www.apache.org/licenses/LICENSE-2.0
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

var assert = require('chai').assert;
var stageLoader = require('../../core/stage-loader');
var types = require('../../core/types');
var experiment = require('../../core/experiment');
var stream = require('../../core/stream');
var Promise = require('bluebird');

function testPipeline(stageList, incb) {
  var cb = function(data) { incb(); };
  stageLoader.processStages(stageList, cb, function(e) { throw e; });
};

// TODO: Terminate this with extreme prejudice
function testOutput(expectedResult) {
  return {
    impl: function(data) {
      assert.deepEqual(expectedResult, data.data[0].data);
      return Promise.resolve({command: 'done', stream: data});
    },
    name: 'testOutput',
    input: types.newTypeVar(),
    output: types.unit
  }
}

function fileComparisonPipeline(jsonFile, htmlFile) {
  return [
    stageLoader.stageSpecificationToStage({name: 'input', options: {data: jsonFile}}),
    stageLoader.stageSpecificationToStage('fileToBuffer'),
    stageLoader.stageSpecificationToStage('bufferToString'),
    stageLoader.stageSpecificationToStage('jsonParse'),
    stageLoader.stageSpecificationToStage("HTMLWriter"),
    stageLoader.stageSpecificationToStage({name: 'updateTag', options: {tag: 'data', in: /.*/, out: htmlFile}}),
    stageLoader.stageSpecificationToStage({name: 'compare', options: {tag: 'data'}})
  ];
}

function tokenizeDetokenizePipeline(jsonFile) {
  return [
    stageLoader.stageSpecificationToStage({name: 'input', options: {data: jsonFile}}),
    stageLoader.stageSpecificationToStage('fileToBuffer'),
    stageLoader.stageSpecificationToStage('bufferToString'),
    stageLoader.stageSpecificationToStage('jsonParse'),
    stageLoader.stageSpecificationToStage("StyleTokenizerFilter"),
    stageLoader.stageSpecificationToStage("StyleDetokenizerFilter"),
    stageLoader.stageSpecificationToStage({name: 'compare', options: {tag: 'data'}})
  ]
}

// TODO: glob these so we can automatically test lots of inputs/outputs.

describe('Simple Pipeline', function() {
  it('should generate valid html', function(done) {
    var output = testOutput('<!DOCTYPE html><base href="http://localhost:8000/simple.html">\n\n
This is some text in a div
\n');
    var pipeline = [{name: 'input', options: {data: 'tests/pipeline/simple.json'}}, 'fileToBuffer', 'bufferToString', 'jsonParse', "HTMLWriter"];
    pipeline = pipeline.map(stageLoader.stageSpecificationToStage);
    pipeline.push(output);
    testPipeline(pipeline, done);
  });

  it('simple json dumps should match prerendered html', function(done) {
    testPipeline(fileComparisonPipeline("tests/pipeline/simple.json", "tests/pipeline/simple.html"), done);
  });

  it('slightly more complicated json dumps should match prerendered html', function(done) {
    testPipeline(fileComparisonPipeline("tests/pipeline/inline-style.json", "tests/pipeline/inline-style.html"), done);
  });
});

describe('Style Tokenizer / Detokenizer', function() {
  it('should be idempotent in the absence of inline style', function(done) {
    testPipeline(tokenizeDetokenizePipeline("tests/pipeline/simple.json"), done);
  });

  it('should be idempotent in the presence of inline style', function(done) {
    testPipeline(tokenizeDetokenizePipeline("tests/pipeline/inline-style.json"), done);
  });
});

describe('experiment', function() {
  it('should be able to run', function(done) {
    testPipeline([{name: 'input', options: {data: 'tests/pipeline/simple.exp'}}, 'fileToBuffer', 'bufferToString', 'doExperiment'].map(stageLoader.stageSpecificationToStage), done);
  });
});

<|endoftext|>