<commit_before>var clone = require('clone');
var each = require('each');
var svgAttributes = require('svg-attributes');

var Route = require('../core/route');
var RoutePattern = require('../core/pattern');
var Util = require('../util');

var styles = require('./styles');

/**
 * Element Types
 */

var types = [
  'labels',
  'segments',
  'segments_front',
  'segments_halo',
  'segment_labels',
  'segment_label_containers',
  'stops_merged',
  'stops_pattern',
  'places',
  'places_icon',
  'multipoints_merged',
  'multipoints_pattern',
  'wireframe_vertices',
  'wireframe_edges'
];

/**
 * Add transform
 */

svgAttributes.push('transform');

/**
 * Expose `Styler`
 */

module.exports = Styler;

/**
 * Styler object
 */

function Styler(styles) {
  if (!(this instanceof Styler)) return new Styler(styles);

  // reset styles
  this.reset();

  // load styles
  if (styles) this.load(styles);
}

/**
 * Clear all current styles
 */

Styler.prototype.clear = function() {
  for (var i in types) {
    this[types[i]] = {};
  }
};

/**
 * Reset to the predefined styles
 */

Styler.prototype.reset = function() {
  for (var i in types) {
    var type = types[i];
    this[type] = clone(styles[type] || {});
    for (var key in this[type]) {
      if (!Array.isArray(this[type][key])) this[type][key] = [this[type][key]];
    }
  }
};

/**
 * Load rules
 *
 * @param {Object} a set of style rules
 */

Styler.prototype.load = function(styles) {
  var self = this;
  for (var i in types) {
    var type = types[i];
    if (styles[type]) {
      for (var key in styles[type]) {
        this[type][key] = (this[type][key] || []).concat(styles[type][key]);
      }
    }
  }
};

/**
 * Style a Segment using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {RenderedSegment} Transitive RenderedSegment object
 */

Styler.prototype.styleSegment = function(display, segment) {

  if (segment.lineGraphHalo) {

    this.applyAttrAndStyle(
      display,
      segment.lineGraphHalo,
      this.segments_halo
    );
  }

  this.applyAttrAndStyle(
    display,
    segment.lineGraph,
    this.segments
  );

  this.applyAttrAndStyle(
    display,
    segment.lineGraphFront,
    this.segments_front
  );
};

/**
 * Style a WireframeEdge using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {WireframeEdge} Transitive WireframeEdge object
 */

Styler.prototype.styleWireframeEdge = function(display, wfEdge) {
  this.applyAttrAndStyle(
    display,
    wfEdge.svgGroup.selectAll('.transitive-wireframe-edge-line'),
    this.wireframe_edges
  );
};

/**
 * Style a Point using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Point} Transitive Point object
 */

Styler.prototype.stylePoint = function(display, point) {
  if (point.getType() === 'STOP') this.styleStop(display, point);
  if (point.getType() === 'PLACE') this.stylePlace(display, point);
  if (point.getType() === 'MULTI') this.styleMultiPoint(display, point);
  if (point.getType() === 'WIREFRAME_VERTEX') this.styleWireframeVertex(display, point);
};

/**
 * Style a Stop using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.styleStop = function(display, stop) {
  this.applyAttrAndStyle(
    display,
    stop.patternMarkers,
    this.stops_pattern
  );

  this.applyAttrAndStyle(
    display,
    stop.mergedMarker,
    this.stops_merged
  );

  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Style a Place using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Place} Transitive Place object
 */

Styler.prototype.stylePlace = function(display, place) {
  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-circle'),
    this.places
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-icon'),
    this.places_icon
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Style a MultiPoint using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.styleMultiPoint = function(display, multipoint) {
  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-pattern'),
    this.multipoints_pattern
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-merged'),
    this.multipoints_merged
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

/**
 * Style a WireframeVertex using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {WireframeVertex} Transitive WireframeVertex object
 */

Styler.prototype.styleWireframeVertex = function(display, wfVertex) {
  this.applyAttrAndStyle(
    display,
    wfVertex.svgGroup.selectAll('.transitive-wireframe-vertex-circle'),
    this.wireframe_vertices
  );
};

/**
 * Style a Point label using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Point} Transitive Point object
 */

Styler.prototype.stylePointLabel = function(display, point) {
  var pointType = point.getType().toLowerCase();

  this.applyAttrAndStyle(
    display,
    point.svgGroup.selectAll('.transitive-' + pointType + '-label'),
    this.labels
  );
};

/**
 * Style a Segment label using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {SegmentLabel} Transitive SegmentLabel object
 */

Styler.prototype.styleSegmentLabel = function(display, label) {
  this.applyAttrAndStyle(
    display,
    label.svgGroup.selectAll('.transitive-segment-label-container'),
    this.segment_label_containers
  );
  this.applyAttrAndStyle(
    display,
    label.svgGroup.selectAll('.transitive-segment-label'),
    this.segment_labels
  );
};

/**
 * Check if it's an attribute or a style and apply accordingly
 *
 * @param {Display} the Display object
 * @param {Object} a D3 list of elements
 * @param {Object} the list of attributes
 */

Styler.prototype.applyAttrAndStyle = function(display, elements, attributes) {
  for (var name in attributes) {
    var rules = attributes[name];
    var fn = svgAttributes.indexOf(name) === -1 ? 'style' : 'attr';

    this.applyRules(display, elements, name, rules, fn);
  }
};

/**
 * Apply style/attribute rules to a list of elements
 *
 * @param {Display} display object
 * @param {Object} elements
 * @param {String} rule name
 * @param {Array} rules
 * @param {String} style/attr
 */

Styler.prototype.applyRules = function(display, elements, name, rules, fn) {
  var self = this;
  elements[fn](name, function(data, index) {
    return self.compute(rules, display, data, index);
  });
};

/**
 * Compute a style rule based on the current display and data
 *
 * @param {Array} array of rules
 * @param {Object} the Display object
 * @param {Object} data associated with this object
 * @param {Number} index of this object
 */

Styler.prototype.compute = function(rules, display, data, index) {
  var computed, self = this;
  for (var i in rules) {
    var rule = rules[i];
    var val = isFunction(rule) ? rule.call(self, display, data, index, styles.utils) :
      rule;
    if (val !== undefined && val !== null) computed = val;
  }
  return computed;
};

/**
 * Return the collection of default segment styles for a mode.
 *
 * @param {String} an OTP mode string
 */

Styler.prototype.getModeStyles = function(mode, display) {

  var modeStyles = {};

  // simulate a segment w/ the specified style
  var segment = {
    focused: true,
    isFocused: function() {
      return true;
    }
  };

  if (mode === "WALK" || mode === "BICYCLE" || mode === "CAR") {
    segment.type = mode;
  } else { // assume a transit mode
    segment.type = "TRANSIT";
    segment.mode = Util.otpModeToGtfsType(mode);
    var route = new Route({
      route_type: segment.mode,
      agency_id: "",
      route_id: "",
      route_short_name: "",
      route_long_name: ""
    });
    var pattern = new RoutePattern({});
    route.addPattern(pattern);
    segment.patterns = [pattern];
  }

  for (var attrName in this.segments) {
    var rules = this.segments[attrName];
    for (var i in rules) {
      var rule = rules[i];
      var val = isFunction(rule) ? rule.call(this, display, segment, 0, styles.utils) :
        rule;
      if (val !== undefined && val !== null) {
        modeStyles[attrName] = val;
      }
    }
  }

  return modeStyles;
};

/**
 * Is function?
 */

function isFunction(val) {
  return Object.prototype.toString.call(val) === '[object Function]';
}
<commit_msg>Consider BICYCLE_RENT in getModeStyles<commit_after>var clone = require('clone');
var each = require('each');
var svgAttributes = require('svg-attributes');

var Route = require('../core/route');
var RoutePattern = require('../core/pattern');
var Util = require('../util');

var styles = require('./styles');

/**
 * Element Types
 */

var types = [
  'labels',
  'segments',
  'segments_front',
  'segments_halo',
  'segment_labels',
  'segment_label_containers',
  'stops_merged',
  'stops_pattern',
  'places',
  'places_icon',
  'multipoints_merged',
  'multipoints_pattern',
  'wireframe_vertices',
  'wireframe_edges'
];

/**
 * Add transform
 */

svgAttributes.push('transform');

/**
 * Expose `Styler`
 */

module.exports = Styler;

/**
 * Styler object
 */

function Styler(styles) {
  if (!(this instanceof Styler)) return new Styler(styles);

  // reset styles
  this.reset();

  // load styles
  if (styles) this.load(styles);
}

/**
 * Clear all current styles
 */

Styler.prototype.clear = function() {
  for (var i in types) {
    this[types[i]] = {};
  }
};

/**
 * Reset to the predefined styles
 */

Styler.prototype.reset = function() {
  for (var i in types) {
    var type = types[i];
    this[type] = clone(styles[type] || {});
    for (var key in this[type]) {
      if (!Array.isArray(this[type][key])) this[type][key] = [this[type][key]];
    }
  }
};

/**
 * Load rules
 *
 * @param {Object} a set of style rules
 */

Styler.prototype.load = function(styles) {
  var self = this;
  for (var i in types) {
    var type = types[i];
    if (styles[type]) {
      for (var key in styles[type]) {
        this[type][key] = (this[type][key] || []).concat(styles[type][key]);
      }
    }
  }
};

/**
 * Style a Segment using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {RenderedSegment} Transitive RenderedSegment object
 */

Styler.prototype.styleSegment = function(display, segment) {

  if (segment.lineGraphHalo) {

    this.applyAttrAndStyle(
      display,
      segment.lineGraphHalo,
      this.segments_halo
    );
  }

  this.applyAttrAndStyle(
    display,
    segment.lineGraph,
    this.segments
  );

  this.applyAttrAndStyle(
    display,
    segment.lineGraphFront,
    this.segments_front
  );
};

/**
 * Style a WireframeEdge using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {WireframeEdge} Transitive WireframeEdge object
 */

Styler.prototype.styleWireframeEdge = function(display, wfEdge) {
  this.applyAttrAndStyle(
    display,
    wfEdge.svgGroup.selectAll('.transitive-wireframe-edge-line'),
    this.wireframe_edges
  );
};

/**
 * Style a Point using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Point} Transitive Point object
 */

Styler.prototype.stylePoint = function(display, point) {
  if (point.getType() === 'STOP') this.styleStop(display, point);
  if (point.getType() === 'PLACE') this.stylePlace(display, point);
  if (point.getType() === 'MULTI') this.styleMultiPoint(display, point);
  if (point.getType() === 'WIREFRAME_VERTEX') this.styleWireframeVertex(display, point);
};

/**
 * Style a Stop using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Stop} Transitive Stop object
 */

Styler.prototype.styleStop = function(display, stop) {
  this.applyAttrAndStyle(
    display,
    stop.patternMarkers,
    this.stops_pattern
  );

  this.applyAttrAndStyle(
    display,
    stop.mergedMarker,
    this.stops_merged
  );

  this.applyAttrAndStyle(
    display,
    stop.svgGroup.selectAll('.transitive-stop-label'),
    this.labels
  );
};

/**
 * Style a Place using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Place} Transitive Place object
 */

Styler.prototype.stylePlace = function(display, place) {
  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-circle'),
    this.places
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-icon'),
    this.places_icon
  );

  this.applyAttrAndStyle(
    display,
    place.svgGroup.selectAll('.transitive-place-label'),
    this.labels
  );
};

/**
 * Style a MultiPoint using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {MultiPoint} Transitive MultiPoint object
 */

Styler.prototype.styleMultiPoint = function(display, multipoint) {
  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-pattern'),
    this.multipoints_pattern
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multipoint-marker-merged'),
    this.multipoints_merged
  );

  this.applyAttrAndStyle(
    display,
    multipoint.svgGroup.selectAll('.transitive-multi-label'),
    this.labels
  );
};

/**
 * Style a WireframeVertex using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {WireframeVertex} Transitive WireframeVertex object
 */

Styler.prototype.styleWireframeVertex = function(display, wfVertex) {
  this.applyAttrAndStyle(
    display,
    wfVertex.svgGroup.selectAll('.transitive-wireframe-vertex-circle'),
    this.wireframe_vertices
  );
};

/**
 * Style a Point label using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {Point} Transitive Point object
 */

Styler.prototype.stylePointLabel = function(display, point) {
  var pointType = point.getType().toLowerCase();

  this.applyAttrAndStyle(
    display,
    point.svgGroup.selectAll('.transitive-' + pointType + '-label'),
    this.labels
  );
};

/**
 * Style a Segment label using the rules defined in styles.js or the Transitive options
 *
 * @param {Display} Transitive Display object
 * @param {SegmentLabel} Transitive SegmentLabel object
 */

Styler.prototype.styleSegmentLabel = function(display, label) {
  this.applyAttrAndStyle(
    display,
    label.svgGroup.selectAll('.transitive-segment-label-container'),
    this.segment_label_containers
  );
  this.applyAttrAndStyle(
    display,
    label.svgGroup.selectAll('.transitive-segment-label'),
    this.segment_labels
  );
};

/**
 * Check if it's an attribute or a style and apply accordingly
 *
 * @param {Display} the Display object
 * @param {Object} a D3 list of elements
 * @param {Object} the list of attributes
 */

Styler.prototype.applyAttrAndStyle = function(display, elements, attributes) {
  for (var name in attributes) {
    var rules = attributes[name];
    var fn = svgAttributes.indexOf(name) === -1 ? 'style' : 'attr';

    this.applyRules(display, elements, name, rules, fn);
  }
};

/**
 * Apply style/attribute rules to a list of elements
 *
 * @param {Display} display object
 * @param {Object} elements
 * @param {String} rule name
 * @param {Array} rules
 * @param {String} style/attr
 */

Styler.prototype.applyRules = function(display, elements, name, rules, fn) {
  var self = this;
  elements[fn](name, function(data, index) {
    return self.compute(rules, display, data, index);
  });
};

/**
 * Compute a style rule based on the current display and data
 *
 * @param {Array} array of rules
 * @param {Object} the Display object
 * @param {Object} data associated with this object
 * @param {Number} index of this object
 */

Styler.prototype.compute = function(rules, display, data, index) {
  var computed, self = this;
  for (var i in rules) {
    var rule = rules[i];
    var val = isFunction(rule) ? rule.call(self, display, data, index, styles.utils) :
      rule;
    if (val !== undefined && val !== null) computed = val;
  }
  return computed;
};

/**
 * Return the collection of default segment styles for a mode.
 *
 * @param {String} an OTP mode string
 */

Styler.prototype.getModeStyles = function(mode, display) {
  var modeStyles = {};

  // simulate a segment w/ the specified style
  var segment = {
    focused: true,
    isFocused: function() {
      return true;
    }
  };

  if (mode === "WALK" || mode === "BICYCLE" ||  mode === "BICYCLE_RENT" || mode === "CAR") {
    segment.type = mode;
  } else { // assume a transit mode
    segment.type = "TRANSIT";
    segment.mode = Util.otpModeToGtfsType(mode);
    var route = new Route({
      route_type: segment.mode,
      agency_id: "",
      route_id: "",
      route_short_name: "",
      route_long_name: ""
    });
    var pattern = new RoutePattern({});
    route.addPattern(pattern);
    segment.patterns = [pattern];
  }

  for (var attrName in this.segments) {
    var rules = this.segments[attrName];
    for (var i in rules) {
      var rule = rules[i];
      var val = isFunction(rule) ? rule.call(this, display, segment, 0, styles.utils) :
        rule;
      if (val !== undefined && val !== null) {
        modeStyles[attrName] = val;
      }
    }
  }

  return modeStyles;
};

/**
 * Is function?
 */

function isFunction(val) {
  return Object.prototype.toString.call(val) === '[object Function]';
}
<|endoftext|>


<commit_before>import superagent from "superagent-es6";

function Api(config) {
  this.config = config;

  var self = this;
  for (var name in config.services) {
    if (!this.hasOwnProperty(name)) {
      this[name] = function (data, fn) {
        var req = self.request(name, data).end(fn ? fn : function (res) {
          req.emit(res.ok ? "success" : "error", res);
        });
        return req;
      };
    }
  }
}

Api.prototype = {
  service: function (id) {
    return this.config.services[id];
  },

  url: function (id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      url += path[0] === "/" ? path : "/" + path;
    }

    return url;
  },

  request: function (id, data) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method || "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }
    var request = superagent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var _req = request(this.url(id), data);
    var header, opts;

    // add global headers
    for (header in this.config.headers) {
      _req.set(header, this.config.headers[header]);
    }

    // add global options to request headers
    for (opts in this.config.options) {
      _req[opts](this.config.options[opts]);
    }

    // add service options to request headers
    for (opts in service.options) {
      _req[opts](service.options[opts]);
    }

    // add service headers
    for (header in service.headers) {
      _req.set(header, service.headers[header]);
    }

    return _req;
  }
};

export default Api;
<commit_msg>fix(api): service handlers are now set in a closure<commit_after>import superagent from "superagent-es6";

function Api(config) {
  this.config = config;

  var self = this;
  // closure
  var serviceHandler = function (service) {
    return function (data, fn) {
      var req = self.request(service, data).end(fn ? fn : function (res) {
        req.emit(res.ok ? "success" : "error", res);
      });
      return req;
    };
  };
  for (var name in config.services) {
    if (!this.hasOwnProperty(name)) {
      // syntatic sugar: install a service handler available on
      // the api instance with service name
      self[name] = serviceHandler(name);
    }
  }
}

Api.prototype = {
  service: function (id) {
    return this.config.services[id];
  },

  url: function (id) {
    var url = this.config.baseUrl;
    var resource = this.service(id);

    // from time being it"s a simple map
    if (resource) {
      var path;

      if (typeof resource === "string") {
        path = resource;
      }

      if (typeof resource === "object" && resource.path !== undefined) {
        path = resource.path;
      }

      if (!path) {
        throw new Error("path is not defined for route $" + id);
      }

      url += path[0] === "/" ? path : "/" + path;
    }

    return url;
  },

  request: function (id, data) {
    var service = this.service(id);
    var method = (typeof service === "string" ? "get" : service.method || "get").toLowerCase();
    // fix for delete being a reserved word
    if (method === "delete") {
      method = "del";
    }
    var request = superagent[method];
    if (!request) {
      throw new Error("Invalid method [" + service.method + "]");
    }

    var _req = request(this.url(id), data);
    var header, opts;

    // add global headers
    for (header in this.config.headers) {
      _req.set(header, this.config.headers[header]);
    }

    // add global options to request headers
    for (opts in this.config.options) {
      _req[opts](this.config.options[opts]);
    }

    // add service options to request headers
    for (opts in service.options) {
      _req[opts](service.options[opts]);
    }

    // add service headers
    for (header in service.headers) {
      _req.set(header, service.headers[header]);
    }

    return _req;
  }
};

export default Api;
<|endoftext|>


<commit_before>'use strict';

var split = require('split-string');
var convert = require('../convert');
var utils = require('../utils');

module.exports = function(options, converter) {
  var opts = Object.assign({}, options);
  var captured = [];

  return function(parser) {
    if (typeof opts.transform === 'function') {
      parser.on('token', function(node) {
        opts.transform.call(parser, node);
      });
    }

    if (opts.strictErrors === true) {
      parser.on('error', function(err) {
        console.log('PARSER ERROR');
        console.log(err);
        process.exit(1);
      });
    }

    parser
      .set('yfm', function() {
        if (this.parsed) return;
        var m = this.match(/^---/);
        if (!m) return;

        var val = this.advanceTo('---');
        if (val && val.split('---').join('').trim() === '') {
          val = '';
        }

        if (val) {
          var node = this.node({type: 'yfm', val: val});
          converter.yfm = node;
          return node;
        }
      })
      .set('text', function() {
        var m = this.match(/^([^{]+)/);
        if (m) {
          var str = this.input;
          var val = m[0];

          while (str[0] === '{' && str[1] !== '{' && str[1] !== '%') {
            var idx = str.indexOf('{', 1);
            if (idx === -1) break;
            val += str.slice(0, idx);
            str = this.input = str.slice(idx);
          }
          return this.node(val);
        }
      })
      .set('tag', function() {
        var parsed = this.parsed;
        var m = this.match(/^\{%(.*?)%\}/);
        if (!m) return;

        var args = m[1].trim();
        var node = {
          type: 'tag',
          args: args,
          rest: ''
        };

        var ch = node.args.charAt(0);
        if (ch === '%') {
          node.type = 'literal';
          node.val = m[1].slice(1);
          return this.node(node);
        }

        if (ch === '!') {
          node.type = 'comment';
          node.args = node.args.slice(1);
          return this.node(node);
        }

        if (ch === '-') {
          args = args.slice(1).trim();
          node.stripLeft = true;
        }

        if (args.slice(-1) === '-') {
          args = args.slice(0, -1).trim();
          node.stripRight = true;
        }

        node.args = utils.namespaceArgs(args, opts);
        node.name = args.trim();
        var segs = utils.splitArgs(args, ' ');
        if (segs.length > 1) {
          node.name = segs[0].trim();
          node.rest = segs.slice(1).join(' ');
        }

        if (utils.hasEndTag(node.name, this.input)) {
          node.hasClose = true;
        } else if (segs.length === 1) {
          node.type = 'expression';
        }

        if (node.name === 'layout') {
          var val = '\nlayout: ' + node.rest.trim();
          if (converter.yfm) {
            converter.yfm.val = val + converter.yfm.val;
            return;
          }
          return this.node({type: 'yfm', val: val});
        }

        if (segs.indexOf('by') !== -1) {
          node.args = node.args.split(' by ').join(' by=');
        }

        if (node.name === 'case' && utils.isString(node.rest)) {
          var key = node.rest;

          var inner = this.advanceTo('{% endcase %}') + '{% endcase %}';
          var lines = inner.split(/\r?\n/);
          var cases = 0;
          node.args = '';

          for (var i = 0; i < lines.length; i++) {
            var line = lines[i];
            if (i === lines.length - 1) {
              lines[i] = '{{/is}}';
            }

            var match = /{% when\s+(.*)%}/.exec(line);
            if (match) {
              var comp = utils.toString(match[1]);
              var replacement = '';

              if (cases === 0) {
                replacement = `{{#is ${key} ${convert.conditional(comp)}}}`;
              } else {
                replacement = `{{else is ${key} ${convert.conditional(comp)}}}`;
              }
              lines[i] = line.replace(/{% when\s+(.*)%}/, replacement);
              cases++;
            }

            inner = lines.join('\n').trim();
          }

          this.input = inner + this.input;
        }

        return this.node(node);
      })

      .set('expression', function() {
        var m = this.match(/^(\{{2,3})(.+?)\}{2,3}/);
        if (!m) return;

        var args = m[2].trim();
        var node = {
          type: 'expression',
          delims: m[1],
          args: args,
          name: args,
          val: args,
          rest: ''
        };

        if (node.args.charAt(0) === '!') {
          node.type = 'comment';
          node.args = node.args.slice(1);
          return this.node(node);
        }

        if (node.args.trim() === 'content') {
          node.type = 'body';
          return this.node(node);
        }

        if (node.args.charAt(0) === '-' && node.args.charAt(1) === ' ') {
          node.args = node.args.slice(1).trim();
          node.name = node.args;
          node.stripLeft = true;
        }

        var len = node.args.length;
        if (node.args[len - 1] === '-' && node.args[len - 2] === ' ') {
          node.args = node.args.slice(0, -1).trim();
          node.name = node.args;
          node.stripRight = true;
        }
        return this.node(node);
      })
      .set('rest', function() {
        var regex = utils.textRegex();
        var match = this.match(regex);
        if (match) {
          return this.node(match[0]);
        }
      });
  };
};
<commit_msg>strip comments from front-matter<commit_after>'use strict';

var split = require('split-string');
var convert = require('../convert');
var utils = require('../utils');

module.exports = function(options, converter) {
  var opts = Object.assign({}, options);
  var captured = [];

  return function(parser) {
    if (typeof opts.transform === 'function') {
      parser.on('token', function(node) {
        opts.transform.call(parser, node);
      });
    }

    if (opts.strictErrors === true) {
      parser.on('error', function(err) {
        console.log('PARSER ERROR');
        console.log(err);
        process.exit(1);
      });
    }

    parser
      .set('yfm', function() {
        if (this.parsed) return;
        var m = this.match(/^---/);
        if (!m) return;

        var val = this.advanceTo('---');
        var lines = val.split(/[\r\n]+/);
        var actual = [''];

        for (var i = 0; i < lines.length; i++) {
          var line = lines[i].trim();
          if (line !== '' && line.charAt(0) !== '#') {
            actual.push(line);
          }
        }

        actual.push('');
        val = actual.join('\n');

        if (val) {
          var node = this.node({type: 'yfm', val: val});
          converter.yfm = node;
          return node;
        }
      })

      .set('text', function() {
        var m = this.match(/^([^{]+)/);
        if (m) {
          var str = this.input;
          var val = m[0];

          while (str[0] === '{' && str[1] !== '{' && str[1] !== '%') {
            var idx = str.indexOf('{', 1);
            if (idx === -1) break;
            val += str.slice(0, idx);
            str = this.input = str.slice(idx);
          }
          return this.node(val);
        }
      })
      .set('tag', function() {
        var parsed = this.parsed;
        var m = this.match(/^\{%(.*?)%\}/);
        if (!m) return;

        var args = m[1].trim();
        var node = {
          type: 'tag',
          args: args,
          rest: ''
        };

        var ch = node.args.charAt(0);
        if (ch === '%') {
          node.type = 'literal';
          node.val = m[1].slice(1);
          return this.node(node);
        }

        if (ch === '!') {
          node.type = 'comment';
          node.args = node.args.slice(1);
          return this.node(node);
        }

        if (ch === '-') {
          args = args.slice(1).trim();
          node.stripLeft = true;
        }

        if (args.slice(-1) === '-') {
          args = args.slice(0, -1).trim();
          node.stripRight = true;
        }

        node.args = utils.namespaceArgs(args, opts);
        node.name = args.trim();
        var segs = utils.splitArgs(args, ' ');
        if (segs.length > 1) {
          node.name = segs[0].trim();
          node.rest = segs.slice(1).join(' ');
        }

        if (utils.hasEndTag(node.name, this.input)) {
          node.hasClose = true;
        } else if (segs.length === 1) {
          node.type = 'expression';
        }

        if (node.name === 'layout') {
          var val = '\nlayout: ' + node.rest.trim();
          if (converter.yfm) {
            converter.yfm.val = val + converter.yfm.val;
            return;
          }
          return this.node({type: 'yfm', val: val});
        }

        if (segs.indexOf('by') !== -1) {
          node.args = node.args.split(' by ').join(' by=');
        }

        if (node.name === 'case' && utils.isString(node.rest)) {
          var key = node.rest;

          var inner = this.advanceTo('{% endcase %}') + '{% endcase %}';
          var lines = inner.split(/\r?\n/);
          var cases = 0;
          node.args = '';

          for (var i = 0; i < lines.length; i++) {
            var line = lines[i];
            if (i === lines.length - 1) {
              lines[i] = '{{/is}}';
            }

            var match = /{% when\s+(.*)%}/.exec(line);
            if (match) {
              var comp = utils.toString(match[1]);
              var replacement = '';

              if (cases === 0) {
                replacement = `{{#is ${key} ${convert.conditional(comp)}}}`;
              } else {
                replacement = `{{else is ${key} ${convert.conditional(comp)}}}`;
              }
              lines[i] = line.replace(/{% when\s+(.*)%}/, replacement);
              cases++;
            }

            inner = lines.join('\n').trim();
          }

          this.input = inner + this.input;
        }

        return this.node(node);
      })

      .set('expression', function() {
        var m = this.match(/^(\{{2,3})(.+?)\}{2,3}/);
        if (!m) return;

        var args = m[2].trim();
        var node = {
          type: 'expression',
          delims: m[1],
          args: args,
          name: args,
          val: args,
          rest: ''
        };

        if (node.args.charAt(0) === '!') {
          node.type = 'comment';
          node.args = node.args.slice(1);
          return this.node(node);
        }

        if (node.args.trim() === 'content') {
          node.type = 'body';
          return this.node(node);
        }

        if (node.args.charAt(0) === '-' && node.args.charAt(1) === ' ') {
          node.args = node.args.slice(1).trim();
          node.name = node.args;
          node.stripLeft = true;
        }

        var len = node.args.length;
        if (node.args[len - 1] === '-' && node.args[len - 2] === ' ') {
          node.args = node.args.slice(0, -1).trim();
          node.name = node.args;
          node.stripRight = true;
        }
        return this.node(node);
      })
      .set('rest', function() {
        var regex = utils.textRegex();
        var match = this.match(regex);
        if (match) {
          return this.node(match[0]);
        }
      });
  };
};
<|endoftext|>


<commit_before>
var AST   = require('../ast'),
    types = require('../types'),
    Scope = require('../typesystem/scope'),
    LLVM  = require('../../../llvm2'),
    Builtins = require('./llvm/builtins')

var Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

function Slots () {
  this.slots = {}
}
Slots.prototype.checkAllocated = function (name) {
  var slot = this.slots[name]
  if (!slot) {
    throw new Error('Slot not allocated: '+name)
  }
}
Slots.prototype.buildAlloc = function (ctx, name) {
  if (this.slots[name]) {
    throw new Error('Slot already allocated: '+name)
  }
  var slot = ctx.builder.buildAlloca(Int8PtrType, name)
  this.slots[name] = slot
}
Slots.prototype.buildSet = function (ctx, name, value) {
  assertInstanceOf(value, Buffer)
  var slot = this.slots[name],
      zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)
  // Get the element pointer
  var ptr = ctx.builder.buildGEP(slot, [zero], name)
  return ctx.builder.buildStore(value, ptr)
}
Slots.prototype.buildGet = function (ctx, name) {
  this.checkAllocated(name)
  var slot = this.slots[name],
      ptr  = ctx.builder.buildGEP(slot, [Int32Zero], name)
  return ctx.builder.buildLoad(ptr, name)
}
Slots.prototype.buildAllocAndSet = function (ctx, name, value) {
  this.buildAlloc(ctx, name)
  return this.buildSet(ctx, name, value)
}

function ConstantSlots () {
  this.slots = {}
}
ConstantSlots.prototype.buildGet = function (ctx, name) {
  var value = this.slots[name]
  if (!value) {
    throw new Error('Constant slot not found: '+name)
  }
  return value
}

AST.Root.prototype.emitToFile = function (outFile) {
  var ctx = {}
  ctx.module       = new LLVM.Module('test')
  ctx.builder      = new LLVM.Builder()
  ctx.pass_manager = new LLVM.FunctionPassManager(ctx.module)
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new ConstantSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Set up the main function
  var mainType  = new LLVM.FunctionType(VoidType, [], false),
      mainFunc  = ctx.module.addFunction('main', mainType),
      mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainEntry)

  ctx.module.dump()
  ctx.module.writeBitcodeToFile(outFile)
}

AST.Root.prototype.buildMain = function (ctx, mainEntry) {
  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  compileBlock(ctx, this, mainEntry)

  // var str = ctx.builder.buildGlobalStringPtr("Hello world!\n", 'greeting')
  // ctx.builder.buildCall(ctx.funcs.puts, [str], '')
  ctx.builder.buildRetVoid()
}

function compileBlock (ctx, block, entry) {
  // Bunch of pre-conditions to make sure we got sane arguments
  if (!(block.statements instanceof Array)) {
    throw new Error('Missing statements in block')
  }
  if (!(block.scope instanceof Scope)) {
    throw new Error('Missing block\'s scope')
  }
  if (!entry) {
    throw new Error('Missing entry point for block')
  }

  // Set up slots for each local
  var scopeLocals = block.scope.locals,
      slots       = new Slots()
  Object.keys(scopeLocals).forEach(function (name) {
    slots.buildAlloc(ctx, name)
  })
  // Add the slots to the map of slots in the context
  ctx.slotsMap[block.scope.id] = slots
  // Set up a new context just for this block
  var blockCtx = new BlockContext(ctx, block, slots)

  var statements = block.statements
  for (var i = 0; i < statements.length; i++) {
    var stmt = statements[i]
    stmt.compile(ctx, blockCtx)
  }
}

function assertInstanceOf (value, type, message) {
  if (!(value instanceof type)) {
    if (!message) {
      message = 'Incorrect type; expected '+type.name+', got '+value.constructor.name
    }
    throw new Error(message)
  }
}

function BlockContext (ctx, block, slots) {
  this.ctx   = ctx
  this.block = block
  this.slots = slots
}

AST.Assignment.prototype.compile = function (ctx, blockCtx) {
  if (this.type === 'var' || this.type === 'let') {
    this.compileNamed(ctx, blockCtx)
  }
}

AST.Assignment.prototype.compileNamed = function (ctx, blockCtx) {
  // Get a value pointer from the rvalue
  var rvalue = this.rvalue.compileToValue(ctx, blockCtx)
  assertInstanceOf(rvalue, Buffer, 'Received non-Buffer from Node#compilerToValue')
  // Get the slot pointer
  blockCtx.slots.buildSet(ctx, this.lvalue.name, rvalue)
}

AST.Literal.prototype.compileToValue = function (ctx, blockCtx) {
  var instance = this.type
  switch (instance.type.constructor) {
    case types.String:
      var stringValue = this.value
      // Build a constant with our string value and return that
      var val = ctx.builder.buildGlobalStringPtr(stringValue, '')
      return val
    default:
      var name = instance.type.constructor.name
      throw new Error('AST.Literal#compileToValue: Cannot handle instance type: '+name)
  }
}

function checkScopePathForClosureOverreach (scopePath) {
  // Figure out the first (outermost) and last (innermost) indices of the closures
  var firstClosingIdx = -1,
      lastClosingIdx  = -1
  for (var i = 0; i < scopePath.length; i++) {
    var s = scopePath[i]
    if (s.isClosing) {
      // If the first closing index has been set then we know we're the first
      // one found
      if (firstClosingIdx === -1) { firstClosingIdx = i }
      // Push back the last closing index if we found another one
      if (i > lastClosingIdx) { lastClosingIdx = i }
    }
  }
  // If the closing indices don't match then we know we've busted through closures
  if (firstClosingIdx !== lastClosingIdx) {
    throw new Error('Too many closures')
  }
  // If the first closing index isn't the outermost one then we've busted
  // beyond a closure
  if (firstClosingIdx > 0) {
    throw new Error('Accessing variable beyond closure')
  }
}

AST.Chain.prototype.compileToValue = function (ctx, blockCtx) {
  // Keep tracking of the scope of the beginning of the chain
  var outermostScope = null
  var itemType = blockCtx.block.scope.get(this.name, function (scope, type) {
    outermostScope = scope
  })

  var scope     = blockCtx.block.scope,
      scopePath = []
  while (scope !== outermostScope) {
    if (!scope) {
      throw new Error('Ran out of scopes!')
    }
    scopePath.unshift(scope)
    scope = scope.parent
  }
  // Outermost scope will now be the first in `scopePath`; innermost scope
  // will be the last in `scopePath`.

  // Check this scope path to make sure we didn't bust any closures
  checkScopePathForClosureOverreach(scopePath)

  // Look up the Slots for the scope that the head of our chain belongs to
  var slots = ctx.slotsMap[outermostScope.id]
  if (!slots) {
    throw new Error("Couldn't find slots for scope #"+outermostScope.id)
  }
  var itemValue = slots.buildGet(ctx, this.name)

  // Handle the tail
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
    case AST.Property:
      assertInstanceOf(itemType, types.Instance)
      // Look up the type of the instance and get the native struct for it
      var type         = itemType.type,
          nativeObject = type.getNativeObject(),
          propertyName = item.name
      // Get the pointer to the property value
      var ptr = nativeObject.buildStructGEPForProperty(ctx, itemValue, propertyName)
      // Update the type and value
      itemType = type.getTypeOfProperty(propertyName)
      itemValue = ctx.builder.buildLoad(ptr, propertyName)
      break
    case AST.Call:
      assertInstanceOf(itemType, types.Function)
      // Compile all the args into values
      var argValues = item.args.map(function (arg) {
        return arg.compileToValue(ctx, blockCtx)
      })
      itemType  = new types.Instance(itemType.ret)
      itemValue = ctx.builder.buildCall(itemValue, argValues, '')
      break
    default:
      throw new Error("Cannot handle item type: "+item.constructor.name)
    }
  }
  return itemValue
}

AST.Chain.prototype.compile = function (ctx, blockCtx) {
  this.compileToValue(ctx, blockCtx)
}

AST.Chain.prototype.compileIntrinsic = function (ctx, blockCtx, baseInstance) {
  var base = baseInstance.type,
      self = this
  var lastIndex = this.tail.length - 1
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
      case AST.Property:
        base = base.getTypeOfProperty(item.name)
        continue
      case AST.Call:
        if (i !== lastIndex) {
          throw new Error('AST.Chain#compileIntrinsic: Can only handle call as last index')
        }
        assertInstanceOf(base, types.Function)
        var nativeFunction = base.getNativeFunction()
        var args = item.args.map(function (arg) {
          return arg.compileToValue(ctx, blockCtx)
        })
        var fn = nativeFunction.fn
        return ctx.builder.buildCall(fn, args, '')
        continue
      default:
        throw new Error('Cannot handle item type: '+item.constructor.name)
    }
  }
  throw new Error('AST.Chain#compileIntrinsic: Unreachable')
}

<commit_msg>Refactor scope path computation and checking<commit_after>
var AST   = require('../ast'),
    types = require('../types'),
    Scope = require('../typesystem/scope'),
    LLVM  = require('../../../llvm2'),
    Builtins = require('./llvm/builtins')

var Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

function Slots () {
  this.slots = {}
}
Slots.prototype.checkAllocated = function (name) {
  var slot = this.slots[name]
  if (!slot) {
    throw new Error('Slot not allocated: '+name)
  }
}
Slots.prototype.buildAlloc = function (ctx, name) {
  if (this.slots[name]) {
    throw new Error('Slot already allocated: '+name)
  }
  var slot = ctx.builder.buildAlloca(Int8PtrType, name)
  this.slots[name] = slot
}
Slots.prototype.buildSet = function (ctx, name, value) {
  assertInstanceOf(value, Buffer)
  var slot = this.slots[name],
      zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)
  // Get the element pointer
  var ptr = ctx.builder.buildGEP(slot, [zero], name)
  return ctx.builder.buildStore(value, ptr)
}
Slots.prototype.buildGet = function (ctx, name) {
  this.checkAllocated(name)
  var slot = this.slots[name],
      ptr  = ctx.builder.buildGEP(slot, [Int32Zero], name)
  return ctx.builder.buildLoad(ptr, name)
}
Slots.prototype.buildAllocAndSet = function (ctx, name, value) {
  this.buildAlloc(ctx, name)
  return this.buildSet(ctx, name, value)
}

function ConstantSlots () {
  this.slots = {}
}
ConstantSlots.prototype.buildGet = function (ctx, name) {
  var value = this.slots[name]
  if (!value) {
    throw new Error('Constant slot not found: '+name)
  }
  return value
}

AST.Root.prototype.emitToFile = function (outFile) {
  var ctx = {}
  ctx.module       = new LLVM.Module('test')
  ctx.builder      = new LLVM.Builder()
  ctx.pass_manager = new LLVM.FunctionPassManager(ctx.module)
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new ConstantSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Set up the main function
  var mainType  = new LLVM.FunctionType(VoidType, [], false),
      mainFunc  = ctx.module.addFunction('main', mainType),
      mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainEntry)

  ctx.module.dump()
  ctx.module.writeBitcodeToFile(outFile)
}

AST.Root.prototype.buildMain = function (ctx, mainEntry) {
  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  compileBlock(ctx, this, mainEntry)

  // var str = ctx.builder.buildGlobalStringPtr("Hello world!\n", 'greeting')
  // ctx.builder.buildCall(ctx.funcs.puts, [str], '')
  ctx.builder.buildRetVoid()
}

function compileBlock (ctx, block, entry) {
  // Bunch of pre-conditions to make sure we got sane arguments
  if (!(block.statements instanceof Array)) {
    throw new Error('Missing statements in block')
  }
  if (!(block.scope instanceof Scope)) {
    throw new Error('Missing block\'s scope')
  }
  if (!entry) {
    throw new Error('Missing entry point for block')
  }

  // Set up slots for each local
  var scopeLocals = block.scope.locals,
      slots       = new Slots()
  Object.keys(scopeLocals).forEach(function (name) {
    slots.buildAlloc(ctx, name)
  })
  // Add the slots to the map of slots in the context
  ctx.slotsMap[block.scope.id] = slots
  // Set up a new context just for this block
  var blockCtx = new BlockContext(ctx, block, slots)

  var statements = block.statements
  for (var i = 0; i < statements.length; i++) {
    var stmt = statements[i]
    stmt.compile(ctx, blockCtx)
  }
}

function assertInstanceOf (value, type, message) {
  if (!(value instanceof type)) {
    if (!message) {
      message = 'Incorrect type; expected '+type.name+', got '+value.constructor.name
    }
    throw new Error(message)
  }
}

function BlockContext (ctx, block, slots) {
  this.ctx   = ctx
  this.block = block
  this.slots = slots
}

AST.Assignment.prototype.compile = function (ctx, blockCtx) {
  if (this.type === 'var' || this.type === 'let') {
    this.compileNamed(ctx, blockCtx)
  }
}

AST.Assignment.prototype.compileNamed = function (ctx, blockCtx) {
  // Get a value pointer from the rvalue
  var rvalue = this.rvalue.compileToValue(ctx, blockCtx)
  assertInstanceOf(rvalue, Buffer, 'Received non-Buffer from Node#compilerToValue')
  // Get the slot pointer
  blockCtx.slots.buildSet(ctx, this.lvalue.name, rvalue)
}

AST.Literal.prototype.compileToValue = function (ctx, blockCtx) {
  var instance = this.type
  switch (instance.type.constructor) {
    case types.String:
      var stringValue = this.value
      // Build a constant with our string value and return that
      var val = ctx.builder.buildGlobalStringPtr(stringValue, '')
      return val
    default:
      var name = instance.type.constructor.name
      throw new Error('AST.Literal#compileToValue: Cannot handle instance type: '+name)
  }
}

function checkScopePathForClosureOverreach (scopePath) {
  // Figure out the first (outermost) and last (innermost) indices of the closures
  var firstClosingIdx = -1,
      lastClosingIdx  = -1
  for (var i = 0; i < scopePath.length; i++) {
    var s = scopePath[i]
    if (s.isClosing) {
      // If the first closing index has been set then we know we're the first
      // one found
      if (firstClosingIdx === -1) { firstClosingIdx = i }
      // Push back the last closing index if we found another one
      if (i > lastClosingIdx) { lastClosingIdx = i }
    }
  }
  // If the closing indices don't match then we know we've busted through closures
  if (firstClosingIdx !== lastClosingIdx) {
    throw new Error('Too many closures')
  }
  // If the first closing index isn't the outermost one then we've busted
  // beyond a closure
  if (firstClosingIdx > 0) {
    throw new Error('Accessing variable beyond closure')
  }
}

function computeScopePath (blockCtx, outermostScope) {
  var scope = blockCtx.block.scope,
      path  = []
  while (true) {
    path.unshift(scope)
    // Stop building the scope path if we encountered the outermost scope
    if (scope === outermostScope) {
      break
    }
    // Otherwise go to the parent scope
    scope = scope.parent
    if (!scope) {
      throw new Error('Ran out of scopes!')
    }
  }
  return path
}

AST.Chain.prototype.compileToValue = function (ctx, blockCtx) {
  // Keep tracking of the scope of the beginning of the chain
  var outermostScope = null
  var itemType = blockCtx.block.scope.get(this.name, function (scope, type) {
    outermostScope = scope
  })

  // Outermost scope will be the first in `scopePath`; innermost scope
  // will be the last in `scopePath`.
  var scopePath = computeScopePath(blockCtx, outermostScope)

  // Sanity-check the `scopePath` to make sure it's outermost scope is the
  // same as the one we got from the Scope class' scope resolver.
  if (scopePath[0] !== outermostScope) {
    throw new Error('Invalid scope path: first scope does not match outermost scope')
  }

  // Check this scope path to make sure we didn't bust any closures
  checkScopePathForClosureOverreach(scopePath)

  // Look up the Slots for the scope that the head of our chain belongs to
  var slots = ctx.slotsMap[outermostScope.id]
  if (!slots) {
    throw new Error("Couldn't find slots for scope #"+outermostScope.id)
  }
  var itemValue = slots.buildGet(ctx, this.name)

  // Handle the tail
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
    case AST.Property:
      assertInstanceOf(itemType, types.Instance)
      // Look up the type of the instance and get the native struct for it
      var type         = itemType.type,
          nativeObject = type.getNativeObject(),
          propertyName = item.name
      // Get the pointer to the property value
      var ptr = nativeObject.buildStructGEPForProperty(ctx, itemValue, propertyName)
      // Update the type and value
      itemType = type.getTypeOfProperty(propertyName)
      itemValue = ctx.builder.buildLoad(ptr, propertyName)
      break
    case AST.Call:
      assertInstanceOf(itemType, types.Function)
      // Compile all the args into values
      var argValues = item.args.map(function (arg) {
        return arg.compileToValue(ctx, blockCtx)
      })
      itemType  = new types.Instance(itemType.ret)
      itemValue = ctx.builder.buildCall(itemValue, argValues, '')
      break
    default:
      throw new Error("Cannot handle item type: "+item.constructor.name)
    }
  }
  return itemValue
}

AST.Chain.prototype.compile = function (ctx, blockCtx) {
  this.compileToValue(ctx, blockCtx)
}

AST.Chain.prototype.compileIntrinsic = function (ctx, blockCtx, baseInstance) {
  var base = baseInstance.type,
      self = this
  var lastIndex = this.tail.length - 1
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
      case AST.Property:
        base = base.getTypeOfProperty(item.name)
        continue
      case AST.Call:
        if (i !== lastIndex) {
          throw new Error('AST.Chain#compileIntrinsic: Can only handle call as last index')
        }
        assertInstanceOf(base, types.Function)
        var nativeFunction = base.getNativeFunction()
        var args = item.args.map(function (arg) {
          return arg.compileToValue(ctx, blockCtx)
        })
        var fn = nativeFunction.fn
        return ctx.builder.buildCall(fn, args, '')
        continue
      default:
        throw new Error('Cannot handle item type: '+item.constructor.name)
    }
  }
  throw new Error('AST.Chain#compileIntrinsic: Unreachable')
}

<|endoftext|>


<commit_before>import React from "react";
import _ from "lodash";
// import {ReactSVGPanZoom} from 'react-svg-pan-zoom';
import * as globals from "./globals";
import graphUtil from "../util/graphUtil";
import Axes from "./graphAxes";
import Hulls from "./hull";
import BarChartsForGroupVotes from "./barChartsForGroupVotes";
import ExploreTid from "./exploreTid";
import TidCarousel from "./tidCarousel";
import Participants from "./graphParticipants";
import Comments from "./graphComments";
import Curate from "./curate";
import HullLabels from "./hullLabels";

class Graph extends React.Component {

  constructor(props) {
    super(props);
    this.hullElems = [];
    this.Viewer = null;

    this.state = {
      selectedComment: null,
      selectedTidCuration: null,
      browserDimensions: window.innerWidth
    };
  }

  componentWillMount() {

    window.addEventListener("resize", () => {
      this.setState({browserDimensions: window.innerWidth})
    })

    // document.getElementById("helpTextGroups").style.display = "none";
    // document.getElementById("visualization_div").style.display = "none";
    // document.getElementById("carouselPane").style.display = "none";
    // document.getElementById("groupSelectionViewContainer").style.display = "none";
  }

  componentWillReceiveProps(nextProps, nextState) {

    if (!nextProps.math) {
      return;
    }

    let tidsToShowSet = _.keyBy(nextProps.tidsToShow);

    let {
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCentroids,
      groupCornerAssignments,
      ptptoisProjected,
    } = graphUtil(nextProps.comments, nextProps.math, nextProps.badTids, nextProps.ptptois);

    commentsPoints = commentsPoints.filter((c) => {
      return !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let tidCarouselComments = nextProps.comments.filter((c) => {
      return !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let selectedComment = this.state.selectedComment

    if (this.state.selectedComment === null && this.state.selectedTidCuration !== null) {
      selectedComment = tidCarouselComments[0]
    }

    this.setState({
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCentroids,
      groupCornerAssignments,
      commentsPoints,
      ptptoisProjected,
      selectedComment,
      tidCarouselComments
    })

  }

  handleCommentHover(selectedComment) {
    return () => {
      // document.getElementById("readReactView").style.display = "none";
      this.setState({
        selectedComment
      });
    }
  }

  handleCommentClick(selectedComment) {
    return () => {
      // document.getElementById("readReactView").style.display = "none";
      this.setState({
        selectedComment
      });
    }
  }

  handleReturnToVoteClicked() {
    // document.getElementById("readReactView").style.display = "block";
    this.setState({selectedComment: null})
  }
  handleCurateButtonClick (tidCuration) {

    this.setState({
      selectedTidCuration: tidCuration,
      selectedComment: null
    }, () => {
      this.props.onCurationChange && this.props.onCurationChange(tidCuration);
    });
  }

  getHullElems(gid) {
    return (elem) => {
      if (elem !== null) {
        this.hullElems[gid] = elem;
      }
    }
  }

  render() {

    let ww = $(document.body).width();
    let w = globals.sideWithPadding;
    let svgScale = 1;
    /*
      if the width of the body is less than the width of the svg...
      scale it down
      if the body is at 500 and the svg is 700, then it's a 5 to 7 ratio
      scaling factor on the svg
    */
    if (ww < w) {
      svgScale = ww / w;
    }
    let svgNegativeMargin = globals.svgHeightWithPadding * (svgScale - 1);

    return (

        <svg width={globals.sideWithPadding} height={globals.svgHeightWithPadding} style={{
          transform: "scale("+svgScale+")",
          transformOrigin: "0% 0%",
          marginBottom: svgNegativeMargin}
        }>
          <filter id="grayscale">
             <feColorMatrix type="saturate" values="0"/>
          </filter>
          <g transform={`translate(${globals.padding}, ${globals.padding})`}>
            {/* Comment https://bl.ocks.org/mbostock/7555321 */}
            <g transform={`translate(${globals.side / 2}, ${15})`}>
              <text
                style={{
                  fontFamily: "Georgia",
                  fontSize: 14,
                  fontStyle: "italic"
                }}
                textAnchor="middle">

              </text>
            </g>
            <Axes
              xCenter={this.state.xCenter}
              yCenter={this.state.yCenter}
              report={this.props.report}/>
            <Hulls
              handleClick={this.handleCurateButtonClick.bind(this)}
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              getHullElems={this.getHullElems.bind(this)}
              hulls={this.state.hulls} />
            <Participants
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              points={this.state.baseClustersScaled}
              ptptois={this.state.ptptoisProjected}/>
            <HullLabels
              handleClick={this.handleCurateButtonClick.bind(this)}
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              groups={this.props.math["group-votes"] || window.preload.firstMath["group-votes"] /* for labels */}
              centroids={this.state.groupCentroids}
              />
            {/*<Comments
              commentsPoints={this.state.commentsPoints}
              selectedComment={this.state.selectedComment}
              handleCommentHover={this.handleCommentHover.bind(this)}
              points={this.state.commentsPoints}
              repfulAgreeTidsByGroup={this.props.repfulAgreeTidsByGroup}
              repfulDisageeTidsByGroup={this.props.repfulDisageeTidsByGroup}
              formatTid={this.props.formatTid}/>*/}
            <BarChartsForGroupVotes
              hullElems={this.hullElems}
              selectedComment={this.state.selectedComment}
              allComments={this.props.comments}
              groups={this.props.math["group-votes"] || window.preload.firstMath["group-votes"]}
              groupCornerAssignments={this.state.groupCornerAssignments}
              />
          </g>
        </svg>

          <Curate
            handleCurateButtonClick={this.handleCurateButtonClick.bind(this)}
            math={this.props.math}
            selectedTidCuration={this.state.selectedTidCuration}
            Strings={this.props.Strings}
            />
          <TidCarousel
            selectedTidCuration={this.state.selectedTidCuration}
            commentsToShow={this.state.tidCarouselComments}
            handleCommentClick={this.handleCommentClick.bind(this)}
            selectedComment={this.state.selectedComment}
            Strings={this.props.Strings}
            />

        <ExploreTid
          handleReturnToVoteClicked={this.handleReturnToVoteClicked.bind(this)}
          selectedComment={this.state.selectedComment}
          votesByMe={this.props.votesByMe}
          selectedTidCuration={this.state.selectedTidCuration}
          math={this.props.math || window.preload.firstMath}
          onVoteClicked={this.props.onVoteClicked}
          Strings={this.props.Strings}
          comments={this.props.comment}/>

    );
  }
}

export default Graph;

/* heading */

// let heading = (
 Opinion Graph

//

//     This graph shows all people and all comments.
//

//

//     Comments, identified by their number, are positioned more closely to comments that were voted on similarly (blue, in the correlation matrix above). Comments are positioned further away from comments that tended to be voted on differently (red, in the correlation matrix above).

//
People are positioned closer to the comments on which they agreed, and further from the comments on which they disagreed. Groups of participants that tended to vote similarly across many comments (elaborated in the previous section) are identified by their similar color.
//
);
//   {this.props.renderHeading ? heading : ""}

/* group labels */

// {/* this.props.math["group-clusters"].map((cluster, i) => {
//   return (<text x={300} y={300}> Renzi Supporters </text>)
// }) : null */}

/* React SVG Pan Zoom */

// componentDidMount() {
//   this.Viewer.fitToViewer();
// }
//

//   <button onClick={event => this.Viewer.zoomOnViewerCenter(1.1)}>Zoom in</button>
//   <button onClick={event => this.Viewer.fitSelection(40, 40, 200, 200)}>Zoom area</button>
//   <button onClick={event => this.Viewer.fitToViewer()}>Fit</button>
//

// <ReactSVGPanZoom
//   style={{outline: "1px solid black", fill: "white"}}
//   width={500} height={500} ref={Viewer => this.Viewer = Viewer}
//   onClick={event => console.log('click', event.x, event.y, event.originalEvent)}
//   onMouseMove={event => console.log('move', event.x, event.y)} >
//
// </ReactSVGPanZoom>
<commit_msg>check viz parent rather than window for embed glitch<commit_after>import React from "react";
import _ from "lodash";
// import {ReactSVGPanZoom} from 'react-svg-pan-zoom';
import * as globals from "./globals";
import graphUtil from "../util/graphUtil";
import Axes from "./graphAxes";
import Hulls from "./hull";
import BarChartsForGroupVotes from "./barChartsForGroupVotes";
import ExploreTid from "./exploreTid";
import TidCarousel from "./tidCarousel";
import Participants from "./graphParticipants";
import Comments from "./graphComments";
import Curate from "./curate";
import HullLabels from "./hullLabels";

class Graph extends React.Component {

  constructor(props) {
    super(props);
    this.hullElems = [];
    this.Viewer = null;

    this.state = {
      selectedComment: null,
      selectedTidCuration: null,
      browserDimensions: window.innerWidth
    };
  }

  componentWillMount() {

    window.addEventListener("resize", () => {
      this.setState({browserDimensions: window.innerWidth})
    })

    // document.getElementById("helpTextGroups").style.display = "none";
    // document.getElementById("visualization_div").style.display = "none";
    // document.getElementById("carouselPane").style.display = "none";
    // document.getElementById("groupSelectionViewContainer").style.display = "none";
  }

  componentWillReceiveProps(nextProps, nextState) {

    if (!nextProps.math) {
      return;
    }

    let tidsToShowSet = _.keyBy(nextProps.tidsToShow);

    let {
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCentroids,
      groupCornerAssignments,
      ptptoisProjected,
    } = graphUtil(nextProps.comments, nextProps.math, nextProps.badTids, nextProps.ptptois);

    commentsPoints = commentsPoints.filter((c) => {
      return !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let tidCarouselComments = nextProps.comments.filter((c) => {
      return !_.isUndefined(tidsToShowSet[c.tid]);
    });

    let selectedComment = this.state.selectedComment

    if (this.state.selectedComment === null && this.state.selectedTidCuration !== null) {
      selectedComment = tidCarouselComments[0]
    }

    this.setState({
      xx,
      yy,
      commentsPoints,
      xCenter,
      yCenter,
      baseClustersScaled,
      commentScaleupFactorX,
      commentScaleupFactorY,
      hulls,
      groupCentroids,
      groupCornerAssignments,
      commentsPoints,
      ptptoisProjected,
      selectedComment,
      tidCarouselComments
    })

  }

  handleCommentHover(selectedComment) {
    return () => {
      // document.getElementById("readReactView").style.display = "none";
      this.setState({
        selectedComment
      });
    }
  }

  handleCommentClick(selectedComment) {
    return () => {
      // document.getElementById("readReactView").style.display = "none";
      this.setState({
        selectedComment
      });
    }
  }

  handleReturnToVoteClicked() {
    // document.getElementById("readReactView").style.display = "block";
    this.setState({selectedComment: null})
  }
  handleCurateButtonClick (tidCuration) {

    this.setState({
      selectedTidCuration: tidCuration,
      selectedComment: null
    }, () => {
      this.props.onCurationChange && this.props.onCurationChange(tidCuration);
    });
  }

  getHullElems(gid) {
    return (elem) => {
      if (elem !== null) {
        this.hullElems[gid] = elem;
      }
    }
  }

  render() {

    let ww = parseInt(getComputedStyle(document.getElementById('visualization_parent_div')).width, 10);
    let w = globals.sideWithPadding;
    let svgScale = 1;
    /*
      if the width of the body is less than the width of the svg...
      scale it down
      if the body is at 500 and the svg is 700, then it's a 5 to 7 ratio
      scaling factor on the svg
    */
    if (ww < w) {
      svgScale = ww / w;
    }
    let svgNegativeMargin = globals.svgHeightWithPadding * (svgScale - 1);

    return (

        <svg width={globals.sideWithPadding} height={globals.svgHeightWithPadding} style={{
          transform: "scale("+svgScale+")",
          transformOrigin: "0% 0%",
          marginBottom: svgNegativeMargin}
        }>
          <filter id="grayscale">
             <feColorMatrix type="saturate" values="0"/>
          </filter>
          <g transform={`translate(${globals.padding}, ${globals.padding})`}>
            {/* Comment https://bl.ocks.org/mbostock/7555321 */}
            <g transform={`translate(${globals.side / 2}, ${15})`}>
              <text
                style={{
                  fontFamily: "Georgia",
                  fontSize: 14,
                  fontStyle: "italic"
                }}
                textAnchor="middle">

              </text>
            </g>
            <Axes
              xCenter={this.state.xCenter}
              yCenter={this.state.yCenter}
              report={this.props.report}/>
            <Hulls
              handleClick={this.handleCurateButtonClick.bind(this)}
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              getHullElems={this.getHullElems.bind(this)}
              hulls={this.state.hulls} />
            <Participants
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              points={this.state.baseClustersScaled}
              ptptois={this.state.ptptoisProjected}/>
            <HullLabels
              handleClick={this.handleCurateButtonClick.bind(this)}
              selectedGroup={_.isNumber(this.state.selectedTidCuration) ? this.state.selectedTidCuration : null}
              groups={this.props.math["group-votes"] || window.preload.firstMath["group-votes"] /* for labels */}
              centroids={this.state.groupCentroids}
              />
            {/*<Comments
              commentsPoints={this.state.commentsPoints}
              selectedComment={this.state.selectedComment}
              handleCommentHover={this.handleCommentHover.bind(this)}
              points={this.state.commentsPoints}
              repfulAgreeTidsByGroup={this.props.repfulAgreeTidsByGroup}
              repfulDisageeTidsByGroup={this.props.repfulDisageeTidsByGroup}
              formatTid={this.props.formatTid}/>*/}
            <BarChartsForGroupVotes
              hullElems={this.hullElems}
              selectedComment={this.state.selectedComment}
              allComments={this.props.comments}
              groups={this.props.math["group-votes"] || window.preload.firstMath["group-votes"]}
              groupCornerAssignments={this.state.groupCornerAssignments}
              />
          </g>
        </svg>

          <Curate
            handleCurateButtonClick={this.handleCurateButtonClick.bind(this)}
            math={this.props.math}
            selectedTidCuration={this.state.selectedTidCuration}
            Strings={this.props.Strings}
            />
          <TidCarousel
            selectedTidCuration={this.state.selectedTidCuration}
            commentsToShow={this.state.tidCarouselComments}
            handleCommentClick={this.handleCommentClick.bind(this)}
            selectedComment={this.state.selectedComment}
            Strings={this.props.Strings}
            />

        <ExploreTid
          handleReturnToVoteClicked={this.handleReturnToVoteClicked.bind(this)}
          selectedComment={this.state.selectedComment}
          votesByMe={this.props.votesByMe}
          selectedTidCuration={this.state.selectedTidCuration}
          math={this.props.math || window.preload.firstMath}
          onVoteClicked={this.props.onVoteClicked}
          Strings={this.props.Strings}
          comments={this.props.comment}/>

    );
  }
}

export default Graph;

/* heading */

// let heading = (
 Opinion Graph

//

//     This graph shows all people and all comments.
//

//

//     Comments, identified by their number, are positioned more closely to comments that were voted on similarly (blue, in the correlation matrix above). Comments are positioned further away from comments that tended to be voted on differently (red, in the correlation matrix above).

//
People are positioned closer to the comments on which they agreed, and further from the comments on which they disagreed. Groups of participants that tended to vote similarly across many comments (elaborated in the previous section) are identified by their similar color.
//
);
//   {this.props.renderHeading ? heading : ""}

/* group labels */

// {/* this.props.math["group-clusters"].map((cluster, i) => {
//   return (<text x={300} y={300}> Renzi Supporters </text>)
// }) : null */}

/* React SVG Pan Zoom */

// componentDidMount() {
//   this.Viewer.fitToViewer();
// }
//

//   <button onClick={event => this.Viewer.zoomOnViewerCenter(1.1)}>Zoom in</button>
//   <button onClick={event => this.Viewer.fitSelection(40, 40, 200, 200)}>Zoom area</button>
//   <button onClick={event => this.Viewer.fitToViewer()}>Fit</button>
//

// <ReactSVGPanZoom
//   style={{outline: "1px solid black", fill: "white"}}
//   width={500} height={500} ref={Viewer => this.Viewer = Viewer}
//   onClick={event => console.log('click', event.x, event.y, event.originalEvent)}
//   onMouseMove={event => console.log('move', event.x, event.y)} >
//
// </ReactSVGPanZoom>
<|endoftext|>


<commit_before>// temporary
// =========

// disable Hello, removing in FF49
user_pref('loop.enabled', false)
user_pref('loop.do_not_disturb', true)

// user interface
// ==============

// search
user_pref('browser.search.suggest.enabled', false)
user_pref('browser.urlbar.suggest.searches', false)

// "fixing" urls
user_pref('keyword.enabled', false)  // don't submit mistyped URLs to Google
user_pref('browser.fixup.alternate.enabled', false)  // http://example should not try http://example.com
user_pref('browser.urlbar.filter.javascript', true)  // javascript: URLs are evil

// new tab page
user_pref('browser.newtab.preload', false)
user_pref('browser.newtabpage.enabled', false)
user_pref('browser.newtabpage.enhanced', false)

// disable about:home tips
user_pref('browser.aboutHomeSnippets.updateUrl', '')

// url bar
user_pref('browser.urlbar.trimURLs', false)  // show me the full URL

// disable warnings
user_pref('browser.tabs.warnOnClose', false)
user_pref('browser.tabs.warnOnCloseOtherTabs', false)
user_pref('browser.tabs.warnOnOpen', false)
user_pref('browser.warnOnQuit', false)
user_pref('general.warnOnAboutConfig', false)
user_pref('network.warnOnAboutNetworking', false)

// disable some browser features
user_pref('reader.parse-on-load.enabled', false)  // reader
user_pref('extensions.pocket.enabled', false)  // Pocket
user_pref('pdfjs.disabled', false)  // PDF reader

// okay, i've already seen these things
user_pref('browser.newtabpage.introShown', true)

// disable clipboard silliness Linux
user_pref('clipboard.autocopy', false)
user_pref('middlemouse.contentLoadURL', false)
user_pref('middlemouse.paste', false)

// html
// ====

// things to disable and enable
user_pref('beacon.enabled', false)  // beacon API
user_pref('browser.send_pings.require_same_host', true)  // probably redundant with below
user_pref('browser.send_pings', false)  // <a ping>
user_pref('device.sensors.enabled', false)  // navigator.sensor API
user_pref('dom.battery.enabled', false)  // battery API
user_pref('dom.disable_beforeunload', false)  // "are you sure you want to leave this page"
user_pref('dom.enable_performance', false)  // navigation timing API
user_pref('dom.event.clipboardevents.enabled', false)  // clipboard events API
user_pref('dom.gamepad.enabled', false)  // gamepad API
user_pref('dom.indexedDB.enabled', false)  // indexedDB
user_pref('dom.netinfo.enabled', false)  // network info API
user_pref('dom.vr.cardboard.enabled', false)  // VR + Cardboard
user_pref('dom.vr.enabled', false)  // VR API
user_pref('dom.vr.oculus.enabled', false)  // VR + Oculus
user_pref('dom.vr.oculus050.enabled', false)  // VR + Oculus
user_pref('dom.webnotifications.enabled', false)  // notifications
user_pref('geo.enabled', false)  // geolocation API
user_pref('geo.wifi.uri', '')  // geolocation API
user_pref('javascript.options.asmjs', false)  // asm
user_pref('javascript.options.wasm', false)  // WebAssembly
user_pref('media.getusermedia.screensharing.allowed_domains', '')  // screen sharing
user_pref('media.getusermedia.screensharing.enabled', false)  // screen sharing
user_pref('media.peerconnection.enabled', false)  // webRTC
user_pref('media.webspeech.recognition.enable', false)  // speech recognition
user_pref('network.manage-offline-status', false)  // navigator.onLine
user_pref('webgl.disabled', true)  // webGL

// remove transitions around fullscreen API
user_pref('full-screen-api.transition-duration.enter', '0 0')
user_pref('full-screen-api.transition-duration.leave', '0 0')

// set defaults for unspecified fonts, etc
user_pref('browser.display.background_color', '#f6f6f6')

// ask to activate Flash
user_pref('plugin.state.flash', 1)

// obliterate Java
user_pref('plugin.state.java', 0)
user_pref('network.jar.block-remote-files', true)
user_pref('network.jar.open-unsafe-types', false)

// privacy
// =======

// tracking protection
user_pref('privacy.trackingprotection.enabled', true)
user_pref('privacy.trackingprotection.pbmode.enabled', true)
user_pref('privacy.trackingprotection.introCount', false)  // don't give me the intro

// disable "safe browsing" so that Google might not know everything i see
user_pref('browser.safebrowsing.enabled', false)
user_pref('browser.safebrowsing.downloads.enabled', false)
user_pref('browser.safebrowsing.malware.enabled', false)

// DNT header
user_pref('privacy.donottrackheader.enabled', true)
user_pref('privacy.donottrackheader.value', 1)

// not sure what this is exactly, but i am disabling it
user_pref('camera.control.face_detection.enabled', false)

// extensions
// ==========

// https everywhere
user_pref('extensions.https_everywhere._observatory.enabled', false)
user_pref('extensions.https_everywhere._observatory.popup_shown', true)
user_pref('extensions.https_everywhere.toolbar_hint_shown', true)
<commit_msg>minor: move some user.js stuff around<commit_after>// temporary
// =========

// disable Hello, removing in FF49
user_pref('loop.enabled', false)
user_pref('loop.do_not_disturb', true)

// user interface
// ==============

// disable some browser features
user_pref('general.smoothScroll', false)  // smooth scrolling
user_pref('reader.parse-on-load.enabled', false)  // reader
user_pref('extensions.pocket.enabled', false)  // Pocket
user_pref('pdfjs.disabled', false)  // PDF reader

// search
user_pref('browser.search.suggest.enabled', false)
user_pref('browser.urlbar.suggest.searches', false)

// "fixing" urls
user_pref('keyword.enabled', false)  // don't submit mistyped URLs to Google
user_pref('browser.fixup.alternate.enabled', false)  // http://example should not try http://example.com
user_pref('browser.urlbar.filter.javascript', true)  // javascript: URLs are evil

// new tab page
user_pref('browser.newtab.preload', false)
user_pref('browser.newtabpage.enabled', false)
user_pref('browser.newtabpage.enhanced', false)

// disable about:home tips
user_pref('browser.aboutHomeSnippets.updateUrl', '')

// url bar
user_pref('browser.urlbar.trimURLs', false)  // show me the full URL

// disable warnings
user_pref('browser.tabs.warnOnClose', false)
user_pref('browser.tabs.warnOnCloseOtherTabs', false)
user_pref('browser.tabs.warnOnOpen', false)
user_pref('browser.warnOnQuit', false)
user_pref('general.warnOnAboutConfig', false)
user_pref('network.warnOnAboutNetworking', false)

// okay, i've already seen these things
user_pref('browser.newtabpage.introShown', true)

// disable clipboard silliness Linux
user_pref('clipboard.autocopy', false)
user_pref('middlemouse.contentLoadURL', false)
user_pref('middlemouse.paste', false)

// html
// ====

// things to disable and enable
user_pref('beacon.enabled', false)  // beacon API
user_pref('browser.send_pings.require_same_host', true)  // probably redundant with below
user_pref('browser.send_pings', false)  // <a ping>
user_pref('device.sensors.enabled', false)  // navigator.sensor API
user_pref('dom.battery.enabled', false)  // battery API
user_pref('dom.disable_beforeunload', false)  // "are you sure you want to leave this page"
user_pref('dom.enable_performance', false)  // navigation timing API
user_pref('dom.event.clipboardevents.enabled', false)  // clipboard events API
user_pref('dom.gamepad.enabled', false)  // gamepad API
user_pref('dom.indexedDB.enabled', false)  // indexedDB
user_pref('dom.netinfo.enabled', false)  // network info API
user_pref('dom.vr.cardboard.enabled', false)  // VR + Cardboard
user_pref('dom.vr.enabled', false)  // VR API
user_pref('dom.vr.oculus.enabled', false)  // VR + Oculus
user_pref('dom.vr.oculus050.enabled', false)  // VR + Oculus
user_pref('dom.webnotifications.enabled', false)  // notifications
user_pref('geo.enabled', false)  // geolocation API
user_pref('geo.wifi.uri', '')  // geolocation API
user_pref('javascript.options.asmjs', false)  // asm
user_pref('javascript.options.wasm', false)  // WebAssembly
user_pref('media.getusermedia.screensharing.allowed_domains', '')  // screen sharing
user_pref('media.getusermedia.screensharing.enabled', false)  // screen sharing
user_pref('media.peerconnection.enabled', false)  // webRTC
user_pref('media.webspeech.recognition.enable', false)  // speech recognition
user_pref('network.manage-offline-status', false)  // navigator.onLine
user_pref('webgl.disabled', true)  // webGL

// remove transitions around fullscreen API
user_pref('full-screen-api.transition-duration.enter', '0 0')
user_pref('full-screen-api.transition-duration.leave', '0 0')

// set defaults for unspecified fonts, etc
user_pref('browser.display.background_color', '#f6f6f6')

// ask to activate Flash
user_pref('plugin.state.flash', 1)

// obliterate Java
user_pref('plugin.state.java', 0)
user_pref('network.jar.block-remote-files', true)
user_pref('network.jar.open-unsafe-types', false)

// privacy
// =======

// tracking protection
user_pref('privacy.trackingprotection.enabled', true)
user_pref('privacy.trackingprotection.pbmode.enabled', true)
user_pref('privacy.trackingprotection.introCount', false)  // don't give me the intro

// disable "safe browsing" so that Google might not know everything i see
user_pref('browser.safebrowsing.enabled', false)
user_pref('browser.safebrowsing.downloads.enabled', false)
user_pref('browser.safebrowsing.malware.enabled', false)

// DNT header
user_pref('privacy.donottrackheader.enabled', true)
user_pref('privacy.donottrackheader.value', 1)

// not sure what this is exactly, but i am disabling it
user_pref('camera.control.face_detection.enabled', false)

// extensions
// ==========

// https everywhere
user_pref('extensions.https_everywhere._observatory.enabled', false)
user_pref('extensions.https_everywhere._observatory.popup_shown', true)
user_pref('extensions.https_everywhere.toolbar_hint_shown', true)
<|endoftext|>


<commit_before>module.exports = {
  "default": "--compiler ls:livescript -r features --strict --snippet-syntax node_modules/cucumber-snippets-livescript"
}
<commit_msg>Stop Cucumber at the first error<commit_after>module.exports = {
  "default": "--compiler ls:livescript -r features --fail-fast --strict --snippet-syntax node_modules/cucumber-snippets-livescript"
}
<|endoftext|>


<commit_before>/**
 * @file Dropdown component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';
import classNames from 'classnames';

import RaisedButton from '../RaisedButton';
import Popup from '../Popup';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import DropdownCalculation from '../_vendors/DropdownCalculation';

class Dropdown extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            popupVisible: false,
            isAbove: false
        };

    }

    /**
     * public
     */
    startRipple = e => {
        this.refs.trigger && this.refs.trigger.startRipple(e);
    };

    /**
     * public
     */
    endRipple = () => {
        this.refs.trigger && this.refs.trigger.endRipple();
    };

    /**
     * public
     */
    triggerRipple = e => {
        this.refs.trigger && this.refs.trigger.triggerRipple(e);
    };

    /**
     * public
     */
    resetPopupPosition = () => {
        this.refs.popup && this.refs.popup.resetPosition();
    };

    /**
     * public
     */
    closePopup = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup, onBlur} = this.props;
            onClosePopup && onClosePopup(e);
            onBlur && onBlur(e);
        });
    };

    togglePopup = e => {

        const popupVisible = !this.state.popupVisible;

        this.setState({
            popupVisible
        }, () => {

            const {onTriggerClick, onFocus, onBlur, onOpenPopup} = this.props;
            onTriggerClick && onTriggerClick(popupVisible);

            if (popupVisible) {
                onFocus && onFocus(e);
                onOpenPopup && onOpenPopup(e);
            } else {
                onBlur && onBlur(e);
            }

        });

    };

    popupRenderHandler = popupEl => {

        if (this.props.position) {
            return;
        }

        const isAbove = DropdownCalculation.isAbove(this.dropdownEl, this.triggerEl, findDOMNode(popupEl));
        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    componentDidMount() {
        this.dropdownEl = this.refs.dropdown;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    render() {

        const {

                children,

                className, triggerClassName, popupClassName, style, triggerStyle, popupStyle, theme, popupTheme,
                position, iconCls, triggerValue, title, rightIconCls, disabled, disableTouchRipple, autoPopupWidth,

                // events
                onMouseOver, onMouseOut

            } = this.props,
            {popupVisible, isAbove} = this.state,

            isAboveFinally = position === Position.TOP || position === Position.TOP_LEFT
                || position === Position.TOP_RIGHT || (!position && isAbove),

            dropdownClassName = classNames('dropdown', {
                activated: popupVisible,
                [className]: className
            }),
            buttonClassName = classNames('dropdown-trigger', isAboveFinally ? 'above' : 'blow', {
                activated: popupVisible,
                [triggerClassName]: triggerClassName
            }),
            dropdownPopupClassName = classNames('dropdown-popup', isAboveFinally ? 'above' : 'blow', {
                [popupClassName]: popupClassName
            }),
            dropdownPopupStyle = Object.assign({
                width: this.triggerEl && this.triggerEl.offsetWidth
            }, popupStyle);

        return (

                <RaisedButton ref="trigger"
                              className={buttonClassName}
                              style={triggerStyle}
                              theme={theme}
                              value={triggerValue}
                              title={title}
                              iconCls={iconCls}
                              rightIconCls={`${rightIconCls} dropdown-trigger-icon`}
                              disabled={disabled}
                              disableTouchRipple={disableTouchRipple}
                              onMouseOver={onMouseOver}
                              onMouseOut={onMouseOut}
                              onClick={this.togglePopup}/>

                <Popup ref="popup"
                       className={dropdownPopupClassName}
                       style={autoPopupWidth ? dropdownPopupStyle : popupStyle}
                       theme={popupTheme}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       hasTriangle={false}
                       position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                       shouldPreventContainerScroll={false}
                       onRender={this.popupRenderHandler}
                       onRequestClose={this.closePopup}>

                    {children}

                </Popup>

        );

    }
}

Dropdown.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the trigger element.
     */
    triggerStyle: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popup theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The value of the dropDown trigger.
     */
    triggerValue: PropTypes.any,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    title: PropTypes.string,

    /**
     * If true, the dropDown will be disabled.
     */
    disabled: PropTypes.bool,

    disableTouchRipple: PropTypes.bool,

    /**
     * Whether following the trigger width or not.
     */
    autoPopupWidth: PropTypes.bool,

    /**
     * If true,the dropdown box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,

    /**
     * Callback function fired when the popup is open.
     */
    onOpenPopup: PropTypes.func,

    /**
     * Callback function fired when the popup is close.
     */
    onClosePopup: PropTypes.func,

    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onTriggerClick: PropTypes.func

};

Dropdown.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    disableTouchRipple: false,
    autoPopupWidth: true,
    autoClose: true,

    shouldPreventContainerScroll: true

};

export default Dropdown;<commit_msg>update Dropdown<commit_after>/**
 * @file Dropdown component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';
import classNames from 'classnames';

import RaisedButton from '../RaisedButton';
import Popup from '../Popup';
import Theme from '../Theme';

import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import DropdownCalculation from '../_vendors/DropdownCalculation';

class Dropdown extends Component {

    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.state = {
            popupVisible: false,
            isAbove: false
        };

    }

    /**
     * public
     */
    startRipple = (e, props) => {
        this.refs.trigger && this.refs.trigger.startRipple(e, props);
    };

    /**
     * public
     */
    endRipple = () => {
        this.refs.trigger && this.refs.trigger.endRipple();
    };

    /**
     * public
     */
    triggerRipple = (e, props) => {
        this.refs.trigger && this.refs.trigger.triggerRipple(e, props);
    };

    /**
     * public
     */
    resetPopupPosition = () => {
        this.refs.popup && this.refs.popup.resetPosition();
    };

    /**
     * public
     */
    closePopup = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup, onBlur} = this.props;
            onClosePopup && onClosePopup(e);
            onBlur && onBlur(e);
        });
    };

    togglePopup = e => {

        const popupVisible = !this.state.popupVisible;

        this.setState({
            popupVisible
        }, () => {

            const {onTriggerClick, onFocus, onBlur, onOpenPopup} = this.props;
            onTriggerClick && onTriggerClick(popupVisible);

            if (popupVisible) {
                onFocus && onFocus(e);
                onOpenPopup && onOpenPopup(e);
            } else {
                onBlur && onBlur(e);
            }

        });

    };

    popupRenderHandler = popupEl => {

        if (this.props.position) {
            return;
        }

        const isAbove = DropdownCalculation.isAbove(this.dropdownEl, this.triggerEl, findDOMNode(popupEl));
        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    };

    componentDidMount() {
        this.dropdownEl = this.refs.dropdown;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    render() {

        const {

                children,

                className, triggerClassName, popupClassName, style, triggerStyle, popupStyle, theme, popupTheme,
                position, iconCls, triggerValue, title, rightIconCls, disabled, disableTouchRipple, autoPopupWidth,

                // events
                onMouseOver, onMouseOut

            } = this.props,
            {popupVisible, isAbove} = this.state,

            isAboveFinally = position === Position.TOP || position === Position.TOP_LEFT
                || position === Position.TOP_RIGHT || (!position && isAbove),

            dropdownClassName = classNames('dropdown', {
                activated: popupVisible,
                [className]: className
            }),
            buttonClassName = classNames('dropdown-trigger', isAboveFinally ? 'above' : 'blow', {
                activated: popupVisible,
                [triggerClassName]: triggerClassName
            }),
            dropdownPopupClassName = classNames('dropdown-popup', isAboveFinally ? 'above' : 'blow', {
                [popupClassName]: popupClassName
            }),
            dropdownPopupStyle = Object.assign({
                width: this.triggerEl && this.triggerEl.offsetWidth
            }, popupStyle);

        return (

                <RaisedButton ref="trigger"
                              className={buttonClassName}
                              style={triggerStyle}
                              theme={theme}
                              value={triggerValue}
                              title={title}
                              iconCls={iconCls}
                              rightIconCls={`${rightIconCls} dropdown-trigger-icon`}
                              disabled={disabled}
                              disableTouchRipple={disableTouchRipple}
                              onMouseOver={onMouseOver}
                              onMouseOut={onMouseOut}
                              onClick={this.togglePopup}/>

                <Popup ref="popup"
                       className={dropdownPopupClassName}
                       style={autoPopupWidth ? dropdownPopupStyle : popupStyle}
                       theme={popupTheme}
                       visible={popupVisible}
                       triggerEl={this.triggerEl}
                       hasTriangle={false}
                       position={position ? position : (isAbove ? Position.TOP_LEFT : Position.BOTTOM_LEFT)}
                       shouldPreventContainerScroll={false}
                       onRender={this.popupRenderHandler}
                       onRequestClose={this.closePopup}>

                    {children}

                </Popup>

        );

    }
}

Dropdown.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

    /**
     * The class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the trigger element.
     */
    triggerStyle: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    /**
     * The popup theme.
     */
    popupTheme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The value of the dropDown trigger.
     */
    triggerValue: PropTypes.any,

    iconCls: PropTypes.string,
    rightIconCls: PropTypes.string,

    title: PropTypes.string,

    /**
     * If true, the dropDown will be disabled.
     */
    disabled: PropTypes.bool,

    disableTouchRipple: PropTypes.bool,

    /**
     * Whether following the trigger width or not.
     */
    autoPopupWidth: PropTypes.bool,

    /**
     * If true,the dropdown box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    shouldPreventContainerScroll: PropTypes.bool,

    /**
     * Callback function fired when the popup is open.
     */
    onOpenPopup: PropTypes.func,

    /**
     * Callback function fired when the popup is close.
     */
    onClosePopup: PropTypes.func,

    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onTriggerClick: PropTypes.func

};

Dropdown.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    disableTouchRipple: false,
    autoPopupWidth: true,
    autoClose: true,

    shouldPreventContainerScroll: true

};

export default Dropdown;<|endoftext|>