<commit_before>module.exports = {
    "buckets": {
        "route": {
            "source": "geojson",
            "type": "line"
        },
        "satellite": {
            "source": "satellite",
            "type": "raster"
        },
        "park": {
            "source": "mapbox streets",
            "layer": "landuse", "field": "class", "value": "park",
            "type": "fill"
        },
        "wood": {
            "source": "mapbox streets",
            "layer": "landuse", "field": "class", "value": "wood",
            "type": "fill"
        },
        "school": {
            "source": "mapbox streets",
            "layer": "landuse", "field": "class", "value": "school",
            "type": "fill"
        },
        "cemetery": {
            "source": "mapbox streets",
            "layer": "landuse", "field": "class", "value": "cemetery",
            "type": "fill"
        },
        "industrial": {
            "source": "mapbox streets",
            "layer": "landuse", "field": "class", "value": "industrial",
            "type": "fill"
        },
        "water": {
            "source": "mapbox streets",
            "layer": "water",
            "type": "fill"
        },
        "waterway": {
            "source": "mapbox streets",
            "layer": "waterway",
            "type": "line"
        },
        "tunnel_large": {
            "source": "mapbox streets",
            "layer": "tunnel", "field": "class", "value": ["motorway", "main"],
            "type": "line"
        },
        "tunnel_regular": {
            "source": "mapbox streets",
            "layer": "tunnel", "field": "class", "value": ["street", "street_limited"],
            "type": "line"
        },
        "tunnel_rail": {
            "source": "mapbox streets",
            "layer": "tunnel", "field": "class", "value": ["minor_rail", "major_rail"],
            "type": "line"
        },
        "bridge_large": {
            "source": "mapbox streets",
            "layer": "bridge", "field": "class", "value": ["motorway", "main"],
            "type": "line"
        },
        "bridge_regular": {
            "source": "mapbox streets",
            "layer": "bridge", "field": "class", "value": ["street", "street_limited"],
            "type": "line"
        },
        "borders": {
            "source": "mapbox streets",
            "layer": "admin",
            "type": "line"
        },
        "building": {
            "source": "mapbox streets",
            "layer": "building",
            "type": "fill"
        },
        "road_large": {
            "source": "mapbox streets",
            "layer": "road", "field": "class", "value": ["motorway", "main"],
            "type": "line", "cap": "round", "join": "bevel"
        },
        "road_regular": {
            "source": "mapbox streets",
            "layer": "road", "field": "class", "value": "street",
            "type": "line", "cap": "round", "join": "bevel"
        },
        "road_limited": {
            "source": "mapbox streets",
            "layer": "road", "field": "class", "value": "street_limited",
            "type": "line", "cap": "round", "join": "butt", "roundLimit": 0.7
        },
        "rail": {
            "source": "mapbox streets",
            "layer": "road", "field": "class", "value": "major_rail",
            "type": "line", "cap": "round", "join": "bevel"
        },
        "path": {
            "source": "mapbox streets",
            "layer": "road", "field": "class", "value": "path",
            "type": "line", "cap": "round", "join": "bevel"
        },
        "country_label": {
            "source": "mapbox streets",
            "layer": "country_label",
            "feature_type": "point",
            "padding": 10,
            "type": "text",
            "text_field": "name",
            "path": "horizontal",
            "font": "Open Sans, Jomolhari, Siyam Rupali, Alef, Arial Unicode MS",
            "fontSize": 16
        },
        "place_label": {
            "source": "mapbox streets",
            "layer": "place_label",
            "feature_type": "point",
            "type": "text",
            "text_field": "name",
            "path": "horizontal",
            "font": "Open Sans, Jomolhari, Siyam Rupali, Alef, Arial Unicode MS",
            "fontSize": 18,
            "alwaysVisible": true
        },
        "road_label": {
            "source": "mapbox streets",
            "layer": "road_label",
            "feature_type": "line",
            "type": "text",
            "text_field": "name",
            "path": "curve",
            "font": "Open Sans, Jomolhari, Siyam Rupali, Alef, Arial Unicode MS",
            "fontSize": 12,
            "textMinDistance": 250,
            "maxAngleDelta": 1.04, // radians
        },
        "embassy_poi": {
            "source": "mapbox streets",
            "layer": "poi_label", "field": "maki", "value": "embassy",
            "type": "point"
        },
        "park_poi": {
            "source": "mapbox streets",
            "layer": "poi_label", "field": "maki", "value": "park",
            "type": "point"
        },
        "restaurant_poi": {
            "source": "mapbox streets",
            "layer": "poi_label", "field": "maki", "value": "restaurant",
            "size": { "x": 12, "y": 12 },
            "type": "point"
        },
        "road_markers": {
            "source": "mapbox streets",
            "layer": "road", "field": "oneway", "value": 1,
            "feature_type": "line",
            "type": "point", "spacing": 200
        },
    },
    "sprite": "img/sprite",
    "constants": {
        "land": "#e8e0d8",
        "water": "#73b6e6",
        "park": "#c8df9f",
        "road": "#fefefe",
        "border": "#6d90ab",
        "wood": "#33AA66",
        "building": "#d9ccbe",
        "building_outline": "#d2c6b9",
        "text": "#000000",
        "satellite_brightness_low": 0,
        "satellite_brightness_high": 1,
        "satellite_saturation": 0.0,
        "satellite_spin": 0,
        "satellite_contrast": 0,
        "road_blur": 1,
        "stroke_width": 0.25
    },
    "structure": [
    {
        "name": "background",
        "bucket": "background"
    },
    {
        "name": "satellite",
        "bucket": "satellite"
    },
    {
        "name": "park",
        "bucket": "park"
    },
    {
        "name": "wood",
        "bucket": "wood",
    },
    {
        "name": "water",
        "bucket": "water",
    },
    {
        "name": "waterway",
        "bucket": "waterway",
    },
    {
        "name": "roads",
        "layers": [
        {
            "name": "tunnel_large_casing",
            "bucket": "tunnel_large",
        },
        {
            "name": "tunnel_regular_casing",
            "bucket": "tunnel_regular",
        },
        {
            "name": "tunnel_large",
            "bucket": "tunnel_large",
        },
        {
            "name": "tunnel_regular",
            "bucket": "tunnel_regular",
        },
        {
            "name": "road_large_casing",
            "bucket": "road_large",
        },
        {
            "name": "road_regular_casing",
            "bucket": "road_regular",
        },
        {
            "name": "road_limited",
            "bucket": "road_limited",
        },
        {
            "name": "road_large",
            "bucket": "road_large",
        },
        {
            "name": "road_regular",
            "bucket": "road_regular",
        },
        {
            "name": "path",
            "bucket": "path",
        },
        {
            "name": "rail",
            "bucket": "rail",
        },
        {
            "name": "tunnel_rail",
            "bucket": "tunnel_rail",
        }]
    },
    {
        "name": "route",
        "bucket": "route"
    },
    {
        "name": "road_markers",
        "bucket": "road_markers",
    },
    {
        "name": "building",
        "bucket": "building",

    },
    {
        "name": "borders",
        "bucket": "borders",
    },
    {
        "name": "bridge_large_casing",
        "bucket": "bridge_large",
    },
    {
        "name": "bridge_large",
        "bucket": "bridge_large",
    },
    {
        "name": "park_poi",
        "bucket": "park_poi",
    },
    {
        "name": "restaurant_poi",
        "bucket": "restaurant_poi",
    },
    {
        "name": "country_label",
        "bucket": "country_label",
    },
    {
        "name": "place_label",
        "bucket": "place_label",
    },
    {
        "name": "road_label",
        "bucket": "road_label",
    },
    ],
    "classes": [
    {
        "name": "default",
        "layers": {
            "route": {
                "color": "#EC8D8D",
                "width": ["exponential", 9, 1.0, 0.21, 4],
            },
            "background": {
                "color": "land",
                "transition-color": { "duration": 500, "delay": 0 }
            },
            "park": {
                "color": "park",
            },
            "wood": {
                "color": "wood",
                "opacity": 0.08,
            },
            "water": {
                "color": "water",
            },
            "waterway": {
                "color": "water",
                "width": ["linear", 9, 1, 0.5, 0.5]
            },
            "tunnel_large_casing": {
                "color": [0, 0, 0, 0.5],
                "width": 1,
                "offset": ["exponential", 9, -1, 0.2, 1],
                "enabled": ["min", 14]
            },
            "tunnel_regular_casing": {
                "color": [0, 0, 0, 0.5],
                "width": 1,
                "offset": ["exponential", 11, 0.5, 0.2, 1],
                "enabled": ["min", 15.5 ]
            },
            "tunnel_large": {
                "color": [ 1, 1, 1, 0.5],
                "width": ["exponential", 9, -1, 0.2, 1]
            },
            "tunnel_regular": {
                "color": [ 1, 1, 1, 0.5],
                "width": ["exponential", 11, -1, 0.2, 1]
            },
            "roads": {
                "type": "composited",
                "opacity": 1,
                "transition-opacity": { "duration": 500, "delay": 0 },
            },
            "road_large_casing": {
                "color": [0.6, 0.6, 0.6, 1],
                "width": ["exponential", 9, 1.0, 0.21, 4],
                "enabled": ["min", 13],
                "opacity": ["linear", 14, 0, 1, 0, 1],
                "transition-width": { "duration": 500, "delay": 0 },
                "blur": "road_blur"
                //"transition-width": { "duration": 500, "delay": 2000 },
                //"transition-color": { "duration": 2000, "delay": 0 }
            },
            "road_regular_casing": {
                "color": [0.6, 0.6, 0.6, 1],
                "width": ["exponential", 10, 0.5, 0.2, 1],
                "enabled": ["min", 15.5 ],
                "opacity": ["linear", 15.5, 0, 1, 0, 1],
                "blur": "road_blur",
            },
            "road_limited": {
                "dasharray": [10, 2],
                "color": "road",
                "blur": "road_blur",
                "width": ["exponential", 10, -1, 0.2, 1],
            },
            "road_large": {
                "color": "road",
                "blur": "road_blur",
                "width": ["exponential", 9, -1, 0.2, 1],
            },
            "road_regular": {
                "color": "road",
                "blur": "road_blur",
                "width": ["exponential", 10, -1, 0.2, 1],
            },
            "path": {
                "color": [1,1,1,1],
                "dasharray": [2,2],
                "width": 2
            },
            "rail": {
                "color": [0.3,0.3,0.3,0.8],
                "dasharray": [2, 1],
                "width" : 3,
                "linejoin": "round"
            },
            "tunnel_rail": {
                "color": [0.3,0.3,0.3,0.3],
                "dasharray": [2, 1],
                "width" : 3,
                "linejoin": "round"
            },
            "road_markers": {
                "enabled": ["min", 15.5],
                "alignment": "line",
                "image": "bicycle-12",
            },
            "building": {
                "color": "building",
                "stroke": "building_outline",
                "transition-opacity": { "duration": 500, "delay": 500 },
                "opacity": ["linear", 14, 0, 1, 0, 1]

            },
            "borders": {
                "color": [0,0,0,0.3],
                "width": 1
            },
            "bridge_large_casing": {
                "color": [0, 0, 0, 0.4],
                "width": ["exponential", 9, 1.5, 0.2, 1],
                "enabled": ["min", 14]
            },
            "bridge_large": {
                "color": "road",
                "width": ["exponential", 9, -1, 0.2, 1]
            },
            "park_poi": {
                "color": "green"
            },
            "restaurant_poi": {
                "image": "restaurant-12",
                "imageSize": 12
            },
            "country_label": {
                "stroke": [1,1,1,0.7],
                "strokeWidth": "stroke_width",
                "color": "text"
            },
            "place_label": {
                "stroke": [1,1,1,0.7],
                "strokeWidth": "stroke_width",
                "color": "text"
            },
            "road_label": {
                "color": "text",
                "stroke": [1,1,1,0.7],
                "strokeWidth": "stroke_width",
                "size": ["exponential", 14, 8, 1, 8, 12]
            }
        }
    }, {
        "name": "satellite",
        "layers": {
            "background": {
                "transition-color": { "duration": 500, "delay": 500 },
                "opacity": 0,
                "color": [1,0,0,0]
            },
            "roads": {
                "transition-opacity": { "duration": 500, "delay": 500 },
                "opacity": 0.5
            },
            "building": {
                "opacity": 0,
                "transition-opacity": { "duration": 500, "delay": 0 },
            },
            "park": {
                "transition-color": { "duration": 500, "delay": 0 },
                "color": [0,0,0,0],
            },
            "water": {
                "opacity": 0
            },
            "place_label": {
                //"color": [1,1,1,1]
            },
            "road_large": {
                "transition-width": { "duration": 500, "delay": 1000 },
                "width": ["exponential", 10, -1, 0.2, 1],
            },
            "road_large_casing": {
                "width": ["exponential", 10, 1.0, 0.21, 4],
                "transition-width": { "duration": 500, "delay": 1000 },
            },
            "road_regular_casing": {
                "transition-width": { "duration": 500, "delay": 1000 },
                "width": ["exponential", 11, 0.5, 0.2, 1],
            },
            "road_regular": {
                "transition-width": { "duration": 500, "delay": 1000 },
                "width": ["exponential", 11, -1, 0.2, 1],
            },
            "satellite": {
                brightness_low: "satellite_brightness_low",
                brightness_high: "satellite_brightness_high",
                saturation: "satellite_saturation",
                spin: "satellite_spin",
                contrast: "satellite_contrast"
            }
        }
    }, {
        "name": "test",
        "layers": {
            "road_large_casing": {
                "width": ["exponential", 8, 1.0, 0.21, 4],
                "color": [1,0,0,1],
                "transition-width": { "duration": 500, "delay": 0 },
                "transition-color": { "duration": 2000, "delay": 500 }
            }
        }
    }]
};
<commit_msg>remove leftover style<commit_after><|endoftext|>


<commit_before>var beginning = (new Date()).getTime();
var times = [ 10,  30,  50, 100, 200, 400];
var dists = [120, 190, 275, 440, 540, 620];
function getPlanetAngle(planet,offset){
  var now = (new Date()).getTime()+(offset||0)-beginning;
  return (now/1000 % times[planet])/times[planet]*-2*Math.PI + Math.PI/2;
}
function getPlanetLoc(planet,offset){
  var angle = getPlanetAngle(planet,offset);
  var x = Math.cos(angle)*dists[planet]/2;
  var y = Math.sin(angle)*dists[planet]/2;
  return [x,y];
}

function flyBetweenPlanets(to,from){
  var a = document.getElementById('container');
  var style = window.getComputedStyle(a);
  generateAnimation(toDOMLoc(getPlanetLoc(to,Number.parseInt(style.webkitAnimationDuration)*1000)),toDOMLoc(getPlanetLoc(from)),0);
}

function getDistance(to,from){
  var locs = [toDOMLoc(getPlanetLoc(to,7000)),toDOMLoc(getPlanetLoc(from))];
  var d = Math.sqrt((locs[0][0]-locs[1][0])*(locs[0][0]-locs[1][0])+(locs[0][1]-locs[1][1])*(locs[0][1]-locs[1][1]));
  return d;
}
function fly(to,from){
  var d = getDistance(to,from);
  var style = document.getElementById('container').style;
  style.webkitAnimationDuration = ''+((d/20) | 0)+'s';
  flyBetweenPlanets(to,from);
}

function toDOMLoc(loc){
  var out = [];
  var a = document.getElementsByClassName('map')[0];
  var style = window.getComputedStyle(a);
  out[0] = loc[0]+Number.parseInt(style.width)/2;
  out[1] = -loc[1]+Number.parseInt(style.height)/2;
  return out;
}

function findKeyframesRule(rule){
//credit: https://gitorious.org/webkit/webkit/source/438fd0b118bd9c2c82b6ab23956447be9c24f136:LayoutTests/animations/change-keyframes.html#Lundefined
    var ss = document.styleSheets;
    for (var i = 0; i < ss.length; ++i) {
      if(ss[i].cssRules)
        for (var j = 0; j < ss[i].cssRules.length; ++j) {
            if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule)
                return ss[i].cssRules[j];
        }
    }

    return null;
}

function generateAnimation(to,from,startAngle){
  var angle = Math.atan2(to[0]-from[0],from[1]-to[1])/Math.PI*180;  //y is negated cus we are using top:
  var fromRotate = "transform: rotate(" + startAngle +"deg);";
  var toRotate = "transform: rotate(" + angle +"deg);";
  var fromLoc = "top:"+from[1] + "px;left:" + from[0] + "px;";
  var toLoc = "top:"+to[1] + "px;left:" + to[0] + "px;";
  var keyframes = findKeyframesRule('fly');
  keyframes.deleteRule("from");
  keyframes.deleteRule("10%");
  keyframes.deleteRule("30%");
  keyframes.deleteRule("90%");
  keyframes.deleteRule("to");

  keyframes.insertRule(
    "from{"
    + fromRotate
    + fromLoc +
    " height:10px;\
      width:10px;\
      margin:-5 0 0 -5;\
    }");

  keyframes.insertRule(
    "10%{"
    + fromRotate +
    "  height:50px;\
      width:50px;\
      margin:-25 0 0 -25;\
    }");
  keyframes.insertRule(
    "30%{"
    + toRotate
    + fromLoc +
    " height:50px; \
      width:50px;\
      margin:-25 0 0 -25;\
    }");
  keyframes.insertRule(
    "90%{"
    + toLoc +
    " height:50px;\
      width:50px;\
      margin:-50 0 0 0;\
    }");
  keyframes.insertRule(
    "to{"
    + toRotate
    + toLoc +
    " height:10px;\
      width:10px;\
      margin:-5 0 0 -5;\
    }");
  var a = document.getElementById('container').style;
  a.display = "none";
  a.webkitAnimationName = 'none';
  setTimeout(start, 10);
}

function start(){
  var a = document.getElementById('container');
  var style = a.style;
  style.webkitAnimationName = 'fly';
  style.display = 'initial';
  a.addEventListener('webkitAnimationEnd',end);
}
function end(){
  var a = document.getElementById('container');
  var style = a.style;
  style.display = 'none';
  onArrive();
}<commit_msg>animating variable<commit_after>var beginning = (new Date()).getTime();
var times = [ 10,  30,  50, 100, 200, 400];
var dists = [120, 190, 275, 440, 540, 620];
function getPlanetAngle(planet,offset){
  var now = (new Date()).getTime()+(offset||0)-beginning;
  return (now/1000 % times[planet])/times[planet]*-2*Math.PI + Math.PI/2;
}
function getPlanetLoc(planet,offset){
  var angle = getPlanetAngle(planet,offset);
  var x = Math.cos(angle)*dists[planet]/2;
  var y = Math.sin(angle)*dists[planet]/2;
  return [x,y];
}

function flyBetweenPlanets(to,from){
  var a = document.getElementById('container');
  var style = window.getComputedStyle(a);
  generateAnimation(toDOMLoc(getPlanetLoc(to,Number.parseInt(style.webkitAnimationDuration)*1000)),toDOMLoc(getPlanetLoc(from)),0);
}

function getDistance(to,from){
  var locs = [toDOMLoc(getPlanetLoc(to,7000)),toDOMLoc(getPlanetLoc(from))];
  var d = Math.sqrt((locs[0][0]-locs[1][0])*(locs[0][0]-locs[1][0])+(locs[0][1]-locs[1][1])*(locs[0][1]-locs[1][1]));
  return d;
}
function fly(to,from){
  var d = getDistance(to,from);
  var style = document.getElementById('container').style;
  style.webkitAnimationDuration = ''+((d/20) | 0)+'s';
  flyBetweenPlanets(to,from);
}

function toDOMLoc(loc){
  var out = [];
  var a = document.getElementsByClassName('map')[0];
  var style = window.getComputedStyle(a);
  out[0] = loc[0]+Number.parseInt(style.width)/2;
  out[1] = -loc[1]+Number.parseInt(style.height)/2;
  return out;
}

function findKeyframesRule(rule){
//credit: https://gitorious.org/webkit/webkit/source/438fd0b118bd9c2c82b6ab23956447be9c24f136:LayoutTests/animations/change-keyframes.html#Lundefined
    var ss = document.styleSheets;
    for (var i = 0; i < ss.length; ++i) {
      if(ss[i].cssRules)
        for (var j = 0; j < ss[i].cssRules.length; ++j) {
            if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule)
                return ss[i].cssRules[j];
        }
    }

    return null;
}

function generateAnimation(to,from,startAngle){
  var angle = Math.atan2(to[0]-from[0],from[1]-to[1])/Math.PI*180;  //y is negated cus we are using top:
  var fromRotate = "transform: rotate(" + startAngle +"deg);";
  var toRotate = "transform: rotate(" + angle +"deg);";
  var fromLoc = "top:"+from[1] + "px;left:" + from[0] + "px;";
  var toLoc = "top:"+to[1] + "px;left:" + to[0] + "px;";
  var keyframes = findKeyframesRule('fly');
  keyframes.deleteRule("from");
  keyframes.deleteRule("10%");
  keyframes.deleteRule("30%");
  keyframes.deleteRule("90%");
  keyframes.deleteRule("to");

  keyframes.insertRule(
    "from{"
    + fromRotate
    + fromLoc +
    " height:10px;\
      width:10px;\
      margin:-5 0 0 -5;\
    }");

  keyframes.insertRule(
    "10%{"
    + fromRotate +
    "  height:50px;\
      width:50px;\
      margin:-25 0 0 -25;\
    }");
  keyframes.insertRule(
    "30%{"
    + toRotate
    + fromLoc +
    " height:50px; \
      width:50px;\
      margin:-25 0 0 -25;\
    }");
  keyframes.insertRule(
    "90%{"
    + toLoc +
    " height:50px;\
      width:50px;\
      margin:-50 0 0 0;\
    }");
  keyframes.insertRule(
    "to{"
    + toRotate
    + toLoc +
    " height:10px;\
      width:10px;\
      margin:-5 0 0 -5;\
    }");
  var a = document.getElementById('container').style;
  a.display = "none";
  a.webkitAnimationName = 'none';
  animating = true;
  setTimeout(start, 10);
}
var animating = false;
function start(){
  var a = document.getElementById('container');
  var style = a.style;
  style.webkitAnimationName = 'fly';
  style.display = 'initial';
  a.addEventListener('webkitAnimationEnd',end);

}
function end(){
  var a = document.getElementById('container');
  var style = a.style;
  style.display = 'none';
  animating = false;
  onArrive();
}<|endoftext|>


<commit_before>/**
 * @fileOverview Interfaces the application with its current architecture.
 * This could be an extension, mobile app, or a hosted web server.
 *
 **/

/**
 * @namespace
 */
var privlyNetworkService = {

  /**
   * Permissions the user may have on creating and updating content.
   * Each of these permissions are associated with a network request.
   * They should only be set to "true" if the associated get/post/delete
   * request could be made without harming the remote server. You can usually
   * establish that the request will not harm data stored remotely by
   * doing a get request that affirms the user's right to perform certain
   * operations.
   */
  permissions: {
    canCreate: false,
    canDestroy: false,
    canUpdate: false,
    canShare: false,
    canShow: false
  },

  /**
   * If this variable is assigned, it will be appended as a get parameter
   * on all requests, eg, `?auth_token=AUTH_TOKEN_HERE`. This should never
   * be referenced by anything but the auth token setters.
   */
  authToken: "",

  /**
   * Set the authentication token if a parameter is supplied, or the
   * current platform has a setter function. This may be called from the
   * context of mobile applications or browser extensions.
   */
  setAuthTokenString: function(authTokenString) {
    if (authTokenString !== undefined) {
      privlyNetworkService.authToken = "auth_token=" + authTokenString;
    } else if(privlyNetworkService.platformName() === "ANDROID") {
      privlyNetworkService.authToken = "auth_token=" +
                                              androidJsBridge.fetchAuthToken();
    }
  },

  /**
   * Adds the auth token to the current URL. If the auth token has not been
   * assigned, nothing is added. If the auth token is assigned, it is added
   * as a get parameter.
   *
   * @param string url the URL that may need an auth token added.
   *
   */
  getAuthenticatedUrl: function(url) {

    // get the parameter string for the auth token
    privlyNetworkService.setAuthTokenString();

    // Don't change the URL if there is no auth token, or the URL
    // is not for the content server
    if( privlyNetworkService.authToken === "" ||
      url.indexOf(privlyNetworkService.contentServerDomain()) !== 0 ) {
      return url;
    }

    // if query parameters already exist on the URL
    if (url.indexOf("?") >= 0 && (url.indexOf("?") < url.indexOf("#") ||
      url.indexOf("#") === -1)) {
      return url.replace("?", "?" + privlyNetworkService.authToken + "&");

    // else if there is an anchor
    } else if(url.indexOf("#") >= 0) {
      return url.replace("#", "?" + privlyNetworkService.authToken + "#");
    } else {
      return url + "?" + privlyNetworkService.authToken;
    }
  },

  /**
   * Determines which platform the script is runing on. This helps determine
   * which request function should be used. The current values are "CHROME"
   * for the Google Chrome extension, and "HOSTED" for all other architectures.
   * HOSTED functions use standard same-origin AJAX requests.
   *
   * @return {string} the name of the platform.
   */
  platformName: function() {
    if (navigator.userAgent.indexOf("iPhone") >= 0 ||
      navigator.userAgent.indexOf("iPad") >= 0) {
      if( navigator.userAgent.indexOf("Safari") >= 0 ) return "HOSTED";
      return "IOS";
    } else if(typeof androidJsBridge !== "undefined") {
      return "ANDROID";
    }  else if (typeof chrome !== "undefined" && typeof chrome.extension !== "undefined") {
      return "CHROME";
    } else if(typeof Components !== "undefined" &&
    typeof Components.classes !== "undefined") {
      return "FIREFOX";
    } else {
      return "HOSTED";
    }
  },

  /**
   * Helper for determining the protocol+domain of a
   * URL.
   *
   * @param {string} url the URL for which we want the domain and protocl
   * @return {string} The string of the protocol and domain.
   */
  getProtocolAndDomain: function(url) {
    var domainGrabber = document.createElement("a");
    domainGrabber.href = url;
    return domainGrabber.protocol + "//" + domainGrabber.host;
  },

  /**
   * The cross-site request forgery tokens for servers initialized via
   * initPrivlyService.
   */
  csrfTokens: {},

  /**
   * Get the CSRF token (if it exists) for a domain. CSRF tokens should be
   * initialized before requesting them here.
   * @param {string} url a URL for which we need to lookup its CSRF token
   */
  getCSRFToken: function(url) {
    return privlyNetworkService.csrfTokens[privlyNetworkService.getProtocolAndDomain(url)];
  },

  /**
   * This function is specific to the privly content server available on GitHub.
   * It initializes a CSRF token, and checks whether the user is logged in.
   *
   * @param loggedInCallback function the function to execute when
   * initialization is successful.
   *
   * @param loginCallback function the function to execute if the user is
   * not logged in.
   *
   * @param errorCallback function the function to execute if the remote
   * server is not available.
   */
  initPrivlyService: function(url, loggedInCallback, loginCallback,
    errorCallback) {

    var csrfTokenAddress = privlyNetworkService.getProtocolAndDomain(url) +
                           "/posts/user_account_data";

    csrfTokenAddress =  privlyNetworkService.getAuthenticatedUrl(csrfTokenAddress);
    $.ajax({
      url: csrfTokenAddress,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        // set the CSRF
        privlyNetworkService.csrfTokens[privlyNetworkService.getProtocolAndDomain(url)] = json.csrf;
        if(json.signedIn) {
          loggedInCallback(json, textStatus, jqXHR);
        } else {
          loginCallback(json, textStatus, jqXHR);
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
        errorCallback(jqXHR, textStatus, errorThrown);
      }
    });

  },

  /**
   * Determines network policy for request. Since network requests can be
   * used to track when a user is reading Privly content (emails for instance),
   * requests must be checked for whitelisting status when the content is
   * injected.
   *
   * @param {string} url The URL that may be able to track the user. Must
   * specify the http or https protocols.
   *
   */
  isWhitelistedDomain: function(url) {

    // Chrome maintains an explicit whitelist in local storage
    if( privlyNetworkService.platformName() === "CHROME" ||
      privlyNetworkService.platformName() === "FIREFOX") {

      // get the user defined whitelist and add in the default whitelist
      var whitelist = [];

      // There is no local storage API on Firefox XUL
      if ( privlyNetworkService.platformName() === "CHROME" &&
        ls.getItem("user_whitelist_csv") !== undefined ) {
        whitelist = whitelist.concat(
          ls.getItem("user_whitelist_csv").split(" , "));
      }
      whitelist.push("priv.ly");
      whitelist.push("dev.privly.org");
      whitelist.push("localhost");
      whitelist.push("privlyalpha.org");
      whitelist.push("privlybeta.org");
      whitelist.push("localhost:3000");
      whitelist.push("localhost:4000");

      // See if the domain is in the whitelist
      for(var i = 0; i < whitelist.length; i++) {
        if( url.indexOf(whitelist[i]) > 0) {
          var url_split = url.split("/");
          if(url_split[2] == whitelist[i] &&
             url_split[1] === "" &&
             (url_split[0] === "http:" || url_split[0] === "https:") )
                return true;
        }
      }
    } else {
      //Hosted, Android, and iOS don't have the same privacy concerns
      return true;
    }
    return false;
  },

  /**
   * Gives the domain for the user's trusted content server.
   *
   * @return {string} The domain content is associated with.
   */
  contentServerDomain: function() {
    var protocolDomainPort = location.protocol +
                             '//'+location.hostname +
                             (location.port ? ':'+location.port: '');

    var platformName = privlyNetworkService.platformName();
    if (platformName === "HOSTED") {
      return protocolDomainPort;
    } else if (platformName === "CHROME" ||
               platformName === "FIREFOX" ||
               platformName === "IOS") {
      return ls.getItem("posting_content_server_url");
    } else if (platformName === "ANDROID") {
      return androidJsBridge.fetchDomainName();
    } else {
      return protocolDomainPort;
    }
  },

  /**
   * Make a same-origin get request for content.
   *
   * This request should always proceed a post request to ensure the post
   * endpoint is expecting integration with the extension.
   *
   * @param {string} url The URL to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   */
  sameOriginGetRequest: function(url, callback) {

    // Add the auth token if the get request is on the user's content
    // server
    if( url.indexOf(privlyNetworkService.contentServerDomain()) === 0 ) {
      url = privlyNetworkService.getAuthenticatedUrl(url);
    }

    $.ajax({
      url: url,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin post request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginPostRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "POST",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin put request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginPutRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "PUT",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin delete request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginDeleteRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "DELETE",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Hide all the elements not required by mobile and adjust the CSS appropriately.
   * Elements will only be modified for mobile apps.
   */
  mobileHide: function() {
    if( privlyNetworkService.platformName() === "IOS" ||
        privlyNetworkService.platformName() === "ANDROID" ) {
      $(".mobile_hide").hide();
      $("body").css("padding-top", "0px");
    }
  },

  /**
   * Assign the href attribute of navigation links appropriately.
   */
  initializeNavigation: function() {
    var domain = privlyNetworkService.contentServerDomain();
    $(".home_domain").text(domain.split("/")[2]);
    $(".account_url").attr("href", domain + "/pages/account");
    $(".legal_nav").attr("href", domain + "/pages/privacy");
    document.getElementById("logout_link").addEventListener('click', function(){
      $.post(domain + "/users/sign_out", "_method=delete", function(data) {
        window.location = "../Login/new.html";
      });
    });

    // Change the target property to be self if the application is hosted
    // by a remote server.
    if( privlyNetworkService.platformName() === "HOSTED" ) {
      $(".home_domain").attr("target", "_self");
      $(".account_url").attr("target", "_self");
      $(".legal_nav").attr("target", "_self");
    }

    privlyNetworkService.mobileHide();
  },

  /**
   * Show/hide the appropriate navigation items for when the user is logged out.
   */
  showLoggedOutNav: function() {

    // Don't show the nav at all if the content is injected.
    if(typeof privlyHostPage !== "undefined" && privlyHostPage.isInjected()) {
      return;
    }
    $(".logged_in_nav").hide();
    $(".logged_out_nav").show();
    $(".injected_hide").show();
    privlyNetworkService.mobileHide();
  },

  /**
   * Show/hide the appropriate navigation items for when the user is logged in.
   */
  showLoggedInNav: function() {

    // Don't show the nav at all if the content is injected.
    if(typeof privlyHostPage !== "undefined" && privlyHostPage.isInjected()) {
      return;
    }
    $(".injected_hide").show();
    $(".logged_in_nav").show();
    $(".logged_out_nav").hide();
    privlyNetworkService.mobileHide();
  }
}
<commit_msg>banner domain goes to root in the hosted context<commit_after>/**
 * @fileOverview Interfaces the application with its current architecture.
 * This could be an extension, mobile app, or a hosted web server.
 *
 **/

/**
 * @namespace
 */
var privlyNetworkService = {

  /**
   * Permissions the user may have on creating and updating content.
   * Each of these permissions are associated with a network request.
   * They should only be set to "true" if the associated get/post/delete
   * request could be made without harming the remote server. You can usually
   * establish that the request will not harm data stored remotely by
   * doing a get request that affirms the user's right to perform certain
   * operations.
   */
  permissions: {
    canCreate: false,
    canDestroy: false,
    canUpdate: false,
    canShare: false,
    canShow: false
  },

  /**
   * If this variable is assigned, it will be appended as a get parameter
   * on all requests, eg, `?auth_token=AUTH_TOKEN_HERE`. This should never
   * be referenced by anything but the auth token setters.
   */
  authToken: "",

  /**
   * Set the authentication token if a parameter is supplied, or the
   * current platform has a setter function. This may be called from the
   * context of mobile applications or browser extensions.
   */
  setAuthTokenString: function(authTokenString) {
    if (authTokenString !== undefined) {
      privlyNetworkService.authToken = "auth_token=" + authTokenString;
    } else if(privlyNetworkService.platformName() === "ANDROID") {
      privlyNetworkService.authToken = "auth_token=" +
                                              androidJsBridge.fetchAuthToken();
    }
  },

  /**
   * Adds the auth token to the current URL. If the auth token has not been
   * assigned, nothing is added. If the auth token is assigned, it is added
   * as a get parameter.
   *
   * @param string url the URL that may need an auth token added.
   *
   */
  getAuthenticatedUrl: function(url) {

    // get the parameter string for the auth token
    privlyNetworkService.setAuthTokenString();

    // Don't change the URL if there is no auth token, or the URL
    // is not for the content server
    if( privlyNetworkService.authToken === "" ||
      url.indexOf(privlyNetworkService.contentServerDomain()) !== 0 ) {
      return url;
    }

    // if query parameters already exist on the URL
    if (url.indexOf("?") >= 0 && (url.indexOf("?") < url.indexOf("#") ||
      url.indexOf("#") === -1)) {
      return url.replace("?", "?" + privlyNetworkService.authToken + "&");

    // else if there is an anchor
    } else if(url.indexOf("#") >= 0) {
      return url.replace("#", "?" + privlyNetworkService.authToken + "#");
    } else {
      return url + "?" + privlyNetworkService.authToken;
    }
  },

  /**
   * Determines which platform the script is runing on. This helps determine
   * which request function should be used. The current values are "CHROME"
   * for the Google Chrome extension, and "HOSTED" for all other architectures.
   * HOSTED functions use standard same-origin AJAX requests.
   *
   * @return {string} the name of the platform.
   */
  platformName: function() {
    if (navigator.userAgent.indexOf("iPhone") >= 0 ||
      navigator.userAgent.indexOf("iPad") >= 0) {
      if( navigator.userAgent.indexOf("Safari") >= 0 ) return "HOSTED";
      return "IOS";
    } else if(typeof androidJsBridge !== "undefined") {
      return "ANDROID";
    }  else if (typeof chrome !== "undefined" && typeof chrome.extension !== "undefined") {
      return "CHROME";
    } else if(typeof Components !== "undefined" &&
    typeof Components.classes !== "undefined") {
      return "FIREFOX";
    } else {
      return "HOSTED";
    }
  },

  /**
   * Helper for determining the protocol+domain of a
   * URL.
   *
   * @param {string} url the URL for which we want the domain and protocl
   * @return {string} The string of the protocol and domain.
   */
  getProtocolAndDomain: function(url) {
    var domainGrabber = document.createElement("a");
    domainGrabber.href = url;
    return domainGrabber.protocol + "//" + domainGrabber.host;
  },

  /**
   * The cross-site request forgery tokens for servers initialized via
   * initPrivlyService.
   */
  csrfTokens: {},

  /**
   * Get the CSRF token (if it exists) for a domain. CSRF tokens should be
   * initialized before requesting them here.
   * @param {string} url a URL for which we need to lookup its CSRF token
   */
  getCSRFToken: function(url) {
    return privlyNetworkService.csrfTokens[privlyNetworkService.getProtocolAndDomain(url)];
  },

  /**
   * This function is specific to the privly content server available on GitHub.
   * It initializes a CSRF token, and checks whether the user is logged in.
   *
   * @param loggedInCallback function the function to execute when
   * initialization is successful.
   *
   * @param loginCallback function the function to execute if the user is
   * not logged in.
   *
   * @param errorCallback function the function to execute if the remote
   * server is not available.
   */
  initPrivlyService: function(url, loggedInCallback, loginCallback,
    errorCallback) {

    var csrfTokenAddress = privlyNetworkService.getProtocolAndDomain(url) +
                           "/posts/user_account_data";

    csrfTokenAddress =  privlyNetworkService.getAuthenticatedUrl(csrfTokenAddress);
    $.ajax({
      url: csrfTokenAddress,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        // set the CSRF
        privlyNetworkService.csrfTokens[privlyNetworkService.getProtocolAndDomain(url)] = json.csrf;
        if(json.signedIn) {
          loggedInCallback(json, textStatus, jqXHR);
        } else {
          loginCallback(json, textStatus, jqXHR);
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
        errorCallback(jqXHR, textStatus, errorThrown);
      }
    });

  },

  /**
   * Determines network policy for request. Since network requests can be
   * used to track when a user is reading Privly content (emails for instance),
   * requests must be checked for whitelisting status when the content is
   * injected.
   *
   * @param {string} url The URL that may be able to track the user. Must
   * specify the http or https protocols.
   *
   */
  isWhitelistedDomain: function(url) {

    // Chrome maintains an explicit whitelist in local storage
    if( privlyNetworkService.platformName() === "CHROME" ||
      privlyNetworkService.platformName() === "FIREFOX") {

      // get the user defined whitelist and add in the default whitelist
      var whitelist = [];

      // There is no local storage API on Firefox XUL
      if ( privlyNetworkService.platformName() === "CHROME" &&
        ls.getItem("user_whitelist_csv") !== undefined ) {
        whitelist = whitelist.concat(
          ls.getItem("user_whitelist_csv").split(" , "));
      }
      whitelist.push("priv.ly");
      whitelist.push("dev.privly.org");
      whitelist.push("localhost");
      whitelist.push("privlyalpha.org");
      whitelist.push("privlybeta.org");
      whitelist.push("localhost:3000");
      whitelist.push("localhost:4000");

      // See if the domain is in the whitelist
      for(var i = 0; i < whitelist.length; i++) {
        if( url.indexOf(whitelist[i]) > 0) {
          var url_split = url.split("/");
          if(url_split[2] == whitelist[i] &&
             url_split[1] === "" &&
             (url_split[0] === "http:" || url_split[0] === "https:") )
                return true;
        }
      }
    } else {
      //Hosted, Android, and iOS don't have the same privacy concerns
      return true;
    }
    return false;
  },

  /**
   * Gives the domain for the user's trusted content server.
   *
   * @return {string} The domain content is associated with.
   */
  contentServerDomain: function() {
    var protocolDomainPort = location.protocol +
                             '//'+location.hostname +
                             (location.port ? ':'+location.port: '');

    var platformName = privlyNetworkService.platformName();
    if (platformName === "HOSTED") {
      return protocolDomainPort;
    } else if (platformName === "CHROME" ||
               platformName === "FIREFOX" ||
               platformName === "IOS") {
      return ls.getItem("posting_content_server_url");
    } else if (platformName === "ANDROID") {
      return androidJsBridge.fetchDomainName();
    } else {
      return protocolDomainPort;
    }
  },

  /**
   * Make a same-origin get request for content.
   *
   * This request should always proceed a post request to ensure the post
   * endpoint is expecting integration with the extension.
   *
   * @param {string} url The URL to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   */
  sameOriginGetRequest: function(url, callback) {

    // Add the auth token if the get request is on the user's content
    // server
    if( url.indexOf(privlyNetworkService.contentServerDomain()) === 0 ) {
      url = privlyNetworkService.getAuthenticatedUrl(url);
    }

    $.ajax({
      url: url,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin post request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginPostRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "POST",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin put request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginPutRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "PUT",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Make a same-origin delete request to the specified server.
   *
   * Warning: Do not use this function without first checking the data returned
   * by a get request for conformance with the application's signature.
   * Basically, you need to see whether the data at the URL expects to interface
   * with your application. The easiest way to do this is to have a version
   * string for your application in the JSON stored on the content server.
   * This prevents some rather nasty cross-site-scripting attacks.
   *
   * @param {string} url The url to make a cross domain request for.
   * @param {function} callback The function to execute after the response
   * returns.
   * @param {object} data The data to be sent with the post request.
   */
  sameOriginDeleteRequest: function(url, callback, data) {
    url = privlyNetworkService.getAuthenticatedUrl(url);
    $.ajax({
      url: url,
      cache: false,
      type: "DELETE",
      data: data,
      dataType: "json",
      headers: {
              Accept: "application/json",
              "X-CSRF-Token": privlyNetworkService.getCSRFToken(url),
              "X-Requested-With": "XMLHttpRequest"
          },
      success: function (json, textStatus, jqXHR) {
        callback({json: json, textStatus: textStatus, jqXHR: jqXHR});
      },
      error: function (jqXHR, textStatus, errorThrown) {
        callback({json: {}, textStatus: textStatus, jqXHR: jqXHR});
      }
    });
  },

  /**
   * Hide all the elements not required by mobile and adjust the CSS appropriately.
   * Elements will only be modified for mobile apps.
   */
  mobileHide: function() {
    if( privlyNetworkService.platformName() === "IOS" ||
        privlyNetworkService.platformName() === "ANDROID" ) {
      $(".mobile_hide").hide();
      $("body").css("padding-top", "0px");
    }
  },

  /**
   * Assign the href attribute of navigation links appropriately.
   */
  initializeNavigation: function() {
    var domain = privlyNetworkService.contentServerDomain();
    $(".home_domain").text(domain.split("/")[2]);
    $(".account_url").attr("href", domain + "/pages/account");
    $(".legal_nav").attr("href", domain + "/pages/privacy");
    document.getElementById("logout_link").addEventListener('click', function(){
      $.post(domain + "/users/sign_out", "_method=delete", function(data) {
        window.location = "../Login/new.html";
      });
    });

    // Change the target property to be self if the application is hosted
    // by a remote server.
    if( privlyNetworkService.platformName() === "HOSTED" ) {
      $(".home_domain").attr("href", domain);
      $(".home_domain").attr("target", "_self");
      $(".account_url").attr("target", "_self");
      $(".legal_nav").attr("target", "_self");
    }

    privlyNetworkService.mobileHide();
  },

  /**
   * Show/hide the appropriate navigation items for when the user is logged out.
   */
  showLoggedOutNav: function() {

    // Don't show the nav at all if the content is injected.
    if(typeof privlyHostPage !== "undefined" && privlyHostPage.isInjected()) {
      return;
    }
    $(".logged_in_nav").hide();
    $(".logged_out_nav").show();
    $(".injected_hide").show();
    privlyNetworkService.mobileHide();
  },

  /**
   * Show/hide the appropriate navigation items for when the user is logged in.
   */
  showLoggedInNav: function() {

    // Don't show the nav at all if the content is injected.
    if(typeof privlyHostPage !== "undefined" && privlyHostPage.isInjected()) {
      return;
    }
    $(".injected_hide").show();
    $(".logged_in_nav").show();
    $(".logged_out_nav").hide();
    privlyNetworkService.mobileHide();
  }
}
<|endoftext|>


<commit_before>/**
 *Static class that:
 * -includes all the data models (by including the class IncludeDataModels.js)
 * -includes class utils (that contains methods such as instantiate)
 * -contains the global variables (such as userAgent, canvas, nF, mX…), global
 * -contains the listener methods
 * -triggers de init, update and draw in Global class
 * @constructor
 */
function Global(){}

Global.userAgent="unknown";

init=function(){
  //console.log("init must be overriden!");
}

cycle=function(){
  //console.log("cycle must be overriden!");
}

resizeWindow=function(){
  console.log("resizeWindow must be overriden!");
}

var listenerArray  = new Array();
var canvas;
var removeDiv;
var userAgent="none";
var userAgentVersion;
var canvasResizeable=true;

//global useful vars
var cW = 1; // canvas width
var cH = 1; // canvas height
var cX = 1; // canvas center x
var cY = 1; // canvas center y
var mX = 0; // cursor x
var mY = 0; // cursor y
var mP = new Point(0, 0); // cursor point
var nF = 0; // number of current frame

var MOUSE_DOWN=false; //true on the frame of mousedown event
var MOUSE_UP=false; //true on the frame of mouseup event
var MOUSE_UP_FAST=false; //true on the frame of mouseup event
var NF_DOWN; //number of frame of last mousedown event
var NF_UP; //number of frame of last mouseup event
var MOUSE_PRESSED; //true if mouse pressed
var mX_DOWN; // cursor x position on last mousedown event
var mY_DOWN; // cursor x position on last mousedown event
var mX_UP; // cursor x position on last mousedown event
var mY_UP; // cursor x position on last mousedown event

//
var deltaWheel = 0;
var cursorStyle = 'auto';
var backGroundColor = 'white';
var cycleActive;

//global constants
var context;
var hddenContext;
var TwoPi = 2*Math.PI;
var HalfPi = 0.5*Math.PI;
var radToGrad = 180/Math.PI;
var gradToRad = Math.PI/180;
var c = console; //use c.log instead of console.log

//private
var _wheelActivated = false;
var _keyboardActivated = false;

var _prevMouseX = 0;
var _prevMouseY = 0;
var _setIntervalId;
var _setTimeOutId;
var _cycleOnMouseMovement = false;
var _interactionCancelledFrame;
var END_CYCLE_DELAY = 3000;

window.addEventListener('load', function(){
	c.log('Moebio Framework v2.201');

 	if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ //test for MSIE x.x;
    	userAgent='IE';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
    	if(userAgentVersion<9) return null;
	} else if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
   		userAgent='FIREFOX';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
   	} else if (navigator.userAgent.match(/Chrome/) != null){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
	 	userAgent='CHROME';
	    userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
	} else if (/Mozilla[\/\s](\d+\.\d+)/.test(navigator.userAgent) || navigator.userAgent.match(/Mozilla/) != null){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
	 	userAgent='MOZILLA';
	    userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
	} else if (navigator.userAgent.match(/Safari/) != null){ //test for MSIE x.x;
    	userAgent='Safari';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
  	} else if(navigator.userAgent.match(/iPad/i) != null){
    	userAgent='IOS';
  	} else if(navigator.userAgent.match(/iPhone/i) != null){
    	userAgent='IOS';
  	}

  	c.log('[G] userAgent:', userAgent);

  	Global.userAgent=userAgent;
    Global.frameRate=30;

	canvas = document.getElementById('main');

	if(canvas!=null){
		removeDiv = document.getElementById('removeDiv');
		removeDiv.style.display = 'none';
		cH=canvas.height;
		cW=canvas.width;
		context = canvas.getContext('2d');

		//hiddenContext = CanvasAndContext.createInvisibleContext();

		cW = context.canvas.width  = window.innerWidth;
		cH = context.canvas.height = window.innerHeight;

		cX = Math.floor(cW*0.5);
		cY = Math.floor(cH*0.5);

		canvas.addEventListener("mousemove", _onMouse, false);
		canvas.addEventListener("mousedown", _onMouse, false);
		canvas.addEventListener("mouseup", _onMouse, false);
		window.addEventListener("resize", onResize, false);

		startCycle();
		init();
	}

}, false);

function _onMouse(e) {
	switch(e.type){
		case "mousemove":
			if(e.clientX){
				mX = e.clientX;
		        mY = e.clientY;
			} else if(e.offsetX) {
		        mX = e.offsetX;
		        mY = e.offsetY;
		    } else if(e.layerX) {
		        mX = e.layerX;
		        mY = e.layerY;
		    }
		  	mP.x = mX;
		  	mP.y = mY;
		  	break;
		case "mousedown":
			NF_DOWN = nF;
			MOUSE_PRESSED = true;
			mX_DOWN = mX;
			mY_DOWN = mY;
			break;
		case "mouseup":
			NF_UP = nF;
			MOUSE_PRESSED = false;
			mX_UP = mX;
			mY_UP = mY;
			break;
	}
}

function onResize(e){
	if(canvasResizeable==false) return;

	canvas.setAttribute('width', document.body.clientWidth);
    canvas.setAttribute('height', document.body.clientHeight);

	cW = context.canvas.width;
	cH = context.canvas.height;

	cX = Math.floor(cW*0.5);
	cY = Math.floor(cH*0.5);

	resizeWindow();
}

function clearContext(){
	context.clearRect(0, 0, cW, cH);
}

function cycleOnMouseMovement(value){
	if(value){
		context.canvas.addEventListener('mousemove', onMoveCycle, false);
		addInteractionEventListener('mousewheel', onMoveCycle, this);
		_cycleOnMouseMovement = true;
		stopCycle();
	} else {
		context.canvas.removeEventListener('mousemove', onMoveCycle, false);
		removeInteractionEventListener('mousewheel', onMoveCycle, this);
		_cycleOnMouseMovement = false;
		startCycle();
	}
}

function enterFrame(){
   	context.clearRect(0, 0, cW, cH);
   	setCursor('default');

   	MOUSE_DOWN = NF_DOWN==nF;
	MOUSE_UP = NF_UP==nF;
	MOUSE_UP_FAST = MOUSE_UP && (nF-NF_DOWN)<9;

  	cycle();

  	nF++;
}

function startCycle(){
	clearTimeout(_setTimeOutId);
	clearInterval(_setIntervalId);
	_setIntervalId = setInterval(enterFrame, 30);
	cycleActive = true;
}

function stopCycle(){
	clearInterval(_setIntervalId);
	cycleActive = false;
}

function onMoveCycle(e){
	if(e.type=='mousemove' && _prevMouseX==mX && _prevMouseY==mY) return;
	reStartCycle();
}

function reStartCycle(){
	_prevMouseX=mX;
	_prevMouseY=mY;

	if(!cycleActive){
		_setIntervalId = setInterval(enterFrame, 30);
		cycleActive = true;
	}

	clearTimeout(_setTimeOutId);
	_setTimeOutId = setTimeout(stopCycle, END_CYCLE_DELAY);
}

//interaction events
function addInteractionEventListener(eventType, onFunction, target){//TODO: listenerArray contains objects instead of arrays
	listenerArray.push(new Array(eventType, onFunction, target));
	switch(eventType){
		case 'mousedown':
		case 'mouseup':
		case 'click':
		case 'mousemove':
			context.canvas.addEventListener(eventType, onCanvasEvent, false);
			break;
		case 'mousewheel':
			if(!_wheelActivated) activateWheel();
			break;
		case 'keydown':
			if(!_keyboardActivated) activateKeyboard();
			break;
	}
}

function onCanvasEvent(e){
	var i;
	for(i=0; listenerArray[i]!=null; i++){
		if(listenerArray[i][0]==e.type.replace('DOMMouseScroll', 'mousewheel')){
			if(_interactionCancelledFrame==nF) return;
			listenerArray[i][1].call(listenerArray[i][2], e);
		}
	}
}

function removeInteractionEventListener(eventType, onFunction, target){ //TODO: finish this (requires single element removing method solved first)
	for(var i=0; listenerArray[i]!=null; i++){
		if(listenerArray[i][0]==eventType && listenerArray[i][1]==onFunction && listenerArray[i][2]==target){
			delete listenerArray[i];
			listenerArray.splice(i, 1);
			i--;
		}
	}
}
function cancelAllInteractions(){
	c.log("cancelAllInteractions, _interactionCancelledFrame:", nF);
	_interactionCancelledFrame = nF;
}

function setBackgroundColor(color){
	if(typeof color == "number"){
		if(arguments.length>3){
			color = 'rgba('+arguments[0]+','+arguments[1]+','+arguments[2]+','+arguments[3]+')';
		} else {
			color = 'rgb('+arguments[0]+','+arguments[1]+','+arguments[2]+')';
		}
	} else if(Array.isArray(color)){
		color = ColorOperators.RGBtoHEX(color[0], color[1], color[2]);
	}
	backGroundColor = color;
	var body = document.getElementById('index');
	body.setAttribute('bgcolor', backGroundColor);
}

function setDivPosition(div, x, y){
	div.setAttribute('style', 'position:absolute;left:'+String(x)+'px;top:'+String(y)+'px;');
}

/////////////////////////////////// keyboard and wheel

function activateKeyboard(){
	_keyboardActivated = true;
	document.onkeydown = onKey;
}
function onKey(e){
	onCanvasEvent(e);
}

/**
 * thanks http://www.adomas.org/javascript-mouse-wheel
 */
function activateWheel(){
	_wheelActivated = true;

	if (window.addEventListener){
		window.addEventListener('DOMMouseScroll', _onWheel, false);
		//window.addEventListener("mousewheel", _onWheel, false); // testing
	}
	window.onmousewheel = document.onmousewheel = _onWheel;

}
function _onWheel(e) {
    if (!e) e = window.event; //IE

    if (e.wheelDelta){
    	deltaWheel = e.wheelDelta/120;
    } else if (e.detail) { /** Mozilla case. */
        deltaWheel = -e.detail/3;
    }
    e.value = deltaWheel;
    e.type = "mousewheel"; //why this doesn't work?
	onCanvasEvent(e);
}

<commit_msg>minor change in Global to test publishing<commit_after>/**
 *Static class that:
 * -includes all the data models (by including the class IncludeDataModels.js)
 * -includes class utils (that contains methods such as instantiate)
 * -contains the global variables (such as userAgent, canvas, nF, mX…), global
 * -contains the listener methods
 * -triggers de init, update and draw in Global class
 * @constructor
 */
function Global(){}

Global.userAgent="unknown";

init=function(){
  //console.log("init must be overriden!");
}

cycle=function(){
  //console.log("cycle must be overriden!");
}

resizeWindow=function(){
  console.log("resizeWindow must be overriden!");
}

var listenerArray  = new Array();
var canvas;
var removeDiv;
var userAgent="none";
var userAgentVersion;
var canvasResizeable=true;

//global useful vars
var cW = 1; // canvas width
var cH = 1; // canvas height
var cX = 1; // canvas center x
var cY = 1; // canvas center y
var mX = 0; // cursor x
var mY = 0; // cursor y
var mP = new Point(0, 0); // cursor point
var nF = 0; // number of current frame

var MOUSE_DOWN=false; //true on the frame of mousedown event
var MOUSE_UP=false; //true on the frame of mouseup event
var MOUSE_UP_FAST=false; //true on the frame of mouseup event
var NF_DOWN; //number of frame of last mousedown event
var NF_UP; //number of frame of last mouseup event
var MOUSE_PRESSED; //true if mouse pressed
var mX_DOWN; // cursor x position on last mousedown event
var mY_DOWN; // cursor x position on last mousedown event
var mX_UP; // cursor x position on last mousedown event
var mY_UP; // cursor x position on last mousedown event

//
var deltaWheel = 0;
var cursorStyle = 'auto';
var backGroundColor = 'white';
var cycleActive;

//global constants
var context;
var hddenContext;
var TwoPi = 2*Math.PI;
var HalfPi = 0.5*Math.PI;
var radToGrad = 180/Math.PI;
var gradToRad = Math.PI/180;
var c = console; //use c.log instead of console.log

//private
var _wheelActivated = false;
var _keyboardActivated = false;

var _prevMouseX = 0;
var _prevMouseY = 0;
var _setIntervalId;
var _setTimeOutId;
var _cycleOnMouseMovement = false;
var _interactionCancelledFrame;
var END_CYCLE_DELAY = 3000;

window.addEventListener('load', function(){
	c.log('Moebio Framework v2.202');

 	if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ //test for MSIE x.x;
    	userAgent='IE';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
    	if(userAgentVersion<9) return null;
	} else if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
   		userAgent='FIREFOX';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
   	} else if (navigator.userAgent.match(/Chrome/) != null){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
	 	userAgent='CHROME';
	    userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
	} else if (/Mozilla[\/\s](\d+\.\d+)/.test(navigator.userAgent) || navigator.userAgent.match(/Mozilla/) != null){ //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
	 	userAgent='MOZILLA';
	    userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
	} else if (navigator.userAgent.match(/Safari/) != null){ //test for MSIE x.x;
    	userAgent='Safari';
    	userAgentVersion=new Number(RegExp.$1) // capture x.x portion and store as a number
  	} else if(navigator.userAgent.match(/iPad/i) != null){
    	userAgent='IOS';
  	} else if(navigator.userAgent.match(/iPhone/i) != null){
    	userAgent='IOS';
  	}

  	c.log('[G] userAgent:', userAgent);

  	Global.userAgent=userAgent;
    Global.frameRate=30;

	canvas = document.getElementById('main');

	if(canvas!=null){
		removeDiv = document.getElementById('removeDiv');
		removeDiv.style.display = 'none';
		cH=canvas.height;
		cW=canvas.width;
		context = canvas.getContext('2d');

		//hiddenContext = CanvasAndContext.createInvisibleContext();

		cW = context.canvas.width  = window.innerWidth;
		cH = context.canvas.height = window.innerHeight;

		cX = Math.floor(cW*0.5);
		cY = Math.floor(cH*0.5);

		canvas.addEventListener("mousemove", _onMouse, false);
		canvas.addEventListener("mousedown", _onMouse, false);
		canvas.addEventListener("mouseup", _onMouse, false);
		window.addEventListener("resize", onResize, false);

		startCycle();
		init();
	}

}, false);

function _onMouse(e) {
	switch(e.type){
		case "mousemove":
			if(e.clientX){
				mX = e.clientX;
		        mY = e.clientY;
			} else if(e.offsetX) {
		        mX = e.offsetX;
		        mY = e.offsetY;
		    } else if(e.layerX) {
		        mX = e.layerX;
		        mY = e.layerY;
		    }
		  	mP.x = mX;
		  	mP.y = mY;
		  	break;
		case "mousedown":
			NF_DOWN = nF;
			MOUSE_PRESSED = true;
			mX_DOWN = mX;
			mY_DOWN = mY;
			break;
		case "mouseup":
			NF_UP = nF;
			MOUSE_PRESSED = false;
			mX_UP = mX;
			mY_UP = mY;
			break;
	}
}

function onResize(e){
	if(canvasResizeable==false) return;

	canvas.setAttribute('width', document.body.clientWidth);
    canvas.setAttribute('height', document.body.clientHeight);

	cW = context.canvas.width;
	cH = context.canvas.height;

	cX = Math.floor(cW*0.5);
	cY = Math.floor(cH*0.5);

	resizeWindow();
}

function clearContext(){
	context.clearRect(0, 0, cW, cH);
}

function cycleOnMouseMovement(value){
	if(value){
		context.canvas.addEventListener('mousemove', onMoveCycle, false);
		addInteractionEventListener('mousewheel', onMoveCycle, this);
		_cycleOnMouseMovement = true;
		stopCycle();
	} else {
		context.canvas.removeEventListener('mousemove', onMoveCycle, false);
		removeInteractionEventListener('mousewheel', onMoveCycle, this);
		_cycleOnMouseMovement = false;
		startCycle();
	}
}

function enterFrame(){
   	context.clearRect(0, 0, cW, cH);
   	setCursor('default');

   	MOUSE_DOWN = NF_DOWN==nF;
	MOUSE_UP = NF_UP==nF;
	MOUSE_UP_FAST = MOUSE_UP && (nF-NF_DOWN)<9;

  	cycle();

  	nF++;
}

function startCycle(){
	clearTimeout(_setTimeOutId);
	clearInterval(_setIntervalId);
	_setIntervalId = setInterval(enterFrame, 30);
	cycleActive = true;
}

function stopCycle(){
	clearInterval(_setIntervalId);
	cycleActive = false;
}

function onMoveCycle(e){
	if(e.type=='mousemove' && _prevMouseX==mX && _prevMouseY==mY) return;
	reStartCycle();
}

function reStartCycle(){
	_prevMouseX=mX;
	_prevMouseY=mY;

	if(!cycleActive){
		_setIntervalId = setInterval(enterFrame, 30);
		cycleActive = true;
	}

	clearTimeout(_setTimeOutId);
	_setTimeOutId = setTimeout(stopCycle, END_CYCLE_DELAY);
}

//interaction events
function addInteractionEventListener(eventType, onFunction, target){//TODO: listenerArray contains objects instead of arrays
	listenerArray.push(new Array(eventType, onFunction, target));
	switch(eventType){
		case 'mousedown':
		case 'mouseup':
		case 'click':
		case 'mousemove':
			context.canvas.addEventListener(eventType, onCanvasEvent, false);
			break;
		case 'mousewheel':
			if(!_wheelActivated) activateWheel();
			break;
		case 'keydown':
			if(!_keyboardActivated) activateKeyboard();
			break;
	}
}

function onCanvasEvent(e){
	var i;
	for(i=0; listenerArray[i]!=null; i++){
		if(listenerArray[i][0]==e.type.replace('DOMMouseScroll', 'mousewheel')){
			if(_interactionCancelledFrame==nF) return;
			listenerArray[i][1].call(listenerArray[i][2], e);
		}
	}
}

function removeInteractionEventListener(eventType, onFunction, target){ //TODO: finish this (requires single element removing method solved first)
	for(var i=0; listenerArray[i]!=null; i++){
		if(listenerArray[i][0]==eventType && listenerArray[i][1]==onFunction && listenerArray[i][2]==target){
			delete listenerArray[i];
			listenerArray.splice(i, 1);
			i--;
		}
	}
}
function cancelAllInteractions(){
	c.log("cancelAllInteractions, _interactionCancelledFrame:", nF);
	_interactionCancelledFrame = nF;
}

function setBackgroundColor(color){
	if(typeof color == "number"){
		if(arguments.length>3){
			color = 'rgba('+arguments[0]+','+arguments[1]+','+arguments[2]+','+arguments[3]+')';
		} else {
			color = 'rgb('+arguments[0]+','+arguments[1]+','+arguments[2]+')';
		}
	} else if(Array.isArray(color)){
		color = ColorOperators.RGBtoHEX(color[0], color[1], color[2]);
	}
	backGroundColor = color;
	var body = document.getElementById('index');
	body.setAttribute('bgcolor', backGroundColor);
}

function setDivPosition(div, x, y){
	div.setAttribute('style', 'position:absolute;left:'+String(x)+'px;top:'+String(y)+'px;');
}

/////////////////////////////////// keyboard and wheel

function activateKeyboard(){
	_keyboardActivated = true;
	document.onkeydown = onKey;
}
function onKey(e){
	onCanvasEvent(e);
}

/**
 * thanks http://www.adomas.org/javascript-mouse-wheel
 */
function activateWheel(){
	_wheelActivated = true;

	if (window.addEventListener){
		window.addEventListener('DOMMouseScroll', _onWheel, false);
		//window.addEventListener("mousewheel", _onWheel, false); // testing
	}
	window.onmousewheel = document.onmousewheel = _onWheel;

}
function _onWheel(e) {
    if (!e) e = window.event; //IE

    if (e.wheelDelta){
    	deltaWheel = e.wheelDelta/120;
    } else if (e.detail) { /** Mozilla case. */
        deltaWheel = -e.detail/3;
    }
    e.value = deltaWheel;
    e.type = "mousewheel"; //why this doesn't work?
	onCanvasEvent(e);
}

<|endoftext|>


<commit_before>/*
 * JSX tokanizer
 */
"use strict";

var Class = require("./Class");
var KeywordToken = require("./KeywordToken");
var SpaceToken = require("./SpaceToken");
var IdentifierToken = require("./IdentifierToken");
var StringToken = require("./StringToken");
var NumberToken = require("./NumberToken");
var RegExpToken = require("./RegExpToken");
var UnknownToken = require("./UnknownToken");

var validate = require("./validate");

var Lexer = Class.extend({

	$makeAlt: function (patterns) {
		return "(?: \n" + patterns.join("\n | \n") + "\n)\n";
	},

	$quoteMeta: function (pattern) {
		return pattern.replace(/([^0-9A-Za-z_])/g, '\\$1');
	},

	/// compile a regular expression
	$rx: function (pat, flags) {
		return RegExp(pat.replace(/[ \t\r\n]/g, ""), flags);
	},

	// static variables
	$initialize: function () {
		this.ident             = " [a-zA-Z_] [a-zA-Z0-9_]* ";
		this.doubleQuoted      = ' "  [^"\\\\]* (?: \\\\. [^"\\\\]* )* " ';
		this.singleQuoted      = " '  [^'\\\\]* (?: \\\\. [^'\\\\]* )* ' ";
		this.stringLiteral     = this.makeAlt([this.singleQuoted, this.doubleQuoted]);
		this.regexpLiteral     = this.doubleQuoted.replace(/"/g, "/");
		this.decimal           = "(?: [0-9][0-9_]* (?: \\. [0-9_]+)? \\b )";
		this.integral          =
			"(?: 0 " + this.makeAlt([
				"(?: [0-7_]+ )",         // octal
				"(?: x [0-9a-fA-F_]+ )", // hex
				"(?: b [01_]+ )"         // binary
			]) + "?)";
		this.numberLiteral     = this.makeAlt([this.decimal, this.integral]);
		this.multiLineComment  = "(?: /\\* (?: [^*] | (?: \\*+ [^*\/]) )* \\*+/)";
		this.singleLineComment = "(?: // [^\\r\\n]* )";
		this.comment           = this.makeAlt([this.multiLineComment, this.singleLineComment]);
		this.whiteSpace        = "[\\x20\\t\\r\\n]+";

		var keyword           = [
			// from ECMA262 (7.6.1)
			// keywords
			"break",    "do",       "instanceof", "typeof",
			"case",     "else",     "new",        "var",
			"catch",    "finally",  "return",     "void",
			"continue", "for",      "switch",     "while",
			"debugger", "function", "this",       "with",
			"default",  "if",       "throw",
			"delete",   "in",       "try",
			// future reserved words
			"class", "enum",   "extends", "super",
			"const", "export", "import",
			// future reserved words within strict mode
			"implements", "let",     "private",   "public", "yield",
			"interface",  "package", "protected", "static",
			// literals
			"null", "true", "false", "undefined",

			// JSX specific reserved words
			"extern", "native",
			"trait", "using",
			"as", "is",
			"operator",
			"assert", "log",
			"__FILE__", "__LINE__"
		];
		this.keyword = {};
		for (var i = 0; i < keyword; i++)
			this.keyword[keyword[i]] = 1;

		// some operators are not used, but recognized
		// in order to make error massages helpful.
		// e.g. "operator -> is not defined. Do you mean this.foo()?"
		var ops = [
			"{",  "}",  "(",  ")",  "[",  "]",
			".",  ";",  ",",  ":",  "?",  "@",
			"->", "\\", "::", "..", "...",

			"<",  ">",  "<=",  ">=",
			"==", "!=", "<=>", "=~", "~!",

			"=",
			"+",  "-",  "*",  "/",  "%",
			"+=", "-=", "*=", "/=", "%=",
			"&",  "|",  "^",
			"&=", "|=", "^=",
			"~",  "!",
			"++", "--",
			"||", "&&"
		];
		for (var i = 0; i < ops.length; i++)
			ops[i] = this.quoteMeta(ops[i]);
		this.operator = this.makeAlt(ops.sort().reverse());

		// regular expressions
		this.rxOperator      = this.rx("^" + this.operator);
		this.rxIdent         = this.rx("^" + this.ident);
		this.rxStringLiteral = this.rx("^" + this.stringLiteral);
		this.rxNumberLiteral = this.rx("^" + this.numberLiteral);
		this.rxRegExpLiteral = this.rx("^" + this.regexpLiteral);
		this.rxSpace         = this.rx("^" + this.makeAlt([this.comment, this.whiteSpace]));
	},

	initialize: function (input) {
		this._input = input;
		this._ungetStack = [];
		//  position properties
		this._pos = 0;
	},

	unget: function (token) {
		this._ungetStack.push(token);
	},

	nextToken: function() {
		if (this._ungetStack.length > 0) {
			return this._ungetStack.pop();
		}

		if (this._input.length <= this._pos) {
			return null;
		}

		var start = this._input.substring(this._pos);
		var matched;
		var token;
		if (matched = start.match(Lexer.rxSpace)) {
			token = new SpaceToken(this._pos);
		}
		else if (matched = start.match(Lexer.rxStringLiteral)) {
			token = new StringToken(matched[0], this._pos);
		}
		else if (matched = start.match(Lexer.rxNumberLiteral)) {
			token = new NumberToken(matched[0], this._pos);
		}
		else if (matched = start.match(Lexer.rxRegExpLiteral)) {
			token = new RegExpToken(matched[0], this._pos);
		}
		else if (matched = start.match(Lexer.rxOperator)) {
			token = new KeywordToken(matched[0], this._pos);
		}
		else if (matched = start.match(Lexer.rxIdent)) {
			if (Lexer.keyword[matched[0]]) {
				token = new KeywordToken(matched[0], this._pos);
			} else {
				token = new IdentifierToken(matched[0], this._pos);
			}
		}
		else {
			matched = start.match(/^./);
			token = new UnknownToken(matched[0], this._pos);
		}

		this._pos += matched[0].length;

		return token;
	}
});

if (typeof(process) !== 'undefined' && process.argv[1] === __filename) {
    // testing in node.js
    process.argv.slice(2).map(function(file) {
        console.log(file);
        var fs   = require("fs");
        var content = fs.readFileSync(file).toString();

        var lexer = new Lexer(content);

        var t0 = Date.now();

        var token;
        while ((token = lexer.nextToken()) !== null) {
			console.log(JSON.stringify(token.serialize()));
        }
        console.log("elapsed %s ms.", Date.now() - t0);
    });
}
else {
    module.exports = Lexer;
}
<commit_msg>report syntax error (and the use of reserved words)<commit_after>/*
 * JSX tokanizer
 */
"use strict";

var Class = require("./Class");
var KeywordToken = require("./KeywordToken");
var SpaceToken = require("./SpaceToken");
var IdentifierToken = require("./IdentifierToken");
var StringToken = require("./StringToken");
var NumberToken = require("./NumberToken");
var RegExpToken = require("./RegExpToken");
var UnknownToken = require("./UnknownToken");

var validate = require("./validate");
var log = console.log;

var Lexer = Class.extend({

	$makeAlt: function (patterns) {
		return "(?: \n" + patterns.join("\n | \n") + "\n)\n";
	},

	$quoteMeta: function (pattern) {
		return pattern.replace(/([^0-9A-Za-z_])/g, '\\$1');
	},

	$asHash: function (array) {
		var hash = {};
		for (var i = 0; i < array.length; ++i)
			hash[array[i]] = 1;
		return hash;
	},

	/// compile a regular expression
	$rx: function (pat, flags) {
		return RegExp(pat.replace(/[ \t\r\n]/g, ""), flags);
	},

	// static variables
	$initialize: function () {
		this.ident             = " [a-zA-Z_] [a-zA-Z0-9_]* ";
		this.doubleQuoted      = ' "  [^"\\\\]* (?: \\\\. [^"\\\\]* )* " ';
		this.singleQuoted      = " '  [^'\\\\]* (?: \\\\. [^'\\\\]* )* ' ";
		this.stringLiteral     = this.makeAlt([this.singleQuoted, this.doubleQuoted]);
		this.regexpLiteral     = this.doubleQuoted.replace(/"/g, "/");
		this.decimal           = "(?: [0-9][0-9_]* (?: \\. [0-9_]+)? \\b )";
		this.integral          =
			"(?: 0 " + this.makeAlt([
				"(?: [0-7_]+ )",         // octal
				"(?: x [0-9a-fA-F_]+ )", // hex
				"(?: b [01_]+ )"         // binary
			]) + "?)";
		this.numberLiteral     = this.makeAlt([this.decimal, this.integral]);
		this.multiLineComment  = "(?: /\\* (?: [^*] | (?: \\*+ [^*\/]) )* \\*+/)";
		this.singleLineComment = "(?: // [^\\r\\n]* )";
		this.comment           = this.makeAlt([this.multiLineComment, this.singleLineComment]);
		this.whiteSpace        = "[\\x20\\t\\r\\n]+";

		this.keyword           = this.asHash([
			// literals shared with ECMA 262
			"null",     "true",     "false",
			// keywords shared with ECMA 262
			"break",    "do",       "instanceof", "typeof",
			"case",     "else",     "new",        "var",
			"catch",    "finally",  "return",     "void",
			"continue", "for",      "switch",     "while",
			"function", "this",
			"default",  "if",       "throw",
			"delete",   "in",       "try",
			// keywords of JSX
			"class",    "extends",  "super",
			"import",   "implements",
			"interface",	"package", "static",
			"assert", "log",
			"__FILE__",	"__LINE__"
		]);
		this.reserved          = this.asHash([
			// literals of ECMA 262 but not used by JSX
			"debugger", "with",
			// future reserved words of ECMA 262
			"const", "export",
			// future reserved words within strict mode of ECMA 262
			"let",     "private",   "public", "yield",
			"protected",

			// JSX specific reserved words
			"extern", "native",
			"trait", "using",
			"as", "is",
			"operator"
		]);

		// some operators are not used, but recognized
		// in order to make error massages helpful.
		// e.g. "operator -> is not defined. Do you mean this.foo()?"
		var ops = [
			"{",  "}",  "(",  ")",  "[",  "]",
			".",  ";",  ",",  ":",  "?",  "@",
			"->", "\\", "::", "..", "...",

			"<",  ">",  "<=",  ">=",
			"==", "!=", "<=>", "=~", "~!",

			"=",
			"+",  "-",  "*",  "/",  "%",
			"+=", "-=", "*=", "/=", "%=",
			"&",  "|",  "^",
			"&=", "|=", "^=",
			"~",  "!",
			"++", "--",
			"||", "&&"
		];
		for (var i = 0; i < ops.length; i++)
			ops[i] = this.quoteMeta(ops[i]);
		this.operator = this.makeAlt(ops.sort().reverse());

		// regular expressions
		this.rxOperator      = this.rx("^" + this.operator);
		this.rxIdent         = this.rx("^" + this.ident);
		this.rxStringLiteral = this.rx("^" + this.stringLiteral);
		this.rxNumberLiteral = this.rx("^" + this.numberLiteral);
		this.rxRegExpLiteral = this.rx("^" + this.regexpLiteral);
		this.rxSpace         = this.rx("^" + this.makeAlt([this.comment, this.whiteSpace]));
	},

	initialize: function (input) {
		this._input = input;
		this._ungetStack = [];
		//  position properties
		this._pos = 0;
	},

	unget: function (token) {
		this._ungetStack.push(token);
	},

	nextToken: function() {
		if (this._ungetStack.length > 0) {
			return this._ungetStack.pop();
		}

		var token = null;
		do {
			if (this._input.length <= this._pos) {
				return null;
			}

			var start = this._input.substring(this._pos);
			var matched;
			var token;
			if (matched = start.match(Lexer.rxSpace)) {
				token = new SpaceToken(this._pos);
			}
			else if (matched = start.match(Lexer.rxStringLiteral)) {
				token = new StringToken(matched[0], this._pos);
			}
			else if (matched = start.match(Lexer.rxNumberLiteral)) {
				token = new NumberToken(matched[0], this._pos);
			}
			else if (matched = start.match(Lexer.rxRegExpLiteral)) {
				token = new RegExpToken(matched[0], this._pos);
			}
			else if (matched = start.match(Lexer.rxOperator)) {
				token = new KeywordToken(matched[0], this._pos);
			}
			else if (matched = start.match(Lexer.rxIdent)) {
				if (Lexer.keyword[matched[0]]) {
					token = new KeywordToken(matched[0], this._pos);
				} else if (Lexer.reserved[matched[0]]) {
					this.reportSyntaxError("keyword " + matched[0] + " is not supported under current version of JSX");
				} else {
					token = new IdentifierToken(matched[0], this._pos);
				}
			}
			else {
				this.reportSyntaxError(null);
				matched = start.match(/^.?(?:\r\n?|\n|$)/); // skip to the end of line
			}

			this._pos += matched[0].length;
		} while (token == null);

		return token;
	},

	reportSyntaxError: function (extra) {
		log("syntax error at %d:%d" + (extra !== null ? ": " + extra : ""));
	}

});

if (typeof(process) !== 'undefined' && process.argv[1] === __filename) {
    // testing in node.js
    process.argv.slice(2).map(function(file) {
        console.log(file);
        var fs   = require("fs");
        var content = fs.readFileSync(file).toString();

        var lexer = new Lexer(content);

        var t0 = Date.now();

        var token;
        while ((token = lexer.nextToken()) !== null) {
			console.log(JSON.stringify(token.serialize()));
        }
        console.log("elapsed %s ms.", Date.now() - t0);
    });
}
else {
    module.exports = Lexer;
}
<|endoftext|>


<commit_before>'use strict';
import {createAction} from 'redux-actions';
import req from 'request';
import Url from 'urlgray';
import urlJoin from 'url-join';

export const FETCH_OK = 'ADDON_VERSION__FETCH_OK';
const fetchOk = createAction(FETCH_OK);

export const DELETE_OK = 'ADDON_VERSION__DELETE_OK';
const deleteOk = createAction(DELETE_OK);

export function fetch(slug) {
  /*
    Fetch versions of an add-on.
  */
  return (dispatch, getState) => {
    const apiArgs = getState().apiArgs || {};
    const dashboardUrl = Url(
      urlJoin(process.env.MKT_API_ROOT, 'extensions/extension/')
    ).q(apiArgs);

    req
      .get(dashboardUrl)
      .then(res => {
        dispatch(fetchOk(res.body.objects));
      });
  };
}

export function del(addonSlug, versionId) {
  /*
    Delete a version of an add-on.
  */
  return (dispatch, getState) => {
    const apiArgs = getState().apiArgs || {};
    const versionUrl = Url(
      urlJoin(process.env.MKT_API_ROOT, 'extensions/extension/', addonSlug,
              'versions', versionId, '/')
    ).q(apiArgs);

    req
      .del(versionUrl)
      .then(res => {
        dispatch(deleteOk({
          addonSlug,
          versionId,
        }));
      });
  };
}
<commit_msg>delete version notification<commit_after>'use strict';
import {createAction} from 'redux-actions';
import req from 'request';
import Url from 'urlgray';
import urlJoin from 'url-join';

import * as notificationActions from '../../site/actions/notification';

export const FETCH_OK = 'ADDON_VERSION__FETCH_OK';
const fetchOk = createAction(FETCH_OK);

export const DELETE_OK = 'ADDON_VERSION__DELETE_OK';
const deleteOk = createAction(DELETE_OK);

export function fetch(slug) {
  /*
    Fetch versions of an add-on.
  */
  return (dispatch, getState) => {
    const apiArgs = getState().apiArgs || {};
    const dashboardUrl = Url(
      urlJoin(process.env.MKT_API_ROOT, 'extensions/extension/')
    ).q(apiArgs);

    req
      .get(dashboardUrl)
      .then(res => {
        dispatch(fetchOk(res.body.objects));
      });
  };
}

export function del(addonSlug, versionId) {
  /*
    Delete a version of an add-on.
  */
  return (dispatch, getState) => {
    const apiArgs = getState().apiArgs || {};
    const versionUrl = Url(
      urlJoin(process.env.MKT_API_ROOT, 'extensions/extension/', addonSlug,
              'versions', versionId, '/')
    ).q(apiArgs);

    req
      .del(versionUrl)
      .then(res => {
        dispatch(deleteOk({
          addonSlug,
          versionId,
        }));
        dispatch(notificationActions.queue(
          'Firefox OS Add-on version successfully deleted.'));
      });
  };
}
<|endoftext|>