diff --git a/dist/torque.full.js b/dist/torque.full.js index 7cf8f9b6..8cf7ef6c 100644 --- a/dist/torque.full.js +++ b/dist/torque.full.js @@ -1,7 +1,7 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.torque=e()}}(function(){var define,module,exports;return function e(t,n,r){function i(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return i(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var s=typeof require=="function"&&require;for(var o=0;oe&&this.time(0),this.rescale(),this):this.options.animationDuration},steps:function(e){return this.options.steps=e,this.rescale()},step:function(e){if(arguments.length===0)return this.range(this.domain(this._time));this._time=this.domainInv(this.rangeInv(e))},pause:function(){this.running=!1,s(this._tick),this.options.onPause&&this.options.onPause()},_tick:function(){var e=+(new Date),t=(e-this._t0)*.001;t=Math.min(this.options.maxDelta,t),this._t0=e,this._time+=t,this.step()>=this.options.steps&&(this.options.loop?this._time=0:(this.time(this.options.animationDuration),this.pause())),this.running&&(this.time(this._time),i(this._tick))}},t.exports=o}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./":10}],2:[function(e,t,n){var r={version:"1.0.0",style:{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]}},layer:{"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"number","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"number","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"number","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}},symbolizers:{"*":{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},trail:{steps:{css:"trail-steps",type:"float","default-value":1,"default-meaning":"no trail steps",doc:"How many steps of trails are going to be rendered"}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon"},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line"},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels"},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color"},"marker-type":{css:"marker-type",type:["rectangle","ellipse"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)"},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float"}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]}};t.exports={version:{latest:r,"1.0.0":r}}},{}],3:[function(e,t,n){(function(n){function i(){}var r=n.carto||e("carto");i.prototype={},i.optionsFromLayer=function(e){var t={};if(!e)return t;var n={"buffer-size":"buffer-size","-torque-frame-count":"steps","-torque-resolution":"resolution","-torque-animation-duration":"animationDuration","-torque-aggregation-function":"countby","-torque-time-attribute":"column","-torque-data-aggregation":"data_aggregation"};for(var r in n){var i=e.eval(r);if(i!==undefined){var s=n[r];t[s]=i}}return t},i.optionsFromCartoCSS=function(e){var t=(new r.RendererJS).render(e),n=t.findLayer({name:"Map"});return i.optionsFromLayer(n)},t.exports.TorqueLayer=i}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{carto:36}],4:[function(e,t,n){(function(e){function r(){var e=arguments,t=e[0];for(var n=1;ni&&(n.x-=i),this.canvas.style[r.CSS_TRANSFORM_]="translate("+Math.round(n.x)+"px,"+Math.round(n.y)+"px)",this.scheduleUpdate()},r.prototype.update_=function(){this.requestAnimationFrameId_=null;if(!this.isAdded_)return;this.isAnimated_&&this.scheduleUpdate(),this.needsResize_&&this.resizeHandler_&&(this.needsResize_=!1,this.resizeHandler_()),this.updateHandler_&&this.updateHandler_()},r.prototype.getTopLeft=function(){return this.topLeft_},r.prototype.scheduleUpdate=function(){this.isAdded_&&!this.requestAnimationFrameId_&&(this.requestAnimationFrameId_=this.requestAnimFrame_.call(window,this.requestUpdateFunction_))},t.exports=r},{}],6:[function(e,t,n){function r(e,t){this.tileSize=new google.maps.Size(256,256),this.maxZoom=19,this.name="Tile #s",this.alt="Canvas tile layer",this.tiles={},this.canvas_setup=e,this.render=t,t||(this.render=e)}r.prototype.create_tile_canvas=function(e,t,n){var r=n.createElement("canvas"),i=n.createElement("canvas");r.style.border=i.style.border="none",r.style.margin=i.style.margin="0",r.style.padding=i.style.padding="0";var s=r.getContext("2d");s.width=r.width=this.tileSize.width,s.height=r.height=this.tileSize.height;var o=i.getContext("2d");i.width=o.width=this.tileSize.width,i.height=o.height=this.tileSize.height;var u=e.x+"_"+e.y+"_"+t;return r.setAttribute("id",u),i.setAttribute("id",u),u in this.tiles&&delete this.tiles[u],this.tiles[u]={canvas:r,ctx:s,hit_canvas:i,hit_ctx:o,coord:e,zoom:t,primitives:null},this.canvas_setup&&this.canvas_setup(this.tiles[u],e,t),r},r.prototype.each=function(e){for(var t in this.tiles){var n=this.tiles[t];e(n)}},r.prototype.recreate=function(){for(var e in this.tiles){var t=this.tiles[e];this.canvas_setup(t,t.coord,t.zoom)}},r.prototype.redraw_tile=function(e){this.render(e,e.coord,e.zoom)},r.prototype.redraw=function(){for(var e in this.tiles){var t=this.tiles[e];this.render(t,t.coord,t.zoom)}},r.prototype.getTile=function(e,t,n){return this.create_tile_canvas(e,t,n)},r.prototype.releaseTile=function(e){var t=e.getAttribute("id");delete this.tiles[t]},t.exports=r},{}],7:[function(e,t,n){function r(){}r.prototype={_initTileLoader:function(e,t){this._map=e,this._projection=t,this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._updateTiles=this._updateTiles.bind(this),this._listeners=[],this._listeners.push(google.maps.event.addListener(this._map,"dragend",this._updateTiles),google.maps.event.addListener(this._map,"zoom_changed",this._updateTiles)),this.tileSize=256,this._updateTiles()},_removeTileLoader:function(){this._listeners.forEach(function(e){google.maps.event.removeListener(e)}),this._removeTiles()},_removeTiles:function(){for(var e in this._tiles)this._removeTile(e)},_reloadTiles:function(){this._removeTiles(),this._updateTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getBounds(),t=this._map.getZoom(),n=this.tileSize,r=1<t.x||it.y)&&this._removeTile(s))},_removeTile:function(e){this.onTileRemoved&&this.onTileRemoved(this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.onTilesLoaded&&this.onTilesLoaded()},getTilePos:function(e){var t=1<=0&&a>=0&&u=0&&this.cancelAnimationFrame.call(window,this.currentAnimationFrame),this.currentAnimationFrame=this.requestAnimationFrame.call(window,this.render)},redraw:function(e){var t=L.DomUtil.getPosition(this._map.getPanes().mapPane);t&&L.DomUtil.setPosition(this._canvas,{x:-t.x,y:-t.y}),e?this.render():this._render()},onResize:function(){},render:function(){throw new Error("render function should be implemented")}})},{"./leaflet_tileloader_mixin":13}],12:[function(e,t,n){typeof L!="undefined"&&e("./torque")},{"./torque":14}],13:[function(e,t,n){L.Mixin.TileLoader={_initTileLoader:function(){this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._map.on({moveend:this._updateTiles},this),this._updateTiles()},_removeTileLoader:function(){this._map.off({moveend:this._updateTiles},this),this._removeTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getPixelBounds(),t=this._map.getZoom(),n=this.options.tileSize;if(t>this.options.maxZoom||te.max.x||re.max.y)&&this._removeTile(s))},_removeTile:function(e){this.fire("tileRemoved",this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.fire("tilesLoaded")},getTilePos:function(e){e=new L.Point(e.x,e.y);var t=this._map._getNewTopLeftPoint(this._map.getCenter()),n=this.options.tileSize;return e.multiplyBy(n).subtract(t)},_addTilesFromCenterOut:function(e){var t=[],n=e.getCenter(),r=this._map.getZoom(),i,s,o;for(i=e.min.y;i<=e.max.y;i++)for(s=e.min.x;s<=e.max.x;s++)o=new L.Point(s,i),o.zoom=r,this._tileShouldBeLoaded(o)&&t.push(o);var u=t.length;if(u===0)return;t.sort(function(e,t){return e.distanceTo(n)-t.distanceTo(n)}),this._tilesToLoad+=u;for(s=0;s0&&l>0&&o.getContext("2d").drawImage(this.getCanvas(),u,a,f,l,u-n.x,a-n.y,f,l)}}}this.prevRenderedKey=this.key},setKey:function(e,t){this.key=e,this.animator.step(e),this._clearTileCaches(),this.redraw(t&&t.direct),this.fire("change:time",{time:this.getTime(),step:this.key})},setStep:function(e){if(e===undefined||e.length!==undefined)throw new Error("setTime only accept scalars");this.setKey(e)},stepToTime:function(e){var t=this.provider.getKeySpan(),n=t.start+(t.end-t.start)*(e/this.provider.getSteps());return new Date(n)},timeToStep:function(e){typeof e=="Date"&&(e=e.getTime());if(!this.provider)return 0;var t=this.provider.getKeySpan(),n=this.provider.getSteps()*(e-t.start)/(t.end-t.start);return n},getStep:function(){return this.key},getTime:function(){return this.stepToTime(this.key)},getTimeSpan:function(){return this.provider.getKeySpan()},setCartoCSS:function(e){if(this.provider.options.named_map)throw new Error("CartoCSS style on named maps is read-only");if(!this.renderer)throw new Error("renderer is not valid");var t=(new n.RendererJS).render(e);this.renderer.setShader(t);var i=r.common.TorqueLayer.optionsFromLayer(t.findLayer({name:"Map"}));return this.provider.setCartoCSS&&this.provider.setCartoCSS(e),this.provider.setOptions(i)&&this._reloadTiles(),r.extend(this.options,i),i.animationDuration&&this.animator.duration(i.animationDuration),this._clearCaches(),this.redraw(),this},getActivePointsBBox:function(e){var t=[];for(var n in this._tiles){var r=this._tiles[n];t=t.concat(this.renderer.getActivePointsBBox(r,e))}return t},getValueForPos:function(e,t,n){n=n===undefined?this.key:n;var r,i,s,o=null,u,a;for(r in this._tiles){i=this._tiles[r],s=this.getTilePos(i.coord),u=e-s.x,a=t-s.y,u>=0&&a>=0&&u1&&(i.new_value(this.name,this.count),this.count=0,this.start())}},i.metric=function(e){return new s(e)},t.exports=i},{}],18:[function(e,t,n){t.exports={json:e("./json"),JsonArray:e("./jsonarray"),windshaft:e("./windshaft")}},{"./json":19,"./jsonarray":20,"./windshaft":21}],19:[function(e,t,n){function a(e){for(var t=1;t>0),e.options.data_steps=t.num_steps>>0,e.options.step=e.options.step||1,e.options.bounds=[[t.ymin,t.xmin],[t.ymax,t.xmax]],e._setReady(!0)},{parseJSON:!0,no_cdn:!0})},{parseJSON:!0,no_cdn:!0})}},t.exports=f},{"../":10,"../profiler":17}],20:[function(e,t,n){function f(e,t){for(var n=1;n=0?t["marker-fill-opacity"]:1,e.globalAlpha>0&&e.fill()),t["marker-line-color"]&&t["marker-line-width"]&&t["marker-line-width"]>i&&(e.globalAlpha=t["marker-line-opacity"]>=0?t["marker-line-opacity"]:1,t["marker-line-width"]!==undefined&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.stroke())}function u(e,t){e.fillStyle=t["marker-fill"];var n=t["marker-width"],r=n*2;if(t["marker-fill"]){if(t["marker-fill-opacity"]!==undefined||t["marker-opacity"]!==undefined)e.globalAlpha=t["marker-fill-opacity"]||t["marker-opacity"];e.fillRect(-n,-n,r,r)}e.globalAlpha=1,t["marker-line-color"]&&t["marker-line-width"]&&(t["marker-line-opacity"]&&(e.globalAlpha=t["marker-line-opacity"]),t["marker-line-width"]&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.strokeRect(-n,-n,r,r))}function a(e,t,n){if(t.complete){if(n["marker-fill-opacity"]!==undefined||n["marker-opacity"]!==undefined)e.globalAlpha=n["marker-fill-opacity"]||n["marker-opacity"];e.drawImage(t,0,0,Math.min(t.width,s),Math.min(t.height,s))}}var r=Math.PI*2,i=.05,s=255;t.exports={renderPoint:o,renderSprite:a,renderRectangle:u,MAX_SPRITE_RADIUS:s}},{}],23:[function(e,t,n){t.exports={cartocss:e("./cartocss_render"),Point:e("./point"),Rectangle:e("./rectangle")}},{"./cartocss_render":22,"./point":24,"./rectangle":25}],24:[function(e,t,n){(function(n){function c(e){return l[e]||e}function h(e,t){if(!e)throw new Error("canvas can't be undefined");this.options=t,this._canvas=e,this._ctx=e.getContext("2d"),this._sprites=[],this._shader=null,this._icons={},this._iconsToLoad=0,this._filters=new u(this._canvas,{canvasClass:t.canvasClass}),this.setCartoCSS(this.options.cartocss||f),this.TILE_SIZE=256,this._style=null,this._gradients={},this._forcePoints=!1}var r=e("../"),i=e("./cartocss_render"),s=e("../profiler"),o=n.carto||e("carto"),u=e("./torque_filters"),a=Math.PI*2,f=["#layer {"," marker-fill: #662506;"," marker-width: 4;"," [value > 1] { marker-fill: #FEE391; }"," [value > 2] { marker-fill: #FEC44F; }"," [value > 3] { marker-fill: #FE9929; }"," [value > 4] { marker-fill: #EC7014; }"," [value > 5] { marker-fill: #CC4C02; }"," [value > 6] { marker-fill: #993404; }"," [value > 7] { marker-fill: #662506; }","}"].join("\n"),l={src:"source-over","src-over":"source-over","dst-over":"destination-over","src-in":"source-in","dst-in":"destination-in","src-out":"source-out","dst-out":"destination-out","src-atop":"source-atop","dst-atop":"destination-atop",xor:"xor",darken:"darken",lighten:"lighten"};r.extend(h.prototype,r.Event,{clearCanvas:function(){var e=this._canvas,t=this._Map["-torque-clear-color"];if(t==="rgba(255, 255, 255, 0)"||!t)this._canvas.width=this._canvas.width;else{var n=this._ctx;n.setTransform(1,0,0,1,0,0);var r=this._Map["comp-op"];n.globalCompositeOperation=c(r),n.fillStyle=t,n.fillRect(0,0,e.width,e.height)}},setCanvas:function(e){this._canvas=e,this._ctx=e.getContext("2d")},setCartoCSS:function(e){this.setShader((new o.RendererJS).render(e))},setShader:function(e){this._sprites=[],this._shader=e,this._Map=this._shader.getDefault().getStyle({},{zoom:0});var t=this._shader.getImageURLs();this._preloadIcons(t)},clearSpriteCache:function(){this._sprites=[]},generateSprite:function(e,t,n){var o=this,u=s.metric("torque.renderer.point.generateSprite").start(),a=e.getStyle({value:t},n);if(this._style===null||this._style!==a)this._style=a;var f=a["marker-width"];if(!f)return null;if(a["marker-opacity"]===0&&!a["marker-line-opacity"])return null;var l=this._createCanvas(),c=l.getContext("2d"),h=a["marker-file"]||a["point-file"],p=h&&this._qualifyURL(h);if(p&&this._iconsToLoad<=0&&this._icons[p]){var d=this._icons[p],v=Math.min(a["marker-width"]*2||d.width,i.MAX_SPRITE_RADIUS*2),m=Math.min((a["marker-height"]||v)*(d.width/d.height),i.MAX_SPRITE_RADIUS*2);l.width=c.width=v,l.height=c.height=m,c.scale(v/d.width,m/d.height),i.renderSprite(c,d,a)}else{var g=(a["marker-line-width"]||0)+f*2,y=c.width=l.width=c.height=l.height=Math.ceil(g);c.translate(y/2,y/2);var b=a["marker-type"];b&&b==="rectangle"?i.renderRectangle(c,a):i.renderPoint(c,a)}u.end(!0);if(r.flags.sprites_to_images){var w=this._createImage();return w.src=l.toDataURL(),w}return l},renderTile:function(e,t,n){if(this._iconsToLoad>0)return this.on("allIconsLoaded",function(){this.renderTile.apply(this,[e,t,n])}),!1;var r=s.metric("torque.renderer.point.renderLayers").start(),i=this._shader.getLayers();for(var o=0,u=i.length;oe.maxDate&&(t=e.maxDate);var h=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),p=e.timeCount[t],d=this.options.resolution/2;if(p){var v=e.timeIndex[t];for(var m=0;m>1)+d,E=h-e.y[g]+d;f.drawImage(b,w,E-(b.height>>1))}}}}a.end(!0)},setBlendMode:function(e){this.options.blendmode=e},getActivePointsBBox:function(e,t){var n=[],i=new r.Mercator,s=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),o=e.timeCount[t],u=e.timeIndex[t];for(var a=0;a>1,a=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),f=e.timeCount[t],l=e.timeIndex[t];for(var c=0;c=0&&m=0&&g0&&!this._forcePoints){var n=Object.keys(e.reduce(function(e,n){var r=t._qualifyURL(n);return t._icons[r]||(e[r]=!0),e},{})),r=t._shader.getLayers().some(function(e){return typeof e.shader["image-filters"]!="undefined"});this._iconsToLoad+=n.length,n.forEach(function(e){t._icons[e]=null;var n=t._createImage();r&&(n.crossOrigin="Anonymous"),t._setImageSrc(n,e,function(i){i?(t._forcePoints=!0,t.clearSpriteCache(),t._iconsToLoad=0,t.fire("allIconsLoaded"),r&&console.info("Only CORS-enabled, or same domain image-files can be used in combination with image-filters"),console.error("Couldn't get marker-file "+e)):(t._icons[e]=n,t._iconsToLoad--,t._iconsToLoad<=0&&(t.clearSpriteCache(),t.fire("allIconsLoaded")))})})}else this.fire("allIconsLoaded")},applyFilters:function(){if(this._style&&this._style["image-filters"]){function e(e){var t="";for(var n=0;n 10] { polygon-fill: #FFFF00; }"," [value > 100] { polygon-fill: #FFCC00; }"," [value > 1000] { polygon-fill: #FE9929; }"," [value > 10000] { polygon-fill: #FF6600; }"," [value > 100000] { polygon-fill: #FF3300; }","}"].join("\n"),s=Math.PI*2;o.prototype={setCartoCSS:function(e){this._cartoCssStyle=(new r.RendererJS).render(e);if(this._cartoCssStyle.getLayers().length>1)throw new Error("only one CartoCSS layer is supported");this._shader=this._cartoCssStyle.getLayers()[0].shader},setCanvas:function(e){if(!e)return;this._canvas=e,this._ctx=e.getContext("2d")},accumulate:function(e,t){var n=Profiler.metric("RectangleRender:accumulate").start(),r,i,s,o,u,a,f,l,c=this.options.resolution,h=256/c,p=new Float32Array(h*h);typeof t!="object"&&(t=[t]);for(u=0;u=200&&e<300||e===304?t(o):t(null)}r=r||{method:"GET",data:null,responseType:"text"},i={url:e,callback:t};var s=XMLHttpRequest;n.XDomainRequest&&!("withCredentials"in s)&&/^(http(s)?:)?\/\//.test(e)&&(s=XDomainRequest);var o=new s;return o.open(r.method,e,!0),"onload"in o?o.onload=o.onerror=u:o.onreadystatechange=function(){o.readyState>3&&u()},o.onprogress=function(){},o.responseType=r.responseType,r.data&&(o.setRequestHeader("Content-type","application/json"),o.setRequestHeader("Accept","*")),o.send(r.data),o}function u(e,t,n){return o(e,n,{data:t,method:"POST"})}var r=e("./core"),i=null;t.exports={get:o,post:u,jsonp:s,lastCall:function(){return i}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./core":4}],28:[function(e,t,n){},{}],29:[function(e,t,n){function u(e,t){return r.isUndefined(t)?""+t:r.isNumber(t)&&(isNaN(t)||!isFinite(t))?t.toString():r.isFunction(t)||r.isRegExp(t)?t.toString():t}function a(e,t){return r.isString(e)?e.length=0;u--)if(n[u]!=s[u])return!1;for(u=n.length-1;u>=0;u--){o=n[u];if(!h(e[o],t[o]))return!1}return!0}function v(e,t){return!e||!t?!1:Object.prototype.toString.call(t)=="[object RegExp]"?t.test(e):e instanceof t?!0:t.call({},e)===!0?!0:!1}function m(e,t,n,i){var s;r.isString(n)&&(i=n,n=null);try{t()}catch(o){s=o}i=(n&&n.name?" ("+n.name+").":".")+(i?" "+i:"."),e&&!s&&l(s,n,"Missing expected exception"+i),!e&&v(s,n)&&l(s,n,"Got unwanted exception"+i);if(e&&s&&n&&!v(s,n)||!e&&s)throw s}var r=e("util/"),i=Array.prototype.slice,s=Object.prototype.hasOwnProperty,o=t.exports=c;o.AssertionError=function(t){this.name="AssertionError",this.actual=t.actual,this.expected=t.expected,this.operator=t.operator,t.message?(this.message=t.message,this.generatedMessage=!1):(this.message=f(this),this.generatedMessage=!0);var n=t.stackStartFunction||l;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var i=r.stack,s=n.name,o=i.indexOf("\n"+s);if(o>=0){var u=i.indexOf("\n",o+1);i=i.substring(u+1)}this.stack=i}}},r.inherits(o.AssertionError,Error),o.fail=l,o.ok=c,o.equal=function(t,n,r){t!=n&&l(t,n,r,"==",o.equal)},o.notEqual=function(t,n,r){t==n&&l(t,n,r,"!=",o.notEqual)},o.deepEqual=function(t,n,r){h(t,n)||l(t,n,r,"deepEqual",o.deepEqual)},o.notDeepEqual=function(t,n,r){h(t,n)&&l(t,n,r,"notDeepEqual",o.notDeepEqual)},o.strictEqual=function(t,n,r){t!==n&&l(t,n,r,"===",o.strictEqual)},o.notStrictEqual=function(t,n,r){t===n&&l(t,n,r,"!==",o.notStrictEqual)},o.throws=function(e,t,n){m.apply(this,[!0].concat(i.call(arguments)))},o.doesNotThrow=function(e,t){m.apply(this,[!1].concat(i.call(arguments)))},o.ifError=function(e){if(e)throw e};var g=Object.keys||function(e){var t=[];for(var n in e)s.call(e,n)&&t.push(n);return t}},{"util/":34}],30:[function(e,t,n){typeof Object.create=="function"?t.exports=function(t,n){t.super_=n,t.prototype=Object.create(n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,n){t.super_=n;var r=function(){};r.prototype=n.prototype,t.prototype=new r,t.prototype.constructor=t}},{}],31:[function(e,t,n){(function(e){function t(e,t){var n=0;for(var r=e.length-1;r>=0;r--){var i=e[r];i==="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function s(e,t){if(e.filter)return e.filter(t);var n=[];for(var r=0;r=-1&&!r;i--){var o=i>=0?arguments[i]:e.cwd();if(typeof o!="string")throw new TypeError("Arguments to path.resolve must be strings");if(!o)continue;n=o+"/"+n,r=o.charAt(0)==="/"}return n=t(s(n.split("/"),function(e){return!!e}),!r).join("/"),(r?"/":"")+n||"."},n.normalize=function(e){var r=n.isAbsolute(e),i=o(e,-1)==="/";return e=t(s(e.split("/"),function(e){return!!e}),!r).join("/"),!e&&!r&&(e="."),e&&i&&(e+="/"),(r?"/":"")+e},n.isAbsolute=function(e){return e.charAt(0)==="/"},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(s(e,function(e,t){if(typeof e!="string")throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},n.relative=function(e,t){function r(e){var t=0;for(;t=0;n--)if(e[n]!=="")break;return t>n?[]:e.slice(t,n-t+1)}e=n.resolve(e).substr(1),t=n.resolve(t).substr(1);var i=r(e.split("/")),s=r(t.split("/")),o=Math.min(i.length,s.length),u=o;for(var a=0;a0){var n=r.shift();n()}}},!0),function(t){r.push(t),window.postMessage("process-tick","*")}):function(t){setTimeout(t,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.on=i,r.addListener=i,r.once=i,r.off=i,r.removeListener=i,r.removeAllListeners=i,r.emit=i,r.binding=function(e){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(e){throw new Error("process.chdir is not supported")}},{}],33:[function(e,t,n){t.exports=function(t){return t&&typeof t=="object"&&typeof t.copy=="function"&&typeof t.fill=="function"&&typeof t.readUInt8=="function"}},{}],34:[function(e,t,n){(function(t,r){function u(e,t){var r={seen:[],stylize:f};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),y(t)?r.showHidden=t:t&&n._extend(r,t),T(r.showHidden)&&(r.showHidden=!1),T(r.depth)&&(r.depth=2),T(r.colors)&&(r.colors=!1),T(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=a),c(r,e,r.depth)}function a(e,t){var n=u.styles[t];return n?"["+u.colors[n][0]+"m"+e+"["+u.colors[n][1]+"m":e}function f(e,t){return e}function l(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}function c(e,t,r){if(e.customInspect&&t&&A(t.inspect)&&t.inspect!==n.inspect&&(!t.constructor||t.constructor.prototype!==t)){var i=t.inspect(r,e);return S(i)||(i=c(e,i,r)),i}var s=h(e,t);if(s)return s;var o=Object.keys(t),u=l(o);e.showHidden&&(o=Object.getOwnPropertyNames(t));if(L(t)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return p(t);if(o.length===0){if(A(t)){var a=t.name?": "+t.name:"";return e.stylize("[Function"+a+"]","special")}if(N(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(k(t))return e.stylize(Date.prototype.toString.call(t),"date");if(L(t))return p(t)}var f="",y=!1,b=["{","}"];g(t)&&(y=!0,b=["[","]"]);if(A(t)){var w=t.name?": "+t.name:"";f=" [Function"+w+"]"}N(t)&&(f=" "+RegExp.prototype.toString.call(t)),k(t)&&(f=" "+Date.prototype.toUTCString.call(t)),L(t)&&(f=" "+p(t));if(o.length!==0||!!y&&t.length!=0){if(r<0)return N(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var E;return y?E=d(e,t,r,u,o):E=o.map(function(n){return v(e,t,r,u,n,y)}),e.seen.pop(),m(E,f,b)}return b[0]+f+b[1]}function h(e,t){if(T(t))return e.stylize("undefined","undefined");if(S(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(E(t))return e.stylize(""+t,"number");if(y(t))return e.stylize(""+t,"boolean");if(b(t))return e.stylize("null","null")}function p(e){return"["+Error.prototype.toString.call(e)+"]"}function d(e,t,n,r,i){var s=[];for(var o=0,u=t.length;o-1&&(s?u=u.split("\n").map(function(e){return" "+e}).join("\n").substr(2):u="\n"+u.split("\n").map(function(e){return" "+e}).join("\n"))):u=e.stylize("[Circular]","special"));if(T(o)){if(s&&i.match(/^\d+$/))return u;o=JSON.stringify(""+i),o.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=e.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=e.stylize(o,"string"))}return o+": "+u}function m(e,t,n){var r=0,i=e.reduce(function(e,t){return r++,t.indexOf("\n")>=0&&r++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return i>60?n[0]+(t===""?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1]:n[0]+t+" "+e.join(", ")+" "+n[1]}function g(e){return Array.isArray(e)}function y(e){return typeof e=="boolean"}function b(e){return e===null}function w(e){return e==null}function E(e){return typeof e=="number"}function S(e){return typeof e=="string"}function x(e){return typeof e=="symbol"}function T(e){return e===void 0}function N(e){return C(e)&&M(e)==="[object RegExp]"}function C(e){return typeof e=="object"&&e!==null}function k(e){return C(e)&&M(e)==="[object Date]"}function L(e){return C(e)&&(M(e)==="[object Error]"||e instanceof Error)}function A(e){return typeof e=="function"}function O(e){return e===null||typeof e=="boolean"||typeof e=="number"||typeof e=="string"||typeof e=="symbol"||typeof e=="undefined"}function M(e){return Object.prototype.toString.call(e)}function _(e){return e<10?"0"+e.toString(10):e.toString(10)}function P(){var e=new Date,t=[_(e.getHours()),_(e.getMinutes()),_(e.getSeconds())].join(":");return[e.getDate(),D[e.getMonth()],t].join(" ")}function H(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var i=/%[sdj%]/g;n.format=function(e){if(!S(e)){var t=[];for(var n=0;n=s)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(t){return"[Circular]"};default:return e}});for(var a=r[n];n1&&(t=arguments[1]),arguments.length>2&&(n=arguments[2]),{is:"tag",val:e,color:t,mode:n,toString:function(r){return'\n "}}},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(i-o)*e*6:e*2<1?i:e*3<2?o+(i-o)*(2/3-e)*6:o}e=s(e)%360/360,t=s(t),n=s(n),r=s(r);if([e,t,n,r].some(isNaN))return null;var i=n<=.5?n*(t+1):n+t-n*t,o=n*2-i;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,r)},hue:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().h)):null},saturation:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().s*100),"%"):null},lightness:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().l*100),"%"):null},alpha:function(t){return"toHSL"in t?new e.Dimension(t.toHSL().a):null},saturate:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.s+=t.value/100,n.s=o(n.s),i(n)}return null},desaturate:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.s-=t.value/100,n.s=o(n.s),i(n)}return null},lighten:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.l+=t.value/100,n.l=o(n.l),i(n)}return null},darken:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.l-=t.value/100,n.l=o(n.l),i(n)}return null},fadein:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.a+=t.value/100,n.a=o(n.a),i(n)}return null},fadeout:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.a-=t.value/100,n.a=o(n.a),i(n)}return null},spin:function(e,t){if("toHSL"in e){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,i(n)}return null},replace:function(e,t,n){return e.is==="field"?e.toString+".replace("+t.toString()+", "+n.toString()+")":e.replace(t,n)},mix:function(t,n,r){var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},"%":function(t){var n=Array.prototype.slice.call(arguments,1),r=t.value;for(var i=0;i4)return e("../../package.json").version.split(".");var n=JSON.parse(s.readFileSync(o.join(r,"../../package.json")));return n.version.split(".")}function l(e,t){var n={bold:[1,22],inverse:[7,27],underline:[4,24],yellow:[33,39],green:[32,39],red:[31,39],grey:[90,39]};return"["+n[t][0]+"m"+e+"["+n[t][1]+"m"}var i=e("util"),s=e("fs"),o=e("path"),a={version:u(),Parser:e("./parser").Parser,Renderer:e("./renderer").Renderer,tree:e("./tree"),RendererJS:e("./renderer_js"),default_reference:e("./torque-reference"),writeError:function(e,t){var n="",r=e.extract,s=[];t=t||{};if(t.silent)return;t.indent=t.indent||"";if(!("index"in e)||!r)return i.error(t.indent+(e.stack||e.message));typeof r[0]=="string"&&s.push(l(e.line-1+" "+r[0],"grey")),r[1]===""&&typeof r[2]=="undefined"&&(r[1]="¶"),s.push(e.line+" "+r[1].slice(0,e.column)+l(l(r[1][e.column],"bold")+r[1].slice(e.column+1),"yellow")),typeof r[2]=="string"&&s.push(l(e.line+1+" "+r[2],"grey")),s=t.indent+s.join("\n"+t.indent)+"\n",n=t.indent+n+l(e.message,"red"),e.filename&&(n+=l(" in ","red")+e.filename),i.error(n,s),e.callLine&&(i.error(l("from ","red")+(e.filename||"")),i.error(l(e.callLine,"grey")+" "+e.callExtract)),e.stack&&i.error(l(e.stack,"red"))}};e("./tree/call"),e("./tree/color"),e("./tree/comment"),e("./tree/definition"),e("./tree/dimension"),e("./tree/element"),e("./tree/expression"),e("./tree/filterset"),e("./tree/filter"),e("./tree/field"),e("./tree/keyword"),e("./tree/layer"),e("./tree/literal"),e("./tree/operation"),e("./tree/quoted"),e("./tree/imagefilter"),e("./tree/reference"),e("./tree/rule"),e("./tree/ruleset"),e("./tree/selector"),e("./tree/style"),e("./tree/url"),e("./tree/value"),e("./tree/variable"),e("./tree/zoom"),e("./tree/invalid"),e("./tree/fontset"),e("./tree/frame_offset"),e("./functions");for(var f in a)n[f]=a[f]}).call(this,e("_process"),"/node_modules/carto/lib/carto" -)},{"../../package.json":72,"./functions":35,"./parser":37,"./renderer":38,"./renderer_js":39,"./torque-reference":40,"./tree":41,"./tree/call":42,"./tree/color":43,"./tree/comment":44,"./tree/definition":45,"./tree/dimension":46,"./tree/element":47,"./tree/expression":48,"./tree/field":49,"./tree/filter":50,"./tree/filterset":51,"./tree/fontset":52,"./tree/frame_offset":53,"./tree/imagefilter":54,"./tree/invalid":55,"./tree/keyword":56,"./tree/layer":57,"./tree/literal":58,"./tree/operation":59,"./tree/quoted":60,"./tree/reference":61,"./tree/rule":62,"./tree/ruleset":63,"./tree/selector":64,"./tree/style":65,"./tree/url":66,"./tree/value":67,"./tree/variable":68,"./tree/zoom":69,_process:32,fs:28,path:31,util:34}],37:[function(e,t,n){(function(t){var r=n,i=e("./tree"),s=t._||e("underscore");r.Parser=function(t){function v(){u=l[o],a=r,c=r}function m(){l[o]=u,r=a,c=r}function g(){r>c&&(l[o]=l[o].slice(r-c),c=r)}function y(e){var t,i,s,u,a,f,p;if(e instanceof Function)return e.call(h.parsers);if(typeof e=="string")t=n.charAt(r)===e?e:null,s=1,g();else{g(),t=e.exec(l[o]);if(!t)return null;s=t[0].length}if(t){var d=r+=s;f=r+l[o].length-s;while(r=0&&r.charAt(i)!=="\n";i--)e.column++;return new Error(s("<%=filename%>:<%=line%>:<%=column%> <%=message%>").template(e))}var n,r,o,u,a,f,l,c,h,p=this,d=function(){};return this.env=t=t||{},this.env.filename=this.env.filename||null,this.env.inputs=this.env.inputs||{},h={extractErrorLine:w,parse:function(e){var s,u,a,h,d,v,m=[],g,b=null;r=o=c=f=0,l=[],n=e.replace(/\r\n/g,"\n"),t.filename&&(p.env.inputs[t.filename]=n);var w=!1;l=function(e){var t=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,s=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,o=0,u,a=e[0],f;for(var l=0,c,h;l0?"missing closing `}`":"missing opening `{`"}),e.map(function(e){return e.join("")})}([[]]);if(b)throw E(b);s=new i.Ruleset([],y(this.parsers.primary)),s.root=!0,s.toList=function(){var e,t,n;return function(e){e.error=function(t){e.errors||(e.errors=new Error("")),e.errors.message?e.errors.message+="\n"+E(t).message:e.errors.message=E(t).message},e.frames=e.frames||[];var t=this.flatten([],[],e);return t.sort(S),t}}();var S=function(e,t){var n=e.specificity,r=t.specificity;return n[0]!=r[0]?r[0]-n[0]:n[1]!=r[1]?r[1]-n[1]:n[2]!=r[2]?r[2]-n[2]:r[3]-n[3]};return s},parsers:{primary:function(){var e,t=[];while((e=y(this.rule)||y(this.ruleset)||y(this.comment))||y(/^[\s\n]+/)||(e=y(this.invalid)))e&&t.push(e);return t},invalid:function(){var e=y(/^[^;\n]*[;\n]/);if(e)return new i.Invalid(e,a)},comment:function(){var e;if(n.charAt(r)!=="/")return;if(n.charAt(r+1)==="/")return new i.Comment(y(/^\/\/.*/),!0);if(e=y(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){if(n.charAt(r)!=='"'&&n.charAt(r)!=="'")return;var e=y(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/);if(e)return new i.Quoted(e[1]||e[2])},field:function(){if(!y("["))return;var e=y(/(^[^\]]+)/);if(!y("]"))return;if(e)return new i.Field(e[1])},comparison:function(){var e=y(/^=~|=|!=|<=|>=|<|>/);if(e)return e},keyword:function(){var e=y(/^[A-Za-z-]+[A-Za-z-0-9_]*/);if(e)return new i.Keyword(e)},call:function(){var e,t;if(!(e=/^([\w\-]+|%)\(/.exec(l[o])))return;e=e[1];if(e==="url")return null;r+=e.length,y("("),t=y(this.entities.arguments);if(!y(")"))return;if(e)return new i.Call(e,t,r)},arguments:function(){var e=[],t;while(t=y(this.expression)){e.push(t);if(!y(","))break}return e},literal:function(){return y(this.entities.dimension)||y(this.entities.keywordcolor)||y(this.entities.hexcolor)||y(this.entities.quoted)},url:function(){var e;if(n.charAt(r)!=="u"||!y(/^url\(/))return;return e=y(this.entities.quoted)||y(this.entities.variable)||y(/^[\-\w%@$\/.&=:;#+?~]+/)||"",y(")")?new i.URL(typeof e.value!="undefined"||e instanceof i.Variable?e:new i.Quoted(e)):new i.Invalid(e,a,"Missing closing ) in URL.")},variable:function(){var e,s=r;if(n.charAt(r)==="@"&&(e=y(/^@[\w-]+/)))return new i.Variable(e,s,t.filename)},hexcolor:function(){var e;if(n.charAt(r)==="#"&&(e=y(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new i.Color(e[1])},keywordcolor:function(){var e=l[o].match(/^[a-z]+/);if(e&&e[0]in i.Reference.data.colors)return new i.Color(i.Reference.data.colors[y(/^[a-z]+/)])},dimension:function(){var e=n.charCodeAt(r);if(e>57||e<45||e===47)return;var t=y(/^(-?\d*\.?\d+(?:[eE][-+]?\d+)?)(\%|\w+)?/);if(t)return new i.Dimension(t[1],t[2],a)}},variable:function(){var e;if(n.charAt(r)==="@"&&(e=y(/^(@[\w-]+)\s*:/)))return e[1]},entity:function(){return y(this.entities.call)||y(this.entities.literal)||y(this.entities.field)||y(this.entities.variable)||y(this.entities.url)||y(this.entities.keyword)},end:function(){return y(";")||b("}")},element:function(){var e=y(/^(?:[.#][\w\-]+|\*|Map)/);if(e)return new i.Element(e)},attachment:function(){var e=y(/^::([\w\-]+(?:\/[\w\-]+)*)/);if(e)return e[1]},selector:function(){var e,t,s,o=[],u,f=new i.Filterset,l,c=[],h=i.FrameOffset.none;segments=0,conditions=0;while((s=y(this.element))||(l=y(this.zoom))||(fo=y(this.frame_offset))||(u=y(this.filter))||(e=y(this.attachment))){segments++;if(s)o.push(s);else if(l)c.push(l),conditions++;else if(fo)h=fo,conditions++;else if(u){var p=f.add(u);if(p)throw E({message:p,index:r-1});conditions++}else{if(t)throw E({message:"Encountered second attachment name.",index:r-1});t=e}var d=n.charAt(r);if(d==="{"||d==="}"||d===";"||d===",")break}if(segments)return new i.Selector(f,c,h,o,t,conditions,a)},filter:function(){v();var e,n,r;if(!y("["))return;if(e=y(/^[a-zA-Z0-9\-_]+/)||y(this.entities.quoted)||y(this.entities.variable)||y(this.entities.keyword)||y(this.entities.field)){e instanceof i.Quoted&&(e=new i.Field(e.toString()));if((n=y(this.entities.comparison))&&(r=y(this.entities.quoted)||y(this.entities.variable)||y(this.entities.dimension)||y(this.entities.keyword)||y(this.entities.field))){if(!y("]"))throw E({message:"Missing closing ] of filter.",index:a-1});return e.is||(e=new i.Field(e)),new i.Filter(e,n,r,a,t.filename)}}},frame_offset:function(){v();var e,t;if(y(/^\[\s*frame-offset/g)&&(e=y(this.entities.comparison))&&(t=y(/^\d+/))&&y("]"))return i.FrameOffset(e,t,a)},zoom:function(){v();var e,t;if(y(/^\[\s*zoom/g)&&(e=y(this.entities.comparison))&&(t=y(this.entities.variable)||y(this.entities.dimension))&&y("]"))return new i.Zoom(e,t,a);m()},block:function(){var e;if(y("{")&&(e=y(this.primary))&&y("}"))return e},ruleset:function(){var e=[],t,n,r,s,o=[];v();while(t=y(this.selector)){e.push(t);while(y(this.comment));if(!y(","))break;while(y(this.comment));}if(t)while(y(this.comment));if(e.length>0&&(s=y(this.block))){if(e.length===1&&e[0].elements.length&&e[0].elements[0].value==="Map"){var u=new i.Ruleset(e,s);return u.isMap=!0,u}return new i.Ruleset(e,s)}m()},rule:function(){var e,s,o=n.charAt(r);v();if(o==="."||o==="#")return;if(e=y(this.variable)||y(this.property)){s=y(this.value);if(s&&y(this.end))return new i.Rule(e,s,a,t.filename);f=r,m()}},font:function(){var e=[],t=[],n,r,s;while(s=y(this.entity))t.push(s);e.push(new i.Expression(t));if(y(","))while(s=y(this.expression)){e.push(s);if(!y(","))break}return new i.Value(e)},value:function(){var e,t=[];while(e=y(this.expression)){t.push(e);if(!y(","))break}if(t.length>1)return new i.Value(t.map(function(e){return e.value[0]}));if(t.length===1)return new i.Value(t)},sub:function(){var e;if(y("(")&&(e=y(this.expression))&&y(")"))return e},multiplication:function(){var e,t,n,r;if(e=y(this.operand)){while((n=y("/")||y("*")||y("%"))&&(t=y(this.operand)))r=new i.Operation(n,[r||e,t],a);return r||e}},addition:function(){var e,t,s,o;if(e=y(this.multiplication)){while((s=y(/^[-+]\s+/)||n.charAt(r-1)!=" "&&(y("+")||y("-")))&&(t=y(this.multiplication)))o=new i.Operation(s,[o||e,t],a);return o||e}},operand:function(){return y(this.sub)||y(this.entity)},expression:function(){var e,t,n=[],r;while(e=y(this.addition)||y(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e=y(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/);if(e)return e[1]}}},h}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./tree":41,underscore:71}],38:[function(e,t,n){(function(n){function s(e,t,n,r){var i=t.filters,s=t.rules,o,u,a;for(var f=0;f'+t+"");break;case"name":case"description":case"legend":case"attribution":case"template":e.push(' ");break;case"format":e.push(' '+t+"");break;case"interactivity":e.push(' '+t.layer+""),e.push(' '+t.fields+"");break;default:"string"==typeof t?e.push(' "):"number"==typeof t?e.push(' '+t+""):"boolean"==typeof t&&e.push(' '+t+"")}return e},[]);N.length&&s.unshift("\n"+N.join("\n")+"\n\n");var C=r(T).map(function(e){return" "+e}).join("");return s.unshift('\n\n\n"),s.push(""),s.join("\n")},t.exports=i,t.exports.addRules=s,t.exports.inheritDefinitions=o,t.exports.sortStyles=a}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./index":36,underscore:71}],39:[function(require,module,exports){(function(global){(function(carto){function CartoCSS(e,t){this.options=t||{},this.imageURLs=[],e&&this.setStyle(e)}var tree=require("./tree"),_=global._||require("underscore");CartoCSS.Layer=function(e,t){this.options=t,this.shader=e},CartoCSS.Layer.prototype={fullName:function(){return this.shader.attachment},name:function(){return this.fullName().split("::")[0]},frames:function(){return this.shader.frames},attachment:function(){return this.fullName().split("::")[1]},eval:function(e){var t=this.shader[e];if(!t||!t.style)return;return t.style({},{zoom:0,"frame-offset":0})},getStyle:function(e,t){var n={};for(var r in this.shader)r!=="attachment"&&r!=="zoom"&&r!=="frames"&&r!=="symbolizers"&&(n[r]=this.shader[r].style(e,t));return n},getSymbolizers:function(){return this.shader.symbolizers},isVariable:function(){for(var e in this.shader)if(e!=="attachment"&&e!=="zoom"&&e!=="frames"&&e!=="symbolizers"&&!this.shader[e].constant)return!0;return!1},getShader:function(){return this.shader},filter:function(e,t,n){for(var r in this.shader){var i=this.shader[r](t,n);if(i)return!0}return!1},transformGeometry:function(e){return e},transformGeometries:function(e){return e}},CartoCSS.prototype={setStyle:function(e){var t=this.parse(e);if(!t)throw new Error(this.parse_env.errors);this.layers=t.map(function(e){return new CartoCSS.Layer(e)})},getLayers:function(){return this.layers},getDefault:function(){return this.findLayer({attachment:"__default__"})},findLayer:function(e){return _.find(this.layers,function(t){for(var n in e){var r=t[n];typeof r=="function"&&(r=r.call(t));if(e[n]!==r)return!1}return!0})},_createFn:function(e){var t=e.join("\n");return this.options.debug&&console.log(t),Function("data","ctx","var _value = null; "+t+"; return _value; ")},_compile:function(shader){typeof shader=="string"&&(shader=eval("(function() { return "+shader+"; })()")),this.shader_src=shader;for(var attr in shader){var c=mapper[attr];c&&(this.compiled[c]=eval("(function() { return shader[attr]; })();"))}},getImageURLs:function(){return this.imageURLs},parse:function(e){var t={frames:[],errors:[],error:function(e){this.errors.push(e)}};this.parse_env=t;var n=null;try{n=(new carto.Parser(t)).parse(e)}catch(r){t.errors.push(r.message);return}if(n){function i(e){return e.elements[0]+"::"+e.attachment}var s=n.toList(t);s.reverse();var o={};for(var u=0;u= minzoom - 1e-6 and scale < maxzoom + 1e-6"},maxzoom:{"default-value":"1.79769e+308",type:"float","default-meaning":"The layer will be visible at the maximum possible scale",doc:"The maximum scale denominator that this layer will be visible at. The default is the numeric limit of the C++ double type, which may vary slightly by system, but is likely a massive number like 1.79769e+308 and ensures that this layer will always be visible unless the value is reduced. A layer's visibility is determined by whether its status is true and if the Map scale >= minzoom - 1e-6 and scale < maxzoom + 1e-6"},queryable:{"default-value":!1,type:"boolean","default-meaning":"The layer will not be available for the direct querying of data values",doc:"This property was added for GetFeatureInfo/WMS compatibility and is rarely used. It is off by default meaning that in a WMS context the layer will not be able to be queried unless the property is explicitly set to true"},"clear-label-cache":{"default-value":!1,type:"boolean","default-meaning":"The renderer's collision detector cache (used for avoiding duplicate labels and overlapping markers) will not be cleared immediately before processing this layer",doc:"This property, by default off, can be enabled to allow a user to clear the collision detector cache before a given layer is processed. This may be desirable to ensure that a given layers data shows up on the map even if it normally would not because of collisions with previously rendered labels or markers"},"group-by":{"default-value":"",type:"string","default-meaning":"No special layer grouping will be used during rendering",doc:"https://github.com/mapnik/mapnik/wiki/Grouped-rendering"},"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"maximum-extent":{"default-value":"none",type:"bbox","default-meaning":"No clipping extent will be used",doc:"An extent to be used to limit the bounds used to query this specific layer data during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Layer."}},symbolizers:{"*":{"image-filters":{css:"image-filters","default-value":"none","default-meaning":"no filters",type:"functions",functions:[["agg-stack-blur",2],["emboss",0],["blur",0],["gray",0],["sobel",0],["edge-detect",0],["x-gradient",0],["y-gradient",0],["invert",0],["sharpen",0],["colorize-alpha",-1],["color-to-alpha",1],["scale-hsla",8]],doc:"A list of image filters."},"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["clear","src","dst","src-over","source-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","lighter","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},map:{"background-color":{css:"background-color","default-value":"none","default-meaning":"transparent",type:"color",doc:"Map Background color"},"background-image":{css:"background-image",type:"uri","default-value":"","default-meaning":"transparent",doc:"An image that is repeated below all features on a map as a background.",description:"Map Background image"},srs:{css:"srs",type:"string","default-value":"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs","default-meaning":"The proj4 literal of EPSG:4326 is assumed to be the Map's spatial reference and all data from layers within this map will be plotted using this coordinate system. If any layers do not declare an srs value then they will be assumed to be in the same srs as the Map and not transformations will be needed to plot them in the Map's coordinate space",doc:"Map spatial reference (proj4 string)"},"buffer-size":{css:"buffer-size","default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:'Extra tolerance around the map (in pixels) used to ensure labels crossing tile boundaries are equally rendered in each tile (e.g. cut in each tile). Not intended to be used in combination with "avoid-edges".'},"maximum-extent":{css:"","default-value":"none",type:"bbox","default-meaning":"No clipping extent will be used",doc:"An extent to be used to limit the bounds used to query all layers during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Map."},base:{css:"base","default-value":"","default-meaning":"This base path defaults to an empty string meaning that any relative paths to files referenced in styles or layers will be interpreted relative to the application process.",type:"string",doc:"Any relative paths used to reference files will be understood as relative to this directory path if the map is loaded from an in memory object rather than from the filesystem. If the map is loaded from the filesystem and this option is not provided it will be set to the directory of the stylesheet."},"paths-from-xml":{css:"","default-value":!0,"default-meaning":"Paths read from XML will be interpreted from the location of the XML",type:"boolean",doc:"value to control whether paths in the XML will be interpreted from the location of the XML or from the working directory of the program that calls load_map()"},"minimum-version":{css:"","default-value":"none","default-meaning":"Mapnik version will not be detected and no error will be thrown about compatibility",type:"string",doc:"The minumum Mapnik version (e.g. 0.7.2) needed to use certain functionality in the stylesheet"},"font-directory":{css:"font-directory",type:"uri","default-value":"none","default-meaning":"No map-specific fonts will be registered",doc:"Path to a directory which holds fonts which should be registered when the Map is loaded (in addition to any fonts that may be automatically registered)."}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon"},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"},gamma:{css:"polygon-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of polygon edges"},"gamma-method":{css:"polygon-gamma-method",type:["power","linear","none","threshold","multiply"],"default-value":"power","default-meaning":"pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA",doc:"An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h"},clip:{css:"polygon-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"polygon-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"polygon-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"polygon-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line"},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels"},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"},"stroke-gamma":{css:"line-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of stroke line"},"stroke-gamma-method":{css:"line-gamma-method",type:["power","linear","none","threshold","multiply"],"default-value":"power","default-meaning":"pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA",doc:"An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h"},"stroke-dasharray":{css:"line-dasharray",type:"numbers",doc:"A pair of length values [a,b], where (a) is the dash length and (b) is the gap length respectively. More than two values are supported for more complex patterns.","default-value":"none","default-meaning":"solid line"},"stroke-dashoffset":{css:"line-dash-offset",type:"numbers",doc:"valid parameter but not currently used in renderers (only exists for experimental svg support in Mapnik which is not yet enabled)","default-value":"none","default-meaning":"solid line"},"stroke-miterlimit":{css:"line-miterlimit" -,type:"float",doc:"The limit on the ratio of the miter length to the stroke-width. Used to automatically convert miter joins to bevel joins for sharp angles to avoid the miter extending beyond the thickness of the stroking path. Normally will not need to be set, but a larger value can sometimes help avoid jaggy artifacts.","default-value":4,"default-meaning":"Will auto-convert miters to bevel line joins when theta is less than 29 degrees as per the SVG spec: 'miterLength / stroke-width = 1 / sin ( theta / 2 )'"},clip:{css:"line-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"line-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},offset:{css:"line-offset",type:"float","default-value":0,"default-meaning":"no offset",doc:"Offsets a line a number of pixels parallel to its actual path. Postive values move the line left, negative values move it right (relative to the directionality of the line)."},rasterizer:{css:"line-rasterizer",type:["full","fast"],"default-value":"full",doc:"Exposes an alternate AGG rendering method that sacrifices some accuracy for speed."},"geometry-transform":{css:"line-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"line-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},placement:{css:"marker-placement",type:["point","line","interior"],"default-value":"point","default-meaning":"Place markers at the center point (centroid) of the geometry",doc:"Attempt to place markers on a point, in the center of a polygon, or if markers-placement:line, then multiple times along a line. 'interior' placement can be used to ensure that points placed on polygons are forced to be inside the polygon interior"},"multi-policy":{css:"marker-multi-policy",type:["each","whole","largest"],"default-value":"each","default-meaning":"If a feature contains multiple geometries and the placement type is either point or interior then a marker will be rendered for each",doc:"A special setting to allow the user to control rendering behavior for 'multi-geometries' (when a feature contains multiple geometries). This setting does not apply to markers placed along lines. The 'each' policy is default and means all geometries will get a marker. The 'whole' policy means that the aggregate centroid between all geometries will be used. The 'largest' policy means that only the largest (by bounding box areas) feature will get a rendered marker (this is how text labeling behaves by default)."},"marker-type":{css:"marker-type",type:["arrow","ellipse","rectangle"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an arrow or an ellipse (a circle if height is equal to width)"},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float",expression:!0},height:{css:"marker-height","default-value":10,doc:"The height of the marker, if using one of the default types.",type:"float",expression:!0},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color"},"allow-overlap":{css:"marker-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping markers are shown or hidden.","default-meaning":"Do not allow makers to overlap with each other - overlapping markers will not be shown."},"ignore-placement":{css:"marker-ignore-placement",type:"boolean","default-value":!1,"default-meaning":"do not store the bbox of this geometry in the collision detector cache",doc:"value to control whether the placement of the feature will prevent the placement of other features"},spacing:{css:"marker-spacing",doc:"Space between repeated labels","default-value":100,type:"float"},"max-error":{css:"marker-max-error",type:"float","default-value":.2,doc:"The maximum difference between actual marker placement and the marker-spacing parameter. Setting a high value can allow the renderer to try to resolve placement conflicts with other symbolizers."},transform:{css:"marker-transform",type:"functions",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]],"default-value":"","default-meaning":"No transformation",doc:"SVG transformation definition"},clip:{css:"marker-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"marker-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"marker-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"marker-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},shield:{name:{css:"shield-name",type:"string",expression:!0,serialization:"content",doc:'Value to use for a shield"s text label. Data columns are specified using brackets like [column_name]'},file:{css:"shield-file",required:!0,type:"uri","default-value":"none",doc:"Image file to render behind the shield text"},"face-name":{css:"shield-face-name",type:"string",validate:"font",doc:"Font name and style to use for the shield text","default-value":"",required:!0},"unlock-image":{css:"shield-unlock-image",type:"boolean",doc:"This parameter should be set to true if you are trying to position text beside rather than on top of the shield image","default-value":!1,"default-meaning":"text alignment relative to the shield image uses the center of the image as the anchor for text positioning."},size:{css:"shield-size",type:"float",doc:"The size of the shield text in pixels"},fill:{css:"shield-fill",type:"color",doc:"The color of the shield text"},placement:{css:"shield-placement",type:["point","line","vertex","interior"],"default-value":"point",doc:"How this shield should be placed. Point placement attempts to place it on top of points, line places along lines multiple times per feature, vertex places on the vertexes of polygons, and interior attempts to place inside of polygons."},"avoid-edges":{css:"shield-avoid-edges",doc:"Tell positioning algorithm to avoid labeling near intersection edges.",type:"boolean","default-value":!1},"allow-overlap":{css:"shield-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping shields are shown or hidden.","default-meaning":"Do not allow shields to overlap with other map elements already placed."},"minimum-distance":{css:"shield-min-distance",type:"float","default-value":0,doc:"Minimum distance to the next shield symbol, not necessarily the same shield."},spacing:{css:"shield-spacing",type:"float","default-value":0,doc:"The spacing between repeated occurrences of the same shield on a line"},"minimum-padding":{css:"shield-min-padding","default-value":0,doc:"Determines the minimum amount of padding that a shield gets relative to other shields",type:"float"},"wrap-width":{css:"shield-wrap-width",type:"unsigned","default-value":0,doc:"Length of a chunk of text in characters before wrapping text"},"wrap-before":{css:"shield-wrap-before",type:"boolean","default-value":!1,doc:"Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width."},"wrap-character":{css:"shield-wrap-character",type:"string","default-value":" ",doc:"Use this character instead of a space to wrap long names."},"halo-fill":{css:"shield-halo-fill",type:"color","default-value":"#FFFFFF","default-meaning":"white",doc:"Specifies the color of the halo around the text."},"halo-radius":{css:"shield-halo-radius",doc:"Specify the radius of the halo in pixels","default-value":0,"default-meaning":"no halo",type:"float"},"character-spacing":{css:"shield-character-spacing",type:"unsigned","default-value":0,doc:"Horizontal spacing between characters (in pixels). Currently works for point placement only, not line placement."},"line-spacing":{css:"shield-line-spacing",doc:"Vertical spacing between lines of multiline labels (in pixels)",type:"unsigned"},dx:{css:"shield-text-dx",type:"float",doc:"Displace text within shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},dy:{css:"shield-text-dy",type:"float",doc:"Displace text within shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},"shield-dx":{css:"shield-dx",type:"float",doc:"Displace shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},"shield-dy":{css:"shield-dy",type:"float",doc:"Displace shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},opacity:{css:"shield-opacity",type:"float",doc:"(Default 1.0) - opacity of the image used for the shield","default-value":1},"text-opacity":{css:"shield-text-opacity",type:"float",doc:"(Default 1.0) - opacity of the text placed on top of the shield","default-value":1},"horizontal-alignment":{css:"shield-horizontal-alignment",type:["left","middle","right","auto"],doc:"The shield's horizontal alignment from its centerpoint","default-value":"auto"},"vertical-alignment":{css:"shield-vertical-alignment",type:["top","middle","bottom","auto"],doc:"The shield's vertical alignment from its centerpoint","default-value":"middle"},"text-transform":{css:"shield-text-transform",type:["none","uppercase","lowercase","capitalize"],doc:"Transform the case of the characters","default-value":"none"},"justify-alignment":{css:"shield-justify-alignment",type:["left","center","right","auto"],doc:"Define how text in a shield's label is justified","default-value":"auto"},clip:{css:"shield-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},"comp-op":{css:"shield-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},"line-pattern":{file:{css:"line-pattern-file",type:"uri","default-value":"none",required:!0,doc:"An image file to be repeated and warped along a line"},clip:{css:"line-pattern-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"line-pattern-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"line-pattern-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"line-pattern-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},"polygon-pattern":{file:{css:"polygon-pattern-file",type:"uri","default-value":"none",required:!0,doc:"Image to use as a repeated pattern fill within a polygon"},alignment:{css:"polygon-pattern-alignment",type:["local","global"],"default-value":"local",doc:"Specify whether to align pattern fills to the layer or to the map."},gamma:{css:"polygon-pattern-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of polygon pattern edges"},opacity:{css:"polygon-pattern-opacity",type:"float",doc:"(Default 1.0) - Apply an opacity level to the image used for the pattern","default-value":1,"default-meaning":"The image is rendered without modifications"},clip:{css:"polygon-pattern-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"polygon-pattern-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"polygon-pattern-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"polygon-pattern-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},raster:{opacity:{css:"raster-opacity","default-value":1,"default-meaning":"opaque",type:"float",doc:"The opacity of the raster symbolizer on top of other symbolizers."},"filter-factor":{css:"raster-filter-factor","default-value":-1,"default-meaning":"Allow the datasource to choose appropriate downscaling.",type:"float",doc:"This is used by the Raster or Gdal datasources to pre-downscale images using overviews. Higher numbers can sometimes cause much better scaled image output, at the cost of speed."},scaling:{css:"raster-scaling",type:["near","fast","bilinear","bilinear8","bicubic","spline16","spline36","hanning","hamming","hermite","kaiser","quadric","catrom","gaussian","bessel","mitchell","sinc","lanczos","blackman"],"default-value":"near",doc:"The scaling algorithm used to making different resolution versions of this raster layer. Bilinear is a good compromise between speed and accuracy, while lanczos gives the highest quality."},"mesh-size":{css:"raster-mesh-size","default-value":16,"default-meaning":"Reprojection mesh will be 1/16 of the resolution of the source image",type:"unsigned",doc:"A reduced resolution mesh is used for raster reprojection, and the total image size is divided by the mesh-size to determine the quality of that mesh. Values for mesh-size larger than the default will result in faster reprojection but might lead to distortion."},"comp-op":{css:"raster-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},"allow-overlap":{css:"point-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping points are shown or hidden.","default-meaning":"Do not allow points to overlap with each other - overlapping markers will not be shown."},"ignore-placement":{css:"point-ignore-placement",type:"boolean","default-value":!1,"default-meaning":"do not store the bbox of this geometry in the collision detector cache",doc:"value to control whether the placement of the feature will prevent the placement of other features"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"},placement:{css:"point-placement",type:["centroid","interior"],doc:"How this point should be placed. Centroid calculates the geometric center of a polygon, which can be outside of it, while interior always places inside of a polygon.","default-value":"centroid"},transform:{css:"point-transform",type:"functions",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]],"default-value":"","default-meaning":"No transformation",doc:"SVG transformation definition"},"comp-op":{css:"point-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},text:{name:{css:"text-name",type:"string",expression:!0,required:!0,"default-value":"",serialization:"content",doc:"Value to use for a text label. Data columns are specified using brackets like [column_name]"},"face-name":{css:"text-face-name",type:"string",validate:"font",doc:"Font name and style to render a label in",required:!0},size:{css:"text-size",type:"float","default-value":10,doc:"Text size in pixels"},"text-ratio":{css:"text-ratio",doc:"Define the amount of text (of the total) present on successive lines when wrapping occurs","default-value":0,type:"unsigned"},"wrap-width":{css:"text-wrap-width",doc:"Length of a chunk of text in characters before wrapping text","default-value":0,type:"unsigned"},"wrap-before":{css:"text-wrap-before",type:"boolean","default-value":!1,doc:"Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width."},"wrap-character":{css:"text-wrap-character",type:"string","default-value":" ",doc:"Use this character instead of a space to wrap long text."},spacing:{css:"text-spacing",type:"unsigned",doc:"Distance between repeated text labels on a line (aka. label-spacing)"},"character-spacing":{css:"text-character-spacing",type:"float","default-value":0,doc:"Horizontal spacing adjustment between characters in pixels"},"line-spacing":{css:"text-line-spacing","default-value":0,type:"unsigned",doc:"Vertical spacing adjustment between lines in pixels"},"label-position-tolerance":{css:"text-label-position-tolerance","default-value":0,type:"unsigned",doc:"Allows the label to be displaced from its ideal position by a number of pixels (only works with placement:line)"},"max-char-angle-delta":{css:"text-max-char-angle-delta",type:"float","default-value":"22.5",doc:"The maximum angle change, in degrees, allowed between adjacent characters in a label. This value internally is converted to radians to the default is 22.5*math.pi/180.0. The higher the value the fewer labels will be placed around around sharp corners."},fill:{css:"text-fill",doc:"Specifies the color for the text","default-value":"#000000",type:"color"},opacity:{css:"text-opacity",doc:"A number from 0 to 1 specifying the opacity for the text","default-value":1,"default-meaning":"Fully opaque",type:"float"},"halo-fill":{css:"text-halo-fill",type:"color","default-value":"#FFFFFF","default-meaning":"white",doc:"Specifies the color of the halo around the text."},"halo-radius":{css:"text-halo-radius",doc:"Specify the radius of the halo in pixels","default-value":0,"default-meaning":"no halo",type:"float"},dx:{css:"text-dx",type:"float",doc:"Displace text by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},dy:{css:"text-dy",type:"float",doc:"Displace text by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},"vertical-alignment":{css:"text-vertical-alignment",type:["top","middle","bottom","auto"],doc:"Position of label relative to point position.","default-value":"auto","default-meaning":'Default affected by value of dy; "bottom" for dy>0, "top" for dy<0.'},"avoid-edges":{css:"text-avoid-edges",doc:"Tell positioning algorithm to avoid labeling near intersection edges.","default-value":!1,type:"boolean"},"minimum-distance":{css:"text-min-distance",doc:"Minimum permitted distance to the next text symbolizer.",type:"float"},"minimum-padding":{css:"text-min-padding",doc:"Determines the minimum amount of padding that a text symbolizer gets relative to other text",type:"float"},"minimum-path-length":{css:"text-min-path-length",type:"float","default-value":0,"default-meaning":"place labels on all paths",doc:"Place labels only on paths longer than this value."},"allow-overlap":{css:"text-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping text is shown or hidden.","default-meaning":"Do not allow text to overlap with other text - overlapping markers will not be shown."},orientation:{css:"text-orientation",type:"float",expression:!0,doc:"Rotate the text."},placement:{css:"text-placement",type:["point","line","vertex","interior"],"default-value":"point",doc:"Control the style of placement of a point versus the geometry it is attached to."},"placement-type":{css:"text-placement-type",doc:'Re-position and/or re-size text to avoid overlaps. "simple" for basic algorithm (using text-placements string,) "dummy" to turn this feature off.',type:["dummy","simple"],"default-value":"dummy"},placements:{css:"text-placements",type:"string","default-value":"",doc:'If "placement-type" is set to "simple", use this "POSITIONS,[SIZES]" string. An example is `text-placements: "E,NE,SE,W,NW,SW";` '},"text-transform":{css:"text-transform",type:["none","uppercase","lowercase","capitalize"],doc:"Transform the case of the characters","default-value":"none"},"horizontal-alignment":{css:"text-horizontal-alignment",type:["left","middle","right","auto"],doc:"The text's horizontal alignment from its centerpoint","default-value":"auto"},"justify-alignment":{css:"text-align",type:["left","right","center","auto"],doc:"Define how text is justified","default-value":"auto","default-meaning":"Auto alignment means that text will be centered by default except when using the `placement-type` parameter - in that case either right or left justification will be used automatically depending on where the text could be fit given the `text-placements` directives"},clip:{css:"text-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},"comp-op":{css:"text-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},building:{fill:{css:"building-fill","default-value":"#FFFFFF",doc:"The color of the buildings walls.",type:"color"},"fill-opacity":{css:"building-fill-opacity",type:"float",doc:"The opacity of the building as a whole, including all walls.","default-value":1},height:{css:"building-height",doc:"The height of the building in pixels.",type:"float",expression:!0,"default-value":"0"}},torque:{"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"float","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"float","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"float","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["linear","cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red -:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]},filter:{value:["true","false","null","point","linestring","polygon","collection"]}};t.exports={version:{latest:r,"2.1.1":r}}},{}],41:[function(e,t,n){typeof t!="undefined"&&(t.exports.find=function(e,t){for(var n=0,r;n255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(n,this.rgb[s],r.rgb[s]);return new e.Color(i)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t"},ev:function(){return this}}})(e("../tree"))},{"../tree":41}],45:[function(e,t,n){(function(t){(function(n){function s(e){function t(e){return e[1].toUpperCase()}return e.charAt(0).toUpperCase()+e.slice(1).replace(/\-./,t)+"Symbolizer"}function o(e){return e.sort(function(e,t){return e[1]-t[1]}).map(function(e){return e[0]})}var r=e("assert"),i=t._||e("underscore");n.Definition=function(t,i){this.elements=t.elements,r.ok(t.filters instanceof n.Filterset),this.rules=i,this.ruleIndex={};for(var s=0;s"+w+"\n":i+=">\n")}return!h||!i?"":" \n"+i+" \n"},n.Definition.prototype.collectSymbolizers=function(e,t){var n={},r;for(var i=t;i1?new e.Expression(this.value.map(function(e){return e.ev(t)})):this.value[0].ev(t)},toString:function(e){return this.value.map(function(t){return t.toString(e)}).join(" ")}}})(e("../tree"))},{"../tree":41}],49:[function(e,t,n){(function(e){e.Field=function(t){this.value=t||""},e.Field.prototype={is:"field",toString:function(){return"["+this.value+"]"},ev:function(){return this}}})(e("../tree"))},{"../tree":41}],50:[function(e,t,n){(function(e){e.Filter=function(t,n,r,i,s){this.key=t,this.op=n,this.val=r,this.index=i,this.filename=s,this.id=this.key+this.op+this.val};var t={"<":[" < ","numeric"],">":[" > ","numeric"],"=":[" = ","both"],"!=":[" != ","both"],"<=":[" <= ","numeric"],">=":[" >= ","numeric"],"=~":[".match(","string",")"]};e.Filter.prototype.ev=function(e){return this.key=this.key.ev(e),this.val=this.val.ev(e),this},e.Filter.prototype.toXML=function(n){e.Reference.data.filter&&(this.key.is==="keyword"&&-1===e.Reference.data.filter.value.indexOf(this.key.toString())&&n.error({message:this.key.toString()+" is not a valid keyword in a filter expression",index:this.index,filename:this.filename}),this.val.is==="keyword"&&-1===e.Reference.data.filter.value.indexOf(this.val.toString())&&n.error({message:this.val.toString()+" is not a valid keyword in a filter expression",index:this.index,filename:this.filename}));var r=this.key.toString(!1),i=this.val.toString(this.val.is=="string");return(t[this.op][1]=="numeric"&&isNaN(i)&&this.val.is!=="field"||t[this.op][1]=="string"&&i[0]!="'")&&n.error({message:'Cannot use operator "'+this.op+'" with value '+this.val,index:this.index,filename:this.filename}),r+t[this.op][0]+i+(t[this.op][2]||"")},e.Filter.prototype.toString=function(){return"["+this.id+"]"}})(e("../tree"))},{"../tree":41}],51:[function(e,t,n){(function(t){var n=e("../tree"),r=t._||e("underscore");n.Filterset=function(){this.filters={}},n.Filterset.prototype.toXML=function(e){var t=[];for(var n in this.filters)t.push("("+this.filters[n].toXML(e).trim()+")");return t.length?" "+t.join(" and ")+"\n":""},n.Filterset.prototype.toString=function(){var e=[];for(var t in this.filters)e.push(this.filters[t].id);return e.sort().join(" ")},n.Filterset.prototype.ev=function(e){for(var t in this.filters)this.filters[t].ev(e);return this},n.Filterset.prototype.clone=function(){var e=new n.Filterset;for(var t in this.filters)e.filters[t]=this.filters[t];return e},n.Filterset.prototype.cloneWith=function(e){var t=[];for(var r in e.filters){var i=this.addable(e.filters[r]);if(i===!1)return!1;i===!0&&t.push(e.filters[r])}if(!t.length)return null;var s=new n.Filterset;for(r in this.filters)s.filters[r]=this.filters[r];while(r=t.shift())s.add(r);return s},n.Filterset.prototype.toJS=function(e){var t={"=":"==="};return r.map(this.filters,function(e){var n=e.op;n in t&&(n=t[n]);var r=e.val;e._val!==undefined&&(r=e._val.toString(!0));var i="data";return i+"."+e.key.value+" "+n+" "+(r.is==="string"?"'"+r+"'":r)}).join(" && ")},n.Filterset.prototype.addable=function(e){var t=e.key.toString(),n=e.val.toString();n.match(/^[0-9]+(\.[0-9]*)?$/)&&(n=parseFloat(n));switch(e.op){case"=":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val.toString()!=n?!1:null;if(this.filters[t+"!="+n]!==undefined)return!1;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return!1;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val":if(t+"="in this.filters)return this.filters[t+"="].val<=n?!1:null;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return!1;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val<=n)return!1;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return null;return!0;case">=":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>=n)return null;return!0;case"<":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val>=n?!1:null;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>=n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val<=n)return null;return!0}},n.Filterset.prototype.conflict=function(e){var t=e.key.toString(),n=e.val.toString();return isNaN(parseFloat(n))||(n=parseFloat(n)),e.op==="="&&this.filters[t+"="]!==undefined&&n!=this.filters[t+"="].val.toString()||e.op==="!="&&this.filters[t+"="]!==undefined&&n==this.filters[t+"="].val.toString()||e.op==="="&&this.filters[t+"!="]!==undefined&&n==this.filters[t+"!="].val.toString()?e.toString()+" added to "+this.toString()+" produces an invalid filter":!1},n.Filterset.prototype.add=function(e,t){var n=e.key.toString(),r,i=e.op,s=this.conflict(e),o;if(s)return s;if(i==="="){for(var u in this.filters)this.filters[u].key==n&&delete this.filters[u];this.filters[n+"="]=e}else if(i==="!=")this.filters[n+"!="+e.val]=e;else if(i==="=~")this.filters[n+"=~"+e.val]=e;else if(i===">"){for(var a in this.filters)this.filters[a].key==n&&this.filters[a].val<=e.val&&delete this.filters[a];this.filters[n+">"]=e}else if(i===">="){for(var f in this.filters)o=+this.filters[f].val.toString(),this.filters[f].key==n&&o",this.filters[n+">"]=e):this.filters[n+">="]=e}else if(i==="<"){for(var l in this.filters)o=+this.filters[l].val.toString(),this.filters[l].key==n&&o>=e.val&&delete this.filters[l];this.filters[n+"<"]=e}else if(i==="<="){for(var c in this.filters)o=+this.filters[c].val.toString(),this.filters[c].key==n&&o>e.val&&delete this.filters[c];this.filters[n+"!="+e.val]!==undefined?(delete this.filters[n+"!="+e.val],e.op="<",this.filters[n+"<"]=e):this.filters[n+"<="]=e}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"../tree":41,underscore:71}],52:[function(e,t,n){(function(e){e._getFontSet=function(t,n){var r=n.join("");if(t._fontMap&&t._fontMap[r])return t._fontMap[r];var i=new e.FontSet(t,n);return t.effects.push(i),t._fontMap||(t._fontMap={}),t._fontMap[r]=i,i},e.FontSet=function(t,n){this.fonts=n,this.name="fontset-"+t.effects.length},e.FontSet.prototype.toXML=function(e){return'\n'+this.fonts.map(function(e){return' '}).join("\n")+"\n"}})(e("../tree"))},{"../tree":41}],53:[function(e,t,n){var r=e("../tree");r.FrameOffset=function(e,t,n){t=parseInt(t,10);if(t>r.FrameOffset.max||t<=0)throw{message:"Only frame-offset levels between 1 and "+r.FrameOffset.max+" supported.",index:n};if(e!=="=")throw{message:"only = operator is supported for frame-offset",index:n};return t},r.FrameOffset.max=32,r.FrameOffset.none=0},{"../tree":41}],54:[function(e,t,n){(function(e){e.ImageFilter=function(t,n){this.filter=t,this.args=n||null},e.ImageFilter.prototype={is:"imagefilter",ev:function(){return this},toString:function(){return this.args?this.filter+"("+this.args.join(",")+")":this.filter}}})(e("../tree"))},{"../tree":41}],55:[function(e,t,n){(function(e){e.Invalid=function(t,n,r){this.chunk=t,this.index=n,this.type="syntax",this.message=r||"Invalid code: "+this.chunk},e.Invalid.prototype.is="invalid",e.Invalid.prototype.ev=function(e){return e.error({chunk:this.chunk,index:this.index,type:"syntax",message:this.message||"Invalid code: "+this.chunk}),{is:"undefined"}}})(e("../tree"))},{"../tree":41}],56:[function(e,t,n){(function(e){e.Keyword=function(t){this.value=t;var n={transparent:"color","true":"boolean","false":"boolean"};this.is=n[t]?n[t]:"keyword"},e.Keyword.prototype={ev:function(){return this},toString:function(){return this.value}}})(e("../tree"))},{"../tree":41}],57:[function(e,t,n){(function(e){e.LayerXML=function(t,n){var r=[];for(var i in t.Datasource)r.push('");var s="";for(var o in t.properties)o==="minzoom"?s+=' maxzoom="'+e.Zoom.ranges[t.properties[o]]+'"\n':o==="maxzoom"?s+=' minzoom="'+e.Zoom.ranges[t.properties[o]+1]+'"\n':s+=" "+o+'="'+t.properties[o]+'"\n';return'\n "+n.reverse().map(function(e){return""+e+""}).join("\n ")+(r.length?"\n \n "+r.join("\n ")+"\n \n":"")+" \n"}})(e("../tree"))},{"../tree":41}],58:[function(e,t,n){(function(e){e.Literal=function(t){this.value=t||"",this.is="field"},e.Literal.prototype={toString:function(){return this.value},ev:function(){return this}}})(e("../tree"))},{"../tree":41}],59:[function(e,t,n){(function(e){e.Operation=function(t,n,r){this.op=t.trim(),this.operands=n,this.index=r},e.Operation.prototype.is="operation",e.Operation.prototype.ev=function(t){var n=this.operands[0].ev(t),r=this.operands[1].ev(t),i;return n.is==="undefined"||r.is==="undefined"?{is:"undefined",value:"undefined"}:(n instanceof e.Dimension&&r instanceof e.Color&&(this.op==="*"||this.op==="+"?(i=r,r=n,n=i):t.error({name:"OperationError",message:"Can't substract or divide a color from a number",index:this.index})),n instanceof e.Quoted&&r instanceof e.Quoted&&this.op!=="+"?(t.error({message:"Can't subtract, divide, or multiply strings.",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):n instanceof e.Field||r instanceof e.Field||n instanceof e.Literal||r instanceof e.Literal?n.is==="color"||r.is==="color"?(t.error({message:"Can't subtract, divide, or multiply colors in expressions.",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):new e.Literal(n.ev(t).toString(!0)+this.op+r.ev(t).toString(!0)):n.operate===undefined?(t.error({message:"Cannot do math with type "+n.is+".",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):n.operate(t,this.op,r))},e.operate=function(e,t,n){switch(e){case"+":return t+n;case"-":return t-n;case"*":return t*n;case"%":return t%n;case"/":return t/n}}})(e("../tree"))},{"../tree":41}],60:[function(e,t,n){(function(e){e.Quoted=function(t){this.value=t||""},e.Quoted.prototype={is:"string",toString:function(e){var t=this.value.replace(/&/g,"&"),n=t.replace(/\'/g,"\\'").replace(/\"/g,""").replace(//g,">");return e===!0?"'"+n+"'":t},ev:function(){return this},operate:function(t,n,r){return new e.Quoted(e.operate(n,this.toString(),r.toString(this.contains_field)))}}})(e("../tree"))},{"../tree":41}],61:[function(e,t,n){(function(t){(function(n){function s(e){var t={};for(var n in e.symbolizers)for(var r in e.symbolizers[n])e.symbolizers[n][r].hasOwnProperty("css")&&(t[e.symbolizers[n][r].css]=[e.symbolizers[n][r],n,r]);return t}function o(e){var t={};for(var n in e.symbolizers)for(var r in e.symbolizers[n])if(e.symbolizers[n][r].type==="functions")for(var i=0;i1){var f=e._getFontSet(n,this.value.value);return'fontset-name="'+f.name+'"'}return r?this.value.toString(n,this.name,i):e.Reference.selectorName(this.name)+'="'+this.value.toString(n,this.name)+'"'},e.Rule.prototype.ev=function(t){return new e.Rule(this.name,this.value.ev(t),this.index,this.filename)}})(e("../tree"))},{"../tree":41}],63:[function(e,t,n){(function(e){e.Ruleset=function(t,n){this.selectors=t,this.rules=n,this._lookups={}},e.Ruleset.prototype={is:"ruleset",ev:function(t){var n,r=new e.Ruleset(this.selectors,this.rules.slice(0));r.root=this.root,t.frames.unshift(r);for(n=0,rule;n1?Array.prototype.push.apply(r,i.find(new e.Selector(null,null,null,t.elements.slice(1)),n)):r.push(i);break}}}),this._lookups[o]=r)},evZooms:function(t){for(var n=0;n\n"+v+""}})(e("../tree"))}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"../tree":41,underscore:71}],66:[function(e,t,n){(function(e){e.URL=function(t,n){this.value=t,this.paths=n},e.URL.prototype={is:"uri",toString:function(){return this.value.toString()},ev:function( -t){return new e.URL(this.value.ev(t),this.paths)}}})(e("../tree"))},{"../tree":41}],67:[function(e,t,n){(function(e){e.Value=function(t){this.value=t},e.Value.prototype={is:"value",ev:function(t){return this.value.length===1?this.value[0].ev(t):new e.Value(this.value.map(function(e){return e.ev(t)}))},toString:function(e,t,n,r){return this.value.map(function(t){return t.toString(e,r)}).join(n||", ")},clone:function(){var t=Object.create(e.Value.prototype);return Array.isArray(t)?t.value=this.value.slice():t.value=this.value,t.is=this.is,t},toJS:function(e){var t=this.ev(e),n=t.toString();return t.is==="color"||t.is==="uri"||t.is==="string"||t.is==="keyword"?n="'"+n+"'":t.is==="field"?n=n.replace(/\[(.*)\]/g,"data['$1']"):t.is==="call"&&(n=JSON.stringify({name:t.name,args:t.args})),"_value = "+n+";"}}})(e("../tree"))},{"../tree":41}],68:[function(e,t,n){(function(e){e.Variable=function(t,n,r){this.name=t,this.index=n,this.filename=r},e.Variable.prototype={is:"variable",toString:function(){return this.name},ev:function(e){var t,n,r=this.name;if(this._css)return this._css;var i=e.frames.filter(function(e){return e.name==this.name}.bind(this));return i.length?i[0].value.ev(e):(e.error({message:"variable "+this.name+" is undefined",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"})}}})(e("../tree"))},{"../tree":41}],69:[function(e,t,n){var r=e("../tree");r.Zoom=function(e,t,n){this.op=e,this.value=t,this.index=n},r.Zoom.prototype.setZoom=function(e){return this.zoom=e,this},r.Zoom.prototype.ev=function(e){var t=0,n=Infinity,i=parseInt(this.value.ev(e).toString(),10),s=0;(i>r.Zoom.maxZoom||i<0)&&e.error({message:"Only zoom levels between 0 and "+r.Zoom.maxZoom+" supported.",index:this.index});switch(this.op){case"=":return this.zoom=1<":t=i+1;break;case">=":t=i;break;case"<":n=i-1;break;case"<=":n=i}for(var o=0;o<=r.Zoom.maxZoom;o++)o>=t&&o<=n&&(s|=1<0&&e.push(" "+r.Zoom.ranges[t]+"\n"),n<22&&e.push(" "+r.Zoom.ranges[n+1]+"\n")}return e},r.Zoom.prototype.toString=function(){var e="";for(var t=0;t<=r.Zoom.maxZoom;t++)e+=this.zoom&1<2;e==null&&(e=[]);if(v&&e.reduce===v)return r&&(t=N.bind(t,r)),i?e.reduce(t,n):e.reduce(t);C(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(k);return n},N.reduceRight=N.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(m&&e.reduceRight===m)return r&&(t=N.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=N.keys(e);s=o.length}C(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(k);return n},N.find=N.detect=function(e,t,n){var r;return L(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},N.filter=N.select=function(e,t,n){var r=[];return e==null?r:g&&e.filter===g?e.filter(t,n):(C(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},N.reject=function(e,t,n){return N.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},N.every=N.all=function(e,t,n){t||(t=N.identity);var r=!0;return e==null?r:y&&e.every===y?e.every(t,n):(C(e,function(e,s,o){if(!(r=r&&t.call(n,e,s,o)))return i}),!!r)};var L=N.some=N.any=function(e,t,n){t||(t=N.identity);var r=!1;return e==null?r:b&&e.some===b?e.some(t,n):(C(e,function(e,s,o){if(r||(r=t.call(n,e,s,o)))return i}),!!r)};N.contains=N.include=function(e,t){return e==null?!1:w&&e.indexOf===w?e.indexOf(t)!=-1:L(e,function(e){return e===t})},N.invoke=function(e,t){var n=f.call(arguments,2),r=N.isFunction(t);return N.map(e,function(e){return(r?t:e[t]).apply(e,n)})},N.pluck=function(e,t){return N.map(e,N.property(t))},N.where=function(e,t){return N.filter(e,N.matches(t))},N.findWhere=function(e,t){return N.find(e,N.matches(t))},N.max=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);var r=-Infinity,i=-Infinity;return C(e,function(e,s,o){var u=t?t.call(n,e,s,o):e;u>i&&(r=e,i=u)}),r},N.min=function(e,t,n){if(!t&&N.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);var r=Infinity,i=Infinity;return C(e,function(e,s,o){var u=t?t.call(n,e,s,o):e;ur||n===void 0)return 1;if(n>>1;n.call(r,e[u])=0;n--)t=[e[n].apply(this,t)];return t[0]}},N.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},N.keys=function(e){if(!N.isObject(e))return[];if(x)return x(e);var t=[];for(var n in e)N.has(e,n)&&t.push(n);return t},N.values=function(e){var t=N.keys(e),n=t.length,r=new Array(n);for(var i=0;i":">",'"':""","'":"'"}};P.unescape=N.invert(P.escape);var H={escape:new RegExp("["+N.keys(P.escape).join("")+"]","g"),unescape:new RegExp("("+N.keys(P.unescape).join("|")+")","g")};N.each(["escape","unescape"],function(e){N[e]=function(t){return t==null?"":(""+t).replace(H[e],function(t){return P[e][t]})}}),N.result=function(e,t){if(e==null)return void 0;var n=e[t];return N.isFunction(n)?n.call(e):n},N.mixin=function(e){C(N.functions(e),function(t){var n=N[t]=e[t];N.prototype[t]=function(){var e=[this._wrapped];return a.apply(e,arguments),q.call(this,n.apply(N,e))}})};var B=0;N.uniqueId=function(e){var t=++B+"";return e?e+t:t},N.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var j=/(.)^/,F={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},I=/\\|'|\r|\n|\t|\u2028|\u2029/g;N.template=function(e,t,n){var r;n=N.defaults({},n,N.templateSettings);var i=new RegExp([(n.escape||j).source,(n.interpolate||j).source,(n.evaluate||j).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(I,function(e){return"\\"+F[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,N);var a=function(e){return r.call(this,e,N)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},N.chain=function(e){return N(e).chain()};var q=function(e){return this._chain?N(e).chain():e};N.mixin(N),C(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=s[e];N.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],q.call(this,n)}}),C(["concat","join","slice"],function(e){var t=s[e];N.prototype[e]=function(){return q.call(this,t.apply(this._wrapped,arguments))}}),N.extend(N.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),typeof define=="function"&&define.amd&&define("underscore",[],function(){return N})}).call(this)},{}],72:[function(e,t,n){t.exports={name:"carto",version:"0.15.1-cdb1",description:"CartoCSS Stylesheet Compiler",url:"https://github.com/cartodb/carto",repository:{type:"git",url:"http://github.com/cartodb/carto.git"},author:{name:"CartoDB",url:"http://cartodb.com/"},keywords:["maps","css","stylesheets"],contributors:[{name:"Tom MacWright",email:"macwright@gmail.com"},{name:"Konstantin Käfer"},{name:"Alexis Sellier",email:"self@cloudhead.net"},{name:"Raul Ochoa",email:"rochoa@cartodb.com"},{name:"Javi Santana",email:"jsantana@cartodb.com"}],licenses:[{type:"Apache"}],bin:{carto:"./bin/carto"},man:["./man/carto.1"],main:"./lib/carto/index",engines:{node:">=0.4.x"},dependencies:{underscore:"~1.6.0","mapnik-reference":"~6.0.2",optimist:"~0.6.0"},devDependencies:{mocha:"1.12.x",jshint:"0.2.x",sax:"0.1.x",istanbul:"~0.2.14",coveralls:"~2.10.1",browserify:"~7.0.0","uglify-js":"1.3.3"},scripts:{pretest:"npm install",test:"mocha -R spec",coverage:"istanbul cover ./node_modules/.bin/_mocha && coveralls < ./coverage/lcov.info"},readme:"# CartoCSS\n\n[![Build Status](https://secure.travis-ci.org/mapbox/carto.png)](http://travis-ci.org/mapbox/carto)\n\nIs as stylesheet renderer for javascript, It's an evolution of the Mapnik renderer from Mapbox.\nPlease, see original [Mapbox repo](http://github.com/mapbox/carto) for more information and credits\n\n## Quick Start\n\n```javascript\n// shader is a CartoCSS object\n\nvar cartocss = [\n '#layer {',\n ' marker-width: [property]',\n ' marker-fill: red',\n '}'\n].join('')\nvar shader = new carto.RendererJS().render(cartocss);\nvar layers = shader.getLayers()\nfor (var i = 0; i < layers.length; ++i) {\n var layer = layers[i];\n console.log(\"layer name: \", layer.fullName())\n console.log(\"- frames: \", layer.frames())\n console.log(\"- attachment: \", layer.attachment())\n\n var layerShader = layer.getStyle({ property: 1 }, { zoom: 10 })\n console.log(layerShader['marker-width']) // 1\n console.log(layerShader['marker-fill']) // #FF0000\n}\n\n```\n\n# API\n\n## RendererJS\n\n### render(cartocss)\n\n## CartoCSS\n\ncompiled cartocss object\n\n### getLayers\n\nreturn the layers, an array of ``CartoCSS.Layer`` object\n\n### getDefault\n\nreturn the default layer (``CartoCSS.Layer``), usually the Map layer\n\n\n### findLayer(where)\n\nfind a layer using where object.\n\n```\nshader.findLayer({ name: 'test' })\n```\n\n## CartoCSS.Layer\n\n### getStyle(props, context)\n\nreturn the evaluated style:\n - props: object containing properties needed to render the style. If the cartocss style uses\n some variables they should be passed in this object\n - context: rendering context variables like ``zoom`` or animation ``frame``\n\n\n\n\n\n\n\n\n\n\n## Reference Documentation\n\n* [mapbox.com/carto](http://mapbox.com/carto/)\n\n\n",readmeFilename:"README.md",bugs:{url:"https://github.com/cartodb/carto/issues"},homepage:"https://github.com/cartodb/carto",_id:"carto@0.15.1-cdb1",_shasum:"62534c2975cbee073f10c6c14a0c7e889c9469e7",_resolved:"https://github.com/CartoDB/carto/archive/master.tar.gz",_from:"https://github.com/CartoDB/carto/archive/master.tar.gz"}},{}]},{},[10])(10)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.torque=e()}}(function(){var define,module,exports;return function e(t,n,r){function i(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return i(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var s=typeof require=="function"&&require;for(var o=0;oe&&this.time(0),this.rescale(),this):this.options.animationDuration},steps:function(e){return this.options.steps=e,this.rescale()},step:function(e){if(arguments.length===0)return this.range(this.domain(this._time));this._time=this.domainInv(this.rangeInv(e))},pause:function(){this.running=!1,s(this._tick),this.options.onPause&&this.options.onPause()},_tick:function(){var e=+(new Date),t=(e-this._t0)*.001;t=Math.min(this.options.maxDelta,t),this._t0=e,this._time+=t,this.step()>=this.options.steps&&(this.options.loop?this._time=0:(this.time(this.options.animationDuration),this.pause())),this.running&&(this.time(this._time),i(this._tick))}},t.exports=o}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./":10}],2:[function(e,t,n){var r={version:"1.0.0",style:{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]}},layer:{"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"number","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"number","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"number","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}},symbolizers:{"*":{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},trail:{steps:{css:"trail-steps",type:"float","default-value":1,"default-meaning":"no trail steps",doc:"How many steps of trails are going to be rendered"}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon"},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line"},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels"},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color"},"marker-type":{css:"marker-type",type:["rectangle","ellipse"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)"},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float"}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]}};t.exports={version:{latest:r,"1.0.0":r}}},{}],3:[function(e,t,n){(function(n){function i(){}var r=n.carto||e("carto");i.prototype={},i.optionsFromLayer=function(e){var t={};if(!e)return t;var n={"buffer-size":"buffer-size","-torque-frame-count":"steps","-torque-resolution":"resolution","-torque-animation-duration":"animationDuration","-torque-aggregation-function":"countby","-torque-time-attribute":"column","-torque-data-aggregation":"data_aggregation"};for(var r in n){var i=e.eval(r);if(i!==undefined){var s=n[r];t[s]=i}}return t},i.optionsFromCartoCSS=function(e){var t=(new r.RendererJS).render(e),n=t.findLayer({name:"Map"});return i.optionsFromLayer(n)},t.exports.TorqueLayer=i}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{carto:32}],4:[function(e,t,n){(function(e){function r(){var e=arguments,t=e[0];for(var n=1;ni&&(n.x-=i),this.canvas.style[r.CSS_TRANSFORM_]="translate("+Math.round(n.x)+"px,"+Math.round(n.y)+"px)",this.scheduleUpdate()},r.prototype.update_=function(){this.requestAnimationFrameId_=null;if(!this.isAdded_)return;this.isAnimated_&&this.scheduleUpdate(),this.needsResize_&&this.resizeHandler_&&(this.needsResize_=!1,this.resizeHandler_()),this.updateHandler_&&this.updateHandler_()},r.prototype.getTopLeft=function(){return this.topLeft_},r.prototype.scheduleUpdate=function(){this.isAdded_&&!this.requestAnimationFrameId_&&(this.requestAnimationFrameId_=this.requestAnimFrame_.call(window,this.requestUpdateFunction_))},t.exports=r},{}],6:[function(e,t,n){function r(e,t){this.tileSize=new google.maps.Size(256,256),this.maxZoom=19,this.name="Tile #s",this.alt="Canvas tile layer",this.tiles={},this.canvas_setup=e,this.render=t,t||(this.render=e)}r.prototype.create_tile_canvas=function(e,t,n){var r=n.createElement("canvas"),i=n.createElement("canvas");r.style.border=i.style.border="none",r.style.margin=i.style.margin="0",r.style.padding=i.style.padding="0";var s=r.getContext("2d");s.width=r.width=this.tileSize.width,s.height=r.height=this.tileSize.height;var o=i.getContext("2d");i.width=o.width=this.tileSize.width,i.height=o.height=this.tileSize.height;var u=e.x+"_"+e.y+"_"+t;return r.setAttribute("id",u),i.setAttribute("id",u),u in this.tiles&&delete this.tiles[u],this.tiles[u]={canvas:r,ctx:s,hit_canvas:i,hit_ctx:o,coord:e,zoom:t,primitives:null},this.canvas_setup&&this.canvas_setup(this.tiles[u],e,t),r},r.prototype.each=function(e){for(var t in this.tiles){var n=this.tiles[t];e(n)}},r.prototype.recreate=function(){for(var e in this.tiles){var t=this.tiles[e];this.canvas_setup(t,t.coord,t.zoom)}},r.prototype.redraw_tile=function(e){this.render(e,e.coord,e.zoom)},r.prototype.redraw=function(){for(var e in this.tiles){var t=this.tiles[e];this.render(t,t.coord,t.zoom)}},r.prototype.getTile=function(e,t,n){return this.create_tile_canvas(e,t,n)},r.prototype.releaseTile=function(e){var t=e.getAttribute("id");delete this.tiles[t]},t.exports=r},{}],7:[function(e,t,n){function r(){}r.prototype={_initTileLoader:function(e,t){this._map=e,this._projection=t,this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._updateTiles=this._updateTiles.bind(this),this._listeners=[],this._listeners.push(google.maps.event.addListener(this._map,"dragend",this._updateTiles),google.maps.event.addListener(this._map,"zoom_changed",this._updateTiles)),this.tileSize=256,this._updateTiles()},_removeTileLoader:function(){this._listeners.forEach(function(e){google.maps.event.removeListener(e)}),this._removeTiles()},_removeTiles:function(){for(var e in this._tiles)this._removeTile(e)},_reloadTiles:function(){this._removeTiles(),this._updateTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getBounds(),t=this._map.getZoom(),n=this.tileSize,r=1<t.x||it.y)&&this._removeTile(s))},_removeTile:function(e){this.onTileRemoved&&this.onTileRemoved(this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.onTilesLoaded&&this.onTilesLoaded()},getTilePos:function(e){var t=1<=0&&a>=0&&u=0&&this.cancelAnimationFrame.call(window,this.currentAnimationFrame),this.currentAnimationFrame=this.requestAnimationFrame.call(window,this.render)},redraw:function(e){var t=L.DomUtil.getPosition(this._map.getPanes().mapPane);t&&L.DomUtil.setPosition(this._canvas,{x:-t.x,y:-t.y}),e?this.render():this._render()},onResize:function(){},render:function(){throw new Error("render function should be implemented")}})},{"./leaflet_tileloader_mixin":13}],12:[function(e,t,n){typeof L!="undefined"&&e("./torque")},{"./torque":14}],13:[function(e,t,n){L.Mixin.TileLoader={_initTileLoader:function(){this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._map.on({moveend:this._updateTiles},this),this._updateTiles()},_removeTileLoader:function(){this._map.off({moveend:this._updateTiles},this),this._removeTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getPixelBounds(),t=this._map.getZoom(),n=this.options.tileSize;if(t>this.options.maxZoom||te.max.x||re.max.y)&&this._removeTile(s))},_removeTile:function(e){this.fire("tileRemoved",this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.fire("tilesLoaded")},getTilePos:function(e){e=new L.Point(e.x,e.y);var t=this._map._getNewTopLeftPoint(this._map.getCenter()),n=this.options.tileSize;return e.multiplyBy(n).subtract(t)},_addTilesFromCenterOut:function(e){var t=[],n=e.getCenter(),r=this._map.getZoom(),i,s,o;for(i=e.min.y;i<=e.max.y;i++)for(s=e.min.x;s<=e.max.x;s++)o=new L.Point(s,i),o.zoom=r,this._tileShouldBeLoaded(o)&&t.push(o);var u=t.length;if(u===0)return;t.sort(function(e,t){return e.distanceTo(n)-t.distanceTo(n)}),this._tilesToLoad+=u;for(s=0;s0&&l>0&&o.getContext("2d").drawImage(this.getCanvas(),u,a,f,l,u-n.x,a-n.y,f,l)}}}this.prevRenderedKey=this.key},setKey:function(e,t){this.key=e,this.animator.step(e),this._clearTileCaches(),this.redraw(t&&t.direct),this.fire("change:time",{time:this.getTime(),step:this.key})},setStep:function(e){if(e===undefined||e.length!==undefined)throw new Error("setTime only accept scalars");this.setKey(e)},stepToTime:function(e){var t=this.provider.getKeySpan(),n=t.start+(t.end-t.start)*(e/this.provider.getSteps());return new Date(n)},timeToStep:function(e){typeof e=="Date"&&(e=e.getTime());if(!this.provider)return 0;var t=this.provider.getKeySpan(),n=this.provider.getSteps()*(e-t.start)/(t.end-t.start);return n},getStep:function(){return this.key},getTime:function(){return this.stepToTime(this.key)},getTimeSpan:function(){return this.provider.getKeySpan()},setCartoCSS:function(e){if(this.provider.options.named_map)throw new Error("CartoCSS style on named maps is read-only");if(!this.renderer)throw new Error("renderer is not valid");var t=(new n.RendererJS).render(e);this.renderer.setShader(t);var i=r.common.TorqueLayer.optionsFromLayer(t.findLayer({name:"Map"}));return this.provider.setCartoCSS&&this.provider.setCartoCSS(e),this.provider.setOptions(i)&&this._reloadTiles(),r.extend(this.options,i),i.animationDuration&&this.animator.duration(i.animationDuration),this._clearCaches(),this.redraw(),this},getActivePointsBBox:function(e){var t=[];for(var n in this._tiles){var r=this._tiles[n];t=t.concat(this.renderer.getActivePointsBBox(r,e))}return t},getValueForPos:function(e,t,n){n=n===undefined?this.key:n;var r,i,s,o=null,u,a;for(r in this._tiles){i=this._tiles[r],s=this.getTilePos(i.coord),u=e-s.x,a=t-s.y,u>=0&&a>=0&&u1&&(i.new_value(this.name,this.count),this.count=0,this.start())}},i.metric=function(e){return new s(e)},t.exports=i},{}],18:[function(e,t,n){t.exports={json:e("./json"),JsonArray:e("./jsonarray"),windshaft:e("./windshaft"),internal:e("./internal")}},{"./internal":19,"./json":20,"./jsonarray":21,"./windshaft":22}],19:[function(e,t,n){var r=e("../"),i=new r.Mercator,s=function(e){this.setReady(!1),this.options=e,this.options.data_aggregation&&(this.options.cumulative=this.options.data_aggregation==="cumulative"),this.points=[],this._tileQueue=[],this.options.bounds=[[Number.MAX_VALUE,Number.MAX_VALUE],[Number.MIN_VALUE,Number.MIN_VALUE]]};s.prototype={addPoint:function(e,t,n,r){typeof n=="number"?(n=parseInt(n),this.timestampType===undefined&&(this.timestampType="number")):(n=new Date(Date.parse(n)),this.timestampType===undefined&&(this.timestampType="date")),this.points.push({lat:parseFloat(e),lon:parseFloat(t),time:n,value:parseFloat(r)||r})},getBounds:function(){return this.options.bounds},getCategories:function(){if(!this.options.countby)return[];var e=this,t=function(t){return t.name==e.points[r].value},n=[];for(var r=0;rthis.options.bounds[1][0]&&(this.options.bounds[1][0]=e.latLonBounds.maxLat),e.latLonBounds.minLatthis.options.bounds[1][1]&&(this.options.bounds[1][1]=e.latLonBounds.maxLon),e.latLonBounds.minLone.latLonBounds.minLat&&t.lone.latLonBounds.minLon}},getPointsInTile:function(e){var t=[];for(var n=0;n0){l[d]===undefined&&(l[d]=[]),l[d][v]===undefined&&(l[d][v]=0),l[d][v]+=h.value,h.value=l[d][v];for(var g=m;g>0),e.options.data_steps=t.num_steps>>0,e.options.step=e.options.step||1,e.options.bounds=[[t.ymin,t.xmin],[t.ymax,t.xmax]],e._setReady(!0)},{parseJSON:!0,no_cdn:!0})},{parseJSON:!0,no_cdn:!0})}},t.exports=f},{"../":10,"../profiler":17}],21:[function(e,t,n){function f(e,t){for(var n=1;n=0?t["marker-fill-opacity"]:1,e.globalAlpha>0&&e.fill()),t["marker-line-color"]&&t["marker-line-width"]&&t["marker-line-width"]>i&&(e.globalAlpha=t["marker-line-opacity"]>=0?t["marker-line-opacity"]:1,t["marker-line-width"]!==undefined&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.stroke())}function u(e,t){e.fillStyle=t["marker-fill"];var n=t["marker-width"],r=n*2;if(t["marker-fill"]){if(t["marker-fill-opacity"]!==undefined||t["marker-opacity"]!==undefined)e.globalAlpha=t["marker-fill-opacity"]||t["marker-opacity"];e.fillRect(-n,-n,r,r)}e.globalAlpha=1,t["marker-line-color"]&&t["marker-line-width"]&&(t["marker-line-opacity"]&&(e.globalAlpha=t["marker-line-opacity"]),t["marker-line-width"]&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.strokeRect(-n,-n,r,r))}function a(e,t,n){if(t.complete){if(n["marker-fill-opacity"]!==undefined||n["marker-opacity"]!==undefined)e.globalAlpha=n["marker-fill-opacity"]||n["marker-opacity"];e.drawImage(t,0,0,Math.min(t.width,s),Math.min(t.height,s))}}var r=Math.PI*2,i=.05,s=255;t.exports={renderPoint:o,renderSprite:a,renderRectangle:u,MAX_SPRITE_RADIUS:s}},{}],24:[function(e,t,n){t.exports={cartocss:e("./cartocss_render"),Point:e("./point"),Rectangle:e("./rectangle")}},{"./cartocss_render":23,"./point":25,"./rectangle":26}],25:[function(e,t,n){(function(n){function c(e){return l[e]||e}function h(e,t){if(!e)throw new Error("canvas can't be undefined");this.options=t,this._canvas=e,this._ctx=e.getContext("2d"),this._sprites=[],this._shader=null,this._icons={},this._iconsToLoad=0,this._filters=new u(this._canvas,{canvasClass:t.canvasClass}),this.setCartoCSS(this.options.cartocss||f),this.TILE_SIZE=256,this._style=null,this._gradients={},this._forcePoints=!1}var r=e("../"),i=e("./cartocss_render"),s=e("../profiler"),o=n.carto||e("carto"),u=e("./torque_filters"),a=Math.PI*2,f=["#layer {"," marker-fill: #662506;"," marker-width: 4;"," [value > 1] { marker-fill: #FEE391; }"," [value > 2] { marker-fill: #FEC44F; }"," [value > 3] { marker-fill: #FE9929; }"," [value > 4] { marker-fill: #EC7014; }"," [value > 5] { marker-fill: #CC4C02; }"," [value > 6] { marker-fill: #993404; }"," [value > 7] { marker-fill: #662506; }","}"].join("\n"),l={src:"source-over","src-over":"source-over","dst-over":"destination-over","src-in":"source-in","dst-in":"destination-in","src-out":"source-out","dst-out":"destination-out","src-atop":"source-atop","dst-atop":"destination-atop",xor:"xor",darken:"darken",lighten:"lighten"};r.extend(h.prototype,r.Event,{clearCanvas:function(){var e=this._canvas,t=this._Map["-torque-clear-color"];if(t==="rgba(255, 255, 255, 0)"||!t)this._canvas.width=this._canvas.width;else{var n=this._ctx;n.setTransform(1,0,0,1,0,0);var r=this._Map["comp-op"];n.globalCompositeOperation=c(r),n.fillStyle=t,n.fillRect(0,0,e.width,e.height)}},setCanvas:function(e){this._canvas=e,this._ctx=e.getContext("2d")},setCartoCSS:function(e){this.setShader((new o.RendererJS).render(e))},setShader:function(e){this._sprites=[],this._shader=e,this._Map=this._shader.getDefault().getStyle({},{zoom:0});var t=this._shader.getImageURLs();this._preloadIcons(t)},clearSpriteCache:function(){this._sprites=[]},generateSprite:function(e,t,n){var o=this,u=s.metric("torque.renderer.point.generateSprite").start(),a=e.getStyle({value:t},n);if(this._style===null||this._style!==a)this._style=a;var f=a["marker-width"];if(!f)return null;if(a["marker-opacity"]===0&&!a["marker-line-opacity"])return null;var l=this._createCanvas(),c=l.getContext("2d"),h=a["marker-file"]||a["point-file"],p=h&&this._qualifyURL(h);if(p&&this._iconsToLoad<=0&&this._icons[p]){var d=this._icons[p],v=Math.min(a["marker-width"]*2||d.width,i.MAX_SPRITE_RADIUS*2),m=Math.min((a["marker-height"]||v)*(d.width/d.height),i.MAX_SPRITE_RADIUS*2);l.width=c.width=v,l.height=c.height=m,c.scale(v/d.width,m/d.height),i.renderSprite(c,d,a)}else{var g=(a["marker-line-width"]||0)+f*2,y=c.width=l.width=c.height=l.height=Math.ceil(g);c.translate(y/2,y/2);var b=a["marker-type"];b&&b==="rectangle"?i.renderRectangle(c,a):i.renderPoint(c,a)}u.end(!0);if(r.flags.sprites_to_images){var w=this._createImage();return w.src=l.toDataURL(),w}return l},renderTile:function(e,t,n){if(this._iconsToLoad>0)return this.on("allIconsLoaded",function(){this.renderTile.apply(this,[e,t,n])}),!1;var r=s.metric("torque.renderer.point.renderLayers").start(),i=this._shader.getLayers();for(var o=0,u=i.length;oe.maxDate&&(t=e.maxDate);var h=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),p=e.timeCount[t],d=this.options.resolution/2;if(p){var v=e.timeIndex[t];for(var m=0;m>1)+d,E=h-e.y[g]+d;f.drawImage(b,w,E-(b.height>>1))}}}}a.end(!0)},setBlendMode:function(e){this.options.blendmode=e},getActivePointsBBox:function(e,t){var n=[],i=new r.Mercator,s=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),o=e.timeCount[t],u=e.timeIndex[t];for(var a=0;a>1,a=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),f=e.timeCount[t],l=e.timeIndex[t];for(var c=0;c=0&&m=0&&g0&&!this._forcePoints){var n=Object.keys(e.reduce(function(e,n){var r=t._qualifyURL(n);return t._icons[r]||(e[r]=!0),e},{})),r=t._shader.getLayers().some(function(e){return typeof e.shader["image-filters"]!="undefined"});this._iconsToLoad+=n.length,n.forEach(function(e){t._icons[e]=null;var n=t._createImage();r&&(n.crossOrigin="Anonymous"),t._setImageSrc(n,e,function(i){i?(t._forcePoints=!0,t.clearSpriteCache(),t._iconsToLoad=0,t.fire("allIconsLoaded"),r&&console.info("Only CORS-enabled, or same domain image-files can be used in combination with image-filters"),console.error("Couldn't get marker-file "+e)):(t._icons[e]=n,t._iconsToLoad--,t._iconsToLoad<=0&&(t.clearSpriteCache(),t.fire("allIconsLoaded")))})})}else this.fire("allIconsLoaded")},applyFilters:function(){if(this._style&&this._style["image-filters"]){function e(e){var t="";for(var n=0;n 10] { polygon-fill: #FFFF00; }"," [value > 100] { polygon-fill: #FFCC00; }"," [value > 1000] { polygon-fill: #FE9929; }"," [value > 10000] { polygon-fill: #FF6600; }"," [value > 100000] { polygon-fill: #FF3300; }","}"].join("\n"),s=Math.PI*2;o.prototype={setCartoCSS:function(e){this._cartoCssStyle=(new r.RendererJS).render(e);if(this._cartoCssStyle.getLayers().length>1)throw new Error("only one CartoCSS layer is supported");this._shader=this._cartoCssStyle.getLayers()[0].shader},setCanvas:function(e){if(!e)return;this._canvas=e,this._ctx=e.getContext("2d")},accumulate:function(e,t){var n=Profiler.metric("RectangleRender:accumulate").start(),r,i,s,o,u,a,f,l,c=this.options.resolution,h=256/c,p=new Float32Array(h*h);typeof t!="object"&&(t=[t]);for(u=0;u=200&&e<300||e===304?t(o):t(null)}r=r||{method:"GET",data:null,responseType:"text"},i={url:e,callback:t};var s=XMLHttpRequest;n.XDomainRequest&&!("withCredentials"in s)&&/^(http(s)?:)?\/\//.test(e)&&(s=XDomainRequest);var o=new s;return o.open(r.method,e,!0),"onload"in o?o.onload=o.onerror=u:o.onreadystatechange=function(){o.readyState>3&&u()},o.onprogress=function(){},o.responseType=r.responseType,r.data&&(o.setRequestHeader("Content-type","application/json"),o.setRequestHeader("Accept","*")),o.send(r.data),o}function u(e,t,n){return o(e,n,{data:t,method:"POST"})}var r=e("./core"),i=null;t.exports={get:o,post:u,jsonp:s,lastCall:function(){return i}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./core":4}],29:[function(e,t,n){function u(e,t){return r.isUndefined(t)?""+t:r.isNumber(t)&&(isNaN(t)||!isFinite(t))?t.toString():r.isFunction(t)||r.isRegExp(t)?t.toString():t}function a(e,t){return r.isString(e)?e.length=0;u--)if(n[u]!=s[u])return!1;for(u=n.length-1;u>=0;u--){o=n[u];if(!h(e[o],t[o]))return!1}return!0}function v(e,t){return!e||!t?!1:Object.prototype.toString.call(t)=="[object RegExp]"?t.test(e):e instanceof t?!0:t.call({},e)===!0?!0:!1}function m(e,t,n,i){var s;r.isString(n)&&(i=n,n=null);try{t()}catch(o){s=o}i=(n&&n.name?" ("+n.name+").":".")+(i?" "+i:"."),e&&!s&&l(s,n,"Missing expected exception"+i),!e&&v(s,n)&&l(s,n,"Got unwanted exception"+i);if(e&&s&&n&&!v(s,n)||!e&&s)throw s}var r=e("util/"),i=Array.prototype.slice,s=Object.prototype.hasOwnProperty,o=t.exports=c;o.AssertionError=function(t){this.name="AssertionError",this.actual=t.actual,this.expected=t.expected,this.operator=t.operator,t.message?(this.message=t.message,this.generatedMessage=!1):(this.message=f(this),this.generatedMessage=!0);var n=t.stackStartFunction||l;if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{var r=new Error;if(r.stack){var i=r.stack,s=n.name,o=i.indexOf("\n"+s);if(o>=0){var u=i.indexOf("\n",o+1);i=i.substring(u+1)}this.stack=i}}},r.inherits(o.AssertionError,Error),o.fail=l,o.ok=c,o.equal=function(t,n,r){t!=n&&l(t,n,r,"==",o.equal)},o.notEqual=function(t,n,r){t==n&&l(t,n,r,"!=",o.notEqual)},o.deepEqual=function(t,n,r){h(t,n)||l(t,n,r,"deepEqual",o.deepEqual)},o.notDeepEqual=function(t,n,r){h(t,n)&&l(t,n,r,"notDeepEqual",o.notDeepEqual)},o.strictEqual=function(t,n,r){t!==n&&l(t,n,r,"===",o.strictEqual)},o.notStrictEqual=function(t,n,r){t===n&&l(t,n,r,"!==",o.notStrictEqual)},o.throws=function(e,t,n){m.apply(this,[!0].concat(i.call(arguments)))},o.doesNotThrow=function(e,t){m.apply(this,[!1].concat(i.call(arguments)))},o.ifError=function(e){if(e)throw e};var g=Object.keys||function(e){var t=[];for(var n in e)s.call(e,n)&&t.push(n);return t}},{"util/":73}],30:[function(e,t,n){},{}],31:[function(e,t,n){(function(e){function i(t){return e.functions.hsla(t.h,t.s,t.l,t.a)}function s(t){return t instanceof e.Dimension?parseFloat(t.unit=="%"?t.value/100:t.value):typeof t=="number"?t:NaN}function o(e){return Math.min(1,Math.max(0,e))}e.functions={rgb:function(e,t,n){return this.rgba(e,t,n,1)},rgba:function(t,n,r,i){var o=[t,n,r].map(function(e){return s(e)});return i=s(i),o.some(isNaN)||isNaN(i)?null:new e.Color(o,i)},stop:function(e){var t,n;return arguments.length>1&&(t=arguments[1]),arguments.length>2&&(n=arguments[2]),{is:"tag",val:e,color:t,mode:n,toString:function(r){return'\n "}}},hsl:function(e,t,n){return this.hsla(e,t,n,1)},hsla:function(e,t,n,r){function u(e){return e=e<0?e+1:e>1?e-1:e,e*6<1?o+(i-o)*e*6:e*2<1?i:e*3<2?o+(i-o)*(2/3-e)*6:o}e=s(e)%360/360,t=s(t),n=s(n),r=s(r);if([e,t,n,r].some(isNaN))return null;var i=n<=.5?n*(t+1):n+t-n*t,o=n*2-i;return this.rgba(u(e+1/3)*255,u(e)*255,u(e-1/3)*255,r)},hue:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().h)):null},saturation:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().s*100),"%"):null},lightness:function(t){return"toHSL"in t?new e.Dimension(Math.round(t.toHSL().l*100),"%"):null},alpha:function(t){return"toHSL"in t?new e.Dimension(t.toHSL().a):null},saturate:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.s+=t.value/100,n.s=o(n.s),i(n)}return null},desaturate:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.s-=t.value/100,n.s=o(n.s),i(n)}return null},lighten:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.l+=t.value/100,n.l=o(n.l),i(n)}return null},darken:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.l-=t.value/100,n.l=o(n.l),i(n)}return null},fadein:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.a+=t.value/100,n.a=o(n.a),i(n)}return null},fadeout:function(e,t){if("toHSL"in e){var n=e.toHSL();return n.a-=t.value/100,n.a=o(n.a),i(n)}return null},spin:function(e,t){if("toHSL"in e){var n=e.toHSL(),r=(n.h+t.value)%360;return n.h=r<0?360+r:r,i(n)}return null},replace:function(e,t,n){return e.is==="field"?e.toString+".replace("+t.toString()+", "+n.toString()+")":e.replace(t,n)},mix:function(t,n,r){var i=r.value/100,s=i*2-1,o=t.toHSL().a-n.toHSL().a,u=((s*o==-1?s:(s+o)/(1+s*o))+1)/2,a=1-u,f=[t.rgb[0]*u+n.rgb[0]*a,t.rgb[1]*u+n.rgb[1]*a,t.rgb[2]*u+n.rgb[2]*a],l=t.alpha*i+n.alpha*(1-i);return new e.Color(f,l)},greyscale:function(t){return this.desaturate(t,new e.Dimension(100))},"%":function(t){var n=Array.prototype.slice.call(arguments,1),r=t.value;for(var i=0;i4)return e("../../package.json").version.split(".");var n=JSON.parse(s.readFileSync(o.join(r,"../../package.json")));return n.version.split(".")}function l(e,t){var n={bold:[1,22],inverse:[7,27],underline:[4,24],yellow:[33,39],green:[32,39],red:[31,39],grey:[90,39]};return"["+n[t][0]+"m"+e+"["+n[t][1]+"m"}var i=e("util"),s=e("fs"),o=e("path"),a={version:u(),Parser:e("./parser").Parser,Renderer:e("./renderer").Renderer,tree:e("./tree"),RendererJS:e("./renderer_js"),default_reference:e("./torque-reference"),writeError:function(e,t){var n="",r=e.extract,s=[];t=t||{};if(t.silent)return;t.indent=t.indent||"";if(!("index"in e)||!r)return i.error(t.indent+(e.stack||e.message));typeof r[0]=="string"&&s.push(l(e.line-1+" "+r[0],"grey")),r[1]===""&&typeof r[2]=="undefined"&&(r[1]="¶"),s.push(e.line+" "+r[1].slice(0,e.column)+l(l(r[1][e.column],"bold")+r[1].slice(e.column+1),"yellow")),typeof r[2]=="string"&&s.push(l(e.line+1+" "+r[2],"grey")),s=t.indent+s.join("\n"+t.indent)+"\n",n=t.indent+n+l(e.message,"red"),e.filename&&(n+=l(" in ","red")+e.filename),i.error(n,s),e.callLine&&(i.error(l("from ","red")+(e.filename||"")),i.error(l(e.callLine,"grey")+" "+e.callExtract)),e.stack&&i.error(l(e.stack,"red"))}};e("./tree/call"),e("./tree/color"),e("./tree/comment"),e("./tree/definition"),e("./tree/dimension"),e("./tree/element"),e("./tree/expression"),e("./tree/filterset"),e("./tree/filter"),e("./tree/field"),e("./tree/keyword"),e("./tree/layer"),e("./tree/literal"),e("./tree/operation"),e("./tree/quoted"),e("./tree/imagefilter"),e("./tree/reference"),e("./tree/rule"),e("./tree/ruleset"),e("./tree/selector"),e("./tree/style"),e("./tree/url"),e("./tree/value"),e("./tree/variable"),e("./tree/zoom"),e("./tree/invalid"),e("./tree/fontset"),e("./tree/frame_offset"),e("./functions");for(var f in a)n[f]=a[f]}).call(this,e("_process"),"/node_modules/carto/lib/carto")},{"../../package.json":66,"./functions":31,"./parser":33,"./renderer":34,"./renderer_js":35,"./torque-reference":36,"./tree":37,"./tree/call":38,"./tree/color":39,"./tree/comment":40,"./tree/definition":41,"./tree/dimension":42,"./tree/element":43,"./tree/expression":44,"./tree/field":45,"./tree/filter":46,"./tree/filterset":47,"./tree/fontset":48,"./tree/frame_offset":49,"./tree/imagefilter":50,"./tree/invalid":51,"./tree/keyword":52,"./tree/layer":53,"./tree/literal":54,"./tree/operation":55,"./tree/quoted":56,"./tree/reference":57,"./tree/rule":58,"./tree/ruleset":59,"./tree/selector":60,"./tree/style":61,"./tree/url":62,"./tree/value":63,"./tree/variable":64,"./tree/zoom":65,_process:70,fs:30,path:69,util:73}],33:[function(e,t,n){(function(t){var r=n,i=e("./tree"),s=t._||e("underscore");r.Parser=function(t){function v(){u=l[o],a=r,c=r}function m(){l[o]=u,r=a,c=r}function g(){r>c&&(l[o]=l[o].slice(r-c),c=r)}function y(e){var t,i,s,u,a,f,p;if(e instanceof Function)return e.call(h.parsers);if(typeof e=="string")t=n.charAt(r)===e?e:null,s=1,g();else{g(),t=e.exec(l[o]);if(!t)return null;s=t[0].length}if(t){var d=r+=s;f=r+l[o].length-s;while(r=0&&r.charAt(o)!=="\n";o--)e.column++;return i=s.template("<%=filename%>:<%=line%>:<%=column%> <%=message%>"),new Error(i(e))}var n,r,o,u,a,f,l,c,h,p=this,d=function(){};return this.env=t=t||{},this.env.filename=this.env.filename||null,this.env.inputs=this.env.inputs||{},h={extractErrorLine:w,parse:function(e){var s,u,a,h,d,v,m=[],g,b=null;r=o=c=f=0,l=[],n=e.replace(/\r\n/g,"\n"),t.filename&&(p.env.inputs[t.filename]=n);var w=!1;l=function(e){var t=0,r=/(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,i=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,s=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,o=0,u,a=e[0],f;for(var l=0,c,h;l0?"missing closing `}`":"missing opening `{`"}),e.map(function(e){return e.join("")})}([[]]);if(b)throw E(b);s=new i.Ruleset([],y(this.parsers.primary)),s.root=!0,s.toList=function(){var e,t,n;return function(e){e.error=function(t){e.errors||(e.errors=new Error("")),e.errors.message?e.errors.message+="\n"+E(t).message:e.errors.message=E(t).message},e.frames=e.frames||[];var t=this.flatten([],[],e);return t.sort(S),t}}();var S=function(e,t){var n=e.specificity,r=t.specificity;return n[0]!=r[0]?r[0]-n[0]:n[1]!=r[1]?r[1]-n[1]:n[2]!=r[2]?r[2]-n[2]:r[3]-n[3]};return s},parsers:{primary:function(){var e,t=[];while((e=y(this.rule)||y(this.ruleset)||y(this.comment))||y(/^[\s\n]+/)||(e=y(this.invalid)))e&&t.push(e);return t},invalid:function(){var e=y(/^[^;\n]*[;\n]/);if(e)return new i.Invalid(e,a)},comment:function(){var e;if(n.charAt(r)!=="/")return;if(n.charAt(r+1)==="/")return new i.Comment(y(/^\/\/.*/),!0);if(e=y(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new i.Comment(e)},entities:{quoted:function(){if(n.charAt(r)!=='"'&&n.charAt(r)!=="'")return;var e=y(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/);if(e)return new i.Quoted(e[1]||e[2])},field:function(){if(!y("["))return;var e=y(/(^[^\]]+)/);if(!y("]"))return;if(e)return new i.Field(e[1])},comparison:function(){var e=y(/^=~|=|!=|<=|>=|<|>/);if(e)return e},keyword:function(){var e=y(/^[A-Za-z-]+[A-Za-z-0-9_]*/);if(e)return new i.Keyword(e)},call:function(){var e,t;if(!(e=/^([\w\-]+|%)\(/.exec(l[o])))return;e=e[1];if(e==="url")return null;r+=e.length,y("("),t=y(this.entities.arguments);if(!y(")"))return;if(e)return new i.Call(e,t,r)},arguments:function(){var e=[],t;while(t=y(this.expression)){e.push(t);if(!y(","))break}return e},literal:function(){return y(this.entities.dimension)||y(this.entities.keywordcolor)||y(this.entities.hexcolor)||y(this.entities.quoted)},url:function(){var e;if(n.charAt(r)!=="u"||!y(/^url\(/))return;return e=y(this.entities.quoted)||y(this.entities.variable)||y(/^[\-\w%@$\/.&=:;#+?~]+/)||"",y(")")?new i.URL(typeof e.value!="undefined"||e instanceof i.Variable?e:new i.Quoted(e)):new i.Invalid(e,a,"Missing closing ) in URL.")},variable:function(){var e,s=r;if(n.charAt(r)==="@"&& +(e=y(/^@[\w-]+/)))return new i.Variable(e,s,t.filename)},hexcolor:function(){var e;if(n.charAt(r)==="#"&&(e=y(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new i.Color(e[1])},keywordcolor:function(){var e=l[o].match(/^[a-z]+/);if(e&&e[0]in i.Reference.data.colors)return new i.Color(i.Reference.data.colors[y(/^[a-z]+/)])},dimension:function(){var e=n.charCodeAt(r);if(e>57||e<45||e===47)return;var t=y(/^(-?\d*\.?\d+(?:[eE][-+]?\d+)?)(\%|\w+)?/);if(t)return new i.Dimension(t[1],t[2],a)}},variable:function(){var e;if(n.charAt(r)==="@"&&(e=y(/^(@[\w-]+)\s*:/)))return e[1]},entity:function(){return y(this.entities.call)||y(this.entities.literal)||y(this.entities.field)||y(this.entities.variable)||y(this.entities.url)||y(this.entities.keyword)},end:function(){return y(";")||b("}")},element:function(){var e=y(/^(?:[.#][\w\-]+|\*|Map)/);if(e)return new i.Element(e)},attachment:function(){var e=y(/^::([\w\-]+(?:\/[\w\-]+)*)/);if(e)return e[1]},selector:function(){var e,t,s,o=[],u,f=new i.Filterset,l,c=[],h=i.FrameOffset.none;segments=0,conditions=0;while((s=y(this.element))||(l=y(this.zoom))||(fo=y(this.frame_offset))||(u=y(this.filter))||(e=y(this.attachment))){segments++;if(s)o.push(s);else if(l)c.push(l),conditions++;else if(fo)h=fo,conditions++;else if(u){var p=f.add(u);if(p)throw E({message:p,index:r-1});conditions++}else{if(t)throw E({message:"Encountered second attachment name.",index:r-1});t=e}var d=n.charAt(r);if(d==="{"||d==="}"||d===";"||d===",")break}if(segments)return new i.Selector(f,c,h,o,t,conditions,a)},filter:function(){v();var e,n,r;if(!y("["))return;if(e=y(/^[a-zA-Z0-9\-_]+/)||y(this.entities.quoted)||y(this.entities.variable)||y(this.entities.keyword)||y(this.entities.field)){e instanceof i.Quoted&&(e=new i.Field(e.toString()));if((n=y(this.entities.comparison))&&(r=y(this.entities.quoted)||y(this.entities.variable)||y(this.entities.dimension)||y(this.entities.keyword)||y(this.entities.field))){if(!y("]"))throw E({message:"Missing closing ] of filter.",index:a-1});return e.is||(e=new i.Field(e)),new i.Filter(e,n,r,a,t.filename)}}},frame_offset:function(){v();var e,t;if(y(/^\[\s*frame-offset/g)&&(e=y(this.entities.comparison))&&(t=y(/^\d+/))&&y("]"))return i.FrameOffset(e,t,a)},zoom:function(){v();var e,t;if(y(/^\[\s*zoom/g)&&(e=y(this.entities.comparison))&&(t=y(this.entities.variable)||y(this.entities.dimension))&&y("]"))return new i.Zoom(e,t,a);m()},block:function(){var e;if(y("{")&&(e=y(this.primary))&&y("}"))return e},ruleset:function(){var e=[],t,n,r,s,o=[];v();while(t=y(this.selector)){e.push(t);while(y(this.comment));if(!y(","))break;while(y(this.comment));}if(t)while(y(this.comment));if(e.length>0&&(s=y(this.block))){if(e.length===1&&e[0].elements.length&&e[0].elements[0].value==="Map"){var u=new i.Ruleset(e,s);return u.isMap=!0,u}return new i.Ruleset(e,s)}m()},rule:function(){var e,s,o=n.charAt(r);v();if(o==="."||o==="#")return;if(e=y(this.variable)||y(this.property)){s=y(this.value);if(s&&y(this.end))return new i.Rule(e,s,a,t.filename);f=r,m()}},font:function(){var e=[],t=[],n,r,s;while(s=y(this.entity))t.push(s);e.push(new i.Expression(t));if(y(","))while(s=y(this.expression)){e.push(s);if(!y(","))break}return new i.Value(e)},value:function(){var e,t=[];while(e=y(this.expression)){t.push(e);if(!y(","))break}if(t.length>1)return new i.Value(t.map(function(e){return e.value[0]}));if(t.length===1)return new i.Value(t)},sub:function(){var e,t=[];if(y("(")){while(e=y(this.expression)){t.push(e);if(!y(","))break}y(")")}if(t.length>1)return new i.Value(t.map(function(e){return e.value[0]}));if(t.length===1)return new i.Value(t)},multiplication:function(){var e,t,n,r;if(e=y(this.operand)){while((n=y("/")||y("*")||y("%"))&&(t=y(this.operand)))r=new i.Operation(n,[r||e,t],a);return r||e}},addition:function(){var e,t,s,o;if(e=y(this.multiplication)){while((s=y(/^[-+]\s+/)||n.charAt(r-1)!=" "&&(y("+")||y("-")))&&(t=y(this.multiplication)))o=new i.Operation(s,[o||e,t],a);return o||e}},operand:function(){return y(this.sub)||y(this.entity)},expression:function(){var e,t,n=[],r;while(e=y(this.addition)||y(this.entity))n.push(e);if(n.length>0)return new i.Expression(n)},property:function(){var e=y(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/);if(e)return e[1]}}},h}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./tree":37,underscore:71}],34:[function(e,t,n){(function(n){function s(e,t,n,r){var i=t.filters,s=t.rules,o,u,a;for(var f=0;f'+t+"");break;case"name":case"description":case"legend":case"attribution":case"template":e.push(' ");break;case"format":e.push(' '+t+"");break;case"interactivity":e.push(' '+t.layer+""),e.push(' '+t.fields+"");break;default:"string"==typeof t?e.push(' "):"number"==typeof t?e.push(' '+t+""):"boolean"==typeof t&&e.push(' '+t+"")}return e},[]);N.length&&s.unshift("\n"+N.join("\n")+"\n\n");var C=r.map(T,function(e){return" "+e}).join("");return s.unshift('\n\n\n"),s.push(""),s.join("\n")},t.exports=i,t.exports.addRules=s,t.exports.inheritDefinitions=o,t.exports.sortStyles=a}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./index":32,underscore:71}],35:[function(require,module,exports){(function(global){(function(carto){function CartoCSS(e,t){this.options=t||{},this.imageURLs=[],e&&this.setStyle(e)}var tree=require("./tree"),_=global._||require("underscore");CartoCSS.Layer=function(e,t){this.options=t,this.shader=e},CartoCSS.Layer.prototype={fullName:function(){return this.shader.attachment},name:function(){return this.fullName().split("::")[0]},frames:function(){return this.shader.frames},attachment:function(){return this.fullName().split("::")[1]},eval:function(e){var t=this.shader[e];if(!t||!t.style)return;return t.style({},{zoom:0,"frame-offset":0})},getStyle:function(e,t){var n={};for(var r in this.shader)r!=="attachment"&&r!=="zoom"&&r!=="frames"&&r!=="symbolizers"&&(n[r]=this.shader[r].style(e,t));return n},getSymbolizers:function(){return this.shader.symbolizers},isVariable:function(){for(var e in this.shader)if(e!=="attachment"&&e!=="zoom"&&e!=="frames"&&e!=="symbolizers"&&!this.shader[e].constant)return!0;return!1},getShader:function(){return this.shader},filter:function(e,t,n){for(var r in this.shader){var i=this.shader[r](t,n);if(i)return!0}return!1},transformGeometry:function(e){return e},transformGeometries:function(e){return e}},CartoCSS.prototype={setStyle:function(e){var t=this.parse(e);if(!t)throw new Error(this.parse_env.errors);this.layers=t.map(function(e){return new CartoCSS.Layer(e)})},getLayers:function(){return this.layers},getDefault:function(){return this.findLayer({attachment:"__default__"})},findLayer:function(e){return _.find(this.layers,function(t){for(var n in e){var r=t[n];typeof r=="function"&&(r=r.call(t));if(e[n]!==r)return!1}return!0})},_createFn:function(e){var t=e.join("\n");return this.options.debug&&console.log(t),Function("data","ctx","var _value = null; "+t+"; return _value; ")},_compile:function(shader){typeof shader=="string"&&(shader=eval("(function() { return "+shader+"; })()")),this.shader_src=shader;for(var attr in shader){var c=mapper[attr];c&&(this.compiled[c]=eval("(function() { return shader[attr]; })();"))}},getImageURLs:function(){return this.imageURLs},parse:function(e){var t={frames:[],errors:[],error:function(e){this.errors.push(e)}};this.parse_env=t;var n=null;try{n=(new carto.Parser(t)).parse(e)}catch(r){t.errors.push(r.message);return}if(n){function i(e){return e.elements[0]+"::"+e.attachment}var s=n.toList(t);s.reverse();var o={};for(var u=0;u= minzoom - 1e-6 and scale < maxzoom + 1e-6"},maxzoom:{"default-value":"1.79769e+308",type:"float","default-meaning":"The layer will be visible at the maximum possible scale",doc:"The maximum scale denominator that this layer will be visible at. The default is the numeric limit of the C++ double type, which may vary slightly by system, but is likely a massive number like 1.79769e+308 and ensures that this layer will always be visible unless the value is reduced. A layer's visibility is determined by whether its status is true and if the Map scale >= minzoom - 1e-6 and scale < maxzoom + 1e-6"},queryable:{"default-value":!1,type:"boolean","default-meaning":"The layer will not be available for the direct querying of data values",doc:"This property was added for GetFeatureInfo/WMS compatibility and is rarely used. It is off by default meaning that in a WMS context the layer will not be able to be queried unless the property is explicitly set to true"},"clear-label-cache":{"default-value":!1,type:"boolean","default-meaning":"The renderer's collision detector cache (used for avoiding duplicate labels and overlapping markers) will not be cleared immediately before processing this layer",doc:"This property, by default off, can be enabled to allow a user to clear the collision detector cache before a given layer is processed. This may be desirable to ensure that a given layers data shows up on the map even if it normally would not because of collisions with previously rendered labels or markers"},"group-by":{"default-value":"",type:"string","default-meaning":"No special layer grouping will be used during rendering",doc:"https://github.com/mapnik/mapnik/wiki/Grouped-rendering"},"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"maximum-extent":{"default-value":"none",type:"bbox","default-meaning":"No clipping extent will be used",doc:"An extent to be used to limit the bounds used to query this specific layer data during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Layer."}},symbolizers:{"*":{"image-filters":{css:"image-filters","default-value":"none","default-meaning":"no filters",type:"functions",functions:[["agg-stack-blur",2],["emboss",0],["blur",0],["gray",0],["sobel",0],["edge-detect",0],["x-gradient",0],["y-gradient",0],["invert",0],["sharpen",0],["colorize-alpha",-1],["color-to-alpha",1],["scale-hsla",8],["ramp",-1]],doc:"A list of image filters."},"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["clear","src","dst","src-over","source-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","lighter","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},map:{"background-color":{css:"background-color","default-value":"none","default-meaning":"transparent",type:"color",doc:"Map Background color"},"background-image":{css:"background-image",type:"uri","default-value":"","default-meaning":"transparent",doc:"An image that is repeated below all features on a map as a background.",description:"Map Background image"},srs:{css:"srs",type:"string","default-value":"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs","default-meaning":"The proj4 literal of EPSG:4326 is assumed to be the Map's spatial reference and all data from layers within this map will be plotted using this coordinate system. If any layers do not declare an srs value then they will be assumed to be in the same srs as the Map and not transformations will be needed to plot them in the Map's coordinate space",doc:"Map spatial reference (proj4 string)"},"buffer-size":{css:"buffer-size","default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:'Extra tolerance around the map (in pixels) used to ensure labels crossing tile boundaries are equally rendered in each tile (e.g. cut in each tile). Not intended to be used in combination with "avoid-edges".'},"maximum-extent":{css:"","default-value":"none",type:"bbox","default-meaning":"No clipping extent will be used",doc:"An extent to be used to limit the bounds used to query all layers during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Map."},base:{css:"base","default-value":"","default-meaning":"This base path defaults to an empty string meaning that any relative paths to files referenced in styles or layers will be interpreted relative to the application process.",type:"string",doc:"Any relative paths used to reference files will be understood as relative to this directory path if the map is loaded from an in memory object rather than from the filesystem. If the map is loaded from the filesystem and this option is not provided it will be set to the directory of the stylesheet."},"paths-from-xml":{css:"","default-value":!0,"default-meaning":"Paths read from XML will be interpreted from the location of the XML",type:"boolean",doc:"value to control whether paths in the XML will be interpreted from the location of the XML or from the working directory of the program that calls load_map()"},"minimum-version":{css:"","default-value":"none","default-meaning":"Mapnik version will not be detected and no error will be thrown about compatibility",type:"string",doc:"The minumum Mapnik version (e.g. 0.7.2) needed to use certain functionality in the stylesheet"},"font-directory":{css:"font-directory",type:"uri","default-value":"none","default-meaning":"No map-specific fonts will be registered",doc:"Path to a directory which holds fonts which should be registered when the Map is loaded (in addition to any fonts that may be automatically registered)."}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon",expression:!0},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"},gamma:{css:"polygon-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of polygon edges"},"gamma-method":{css:"polygon-gamma-method",type:["power","linear","none","threshold","multiply"],"default-value":"power","default-meaning":"pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA",doc:"An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h"},clip:{css:"polygon-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"polygon-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"polygon-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"polygon-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line",expression:!0},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels",expression:!0},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"},"stroke-gamma":{css:"line-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of stroke line"},"stroke-gamma-method":{css:"line-gamma-method",type:["power","linear","none","threshold","multiply"],"default-value":"power","default-meaning":"pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA",doc:"An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h"},"stroke-dasharray":{css:"line-dasharray",type:"numbers",doc:"A pair of length values [a,b], where (a) is the dash length and (b) is the gap length respectively. More than two values are supported for more complex patterns.","default-value":"none","default-meaning":"solid line"},"stroke-dashoffset":{css:"line-dash-offset",type:"numbers",doc:"valid parameter but not currently used in renderers (only exists for experimental svg support in Mapnik which is not yet enabled)","default-value":"none","default-meaning":"solid line"},"stroke-miterlimit":{css:"line-miterlimit",type:"float",doc:"The limit on the ratio of the miter length to the stroke-width. Used to automatically convert miter joins to bevel joins for sharp angles to avoid the miter extending beyond the thickness of the stroking path. Normally will not need to be set, but a larger value can sometimes help avoid jaggy artifacts.","default-value":4,"default-meaning":"Will auto-convert miters to bevel line joins when theta is less than 29 degrees as per the SVG spec: 'miterLength / stroke-width = 1 / sin ( theta / 2 )'"},clip:{css:"line-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"line-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},offset:{css:"line-offset",type:"float","default-value":0,"default-meaning":"no offset",doc:"Offsets a line a number of pixels parallel to its actual path. Postive values move the line left, negative values move it right (relative to the directionality of the line)."},rasterizer:{css:"line-rasterizer",type:["full","fast"],"default-value":"full",doc:"Exposes an alternate AGG rendering method that sacrifices some accuracy for speed."},"geometry-transform":{css:"line-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"line-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},placement:{css:"marker-placement",type:["point","line","interior"],"default-value":"point","default-meaning":"Place markers at the center point (centroid) of the geometry",doc:"Attempt to place markers on a point, in the center of a polygon, or if markers-placement:line, then multiple times along a line. 'interior' placement can be used to ensure that points placed on polygons are forced to be inside the polygon interior"},"multi-policy":{css:"marker-multi-policy",type:["each","whole","largest"],"default-value":"each","default-meaning":"If a feature contains multiple geometries and the placement type is either point or interior then a marker will be rendered for each",doc:"A special setting to allow the user to control rendering behavior for 'multi-geometries' (when a feature contains multiple geometries). This setting does not apply to markers placed along lines. The 'each' policy is default and means all geometries will get a marker. The 'whole' policy means that the aggregate centroid between all geometries will be used. The 'largest' policy means that only the largest (by bounding box areas) feature will get a rendered marker (this is how text labeling behaves by default)."},"marker-type":{css:"marker-type",type:["arrow","ellipse","rectangle"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an arrow or an ellipse (a circle if height is equal to width)" +},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float",expression:!0},height:{css:"marker-height","default-value":10,doc:"The height of the marker, if using one of the default types.",type:"float",expression:!0},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color",expression:!0},"allow-overlap":{css:"marker-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping markers are shown or hidden.","default-meaning":"Do not allow makers to overlap with each other - overlapping markers will not be shown."},"ignore-placement":{css:"marker-ignore-placement",type:"boolean","default-value":!1,"default-meaning":"do not store the bbox of this geometry in the collision detector cache",doc:"value to control whether the placement of the feature will prevent the placement of other features"},spacing:{css:"marker-spacing",doc:"Space between repeated labels","default-value":100,type:"float"},"max-error":{css:"marker-max-error",type:"float","default-value":.2,doc:"The maximum difference between actual marker placement and the marker-spacing parameter. Setting a high value can allow the renderer to try to resolve placement conflicts with other symbolizers."},transform:{css:"marker-transform",type:"functions",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]],"default-value":"","default-meaning":"No transformation",doc:"SVG transformation definition"},clip:{css:"marker-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"marker-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"marker-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"marker-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},shield:{name:{css:"shield-name",type:"string",expression:!0,serialization:"content",doc:'Value to use for a shield"s text label. Data columns are specified using brackets like [column_name]'},file:{css:"shield-file",required:!0,type:"uri","default-value":"none",doc:"Image file to render behind the shield text"},"face-name":{css:"shield-face-name",type:"string",validate:"font",doc:"Font name and style to use for the shield text","default-value":"",required:!0},"unlock-image":{css:"shield-unlock-image",type:"boolean",doc:"This parameter should be set to true if you are trying to position text beside rather than on top of the shield image","default-value":!1,"default-meaning":"text alignment relative to the shield image uses the center of the image as the anchor for text positioning."},size:{css:"shield-size",type:"float",doc:"The size of the shield text in pixels"},fill:{css:"shield-fill",type:"color",doc:"The color of the shield text"},placement:{css:"shield-placement",type:["point","line","vertex","interior"],"default-value":"point",doc:"How this shield should be placed. Point placement attempts to place it on top of points, line places along lines multiple times per feature, vertex places on the vertexes of polygons, and interior attempts to place inside of polygons."},"avoid-edges":{css:"shield-avoid-edges",doc:"Tell positioning algorithm to avoid labeling near intersection edges.",type:"boolean","default-value":!1},"allow-overlap":{css:"shield-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping shields are shown or hidden.","default-meaning":"Do not allow shields to overlap with other map elements already placed."},"minimum-distance":{css:"shield-min-distance",type:"float","default-value":0,doc:"Minimum distance to the next shield symbol, not necessarily the same shield."},spacing:{css:"shield-spacing",type:"float","default-value":0,doc:"The spacing between repeated occurrences of the same shield on a line"},"minimum-padding":{css:"shield-min-padding","default-value":0,doc:"Determines the minimum amount of padding that a shield gets relative to other shields",type:"float"},"wrap-width":{css:"shield-wrap-width",type:"unsigned","default-value":0,doc:"Length of a chunk of text in characters before wrapping text"},"wrap-before":{css:"shield-wrap-before",type:"boolean","default-value":!1,doc:"Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width."},"wrap-character":{css:"shield-wrap-character",type:"string","default-value":" ",doc:"Use this character instead of a space to wrap long names."},"halo-fill":{css:"shield-halo-fill",type:"color","default-value":"#FFFFFF","default-meaning":"white",doc:"Specifies the color of the halo around the text."},"halo-radius":{css:"shield-halo-radius",doc:"Specify the radius of the halo in pixels","default-value":0,"default-meaning":"no halo",type:"float"},"character-spacing":{css:"shield-character-spacing",type:"unsigned","default-value":0,doc:"Horizontal spacing between characters (in pixels). Currently works for point placement only, not line placement."},"line-spacing":{css:"shield-line-spacing",doc:"Vertical spacing between lines of multiline labels (in pixels)",type:"unsigned"},dx:{css:"shield-text-dx",type:"float",doc:"Displace text within shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},dy:{css:"shield-text-dy",type:"float",doc:"Displace text within shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},"shield-dx":{css:"shield-dx",type:"float",doc:"Displace shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},"shield-dy":{css:"shield-dy",type:"float",doc:"Displace shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},opacity:{css:"shield-opacity",type:"float",doc:"(Default 1.0) - opacity of the image used for the shield","default-value":1},"text-opacity":{css:"shield-text-opacity",type:"float",doc:"(Default 1.0) - opacity of the text placed on top of the shield","default-value":1},"horizontal-alignment":{css:"shield-horizontal-alignment",type:["left","middle","right","auto"],doc:"The shield's horizontal alignment from its centerpoint","default-value":"auto"},"vertical-alignment":{css:"shield-vertical-alignment",type:["top","middle","bottom","auto"],doc:"The shield's vertical alignment from its centerpoint","default-value":"middle"},"text-transform":{css:"shield-text-transform",type:["none","uppercase","lowercase","capitalize"],doc:"Transform the case of the characters","default-value":"none"},"justify-alignment":{css:"shield-justify-alignment",type:["left","center","right","auto"],doc:"Define how text in a shield's label is justified","default-value":"auto"},clip:{css:"shield-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},"comp-op":{css:"shield-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},"line-pattern":{file:{css:"line-pattern-file",type:"uri","default-value":"none",required:!0,doc:"An image file to be repeated and warped along a line"},clip:{css:"line-pattern-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"line-pattern-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"line-pattern-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"line-pattern-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},"polygon-pattern":{file:{css:"polygon-pattern-file",type:"uri","default-value":"none",required:!0,doc:"Image to use as a repeated pattern fill within a polygon"},alignment:{css:"polygon-pattern-alignment",type:["local","global"],"default-value":"local",doc:"Specify whether to align pattern fills to the layer or to the map."},gamma:{css:"polygon-pattern-gamma",type:"float","default-value":1,"default-meaning":"fully antialiased",range:"0-1",doc:"Level of antialiasing of polygon pattern edges"},opacity:{css:"polygon-pattern-opacity",type:"float",doc:"(Default 1.0) - Apply an opacity level to the image used for the pattern","default-value":1,"default-meaning":"The image is rendered without modifications"},clip:{css:"polygon-pattern-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},smooth:{css:"polygon-pattern-smooth",type:"float","default-value":0,"default-meaning":"no smoothing",range:"0-1",doc:"Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries."},"geometry-transform":{css:"polygon-pattern-geometry-transform",type:"functions","default-value":"none","default-meaning":"geometry will not be transformed",doc:"Allows transformation functions to be applied to the geometry.",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]]},"comp-op":{css:"polygon-pattern-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},raster:{opacity:{css:"raster-opacity","default-value":1,"default-meaning":"opaque",type:"float",doc:"The opacity of the raster symbolizer on top of other symbolizers."},"filter-factor":{css:"raster-filter-factor","default-value":-1,"default-meaning":"Allow the datasource to choose appropriate downscaling.",type:"float",doc:"This is used by the Raster or Gdal datasources to pre-downscale images using overviews. Higher numbers can sometimes cause much better scaled image output, at the cost of speed."},scaling:{css:"raster-scaling",type:["near","fast","bilinear","bilinear8","bicubic","spline16","spline36","hanning","hamming","hermite","kaiser","quadric","catrom","gaussian","bessel","mitchell","sinc","lanczos","blackman"],"default-value":"near",doc:"The scaling algorithm used to making different resolution versions of this raster layer. Bilinear is a good compromise between speed and accuracy, while lanczos gives the highest quality."},"mesh-size":{css:"raster-mesh-size","default-value":16,"default-meaning":"Reprojection mesh will be 1/16 of the resolution of the source image",type:"unsigned",doc:"A reduced resolution mesh is used for raster reprojection, and the total image size is divided by the mesh-size to determine the quality of that mesh. Values for mesh-size larger than the default will result in faster reprojection but might lead to distortion."},"comp-op":{css:"raster-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},"allow-overlap":{css:"point-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping points are shown or hidden.","default-meaning":"Do not allow points to overlap with each other - overlapping markers will not be shown."},"ignore-placement":{css:"point-ignore-placement",type:"boolean","default-value":!1,"default-meaning":"do not store the bbox of this geometry in the collision detector cache",doc:"value to control whether the placement of the feature will prevent the placement of other features"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"},placement:{css:"point-placement",type:["centroid","interior"],doc:"How this point should be placed. Centroid calculates the geometric center of a polygon, which can be outside of it, while interior always places inside of a polygon.","default-value":"centroid"},transform:{css:"point-transform",type:"functions",functions:[["matrix",6],["translate",2],["scale",2],["rotate",3],["skewX",1],["skewY",1]],"default-value":"","default-meaning":"No transformation",doc:"SVG transformation definition"},"comp-op":{css:"point-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},text:{name:{css:"text-name",type:"string",expression:!0,required:!0,"default-value":"",serialization:"content",doc:"Value to use for a text label. Data columns are specified using brackets like [column_name]"},"face-name":{css:"text-face-name",type:"string",validate:"font",doc:"Font name and style to render a label in",required:!0},size:{css:"text-size",type:"float","default-value":10,doc:"Text size in pixels"},"text-ratio":{css:"text-ratio",doc:"Define the amount of text (of the total) present on successive lines when wrapping occurs","default-value":0,type:"unsigned"},"wrap-width":{css:"text-wrap-width",doc:"Length of a chunk of text in characters before wrapping text","default-value":0,type:"unsigned"},"wrap-before":{css:"text-wrap-before",type:"boolean","default-value":!1,doc:"Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width."},"wrap-character":{css:"text-wrap-character",type:"string","default-value":" ",doc:"Use this character instead of a space to wrap long text."},spacing:{css:"text-spacing",type:"unsigned",doc:"Distance between repeated text labels on a line (aka. label-spacing)"},"character-spacing":{css:"text-character-spacing",type:"float","default-value":0,doc:"Horizontal spacing adjustment between characters in pixels"},"line-spacing":{css:"text-line-spacing","default-value":0,type:"unsigned",doc:"Vertical spacing adjustment between lines in pixels"},"label-position-tolerance":{css:"text-label-position-tolerance","default-value":0,type:"unsigned",doc:"Allows the label to be displaced from its ideal position by a number of pixels (only works with placement:line)"},"max-char-angle-delta":{css:"text-max-char-angle-delta",type:"float","default-value":"22.5",doc:"The maximum angle change, in degrees, allowed between adjacent characters in a label. This value internally is converted to radians to the default is 22.5*math.pi/180.0. The higher the value the fewer labels will be placed around around sharp corners."},fill:{css:"text-fill",doc:"Specifies the color for the text","default-value":"#000000",type:"color"},opacity:{css:"text-opacity",doc:"A number from 0 to 1 specifying the opacity for the text","default-value":1,"default-meaning":"Fully opaque",type:"float"},"halo-fill":{css:"text-halo-fill",type:"color","default-value":"#FFFFFF","default-meaning":"white",doc:"Specifies the color of the halo around the text."},"halo-radius":{css:"text-halo-radius",doc:"Specify the radius of the halo in pixels","default-value":0,"default-meaning":"no halo",type:"float"},dx:{css:"text-dx",type:"float",doc:"Displace text by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right","default-value":0},dy:{css:"text-dy",type:"float",doc:"Displace text by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down","default-value":0},"vertical-alignment":{css:"text-vertical-alignment",type:["top","middle","bottom","auto"],doc:"Position of label relative to point position.","default-value":"auto","default-meaning":'Default affected by value of dy; "bottom" for dy>0, "top" for dy<0.'},"avoid-edges":{css:"text-avoid-edges",doc:"Tell positioning algorithm to avoid labeling near intersection edges.","default-value":!1,type:"boolean"},"minimum-distance":{css:"text-min-distance",doc:"Minimum permitted distance to the next text symbolizer.",type:"float"},"minimum-padding":{css:"text-min-padding",doc:"Determines the minimum amount of padding that a text symbolizer gets relative to other text",type:"float"},"minimum-path-length":{css:"text-min-path-length",type:"float","default-value":0,"default-meaning":"place labels on all paths",doc:"Place labels only on paths longer than this value."},"allow-overlap":{css:"text-allow-overlap",type:"boolean","default-value":!1,doc:"Control whether overlapping text is shown or hidden.","default-meaning":"Do not allow text to overlap with other text - overlapping markers will not be shown."},orientation:{css:"text-orientation",type:"float",expression:!0,doc:"Rotate the text."},placement:{css:"text-placement",type:["point","line","vertex","interior"],"default-value":"point",doc:"Control the style of placement of a point versus the geometry it is attached to."},"placement-type":{css:"text-placement-type",doc:'Re-position and/or re-size text to avoid overlaps. "simple" for basic algorithm (using text-placements string,) "dummy" to turn this feature off.',type:["dummy","simple"],"default-value":"dummy"},placements:{css:"text-placements",type:"string","default-value":"",doc:'If "placement-type" is set to "simple", use this "POSITIONS,[SIZES]" string. An example is `text-placements: "E,NE,SE,W,NW,SW";` '},"text-transform":{css:"text-transform",type:["none","uppercase","lowercase","capitalize"],doc:"Transform the case of the characters","default-value":"none"},"horizontal-alignment":{css:"text-horizontal-alignment",type:["left","middle","right","auto"],doc:"The text's horizontal alignment from its centerpoint","default-value":"auto"},"justify-alignment":{css:"text-align",type:["left","right","center","auto"],doc:"Define how text is justified","default-value":"auto","default-meaning":"Auto alignment means that text will be centered by default except when using the `placement-type` parameter - in that case either right or left justification will be used automatically depending on where the text could be fit given the `text-placements` directives"},clip:{css:"text-clip",type:"boolean","default-value":!0,"default-meaning":"geometry will be clipped to map bounds before rendering",doc:"geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts."},"comp-op":{css:"text-comp-op","default-value":"src-over","default-meaning":"add the current symbolizer on top of other symbolizer",doc:"Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.",type:["clear","src","dst","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","plus","minus","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","contrast","invert","invert-rgb","grain-merge","grain-extract","hue","saturation","color","value"]}},building:{fill:{css:"building-fill","default-value":"#FFFFFF",doc:"The color of the buildings walls.",type:"color"},"fill-opacity":{css:"building-fill-opacity",type:"float",doc:"The opacity of the building as a whole, including all walls.","default-value":1},height:{css:"building-height",doc:"The height of the building in pixels.",type:"float",expression:!0,"default-value":"0"}},torque:{"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"float","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"float","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"float","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["linear","cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]},filter:{value:["true","false","null","point","linestring","polygon","collection"]}};t.exports={version:{latest:r,"2.1.1":r}}},{}],37:[function(e,t,n){typeof t!="undefined"&&(t.exports.find=function(e,t){for(var n=0,r;n255?255:e<0?0:e).toString(16),e.length===1?"0"+e:e}).join("")},operate:function(t,n,r){var i=[];r instanceof e.Color||(r=r.toColor());for(var s=0;s<3;s++)i[s]=e.operate(n,this.rgb[s],r.rgb[s]);return new e.Color(i)},toHSL:function(){var e=this.rgb[0]/255,t=this.rgb[1]/255,n=this.rgb[2]/255,r=this.alpha,i=Math.max(e,t,n),s=Math.min(e,t,n),o,u,a=(i+s)/2,f=i-s;if(i===s)o=u=0;else{u=a>.5?f/(2-i-s):f/(i+s);switch(i){case e:o=(t-n)/f+(t"},ev:function(){return this}}})(e("../tree"))},{"../tree":37}],41:[function(e,t,n){(function(t){(function(n){function s(e){function t(e){return e[1].toUpperCase()}return e.charAt(0).toUpperCase()+e.slice(1).replace(/\-./,t)+"Symbolizer"}function o(e){return e.sort(function(e,t){return e[1]-t[1]}).map(function(e){return e[0]})}var r=e("assert"),i=t._||e("underscore");n.Definition=function(t,i){this.elements=t.elements,r.ok(t.filters instanceof n.Filterset),this.rules=i,this.ruleIndex={};for(var s=0;s"+w+"\n":i+=">\n")}return!h||!i?"":" \n"+i+" \n"},n.Definition.prototype.collectSymbolizers=function(e,t){var n={},r;for(var i=t;i1?new e.Expression(this.value.map(function(e){return e.ev(t)})):this.value[0].ev(t)},toString:function(e){return this.value.map(function(t){return t.toString(e)}).join(" ")}}})(e("../tree"))},{"../tree":37}],45:[function(e,t,n){(function(e){e.Field=function(t){this.value=t||""},e.Field.prototype={is:"field",toString:function(){return"["+this.value+"]"},ev:function(){return this}}})(e("../tree"))},{"../tree":37}],46:[function(e,t,n){(function(e){e.Filter=function(t,n,r,i,s){this.key=t,this.op=n,this.val=r,this.index=i,this.filename=s,this.id=this.key+this.op+this.val};var t={"<":[" < ","numeric"],">":[" > ","numeric"],"=":[" = ","both"],"!=":[" != ","both"],"<=":[" <= ","numeric"],">=":[" >= ","numeric"],"=~":[".match(","string",")"]};e.Filter.prototype.ev=function(e){return this.key=this.key.ev(e),this.val=this.val.ev(e),this},e.Filter.prototype.toXML=function(n){e.Reference.data.filter&&(this.key.is==="keyword"&&-1===e.Reference.data.filter.value.indexOf(this.key.toString())&&n.error({message:this.key.toString()+" is not a valid keyword in a filter expression",index:this.index,filename:this.filename}),this.val.is==="keyword"&&-1===e.Reference.data.filter.value.indexOf(this.val.toString())&&n.error({message:this.val.toString()+" is not a valid keyword in a filter expression",index:this.index,filename:this.filename}));var r=this.key.toString(!1),i=this.val.toString(this.val.is=="string");return(t[this.op][1]=="numeric"&&isNaN(i)&&this.val.is!=="field"||t[this.op][1]=="string"&&i[0]!="'")&&n.error({message:'Cannot use operator "'+this.op+'" with value '+this.val,index:this.index,filename:this.filename}),r+t[this.op][0]+i+(t[this.op][2]||"")},e.Filter.prototype.toString=function(){return"["+this.id+"]"}})(e("../tree"))},{"../tree":37}],47:[function(e,t,n){(function(t){var n=e("../tree"),r=t._||e("underscore");n.Filterset=function(){this.filters={}},n.Filterset.prototype.toXML=function(e){var t=[];for(var n in this.filters)t.push("("+this.filters[n].toXML(e).trim()+")");return t.length?" "+t.join(" and ")+"\n":""},n.Filterset.prototype.toString=function(){var e=[];for(var t in this.filters)e.push(this.filters[t].id);return e.sort().join(" ")},n.Filterset.prototype.ev=function(e){for(var t in this.filters)this.filters[t].ev(e);return this},n.Filterset.prototype.clone=function(){var e=new n.Filterset;for(var t in this.filters)e.filters[t]=this.filters[t];return e},n.Filterset.prototype.cloneWith=function(e){var t=[];for(var r in e.filters){var i=this.addable(e.filters[r]);if(i===!1)return!1;i===!0&&t.push(e.filters[r])}if(!t.length)return null;var s=new n.Filterset;for(r in this.filters)s.filters[r]=this.filters[r];while(r=t.shift())s.add(r);return s},n.Filterset.prototype.toJS=function(e){var t={"=":"==="};return r.map(this.filters,function(e){var n=e.op;n in t&&(n=t[n]);var r=e.val;e._val!==undefined&&(r=e._val.toString(!0));var i="data";return i+"['"+e.key.value+"'] "+n+" "+(r.is==="string"?"'"+r.toString().replace(/'/g,"\\'")+"'":r)}).join(" && ")},n.Filterset.prototype.addable=function(e){var t=e.key.toString(),n=e.val.toString();n.match(/^[0-9]+(\.[0-9]*)?$/)&&(n=parseFloat(n));switch(e.op){case"=":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val.toString()!=n?!1:null;if(this.filters[t+"!="+n]!==undefined)return!1;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return!1;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val":if(t+"="in this.filters)return this.filters[t+"="].val<=n?!1:null;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return!1;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val<=n)return!1;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return null;return!0;case">=":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val"]!==undefined&&this.filters[t+">"].val>=n)return null;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>=n)return null;return!0;case"<":if(this.filters[t+"="]!==undefined)return this.filters[t+"="].val>=n?!1:null;if(this.filters[t+">"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>=n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val"]!==undefined&&this.filters[t+">"].val>=n)return!1;if(this.filters[t+">="]!==undefined&&this.filters[t+">="].val>n)return!1;if(this.filters[t+"<"]!==undefined&&this.filters[t+"<"].val<=n)return null;if(this.filters[t+"<="]!==undefined&&this.filters[t+"<="].val<=n)return null;return!0}},n.Filterset.prototype.conflict=function(e){var t=e.key.toString(),n=e.val.toString();return isNaN(parseFloat(n))||(n=parseFloat(n)),e.op==="="&&this.filters[t+"="]!==undefined&&n!=this.filters[t+"="].val.toString()||e.op==="!="&&this.filters[t+"="]!==undefined&&n==this.filters[t+"="].val.toString()||e.op==="="&&this.filters[t+"!="]!==undefined&&n==this.filters[t+"!="].val.toString()?e.toString()+" added to "+this.toString()+" produces an invalid filter":!1},n.Filterset.prototype.add=function(e,t){var n=e.key.toString(),r,i=e.op,s=this.conflict(e),o;if(s)return s;if(i==="="){for(var u in this.filters)this.filters[u].key==n&&delete this.filters[u];this.filters[n+"="]=e}else if(i==="!=")this.filters[n+"!="+e.val]=e;else if(i==="=~")this.filters[n+"=~"+e.val]=e;else if(i===">"){for(var a in this.filters)this.filters[a].key==n&&this.filters[a].val<=e.val&&delete this.filters[a];this.filters[n+">"]=e}else if(i===">="){for(var f in this.filters)o=+this.filters[f].val.toString(),this.filters[f].key==n&&o",this.filters[n+">"]=e):this.filters[n+">="]=e}else if(i==="<"){for(var l in this.filters)o=+this.filters[l].val.toString(),this.filters[l].key==n&&o>=e.val&&delete this.filters[l];this.filters[n+"<"]=e}else if(i==="<="){for(var c in this.filters)o=+this.filters[c].val.toString(),this.filters[c].key==n&&o>e.val&&delete this.filters[c];this.filters[n+"!="+e.val]!==undefined?(delete this.filters[n+"!="+e.val],e.op="<",this.filters[n+"<"]=e):this.filters[n+"<="]=e}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"../tree":37,underscore:71}],48:[function(e,t,n){(function(e){e._getFontSet=function(t,n){var r=n.join("");if(t._fontMap&&t._fontMap[r])return t._fontMap[r];var i=new e.FontSet(t,n);return t.effects.push(i),t._fontMap||(t._fontMap={}),t._fontMap[r]=i,i},e.FontSet=function(t,n){this.fonts=n,this.name="fontset-"+t.effects.length},e.FontSet.prototype.toXML=function(e){return'\n'+this.fonts.map(function(e){return' '}).join("\n")+"\n"}})(e("../tree"))},{"../tree":37}],49:[function(e,t,n){var r=e("../tree");r.FrameOffset=function(e,t,n){t=parseInt(t,10);if(t>r.FrameOffset.max||t<=0)throw{message:"Only frame-offset levels between 1 and "+r.FrameOffset.max+" supported.",index:n};if(e!=="=")throw{message:"only = operator is supported for frame-offset",index:n};return t},r.FrameOffset.max=32,r.FrameOffset.none=0},{"../tree":37}],50:[function(e,t,n){(function(e){e.ImageFilter=function(t,n){this.filter=t,this.args=n||null},e.ImageFilter.prototype={is:"imagefilter",ev:function(){return this},toString:function(){return this.args?this.filter+"("+this.args.join(",")+")":this.filter}}})(e("../tree"))},{"../tree":37}],51:[function(e,t,n){(function(e){e.Invalid=function(t,n,r){this.chunk=t,this.index=n,this.type="syntax",this.message=r||"Invalid code: "+this.chunk},e.Invalid.prototype.is="invalid",e.Invalid.prototype.ev=function(e){return e.error({chunk:this.chunk,index:this.index,type:"syntax",message:this.message||"Invalid code: "+this.chunk}),{is:"undefined"}}})(e("../tree"))},{"../tree":37}],52:[function(e,t,n){(function(e){e.Keyword=function(t){this.value=t;var n={transparent:"color","true":"boolean","false":"boolean"};this.is=n[t]?n[t]:"keyword"},e.Keyword.prototype={ev:function(){return this},toString:function(){return this.value}}})(e("../tree"))},{"../tree":37}],53:[function(e,t,n){(function(e){e.LayerXML=function(t,n){var r=[];for(var i in t.Datasource)r.push('");var s="";for(var o in t.properties)o==="minzoom"?s+=' maxzoom="'+e.Zoom.ranges[t.properties[o]]+'"\n':o==="maxzoom"?s+=' minzoom="'+e.Zoom.ranges[t.properties[o]+1]+'"\n':s+=" "+o+'="'+t.properties[o]+'"\n';return'\n "+n.reverse().map(function(e){return""+e+""}).join("\n ")+(r.length?"\n \n "+r.join("\n ")+"\n \n":"")+" \n"}})(e("../tree"))},{"../tree":37}],54:[function(e,t,n){(function(e){e.Literal=function(t){this.value=t||"",this.is="field"},e.Literal.prototype={toString:function(){return this.value},ev:function(){return this}}})(e("../tree"))},{"../tree":37}],55:[function(e,t,n){(function(e){e.Operation=function(t,n,r){this.op=t.trim(),this.operands=n,this.index=r},e.Operation.prototype.is="operation",e.Operation.prototype.ev=function(t){var n=this.operands[0].ev(t),r=this.operands[1].ev(t),i;return n.is==="undefined"||r.is==="undefined"?{is:"undefined",value:"undefined"}:(n instanceof e.Dimension&&r instanceof e.Color&&(this.op==="*"||this.op==="+"?(i=r,r=n,n=i):t.error({name:"OperationError",message:"Can't substract or divide a color from a number",index:this.index})),n instanceof e.Quoted&&r instanceof e.Quoted&&this.op!=="+"?(t.error({message:"Can't subtract, divide, or multiply strings.",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):n instanceof e.Field||r instanceof e.Field||n instanceof e.Literal||r instanceof e.Literal?n.is==="color"||r.is==="color"?(t.error({message:"Can't subtract, divide, or multiply colors in expressions.",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):new e.Literal(n.ev(t).toString(!0)+this.op+r.ev(t).toString(!0)):n.operate===undefined?(t.error({message:"Cannot do math with type "+n.is+".",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"}):n.operate(t,this.op,r))},e.operate=function(e,t,n){switch(e){case"+":return t+n;case"-":return t-n;case"*":return t*n;case"%":return t%n;case"/":return t/n}}})(e("../tree"))},{"../tree":37}],56:[function(e,t,n){(function(e){e.Quoted=function(t){this.value=t||""},e.Quoted.prototype={is:"string",toString:function(e){var t=this.value.replace(/&/g,"&"),n=t.replace(/\'/g,"\\'").replace(/\"/g,""").replace(//g,">");return e===!0?"'"+n+"'":t},ev:function(){return this},operate:function(t,n,r){return new e.Quoted(e.operate(n,this.toString(),r.toString(this.contains_field)))}}})(e("../tree"))},{"../tree":37}],57:[function(e,t,n){(function(t){(function(n){function s(e){var t={};for(var n in e.symbolizers)for(var r in e.symbolizers[n])e.symbolizers[n][r].hasOwnProperty("css")&&(t[e.symbolizers[n][r].css]=[e.symbolizers[n][r],n,r]);return t}function o(e){var t={};for(var n in e.symbolizers)for(var r in e.symbolizers[n])if(e.symbolizers[n][r].type==="functions")for(var i=0;i1){var f=e._getFontSet(n,this.value.value);return'fontset-name="'+f.name+'"'}return r?this.value.toString(n,this.name,i):e.Reference.selectorName(this.name)+'="'+this.value.toString(n,this.name)+'"'},e.Rule.prototype.ev=function(t){return new e.Rule(this.name,this.value.ev(t),this.index,this.filename)}})(e("../tree"))},{"../tree":37}],59:[function(e,t,n){(function(e){e.Ruleset=function(t,n){this.selectors=t,this.rules=n,this._lookups={}},e.Ruleset.prototype={is:"ruleset",ev:function(t){var n,r=new e.Ruleset(this.selectors,this.rules.slice(0));r.root=this.root,t.frames.unshift(r);for(n=0,rule;n1?Array.prototype.push.apply(r,i.find(new e.Selector(null,null,null,t.elements.slice(1)),n)):r.push(i);break}}}),this._lookups[o]=r)},evZooms:function(t){for(var n=0;n\n"+v+""}})(e("../tree"))}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"../tree":37,underscore:71}],62:[function(e,t,n){(function(e){e.URL=function(t,n){this.value=t,this.paths=n},e.URL.prototype={is:"uri",toString:function(){return this.value.toString()},ev:function(t){return new e.URL(this.value.ev(t),this.paths)}}})(e("../tree"))},{"../tree":37}],63:[function(e,t,n){(function(e){e.Value=function(t){this.value=t},e.Value.prototype={is:"value",ev:function(t){return this.value.length===1?this.value[0].ev(t):new e.Value(this.value.map(function(e){return e.ev(t)}))},toString:function(e,t,n,r){return this.value.map(function(t){return t.toString(e,r)}).join(n||", ")},clone:function(){var t=Object.create(e.Value.prototype);return Array.isArray(t)?t.value=this.value.slice():t.value=this.value,t.is=this.is,t},toJS:function(e){var t=this.ev(e),n=t.toString();return t.is==="color"||t.is==="uri"||t.is==="string"||t.is==="keyword"?n="'"+n+"'":t.is==="field"?n=n.replace(/\[(.*)\]/g,"data['$1']"):t.is==="call"&&(n=JSON.stringify({name:t.name,args:t.args})),"_value = "+n+";"}}})(e("../tree"))},{"../tree":37}],64:[function(e,t,n){(function(e){e.Variable=function(t,n,r){this.name=t,this.index=n,this.filename=r},e.Variable.prototype={is:"variable",toString:function(){return this.name},ev:function(e){var t,n,r=this.name;if(this._css)return this._css;var i=e.frames.filter(function(e){return e.name==this.name}.bind(this));return i.length?i[0].value.ev(e):(e.error({message:"variable "+this.name+" is undefined",index:this.index,type:"runtime",filename:this.filename}),{is:"undefined",value:"undefined"})}}})(e("../tree"))},{"../tree":37}],65:[function(e,t,n){var r=e("../tree");r.Zoom=function(e,t,n){this.op=e,this.value=t,this.index=n},r.Zoom.prototype.setZoom=function(e){return this.zoom=e,this},r.Zoom.prototype.ev=function(e){var t=0,n=Infinity,i=parseInt(this.value.ev(e).toString(),10),s=0;(i>r.Zoom.maxZoom||i<0)&&e.error({message:"Only zoom levels between 0 and "+r.Zoom.maxZoom+" supported.",index:this.index});switch(this.op){case"=":return this.zoom=1<":t=i+1;break;case">=":t=i;break;case"<":n=i-1;break;case"<=":n=i}for(var o=0;o<=r.Zoom.maxZoom;o++)o>=t&&o<=n&&(s|=1<0&&e.push(" "+r.Zoom.ranges[t]+"\n"),n<22&&e.push(" "+r.Zoom.ranges[n+1]+"\n")}return e},r.Zoom.prototype.toString=function(){var e="";for(var t=0;t<=r.Zoom.maxZoom;t++)e+=this.zoom&1<=0.4.x"},homepage:"https://github.com/cartodb/carto#readme",keywords:["css","maps","stylesheets"],licenses:[{type:"Apache"}],main:"./lib/carto/index",man:["./man/carto.1"],name:"carto",optionalDependencies:{},readme:"# CartoCSS\n\n[![Build Status](https://travis-ci.org/CartoDB/carto.png?branch=master)](https://travis-ci.org/CartoDB/carto)\n\nIs as stylesheet renderer for javascript, It's an evolution of the Mapnik renderer from Mapbox.\nPlease, see original [Mapbox repo](http://github.com/mapbox/carto) for more information and credits\n\n## Quick Start\n\n```javascript\n// shader is a CartoCSS object\n\nvar cartocss = [\n '#layer {',\n ' marker-width: [property]',\n ' marker-fill: red',\n '}'\n].join('')\nvar shader = new carto.RendererJS().render(cartocss);\nvar layers = shader.getLayers()\nfor (var i = 0; i < layers.length; ++i) {\n var layer = layers[i];\n console.log(\"layer name: \", layer.fullName())\n console.log(\"- frames: \", layer.frames())\n console.log(\"- attachment: \", layer.attachment())\n\n var layerShader = layer.getStyle({ property: 1 }, { zoom: 10 })\n console.log(layerShader['marker-width']) // 1\n console.log(layerShader['marker-fill']) // #FF0000\n}\n\n```\n\n# API\n\n## RendererJS\n\n### render(cartocss)\n\n## CartoCSS\n\ncompiled cartocss object\n\n### getLayers\n\nreturn the layers, an array of ``CartoCSS.Layer`` object\n\n### getDefault\n\nreturn the default layer (``CartoCSS.Layer``), usually the Map layer\n\n\n### findLayer(where)\n\nfind a layer using where object.\n\n```\nshader.findLayer({ name: 'test' })\n```\n\n## CartoCSS.Layer\n\n### getStyle(props, context)\n\nreturn the evaluated style:\n - props: object containing properties needed to render the style. If the cartocss style uses\n some variables they should be passed in this object\n - context: rendering context variables like ``zoom`` or animation ``frame``\n\n\n\n\n\n\n\n\n\n\n## Reference Documentation\n\n* [mapbox.com/carto](http://mapbox.com/carto/)\n\n\n" +,readmeFilename:"README.md",repository:{type:"git",url:"git+ssh://git@github.com/cartodb/carto.git"},scripts:{coverage:"istanbul cover ./node_modules/.bin/_mocha && coveralls < ./coverage/lcov.info",pretest:"npm install",test:"mocha -R spec"},url:"https://github.com/cartodb/carto",version:"0.15.1-cdb1"}},{}],67:[function(e,t,n){typeof Object.create=="function"?t.exports=function(t,n){t.super_=n,t.prototype=Object.create(n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,n){t.super_=n;var r=function(){};r.prototype=n.prototype,t.prototype=new r,t.prototype.constructor=t}},{}],68:[function(e,t,n){(function(n){var r=e("fs"),i=e("path"),s=e("fs").existsSync||e("path").existsSync;t.exports.version={};var o=["2.0.0","2.0.1","2.0.2","2.1.0","2.1.1","2.2.0","2.3.0","3.0.0"];o.map(function(r){t.exports.version[r]=e(i.join(n,r,"reference.json"));var o=i.join(n,r,"datasources.json");s(o)&&(t.exports.version[r].datasources=e(o).datasources)})}).call(this,"/node_modules/mapnik-reference")},{fs:30,path:69}],69:[function(e,t,n){(function(e){function t(e,t){var n=0;for(var r=e.length-1;r>=0;r--){var i=e[r];i==="."?e.splice(r,1):i===".."?(e.splice(r,1),n++):n&&(e.splice(r,1),n--)}if(t)for(;n--;n)e.unshift("..");return e}function s(e,t){if(e.filter)return e.filter(t);var n=[];for(var r=0;r=-1&&!r;i--){var o=i>=0?arguments[i]:e.cwd();if(typeof o!="string")throw new TypeError("Arguments to path.resolve must be strings");if(!o)continue;n=o+"/"+n,r=o.charAt(0)==="/"}return n=t(s(n.split("/"),function(e){return!!e}),!r).join("/"),(r?"/":"")+n||"."},n.normalize=function(e){var r=n.isAbsolute(e),i=o(e,-1)==="/";return e=t(s(e.split("/"),function(e){return!!e}),!r).join("/"),!e&&!r&&(e="."),e&&i&&(e+="/"),(r?"/":"")+e},n.isAbsolute=function(e){return e.charAt(0)==="/"},n.join=function(){var e=Array.prototype.slice.call(arguments,0);return n.normalize(s(e,function(e,t){if(typeof e!="string")throw new TypeError("Arguments to path.join must be strings");return e}).join("/"))},n.relative=function(e,t){function r(e){var t=0;for(;t=0;n--)if(e[n]!=="")break;return t>n?[]:e.slice(t,n-t+1)}e=n.resolve(e).substr(1),t=n.resolve(t).substr(1);var i=r(e.split("/")),s=r(t.split("/")),o=Math.min(i.length,s.length),u=o;for(var a=0;a0){var n=r.shift();n()}}},!0),function(t){r.push(t),window.postMessage("process-tick","*")}):function(t){setTimeout(t,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.on=i,r.addListener=i,r.once=i,r.off=i,r.removeListener=i,r.removeAllListeners=i,r.emit=i,r.binding=function(e){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(e){throw new Error("process.chdir is not supported")}},{}],71:[function(e,t,n){(function(){function N(e){function t(t,n,r,i,s,o){for(;s>=0&&s0?0:u-1;return arguments.length<3&&(i=n[o?o[a]:a],a+=e),t(n,r,i,o,a,u)}}function L(e){return function(t,n,r){n=y(n,r);var i=x(t),s=e>0?0:i-1;for(;s>=0&&s0?o=s>=0?s:Math.max(s+u,o):u=s>=0?Math.min(s+1,u):s+u+1;else if(n&&s&&u)return s=n(r,i),r[s]===i?s:-1;if(i!==i)return s=t(a.call(r,o,u),m.isNaN),s>=0?s+o:-1;for(s=e>0?o:u-1;s>=0&&s=0&&t<=S};m.each=m.forEach=function(e,t,n){t=g(t,n);var r,i;if(T(e))for(r=0,i=e.length;r=0},m.invoke=function(e,t){var n=a.call(arguments,2),r=m.isFunction(t);return m.map(e,function(e){var i=r?t:e[t];return i==null?i:i.apply(e,n)})},m.pluck=function(e,t){return m.map(e,m.property(t))},m.where=function(e,t){return m.filter(e,m.matcher(t))},m.findWhere=function(e,t){return m.find(e,m.matcher(t))},m.max=function(e,t,n){var r=-Infinity,i=-Infinity,s,o;if(t==null&&e!=null){e=T(e)?e:m.values(e);for(var u=0,a=e.length;ur&&(r=s)}else t=y(t,n),m.each(e,function(e,n,s){o=t(e,n,s);if(o>i||o===-Infinity&&r===-Infinity)r=e,i=o});return r},m.min=function(e,t,n){var r=Infinity,i=Infinity,s,o;if(t==null&&e!=null){e=T(e)?e:m.values(e);for(var u=0,a=e.length;ur||n===void 0)return 1;if(nt?(o&&(clearTimeout(o),o=null),u=f,s=e.apply(r,i),o||(r=i=null)):!o&&n.trailing!==!1&&(o=setTimeout(a,l)),s}},m.debounce=function(e,t,n){var r,i,s,o,u,a=function(){var f=m.now()-o;f=0?r=setTimeout(a,t-f):(r=null,n||(u=e.apply(s,i),r||(s=i=null)))};return function(){s=this,i=arguments,o=m.now();var f=n&&!r;return r||(r=setTimeout(a,t)),f&&(u=e.apply(s,i),s=i=null),u}},m.wrap=function(e,t){return m.partial(t,e)},m.negate=function(e){return function(){return!e.apply(this,arguments)}},m.compose=function(){var e=arguments,t=e.length-1;return function(){var n=t,r=e[t].apply(this,arguments);while(n--)r=e[n].call(this,r);return r}},m.after=function(e,t){return function(){if(--e<1)return t.apply(this,arguments)}},m.before=function(e,t){var n;return function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=null),n}},m.once=m.partial(m.before,2);var M=!{toString:null}.propertyIsEnumerable("toString"),_=["valueOf","isPrototypeOf","toString","propertyIsEnumerable","hasOwnProperty","toLocaleString"];m.keys=function(e){if(!m.isObject(e))return[];if(h)return h(e);var t=[];for(var n in e)m.has(e,n)&&t.push(n);return M&&D(e,t),t},m.allKeys=function(e){if(!m.isObject(e))return[];var t=[];for(var n in e)t.push(n);return M&&D(e,t),t},m.values=function(e){var t=m.keys(e),n=t.length,r=Array(n);for(var i=0;i":">",'"':""","'":"'","`":"`"},B=m.invert(H),j=function(e){var t=function(t){return e[t]},n="(?:"+m.keys(e).join("|")+")",r=RegExp(n),i=RegExp(n,"g");return function(e){return e=e==null?"":""+e,r.test(e)?e.replace(i,t):e}};m.escape=j(H),m.unescape=j(B),m.result=function(e,t,n){var r=e==null?void 0:e[t];return r===void 0&&(r=n),m.isFunction(r)?r.call(e):r};var F=0;m.uniqueId=function(e){var t=++F+"";return e?e+t:t},m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var I=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},R=/\\|'|\r|\n|\u2028|\u2029/g,U=function(e){return"\\"+q[e]};m.template=function(e,t,n){!t&&n&&(t=n),t=m.defaults({},t,m.templateSettings);var r=RegExp([(t.escape||I).source,(t.interpolate||I).source,(t.evaluate||I).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){return s+=e.slice(i,u).replace(R,U),i=u+t.length,n?s+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?s+="'+\n((__t=("+r+"))==null?'':__t)+\n'":o&&(s+="';\n"+o+"\n__p+='"),t}),s+="';\n",t.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(t.variable||"obj","_",s)}catch(u){throw u.source=s,u}var a=function(e){return o.call(this,e,m)},f=t.variable||"obj";return a.source="function("+f+"){\n"+s+"}",a},m.chain=function(e){var t=m(e);return t._chain=!0,t};var z=function(e,t){return e._chain?m(t).chain():t};m.mixin=function(e){m.each(m.functions(e),function(t){var n=m[t]=e[t];m.prototype[t]=function(){var e=[this._wrapped];return u.apply(e,arguments),z(this,n.apply(m,e))}})},m.mixin(m),m.each(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=i[e];m.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e==="shift"||e==="splice")&&n.length===0&&delete n[0],z(this,n)}}),m.each(["concat","join","slice"],function(e){var t=i[e];m.prototype[e]=function(){return z(this,t.apply(this._wrapped,arguments))}}),m.prototype.value=function(){return this._wrapped},m.prototype.valueOf=m.prototype.toJSON=m.prototype.value,m.prototype.toString=function(){return""+this._wrapped},typeof define=="function"&&define.amd&&define("underscore",[],function(){return m})}).call(this)},{}],72:[function(e,t,n){t.exports=function(t){return t&&typeof t=="object"&&typeof t.copy=="function"&&typeof t.fill=="function"&&typeof t.readUInt8=="function"}},{}],73:[function(e,t,n){(function(t,r){function u(e,t){var r={seen:[],stylize:f};return arguments.length>=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),y(t)?r.showHidden=t:t&&n._extend(r,t),T(r.showHidden)&&(r.showHidden=!1),T(r.depth)&&(r.depth=2),T(r.colors)&&(r.colors=!1),T(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=a),c(r,e,r.depth)}function a(e,t){var n=u.styles[t];return n?"["+u.colors[n][0]+"m"+e+"["+u.colors[n][1]+"m":e}function f(e,t){return e}function l(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}function c(e,t,r){if(e.customInspect&&t&&A(t.inspect)&&t.inspect!==n.inspect&&(!t.constructor||t.constructor.prototype!==t)){var i=t.inspect(r,e);return S(i)||(i=c(e,i,r)),i}var s=h(e,t);if(s)return s;var o=Object.keys(t),u=l(o);e.showHidden&&(o=Object.getOwnPropertyNames(t));if(L(t)&&(o.indexOf("message")>=0||o.indexOf("description")>=0))return p(t);if(o.length===0){if(A(t)){var a=t.name?": "+t.name:"";return e.stylize("[Function"+a+"]","special")}if(N(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(k(t))return e.stylize(Date.prototype.toString.call(t),"date");if(L(t))return p(t)}var f="",y=!1,b=["{","}"];g(t)&&(y=!0,b=["[","]"]);if(A(t)){var w=t.name?": "+t.name:"";f=" [Function"+w+"]"}N(t)&&(f=" "+RegExp.prototype.toString.call(t)),k(t)&&(f=" "+Date.prototype.toUTCString.call(t)),L(t)&&(f=" "+p(t));if(o.length!==0||!!y&&t.length!=0){if(r<0)return N(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var E;return y?E=d(e,t,r,u,o):E=o.map(function(n){return v(e,t,r,u,n,y)}),e.seen.pop(),m(E,f,b)}return b[0]+f+b[1]}function h(e,t){if(T(t))return e.stylize("undefined","undefined");if(S(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}if(E(t))return e.stylize(""+t,"number");if(y(t))return e.stylize(""+t,"boolean");if(b(t))return e.stylize("null","null")}function p(e){return"["+Error.prototype.toString.call(e)+"]"}function d(e,t,n,r,i){var s=[];for(var o=0,u=t.length;o-1&&(s?u=u.split("\n").map(function(e){return" "+e}).join("\n").substr(2):u="\n"+u.split("\n").map(function(e){return" "+e}).join("\n"))):u=e.stylize("[Circular]","special"));if(T(o)){if(s&&i.match(/^\d+$/))return u;o=JSON.stringify(""+i),o.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(o=o.substr(1,o.length-2),o=e.stylize(o,"name")):(o=o.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),o=e.stylize(o,"string"))}return o+": "+u}function m(e,t,n){var r=0,i=e.reduce(function(e,t){return r++,t.indexOf("\n")>=0&&r++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0);return i>60?n[0]+(t===""?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1]:n[0]+t+" "+e.join(", ")+" "+n[1]}function g(e){return Array.isArray(e)}function y(e){return typeof e=="boolean"}function b(e){return e===null}function w(e){return e==null}function E(e){return typeof e=="number"}function S(e){return typeof e=="string"}function x(e){return typeof e=="symbol"}function T(e){return e===void 0}function N(e){return C(e)&&M(e)==="[object RegExp]"}function C(e){return typeof e=="object"&&e!==null}function k(e){return C(e)&&M(e)==="[object Date]"}function L(e){return C(e)&&(M(e)==="[object Error]"||e instanceof Error)}function A(e){return typeof e=="function"}function O(e){return e===null||typeof e=="boolean"||typeof e=="number"||typeof e=="string"||typeof e=="symbol"||typeof e=="undefined"}function M(e){return Object.prototype.toString.call(e)}function _(e){return e<10?"0"+e.toString(10):e.toString(10)}function P(){var e=new Date,t=[_(e.getHours()),_(e.getMinutes()),_(e.getSeconds())].join(":");return[e.getDate(),D[e.getMonth()],t].join(" ")}function H(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var i=/%[sdj%]/g;n.format=function(e){if(!S(e)){var t=[];for(var n=0;n=s)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(t){return"[Circular]"};default:return e}});for(var a=r[n];n this.options.bounds[1][0]) this.options.bounds[1][0] = tile.latLonBounds.maxLat; + if (tile.latLonBounds.minLat < this.options.bounds[0][0]) this.options.bounds[0][0] = tile.latLonBounds.minLat; + if (tile.latLonBounds.maxLon > this.options.bounds[1][1]) this.options.bounds[1][1] = tile.latLonBounds.maxLon; + if (tile.latLonBounds.minLon < this.options.bounds[0][1]) this.options.bounds[0][1] = tile.latLonBounds.minLon; + + /* Function to find out if a point falls into this tile */ + tile.contains = function (point) { + return point.lat < tile.latLonBounds.maxLat && point.lat > tile.latLonBounds.minLat && point.lon < tile.latLonBounds.maxLon && point.lon > tile.latLonBounds.minLon; + } + }, + /* + * Get the all the data points, no matter their timestamp, that fall into the tile + */ + getPointsInTile: function (tile) { + var pointsInTile = []; + + for (var i = 0; i < this.points.length; i++) { + if (tile.contains(this.points[i])) { + pointsInTile.push(this.points[i]); + } + } + + return pointsInTile; + }, + processTile: function (tile, pointsInThisTile) { + /* + * For each this.points[i], x[i] and y[i] are the offsets in pixels from the tile boundaries. + */ + var x = []; + var y = []; + + /* + * pointsInTilePerTimestamp: + */ + var pointsInThisTileByTimestamp = []; + + var timeCount = []; + var timeIndex = []; + var renderData = []; + var renderDataPos = []; + + var accumulatedValues = []; + + for (var pointIdx = 0; pointIdx < pointsInThisTile.length; pointIdx++) { + var point = pointsInThisTile[pointIdx]; + + var tileXY = mercatorUtils.latLonToTilePoint(point.lat, point.lon, tile.x, tile.y, tile.zoom); + + var xInTile = tileXY.x; + var yInTile = tileXY.y; + x[pointIdx] = xInTile; + y[pointIdx] = yInTile; + + var pointTimestamp = this.timestamps[point.time]; + + if (this.options.cumulative && this.maxTimestamp > 0) { + if (accumulatedValues[xInTile] === undefined) { + accumulatedValues[xInTile] = []; + } + if (accumulatedValues[xInTile][yInTile] === undefined) { + accumulatedValues[xInTile][yInTile] = 0; + } + accumulatedValues[xInTile][yInTile] += point.value; + point.value = accumulatedValues[xInTile][yInTile]; + for (var futureTimestamps = pointTimestamp; futureTimestamps < this.maxTimestamp; futureTimestamps++) { + var pointsInTileForFutureTimestamp = pointsInThisTileByTimestamp[futureTimestamps] || (pointsInThisTileByTimestamp[futureTimestamps] = []); + pointsInTileForFutureTimestamp.push({idx: pointIdx, value: point.value}); + } + } else { + var pointsInTileForThisTimestamp = pointsInThisTileByTimestamp[pointTimestamp] || (pointsInThisTileByTimestamp[pointTimestamp] = []); + pointsInTileForThisTimestamp.push({idx: pointIdx, value: point.value}); + } + } + + var pointsInThisTileByTimestamp_keys = Object.keys(pointsInThisTileByTimestamp); + var maxTileTimestamp = pointsInThisTileByTimestamp_keys[pointsInThisTileByTimestamp_keys.length - 1] || 0; + + var renderDataIndex = 0; + var timeStampIndex = 0; + for (var timestamp = 0; timestamp <= maxTileTimestamp; timestamp++) { + var pointsInThisTileForThisTimestamp = pointsInThisTileByTimestamp[timestamp]; + if (pointsInThisTileForThisTimestamp) { + for (var i = 0; i < pointsInThisTileForThisTimestamp.length; i++) { + var point = pointsInThisTileForThisTimestamp[i]; + renderDataPos[renderDataIndex] = point.idx; + renderData[renderDataIndex] = point.value; + ++renderDataIndex; + } + } + timeIndex[timestamp] = timeStampIndex; + var increase = pointsInThisTileForThisTimestamp ? pointsInThisTileForThisTimestamp.length : 0; + timeCount[timestamp] = increase; + timeStampIndex += increase; + } + return { + x: x, + y: y, + z: tile.zoom, + coord: { + x: tile.x, + y: tile.y, + z: tile.zoom + }, + timeCount: timeCount, + timeIndex: timeIndex, + renderDataPos: renderDataPos, + renderData: renderData, + maxDate: maxTileTimestamp + }; + }, + getKeySpan: function () { + return { + start: this.options.start, + end: this.options.end, + step: this.options.step || ((this.options.end - this.options.start) / this.getSteps()), + steps: this.getSteps(), + columnType: this.timestampType + }; + }, + getSteps: function () { + return this.options.steps; + }, + setSteps: function(steps, opt) { + opt = opt || {}; + if (this.options.steps !== steps) { + this.options.steps = steps; + this.options.step = (this.options.end - this.options.start) / this.getSteps(); + this.options.step = this.options.step || 1; + if (!opt.silent) this.reload(); + } + } }; -},{"./json":19,"./jsonarray":20,"./windshaft":21}],19:[function(require,module,exports){ +module.exports = internal; + +},{"../":10}],20:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -3677,7 +3988,7 @@ var Profiler = require('../profiler'); module.exports = json; -},{"../":10,"../profiler":17}],20:[function(require,module,exports){ +},{"../":10,"../profiler":17}],21:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -3907,7 +4218,7 @@ var Profiler = require('../profiler'); module.exports = json; -},{"../":10,"../profiler":17}],21:[function(require,module,exports){ +},{"../":10,"../profiler":17}],22:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -4397,7 +4708,7 @@ var Profiler = require('../profiler'); module.exports = windshaft; -},{"../":10,"../profiler":17}],22:[function(require,module,exports){ +},{"../":10,"../profiler":17}],23:[function(require,module,exports){ var TAU = Math.PI*2; // min value to render a line. // it does not make sense to render a line of a width is not even visible @@ -4490,13 +4801,13 @@ module.exports = { MAX_SPRITE_RADIUS: MAX_SPRITE_RADIUS }; -},{}],23:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ module.exports = { cartocss: require('./cartocss_render'), Point: require('./point'), Rectangle: require('./rectangle') }; -},{"./cartocss_render":22,"./point":24,"./rectangle":25}],24:[function(require,module,exports){ +},{"./cartocss_render":23,"./point":25,"./rectangle":26}],25:[function(require,module,exports){ (function (global){ var torque = require('../'); var cartocss = require('./cartocss_render'); @@ -4947,7 +5258,7 @@ var Filters = require('./torque_filters'); module.exports = PointRenderer; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../":10,"../profiler":17,"./cartocss_render":22,"./torque_filters":26,"carto":36}],25:[function(require,module,exports){ +},{"../":10,"../profiler":17,"./cartocss_render":23,"./torque_filters":27,"carto":32}],26:[function(require,module,exports){ (function (global){ var carto = global.carto || require('carto'); @@ -5111,7 +5422,7 @@ var carto = global.carto || require('carto'); module.exports = RectanbleRenderer; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"carto":36}],26:[function(require,module,exports){ +},{"carto":32}],27:[function(require,module,exports){ /* Based on simpleheat, a tiny JavaScript library for drawing heatmaps with Canvas, by Vladimir Agafonkin @@ -5203,7 +5514,7 @@ torque_filters.prototype = { module.exports = torque_filters; -},{}],27:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ (function (global){ var torque = require('./core'); @@ -5307,9 +5618,7 @@ module.exports = { }; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./core":4}],28:[function(require,module,exports){ - -},{}],29:[function(require,module,exports){ +},{"./core":4}],29:[function(require,module,exports){ // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 // // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! @@ -5671,2943 +5980,2378 @@ var objectKeys = Object.keys || function (obj) { return keys; }; -},{"util/":34}],30:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} +},{"util/":73}],30:[function(require,module,exports){ },{}],31:[function(require,module,exports){ -(function (process){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. +(function (tree) { -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c); }); + a = number(a); + if (rgb.some(isNaN) || isNaN(a)) return null; + return new tree.Color(rgb, a); + }, + // Only require val + stop: function (val) { + var color, mode; + if (arguments.length > 1) color = arguments[1]; + if (arguments.length > 2) mode = arguments[2]; - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } + return { + is: 'tag', + val: val, + color: color, + mode: mode, + toString: function(env) { + return '\n\t'; + } + }; + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); + if ([h, s, l, a].some(isNaN)) return null; - return parts; -} + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s, + m1 = l * 2 - m2; -// Split a filename into [root, dir, basename, ext], unix version -// 'root' is just a slash, or nothing. -var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; -var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); -}; + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + if (!('toHSL' in color)) return null; + return new tree.Dimension(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + if (!('toHSL' in color)) return null; + return new tree.Dimension(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + if (!('toHSL' in color)) return null; + return new tree.Dimension(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + if (!('toHSL' in color)) return null; + return new tree.Dimension(color.toHSL().a); + }, + saturate: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + if (!('toHSL' in color)) return null; + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; + hsl.h = hue < 0 ? 360 + hue : hue; - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); + return hsla(hsl); + }, + replace: function (entity, a, b) { + if (entity.is === 'field') { + return entity.toString + '.replace(' + a.toString() + ', ' + b.toString() + ')'; + } else { + return entity.replace(a, b); + } + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; - return (isAbsolute ? '/' : '') + path; -}; + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; + var alpha = color1.alpha * p + color2.alpha * (1 - p); -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); + return new tree.Color(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new tree.Dimension(100)); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%s/, args[i].value) + .replace(/%[da]/, args[i].toString()); + } + str = str.replace(/%%/g, '%'); + return new tree.Quoted(str); } - return p; - }).join('/')); }; +var image_filter_functors = [ + 'emboss', 'blur', 'gray', 'sobel', 'edge-detect', + 'x-gradient', 'y-gradient', 'sharpen']; -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } +for (var i = 0; i < image_filter_functors.length; i++) { + var f = image_filter_functors[i]; + tree.functions[f] = (function(f) { + return function() { + return new tree.ImageFilter(f); + }; + })(f); +} - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } +tree.functions['agg-stack-blur'] = function(x, y) { + return new tree.ImageFilter('agg-stack-blur', [x, y]); +}; - if (start > end) return []; - return arr.slice(start, end - start + 1); - } +tree.functions['scale-hsla'] = function(h0,h1,s0,s1,l0,l1,a0,a1) { + return new tree.ImageFilter('scale-hsla', [h0,h1,s0,s1,l0,l1,a0,a1]); +}; - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); +function hsla(h) { + return tree.functions.hsla(h.h, h.s, h.l, h.a); +} - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + return NaN; } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } +} - outputParts = outputParts.concat(toParts.slice(samePartsLength)); +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} - return outputParts.join('/'); -}; +})(require('./tree')); -exports.sep = '/'; -exports.delimiter = ':'; +},{"./tree":37}],32:[function(require,module,exports){ +(function (process,__dirname){ +var util = require('util'), + fs = require('fs'), + path = require('path'); -exports.dirname = function(path) { - var result = splitPath(path), - root = result[0], - dir = result[1]; - if (!root && !dir) { - // No dirname whatsoever - return '.'; - } +function getVersion() { + if (process.browser) { + return require('../../package.json').version.split('.'); + } else if (parseInt(process.version.split('.')[1], 10) > 4) { + return require('../../package.json').version.split('.'); + } else { + // older node + var package_json = JSON.parse(fs.readFileSync(path.join(__dirname,'../../package.json'))); + return package_json.version.split('.'); + } +} - if (dir) { - // It has a dirname, strip trailing slash - dir = dir.substr(0, dir.length - 1); - } +var carto = { + version: getVersion(), + Parser: require('./parser').Parser, + Renderer: require('./renderer').Renderer, + tree: require('./tree'), + RendererJS: require('./renderer_js'), + default_reference: require('./torque-reference'), - return root + dir; -}; + // @TODO + writeError: function(ctx, options) { + var message = ''; + var extract = ctx.extract; + var error = []; + options = options || {}; -exports.basename = function(path, ext) { - var f = splitPath(path)[2]; - // TODO: make this comparison case-insensitive on windows? - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; + if (options.silent) { return; } + options.indent = options.indent || ''; -exports.extname = function(path) { - return splitPath(path)[3]; -}; + if (!('index' in ctx) || !extract) { + return util.error(options.indent + (ctx.stack || ctx.message)); + } -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} + if (typeof(extract[0]) === 'string') { + error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); + } -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; + if (extract[1] === '' && typeof extract[2] === 'undefined') { + extract[1] = '¶'; + } + error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) + + stylize(stylize(extract[1][ctx.column], 'bold') + + extract[1].slice(ctx.column + 1), 'yellow')); -}).call(this,require('_process')) -},{"_process":32}],32:[function(require,module,exports){ -// shim for using process in browser + if (typeof(extract[2]) === 'string') { + error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); + } + error = options.indent + error.join('\n' + options.indent) + '\033[0m\n'; -var process = module.exports = {}; + message = options.indent + message + stylize(ctx.message, 'red'); + if (ctx.filename) (message += stylize(' in ', 'red') + ctx.filename); -process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canMutationObserver = typeof window !== 'undefined' - && window.MutationObserver; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; + util.error(message, error); - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; + if (ctx.callLine) { + util.error(stylize('from ', 'red') + (ctx.filename || '')); + util.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract); + } + if (ctx.stack) { util.error(stylize(ctx.stack, 'red')); } } +}; - var queue = []; +require('./tree/call'); +require('./tree/color'); +require('./tree/comment'); +require('./tree/definition'); +require('./tree/dimension'); +require('./tree/element'); +require('./tree/expression'); +require('./tree/filterset'); +require('./tree/filter'); +require('./tree/field'); +require('./tree/keyword'); +require('./tree/layer'); +require('./tree/literal'); +require('./tree/operation'); +require('./tree/quoted'); +require('./tree/imagefilter'); +require('./tree/reference'); +require('./tree/rule'); +require('./tree/ruleset'); +require('./tree/selector'); +require('./tree/style'); +require('./tree/url'); +require('./tree/value'); +require('./tree/variable'); +require('./tree/zoom'); +require('./tree/invalid'); +require('./tree/fontset'); +require('./tree/frame_offset'); +require('./functions'); - if (canMutationObserver) { - var hiddenDiv = document.createElement("div"); - var observer = new MutationObserver(function () { - var queueList = queue.slice(); - queue.length = 0; - queueList.forEach(function (fn) { - fn(); - }); - }); +for (var k in carto) { exports[k] = carto[k]; } - observer.observe(hiddenDiv, { attributes: true }); +// Stylize a string +function stylize(str, style) { + var styles = { + 'bold' : [1, 22], + 'inverse' : [7, 27], + 'underline' : [4, 24], + 'yellow' : [33, 39], + 'green' : [32, 39], + 'red' : [31, 39], + 'grey' : [90, 39] + }; + return '\033[' + styles[style][0] + 'm' + str + + '\033[' + styles[style][1] + 'm'; +} - return function nextTick(fn) { - if (!queue.length) { - hiddenDiv.setAttribute('yes', 'no'); - } - queue.push(fn); - }; - } +}).call(this,require('_process'),"/node_modules/carto/lib/carto") +},{"../../package.json":66,"./functions":31,"./parser":33,"./renderer":34,"./renderer_js":35,"./torque-reference":36,"./tree":37,"./tree/call":38,"./tree/color":39,"./tree/comment":40,"./tree/definition":41,"./tree/dimension":42,"./tree/element":43,"./tree/expression":44,"./tree/field":45,"./tree/filter":46,"./tree/filterset":47,"./tree/fontset":48,"./tree/frame_offset":49,"./tree/imagefilter":50,"./tree/invalid":51,"./tree/keyword":52,"./tree/layer":53,"./tree/literal":54,"./tree/operation":55,"./tree/quoted":56,"./tree/reference":57,"./tree/rule":58,"./tree/ruleset":59,"./tree/selector":60,"./tree/style":61,"./tree/url":62,"./tree/value":63,"./tree/variable":64,"./tree/zoom":65,"_process":70,"fs":30,"path":69,"util":73}],33:[function(require,module,exports){ +(function (global){ +var carto = exports, + tree = require('./tree'), + _ = global._ || require('underscore'); - if (canPost) { - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. +carto.Parser = function Parser(env) { + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } + var that = this; - return function nextTick(fn) { - setTimeout(fn, 0); - }; -})(); + // This function is called after all files + // have been imported through `@import`. + var finish = function() {}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; + function save() { + temp = chunks[j]; + memo = i; + current = i; + } + function restore() { + chunks[j] = temp; + i = memo; + current = i; + } -function noop() {} + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k; -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; + // Non-terminal + if (tok instanceof Function) { + return tok.call(parser.parsers); + // Terminal + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync(); + } else { + sync(); -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; + match = tok.exec(chunks[j]); + if (match) { + length = match[0].length; + } else { + return null; + } + } -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + if (match) { + var mem = i += length; + endIndex = i + chunks[j].length - length; -},{}],33:[function(require,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],34:[function(require,module,exports){ -(function (process,global){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break; } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } + if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; + if (typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; - } else { - str += ' ' + inspect(x); } - } - return str; -}; + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + return !!tok.test(chunks[j]); + } + } -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } + function extractErrorLine(style, errorIndex) { + return (style.slice(0, errorIndex).match(/\n/g) || '').length + 1; + } - if (process.noDeprecation === true) { - return fn; - } - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } + // Make an error object from a passed set of properties. + // Accepted properties: + // - `message`: Text of the error message. + // - `filename`: Filename where the error occurred. + // - `index`: Char. index where the error occurred. + function makeError(err) { + var einput; + var errorTemplate; - return deprecated; -}; + _.defaults(err, { + index: furthest, + filename: env.filename, + message: 'Parse error.', + line: 0, + column: -1 + }); + if (err.filename && that.env.inputs && that.env.inputs[err.filename]) { + einput = that.env.inputs[err.filename]; + } else { + einput = input; + } -var debugs = {}; -var debugEnviron; -exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; + err.line = extractErrorLine(einput, err.index); + for (var n = err.index; n >= 0 && einput.charAt(n) !== '\n'; n--) { + err.column++; + } + errorTemplate = _.template('<%=filename%>:<%=line%>:<%=column%> <%=message%>'); + return new Error(errorTemplate(err)); } - } - return debugs[set]; -}; + this.env = env = env || {}; + this.env.filename = this.env.filename || null; + this.env.inputs = this.env.inputs || {}; -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; + // The Parser + parser = { + extractErrorLine: extractErrorLine, + // + // Parse an input string into an abstract syntax tree. + // Throws an error on parse errors. + parse: function(str) { + var root, start, end, zone, line, lines, buff = [], c, error = null; -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; + i = j = current = furthest = 0; + chunks = []; + input = str.replace(/\r\n/g, '\n'); + if (env.filename) { + that.env.inputs[env.filename] = input; + } -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; + var early_exit = false; + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } -function stylizeNoColor(str, styleType) { - return str; -} + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break; } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break; } + case '(': if (! inParam) { inParam = true; chunk.push(c); break; } + case ')': if ( inParam) { inParam = false; chunk.push(c); break; } + default: chunk.push(c); + } + i++; + } + if (level !== 0) { + error = { + index: i - 1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`" + }; + } -function arrayToHash(array) { - var hash = {}; + return chunks.map(function (c) { return c.join(''); }); + })([[]]); - array.forEach(function(val, idx) { - hash[val] = true; - }); + if (error) { + throw makeError(error); + } - return hash; -} + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. + root = new tree.Ruleset([], $(this.parsers.primary)); + root.root = true; + // Get an array of Ruleset objects, flattened + // and sorted according to specificitySort + root.toList = (function() { + var line, lines, column; + return function(env) { + env.error = function(e) { + if (!env.errors) env.errors = new Error(''); + if (env.errors.message) { + env.errors.message += '\n' + makeError(e).message; + } else { + env.errors.message = makeError(e).message; + } + }; + env.frames = env.frames || []; -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } + // call populates Invalid-caused errors + var definitions = this.flatten([], [], env); + definitions.sort(specificitySort); + return definitions; + }; + })(); - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); + // Sort rules by specificity: this function expects selectors to be + // split already. + // + // Written to be used as a .sort(Function); + // argument. + // + // [1, 0, 0, 467] > [0, 0, 1, 520] + var specificitySort = function(a, b) { + var as = a.specificity; + var bs = b.specificity; - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } + if (as[0] != bs[0]) return bs[0] - as[0]; + if (as[1] != bs[1]) return bs[1] - as[1]; + if (as[2] != bs[2]) return bs[2] - as[2]; + return bs[3] - as[3]; + }; - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } + return root; + }, - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + parsers: { + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + primary: function() { + var node, root = []; - var base = '', array = false, braces = ['{', '}']; + while ((node = $(this.rule) || $(this.ruleset) || + $(this.comment)) || + $(/^[\s\n]+/) || (node = $(this.invalid))) { + if (node) root.push(node); + } + return root; + }, - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } + invalid: function () { + var chunk = $(/^[^;\n]*[;\n]/); - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } + // To fail gracefully, match everything until a semicolon or linebreak. + if (chunk) { + return new tree.Invalid(chunk, memo); + } + }, - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function() { + var comment; - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } + if (input.charAt(i) !== '/') return; - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } + if (input.charAt(i + 1) === '/') { + return new tree.Comment($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new tree.Comment(comment); + } + }, - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } + // Entities are tokens which can be found inside an Expression + entities: { - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } + // A string, which supports escaping " and ' "milky way" 'he\'s the one!' + quoted: function() { + if (input.charAt(i) !== '"' && input.charAt(i) !== "'") return; + var str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/); + if (str) { + return new tree.Quoted(str[1] || str[2]); + } + }, - ctx.seen.push(value); + // A reference to a Mapnik field, like [NAME] + // Behind the scenes, this has the same representation, but Carto + // needs to be careful to warn when unsupported operations are used. + field: function() { + if (! $('[')) return; + var field_name = $(/(^[^\]]+)/); + if (! $(']')) return; + if (field_name) return new tree.Field(field_name[1]); + }, - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - - ctx.seen.pop(); + // This is a comparison operator + comparison: function() { + var str = $(/^=~|=|!=|<=|>=|<|>/); + if (str) { + return str; + } + }, - return reduceToSingleString(output, base, braces); -} + // A catch-all word, such as: hard-light + // These can start with either a letter or a dash (-), + // and then contain numbers, underscores, and letters. + keyword: function() { + var k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/); + if (k) { return new tree.Keyword(k); } + }, + // A function call like rgb(255, 0, 255) + // The arguments are parsed with the `entities.arguments` parser. + call: function() { + var name, args; -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} + if (!(name = /^([\w\-]+|%)\(/.exec(chunks[j]))) return; + name = name[1]; -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} + if (name === 'url') { + // url() is handled by the url parser instead + return null; + } else { + i += name.length; + } + $('('); // Parse the '(' and consume whitespace. -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} + args = $(this.entities['arguments']); + if (!$(')')) return; -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } + if (name) { + return new tree.Call(name, args, i); + } + }, + // Arguments are comma-separated expressions + 'arguments': function() { + var args = [], arg; - return name + ': ' + str; -} + while (arg = $(this.expression)) { + args.push(arg); + if (! $(',')) { break; } + } + return args; + }, + literal: function() { + return $(this.entities.dimension) || + $(this.entities.keywordcolor) || + $(this.entities.hexcolor) || + $(this.entities.quoted); + }, -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + url: function() { + var value; - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^[\-\w%@$\/.&=:;#+?~]+/) || ''; + if (! $(')')) { + return new tree.Invalid(value, memo, 'Missing closing ) in URL.'); + } else { + return new tree.URL((typeof value.value !== 'undefined' || + value instanceof tree.Variable) ? + value : new tree.Quoted(value)); + } + }, - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + variable: function() { + var name, index = i; + if (input.charAt(i) === '@' && (name = $(/^@[\w-]+/))) { + return new tree.Variable(name, index, env.filename); + } + }, -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; + hexcolor: function() { + var rgb; + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new tree.Color(rgb[1]); + } + }, -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; + keywordcolor: function() { + var rgb = chunks[j].match(/^[a-z]+/); + if (rgb && rgb[0] in tree.Reference.data.colors) { + return new tree.Color(tree.Reference.data.colors[$(/^[a-z]+/)]); + } + }, -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; + // A Dimension, that is, a number and a unit. The only + // unit that has an effect is % + dimension: function() { + var c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + var value = $(/^(-?\d*\.?\d+(?:[eE][-+]?\d+)?)(\%|\w+)?/); + if (value) { + return new tree.Dimension(value[1], value[2], memo); + } + } -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; + }, -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; + // The variable part of a variable definition. + // Used in the `rule` parser. Like @fink: + variable: function() { + var name; -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { + return name[1]; + } + }, -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + entity: function() { + return $(this.entities.call) || + $(this.entities.literal) || + $(this.entities.field) || + $(this.entities.variable) || + $(this.entities.url) || + $(this.entities.keyword); + }, -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + end: function() { + return $(';') || peek('}'); + }, -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; + // Elements are the building blocks for Selectors. They consist of + // an element name, such as a tag a class, or `*`. + element: function() { + var e = $(/^(?:[.#][\w\-]+|\*|Map)/); + if (e) return new tree.Element(e); + }, -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; + // Attachments allow adding multiple lines, polygons etc. to an + // object. There can only be one attachment per selector. + attachment: function() { + var s = $(/^::([\w\-]+(?:\/[\w\-]+)*)/); + if (s) return s[1]; + }, -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; + // Selectors are made out of one or more Elements, see above. + selector: function() { + var a, attachment, + e, elements = [], + f, filters = new tree.Filterset(), + z, zooms = [], + frame_offset = tree.FrameOffset.none; + segments = 0, conditions = 0; -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; + while ( + (e = $(this.element)) || + (z = $(this.zoom)) || + (fo = $(this.frame_offset)) || + (f = $(this.filter)) || + (a = $(this.attachment)) + ) { + segments++; + if (e) { + elements.push(e); + } else if (z) { + zooms.push(z); + conditions++; + } else if (fo) { + frame_offset = fo; + conditions++; + } else if (f) { + var err = filters.add(f); + if (err) { + throw makeError({ + message: err, + index: i - 1 + }); + } + conditions++; + } else if (attachment) { + throw makeError({ + message: 'Encountered second attachment name.', + index: i - 1 + }); + } else { + attachment = a; + } -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; + var c = input.charAt(i); + if (c === '{' || c === '}' || c === ';' || c === ',') { break; } + } -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; + if (segments) { + return new tree.Selector(filters, zooms, frame_offset, elements, attachment, conditions, memo); + } + }, -exports.isBuffer = require('./support/isBuffer'); + filter: function() { + save(); + var key, op, val; + if (! $('[')) return; + if (key = $(/^[a-zA-Z0-9\-_]+/) || + $(this.entities.quoted) || + $(this.entities.variable) || + $(this.entities.keyword) || + $(this.entities.field)) { + // TODO: remove at 1.0.0 + if (key instanceof tree.Quoted) { + key = new tree.Field(key.toString()); + } + if ((op = $(this.entities.comparison)) && + (val = $(this.entities.quoted) || + $(this.entities.variable) || + $(this.entities.dimension) || + $(this.entities.keyword) || + $(this.entities.field))) { + if (! $(']')) { + throw makeError({ + message: 'Missing closing ] of filter.', + index: memo - 1 + }); + } + if (!key.is) key = new tree.Field(key); + return new tree.Filter(key, op, val, memo, env.filename); + } + } + }, -function objectToString(o) { - return Object.prototype.toString.call(o); -} + frame_offset: function() { + save(); + var op, val; + if ($(/^\[\s*frame-offset/g) && + (op = $(this.entities.comparison)) && + (val = $(/^\d+/)) && + $(']')) { + return tree.FrameOffset(op, val, memo); + } + }, + zoom: function() { + save(); + var op, val; + if ($(/^\[\s*zoom/g) && + (op = $(this.entities.comparison)) && + (val = $(this.entities.variable) || $(this.entities.dimension)) && $(']')) { + return new tree.Zoom(op, val, memo); + } else { + // backtrack + restore(); + } + }, -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} + // The `block` rule is used by `ruleset` + // It's a wrapper around the `primary` rule, with added `{}`. + block: function() { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; + // div, .class, body > p {...} + ruleset: function() { + var selectors = [], s, f, l, rules, filters = []; + save(); -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} + while (s = $(this.selector)) { + selectors.push(s); + while ($(this.comment)) {} + if (! $(',')) { break; } + while ($(this.comment)) {} + } + if (s) { + while ($(this.comment)) {} + } + if (selectors.length > 0 && (rules = $(this.block))) { + if (selectors.length === 1 && + selectors[0].elements.length && + selectors[0].elements[0].value === 'Map') { + var rs = new tree.Ruleset(selectors, rules); + rs.isMap = true; + return rs; + } + return new tree.Ruleset(selectors, rules); + } else { + // Backtrack + restore(); + } + }, -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); -}; + rule: function() { + var name, value, c = input.charAt(i); + save(); + if (c === '.' || c === '#') { return; } -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = require('inherits'); + if (name = $(this.variable) || $(this.property)) { + value = $(this.value); -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; + if (value && $(this.end)) { + return new tree.Rule(name, value, memo, env.filename); + } else { + furthest = i; + restore(); + } + } + }, - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; + font: function() { + var value = [], expression = [], weight, font, e; -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} + while (e = $(this.entity)) { + expression.push(e); + } -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":33,"_process":32,"inherits":30}],35:[function(require,module,exports){ -(function (tree) { + value.push(new tree.Expression(expression)); -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c); }); - a = number(a); - if (rgb.some(isNaN) || isNaN(a)) return null; - return new tree.Color(rgb, a); - }, - // Only require val - stop: function (val) { - var color, mode; - if (arguments.length > 1) color = arguments[1]; - if (arguments.length > 2) mode = arguments[2]; + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break; } + } + } + return new tree.Value(value); + }, - return { - is: 'tag', - val: val, - color: color, - mode: mode, - toString: function(env) { - return '\n\t'; - } - }; - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - if ([h, s, l, a].some(isNaN)) return null; + // A Value is a comma-delimited list of Expressions + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + value: function() { + var e, expressions = []; - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s, - m1 = l * 2 - m2; + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); + if (expressions.length > 1) { + return new tree.Value(expressions.map(function(e) { + return e.value[0]; + })); + } else if (expressions.length === 1) { + return new tree.Value(expressions); + } + }, + // A sub-expression, contained by parenthensis + sub: function() { + var e, expressions = []; - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - if (!('toHSL' in color)) return null; - return new tree.Dimension(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - if (!('toHSL' in color)) return null; - return new tree.Dimension(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - if (!('toHSL' in color)) return null; - return new tree.Dimension(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - if (!('toHSL' in color)) return null; - return new tree.Dimension(color.toHSL().a); - }, - saturate: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + if ($('(')) { + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break; } + } + $(')'); + } - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + if (expressions.length > 1) { + return new tree.Value(expressions.map(function(e) { + return e.value[0]; + })); + } else if (expressions.length === 1) { + return new tree.Value(expressions); + } + }, + // This is a misnomer because it actually handles multiplication + // and division. + multiplication: function() { + var m, a, op, operation; + if (m = $(this.operand)) { + while ((op = ($('/') || $('*') || $('%'))) && (a = $(this.operand))) { + operation = new tree.Operation(op, [operation || m, a], memo); + } + return operation || m; + } + }, + addition: function() { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new tree.Operation(op, [operation || m, a], memo); + } + return operation || m; + } + }, - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + operand: function() { + return $(this.sub) || $(this.entity); + }, - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + // Expressions either represent mathematical operations, + // or white-space delimited Entities. @var * 2 + expression: function() { + var e, delim, entities = [], d; - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); + if (entities.length > 0) { + return new tree.Expression(entities); + } + }, + property: function() { + var name = $(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/); + if (name) return name[1]; + } + } + }; + return parser; +}; - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - if (!('toHSL' in color)) return null; - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./tree":37,"underscore":71}],34:[function(require,module,exports){ +(function (global){ +var _ = global._ || require('underscore'); +var carto = require('./index'); - hsl.h = hue < 0 ? 360 + hue : hue; +carto.Renderer = function Renderer(env, options) { + this.env = env || {}; + this.options = options || {}; + this.options.mapnik_version = this.options.mapnik_version || '3.0.0'; +}; - return hsla(hsl); - }, - replace: function (entity, a, b) { - if (entity.is === 'field') { - return entity.toString + '.replace(' + a.toString() + ', ' + b.toString() + ')'; - } else { - return entity.replace(a, b); - } - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; +/** + * Prepare a MSS document (given as an string) into a + * XML Style fragment (mostly useful for debugging) + * + * @param {String} data the mss contents as a string. + */ +carto.Renderer.prototype.renderMSS = function render(data) { + // effects is a container for side-effects, which currently + // are limited to FontSets. + var env = _.defaults(this.env, { + benchmark: false, + validation_data: false, + effects: [] + }); - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; + if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) { + throw new Error("Could not set mapnik version to " + this.options.mapnik_version); + } - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; + var output = []; + var styles = []; - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new tree.Color(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new tree.Dimension(100)); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%s/, args[i].value) - .replace(/%[da]/, args[i].toString()); - } - str = str.replace(/%%/g, '%'); - return new tree.Quoted(str); - } -}; + if (env.benchmark) console.time('Parsing MSS'); + var parser = (carto.Parser(env)).parse(data); + if (env.benchmark) console.timeEnd('Parsing MSS'); -var image_filter_functors = [ - 'emboss', 'blur', 'gray', 'sobel', 'edge-detect', - 'x-gradient', 'y-gradient', 'sharpen']; + if (env.benchmark) console.time('Rule generation'); + var rule_list = parser.toList(env); + if (env.benchmark) console.timeEnd('Rule generation'); -for (var i = 0; i < image_filter_functors.length; i++) { - var f = image_filter_functors[i]; - tree.functions[f] = (function(f) { - return function() { - return new tree.ImageFilter(f); - }; - })(f); -} + if (env.benchmark) console.time('Rule inheritance'); + var rules = inheritDefinitions(rule_list, env); + if (env.benchmark) console.timeEnd('Rule inheritance'); -tree.functions['agg-stack-blur'] = function(x, y) { - return new tree.ImageFilter('agg-stack-blur', [x, y]); -}; + if (env.benchmark) console.time('Style sort'); + var sorted = sortStyles(rules,env); + if (env.benchmark) console.timeEnd('Style sort'); -tree.functions['scale-hsla'] = function(h0,h1,s0,s1,l0,l1,a0,a1) { - return new tree.ImageFilter('scale-hsla', [h0,h1,s0,s1,l0,l1,a0,a1]); + if (env.benchmark) console.time('Total Style generation'); + for (var k = 0, rule, style_name; k < sorted.length; k++) { + rule = sorted[k]; + style_name = 'style' + (rule.attachment !== '__default__' ? '-' + rule.attachment : ''); + styles.push(style_name); + var bench_name = '\tStyle "'+style_name+'" (#'+k+') toXML'; + if (env.benchmark) console.time(bench_name); + // env.effects can be modified by this call + output.push(carto.tree.StyleXML(style_name, rule.attachment, rule, env)); + if (env.benchmark) console.timeEnd(bench_name); + } + if (env.benchmark) console.timeEnd('Total Style generation'); + if (env.errors) throw env.errors; + return output.join('\n'); }; -function hsla(h) { - return tree.functions.hsla(h.h, h.s, h.l, h.a); -} +/** + * Prepare a MML document (given as an object) into a + * fully-localized XML file ready for Mapnik2 consumption + * + * @param {String} m - the JSON file as a string. + */ +carto.Renderer.prototype.render = function render(m) { + // effects is a container for side-effects, which currently + // are limited to FontSets. + var env = _.defaults(this.env, { + benchmark: false, + validation_data: false, + effects: [], + ppi: 90.714 + }); -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - return NaN; + if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) { + throw new Error("Could not set mapnik version to " + this.options.mapnik_version); } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} -})(require('./tree')); + var output = []; -},{"./tree":41}],36:[function(require,module,exports){ -(function (process,__dirname){ -var util = require('util'), - fs = require('fs'), - path = require('path'); + // Transform stylesheets into definitions. + var definitions = _.chain(m.Stylesheet) + .map(function(s) { + if (typeof s == 'string') { + throw new Error("Stylesheet object is expected not a string: '" + s + "'"); + } + // Passing the environment from stylesheet to stylesheet, + // allows frames and effects to be maintained. + env = _.extend(env, {filename:s.id}); + var time = +new Date(), + root = (carto.Parser(env)).parse(s.data); + if (env.benchmark) + console.warn('Parsing time: ' + (new Date() - time) + 'ms'); + return root.toList(env); + }) + .flatten() + .value(); -function getVersion() { - if (process.browser) { - return require('../../package.json').version.split('.'); - } else if (parseInt(process.version.split('.')[1], 10) > 4) { - return require('../../package.json').version.split('.'); - } else { - // older node - var package_json = JSON.parse(fs.readFileSync(path.join(__dirname,'../../package.json'))); - return package_json.version.split('.'); + function appliesTo(name, classIndex) { + return function(definition) { + return definition.appliesTo(l.name, classIndex); + }; } -} - -var carto = { - version: getVersion(), - Parser: require('./parser').Parser, - Renderer: require('./renderer').Renderer, - tree: require('./tree'), - RendererJS: require('./renderer_js'), - default_reference: require('./torque-reference'), - - // @TODO - writeError: function(ctx, options) { - var message = ''; - var extract = ctx.extract; - var error = []; - - options = options || {}; - - if (options.silent) { return; } - options.indent = options.indent || ''; + // Iterate through layers and create styles custom-built + // for each of them, and apply those styles to the layers. + var styles, l, classIndex, rules, sorted, matching; + for (var i = 0; i < m.Layer.length; i++) { + l = m.Layer[i]; + styles = []; + classIndex = {}; - if (!('index' in ctx) || !extract) { - return util.error(options.indent + (ctx.stack || ctx.message)); + if (env.benchmark) console.warn('processing layer: ' + l.id); + // Classes are given as space-separated alphanumeric strings. + var classes = (l['class'] || '').split(/\s+/g); + for (var j = 0; j < classes.length; j++) { + classIndex[classes[j]] = true; } + matching = definitions.filter(appliesTo(l.name, classIndex)); + rules = inheritDefinitions(matching, env); + sorted = sortStyles(rules, env); - if (typeof(extract[0]) === 'string') { - error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); - } + for (var k = 0, rule, style_name; k < sorted.length; k++) { + rule = sorted[k]; + style_name = l.name + (rule.attachment !== '__default__' ? '-' + rule.attachment : ''); - if (extract[1] === '' && typeof extract[2] === 'undefined') { - extract[1] = '¶'; - } - error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) + - stylize(stylize(extract[1][ctx.column], 'bold') + - extract[1].slice(ctx.column + 1), 'yellow')); + // env.effects can be modified by this call + var styleXML = carto.tree.StyleXML(style_name, rule.attachment, rule, env); - if (typeof(extract[2]) === 'string') { - error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); + if (styleXML) { + output.push(styleXML); + styles.push(style_name); + } } - error = options.indent + error.join('\n' + options.indent) + '\033[0m\n'; - - message = options.indent + message + stylize(ctx.message, 'red'); - if (ctx.filename) (message += stylize(' in ', 'red') + ctx.filename); - - util.error(message, error); - if (ctx.callLine) { - util.error(stylize('from ', 'red') + (ctx.filename || '')); - util.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract); - } - if (ctx.stack) { util.error(stylize(ctx.stack, 'red')); } + output.push(carto.tree.LayerXML(l, styles)); } -}; -require('./tree/call'); -require('./tree/color'); -require('./tree/comment'); -require('./tree/definition'); -require('./tree/dimension'); -require('./tree/element'); -require('./tree/expression'); -require('./tree/filterset'); -require('./tree/filter'); -require('./tree/field'); -require('./tree/keyword'); -require('./tree/layer'); -require('./tree/literal'); -require('./tree/operation'); -require('./tree/quoted'); -require('./tree/imagefilter'); -require('./tree/reference'); -require('./tree/rule'); -require('./tree/ruleset'); -require('./tree/selector'); -require('./tree/style'); -require('./tree/url'); -require('./tree/value'); -require('./tree/variable'); -require('./tree/zoom'); -require('./tree/invalid'); -require('./tree/fontset'); -require('./tree/frame_offset'); -require('./functions'); + output.unshift(env.effects.map(function(e) { + return e.toXML(env); + }).join('\n')); -for (var k in carto) { exports[k] = carto[k]; } + var map_properties = getMapProperties(m, definitions, env); -// Stylize a string -function stylize(str, style) { - var styles = { - 'bold' : [1, 22], - 'inverse' : [7, 27], - 'underline' : [4, 24], - 'yellow' : [33, 39], - 'green' : [32, 39], - 'red' : [31, 39], - 'grey' : [90, 39] - }; - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; -} + // Exit on errors. + if (env.errors) throw env.errors; -}).call(this,require('_process'),"/node_modules/carto/lib/carto") -},{"../../package.json":72,"./functions":35,"./parser":37,"./renderer":38,"./renderer_js":39,"./torque-reference":40,"./tree":41,"./tree/call":42,"./tree/color":43,"./tree/comment":44,"./tree/definition":45,"./tree/dimension":46,"./tree/element":47,"./tree/expression":48,"./tree/field":49,"./tree/filter":50,"./tree/filterset":51,"./tree/fontset":52,"./tree/frame_offset":53,"./tree/imagefilter":54,"./tree/invalid":55,"./tree/keyword":56,"./tree/layer":57,"./tree/literal":58,"./tree/operation":59,"./tree/quoted":60,"./tree/reference":61,"./tree/rule":62,"./tree/ruleset":63,"./tree/selector":64,"./tree/style":65,"./tree/url":66,"./tree/value":67,"./tree/variable":68,"./tree/zoom":69,"_process":32,"fs":28,"path":31,"util":34}],37:[function(require,module,exports){ -(function (global){ -var carto = exports, - tree = require('./tree'), - _ = global._ || require('underscore'); + // Pass TileJSON and other custom parameters through to Mapnik XML. + var parameters = _.reduce(m, function(memo, v, k) { + if (!v && v !== 0) return memo; -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -carto.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; + switch (k) { + // Known skippable properties. + case 'srs': + case 'Layer': + case 'Stylesheet': + break; + // Non URL-bound TileJSON properties. + case 'bounds': + case 'center': + case 'minzoom': + case 'maxzoom': + case 'version': + memo.push(' ' + v + ''); + break; + // Properties that require CDATA. + case 'name': + case 'description': + case 'legend': + case 'attribution': + case 'template': + memo.push(' '); + break; + // Mapnik image format. + case 'format': + memo.push(' ' + v + ''); + break; + // Mapnik interactivity settings. + case 'interactivity': + memo.push(' ' + v.layer + ''); + memo.push(' ' + v.fields + ''); + break; + // Support any additional scalar properties. + default: + if ('string' === typeof v) { + memo.push(' '); + } else if ('number' === typeof v) { + memo.push(' ' + v + ''); + } else if ('boolean' === typeof v) { + memo.push(' ' + v + ''); + } + break; + } + return memo; + }, []); + if (parameters.length) output.unshift( + '\n' + + parameters.join('\n') + + '\n\n' + ); - var that = this; + var properties = _.map(map_properties, function(v) { return ' ' + v; }).join(''); - // This function is called after all files - // have been imported through `@import`. - var finish = function() {}; + output.unshift( + '\n' + + '\n' + + '\n'); + output.push(''); + return output.join('\n'); +}; - function save() { - temp = chunks[j]; - memo = i; - current = i; - } - function restore() { - chunks[j] = temp; - i = memo; - current = i; - } +/** + * This function currently modifies 'current' + * @param {Array} current current list of rules + * @param {Object} definition a Definition object to add to the rules + * @param {Object} byFilter an object/dictionary of existing filters. This is + * actually keyed `attachment->filter` + * @param {Object} env the current environment +*/ +function addRules(current, definition, byFilter, env) { + var newFilters = definition.filters, + newRules = definition.rules, + updatedFilters, clone, previous; - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; + // The current definition might have been split up into + // multiple definitions already. + for (var k = 0; k < current.length; k++) { + updatedFilters = current[k].filters.cloneWith(newFilters); + if (updatedFilters) { + previous = byFilter[updatedFilters]; + if (previous) { + // There's already a definition with those exact + // filters. Add the current definitions' rules + // and stop processing it as the existing rule + // has already gone down the inheritance chain. + previous.addRules(newRules); + } else { + clone = current[k].clone(updatedFilters); + // Make sure that we're only maintaining the clone + // when we did actually add rules. If not, there's + // no need to keep the clone around. + if (clone.addRules(newRules)) { + // We inserted an element before this one, so we need + // to make sure that in the next loop iteration, we're + // not performing the same task for this element again, + // hence the k++. + byFilter[updatedFilters] = clone; + current.splice(k, 0, clone); + k++; + } + } + } else if (updatedFilters === null) { + // if updatedFilters is null, then adding the filters doesn't + // invalidate or split the selector, so we addRules to the + // combined selector + + // Filters can be added, but they don't change the + // filters. This means we don't have to split the + // definition. + // + // this is cloned here because of shared classes, see + // sharedclass.mss + current[k] = current[k].clone(); + current[k].addRules(newRules); } + // if updatedFeatures is false, then the filters split the rule, + // so they aren't the same inheritance chain } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k; + return current; +} - // Non-terminal - if (tok instanceof Function) { - return tok.call(parser.parsers); - // Terminal - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync(); - } else { - sync(); +/** + * Apply inherited styles from their ancestors to them. + * + * called either once per render (in the case of mss) or per layer + * (for mml) + * + * @param {Object} definitions - a list of definitions objects + * that contain .rules + * @param {Object} env - the environment + * @return {Array} an array of arrays is returned, + * in which each array refers to a specific attachment + */ +function inheritDefinitions(definitions, env) { + var inheritTime = +new Date(); + // definitions are ordered by specificity, + // high (index 0) to low + var byAttachment = {}, + byFilter = {}; + var result = []; + var current, previous, attachment; - match = tok.exec(chunks[j]); - if (match) { - length = match[0].length; - } else { - return null; - } - } + // Evaluate the filters specified by each definition with the given + // environment to correctly resolve variable references + definitions.forEach(function(d) { + d.filters.ev(env); + }); - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - if (match) { - var mem = i += length; - endIndex = i + chunks[j].length - length; + for (var i = 0; i < definitions.length; i++) { - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break; } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; + attachment = definitions[i].attachment; + current = [definitions[i]]; - if (chunks[j].length === 0 && j < chunks.length - 1) { j++; } + if (!byAttachment[attachment]) { + byAttachment[attachment] = []; + byAttachment[attachment].attachment = attachment; + byFilter[attachment] = {}; + result.push(byAttachment[attachment]); + } - if (typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; + // Iterate over all subsequent rules. + for (var j = i + 1; j < definitions.length; j++) { + if (definitions[j].attachment === attachment) { + // Only inherit rules from the same attachment. + current = addRules(current, definitions[j], byFilter[attachment], env); } } - } - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - return !!tok.test(chunks[j]); + for (var k = 0; k < current.length; k++) { + byFilter[attachment][current[k].filters] = current[k]; + byAttachment[attachment].push(current[k]); } } - function extractErrorLine(style, errorIndex) { - return (style.slice(0, errorIndex).match(/\n/g) || '').length + 1; - } - + if (env.benchmark) console.warn('Inheritance time: ' + ((new Date() - inheritTime)) + 'ms'); - // Make an error object from a passed set of properties. - // Accepted properties: - // - `message`: Text of the error message. - // - `filename`: Filename where the error occurred. - // - `index`: Char. index where the error occurred. - function makeError(err) { - var einput; + return result; - _(err).defaults({ - index: furthest, - filename: env.filename, - message: 'Parse error.', - line: 0, - column: -1 - }); +} - if (err.filename && that.env.inputs && that.env.inputs[err.filename]) { - einput = that.env.inputs[err.filename]; - } else { - einput = input; - } - - err.line = extractErrorLine(einput, err.index); - for (var n = err.index; n >= 0 && einput.charAt(n) !== '\n'; n--) { - err.column++; +// Sort styles by the minimum index of their rules. +// This sorts a slice of the styles, so it returns a sorted +// array but does not change the input. +function sortStylesIndex(a, b) { return b.index - a.index; } +function sortStyles(styles, env) { + for (var i = 0; i < styles.length; i++) { + var style = styles[i]; + style.index = Infinity; + for (var b = 0; b < style.length; b++) { + var rules = style[b].rules; + for (var r = 0; r < rules.length; r++) { + var rule = rules[r]; + if (rule.index < style.index) { + style.index = rule.index; + } + } } - - return new Error(_('<%=filename%>:<%=line%>:<%=column%> <%=message%>').template(err)); } - this.env = env = env || {}; - this.env.filename = this.env.filename || null; - this.env.inputs = this.env.inputs || {}; + var result = styles.slice(); + result.sort(sortStylesIndex); + return result; +} - // The Parser - parser = { +/** + * Find a rule like Map { background-color: #fff; }, + * if any, and return a list of properties to be inserted + * into the 0) ? "missing closing `}`" : "missing opening `{`" - }; - } - return chunks.map(function (c) { return c.join(''); }); - })([[]]); +CartoCSS.Layer.prototype = { - if (error) { - throw makeError(error); - } + fullName: function() { + return this.shader.attachment; + }, - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. - root = new tree.Ruleset([], $(this.parsers.primary)); - root.root = true; + name: function() { + return this.fullName().split('::')[0]; + }, - // Get an array of Ruleset objects, flattened - // and sorted according to specificitySort - root.toList = (function() { - var line, lines, column; - return function(env) { - env.error = function(e) { - if (!env.errors) env.errors = new Error(''); - if (env.errors.message) { - env.errors.message += '\n' + makeError(e).message; - } else { - env.errors.message = makeError(e).message; - } - }; - env.frames = env.frames || []; + // frames this layer need to be rendered + frames: function() { + return this.shader.frames; + }, + attachment: function() { + return this.fullName().split('::')[1]; + }, - // call populates Invalid-caused errors - var definitions = this.flatten([], [], env); - definitions.sort(specificitySort); - return definitions; - }; - })(); + eval: function(prop) { + var p = this.shader[prop]; + if (!p || !p.style) return; + return p.style({}, { zoom: 0, 'frame-offset': 0 }); + }, - // Sort rules by specificity: this function expects selectors to be - // split already. - // - // Written to be used as a .sort(Function); - // argument. - // - // [1, 0, 0, 467] > [0, 0, 1, 520] - var specificitySort = function(a, b) { - var as = a.specificity; - var bs = b.specificity; + /* + * `props`: feature properties + * `context`: rendering properties, i.e zoom + */ + getStyle: function(props, context) { + var style = {}; + for(var i in this.shader) { + if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') { + style[i] = this.shader[i].style(props, context); + } + } + return style; + }, - if (as[0] != bs[0]) return bs[0] - as[0]; - if (as[1] != bs[1]) return bs[1] - as[1]; - if (as[2] != bs[2]) return bs[2] - as[2]; - return bs[3] - as[3]; - }; + /** + * return the symbolizers that need to be rendered with + * this style. The order is the rendering order. + * @returns a list with 3 possible values 'line', 'marker', 'polygon' + */ + getSymbolizers: function() { + return this.shader.symbolizers; + }, - return root; - }, + /** + * returns if the style varies with some feature property. + * Useful to optimize rendering + */ + isVariable: function() { + for(var i in this.shader) { + if(i !== 'attachment' && i !== 'zoom' && i !== 'frames' && i !== 'symbolizers') { + if (!this.shader[i].constant) { + return true; + } + } + } + return false; + }, - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - parsers: { - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - primary: function() { - var node, root = []; - - while ((node = $(this.rule) || $(this.ruleset) || - $(this.comment)) || - $(/^[\s\n]+/) || (node = $(this.invalid))) { - if (node) root.push(node); - } - return root; - }, + getShader: function() { + return this.shader; + }, - invalid: function () { - var chunk = $(/^[^;\n]*[;\n]/); + /** + * returns true if a feature needs to be rendered + */ + filter: function(featureType, props, context) { + for(var i in this.shader) { + var s = this.shader[i](props, context); + if(s) { + return true; + } + } + return false; + }, - // To fail gracefully, match everything until a semicolon or linebreak. - if (chunk) { - return new tree.Invalid(chunk, memo); - } - }, + // + // given a geoemtry type returns the transformed one acording the CartoCSS + // For points there are two kind of types: point and sprite, the first one + // is a circle, second one is an image sprite + // + // the other geometry types are the same than geojson (polygon, linestring...) + // + transformGeometry: function(type) { + return type; + }, - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function() { - var comment; + transformGeometries: function(geojson) { + return geojson; + } - if (input.charAt(i) !== '/') return; +}; - if (input.charAt(i + 1) === '/') { - return new tree.Comment($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new tree.Comment(comment); - } - }, +CartoCSS.prototype = { - // Entities are tokens which can be found inside an Expression - entities: { + setStyle: function(style) { + var layers = this.parse(style); + if(!layers) { + throw new Error(this.parse_env.errors); + } + this.layers = layers.map(function(shader) { + return new CartoCSS.Layer(shader); + }); + }, - // A string, which supports escaping " and ' "milky way" 'he\'s the one!' - quoted: function() { - if (input.charAt(i) !== '"' && input.charAt(i) !== "'") return; - var str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/); - if (str) { - return new tree.Quoted(str[1] || str[2]); - } - }, + getLayers: function() { + return this.layers; + }, - // A reference to a Mapnik field, like [NAME] - // Behind the scenes, this has the same representation, but Carto - // needs to be careful to warn when unsupported operations are used. - field: function() { - if (! $('[')) return; - var field_name = $(/(^[^\]]+)/); - if (! $(']')) return; - if (field_name) return new tree.Field(field_name[1]); - }, + getDefault: function() { + return this.findLayer({ attachment: '__default__' }); + }, - // This is a comparison operator - comparison: function() { - var str = $(/^=~|=|!=|<=|>=|<|>/); - if (str) { - return str; - } - }, + findLayer: function(where) { + return _.find(this.layers, function(value) { + for (var key in where) { + var v = value[key]; + if (typeof(v) === 'function') { + v = v.call(value); + } + if (where[key] !== v) return false; + } + return true; + }); + }, - // A catch-all word, such as: hard-light - // These can start with either a letter or a dash (-), - // and then contain numbers, underscores, and letters. - keyword: function() { - var k = $(/^[A-Za-z-]+[A-Za-z-0-9_]*/); - if (k) { return new tree.Keyword(k); } - }, + _createFn: function(ops) { + var body = ops.join('\n'); + if(this.options.debug) console.log(body); + return Function("data","ctx", "var _value = null; " + body + "; return _value; "); + }, - // A function call like rgb(255, 0, 255) - // The arguments are parsed with the `entities.arguments` parser. - call: function() { - var name, args; + _compile: function(shader) { + if(typeof shader === 'string') { + shader = eval("(function() { return " + shader +"; })()"); + } + this.shader_src = shader; + for(var attr in shader) { + var c = mapper[attr]; + if(c) { + this.compiled[c] = eval("(function() { return shader[attr]; })();"); + } + } + }, + getImageURLs: function(){ + return this.imageURLs; + }, - if (!(name = /^([\w\-]+|%)\(/.exec(chunks[j]))) return; + parse: function(cartocss) { + var parse_env = { + frames: [], + errors: [], + error: function(obj) { + this.errors.push(obj); + } + }; + this.parse_env = parse_env; - name = name[1]; + var ruleset = null; + try { + ruleset = (new carto.Parser(parse_env)).parse(cartocss); + } catch(e) { + // add the style.mss string to match the response from the server + parse_env.errors.push(e.message); + return; + } + if(ruleset) { - if (name === 'url') { - // url() is handled by the url parser instead - return null; - } else { - i += name.length; - } + function defKey(def) { + return def.elements[0] + "::" + def.attachment; + } + var defs = ruleset.toList(parse_env); + defs.reverse(); + // group by elements[0].value::attachment + var layers = {}; + for(var i = 0; i < defs.length; ++i) { + var def = defs[i]; + var key = defKey(def); + var layer = layers[key] = (layers[key] || { + symbolizers: [] + }); + for(var u = 0; u 57 || c < 45) || c === 47) return; - var value = $(/^(-?\d*\.?\d+(?:[eE][-+]?\d+)?)(\%|\w+)?/); - if (value) { - return new tree.Dimension(value[1], value[2], memo); - } - } - }, - - // The variable part of a variable definition. - // Used in the `rule` parser. Like @fink: - variable: function() { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { - return name[1]; - } - }, - - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - entity: function() { - return $(this.entities.call) || - $(this.entities.literal) || - $(this.entities.field) || - $(this.entities.variable) || - $(this.entities.url) || - $(this.entities.keyword); - }, - - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - end: function() { - return $(';') || peek('}'); - }, - - // Elements are the building blocks for Selectors. They consist of - // an element name, such as a tag a class, or `*`. - element: function() { - var e = $(/^(?:[.#][\w\-]+|\*|Map)/); - if (e) return new tree.Element(e); - }, - - // Attachments allow adding multiple lines, polygons etc. to an - // object. There can only be one attachment per selector. - attachment: function() { - var s = $(/^::([\w\-]+(?:\/[\w\-]+)*)/); - if (s) return s[1]; - }, + // uniq the frames + for(i = 0; i < ordered_layers.length; ++i) { + ordered_layers[i].frames = _.uniq(ordered_layers[i].frames); + } - // Selectors are made out of one or more Elements, see above. - selector: function() { - var a, attachment, - e, elements = [], - f, filters = new tree.Filterset(), - z, zooms = [], - frame_offset = tree.FrameOffset.none; - segments = 0, conditions = 0; + return ordered_layers; - while ( - (e = $(this.element)) || - (z = $(this.zoom)) || - (fo = $(this.frame_offset)) || - (f = $(this.filter)) || - (a = $(this.attachment)) - ) { - segments++; - if (e) { - elements.push(e); - } else if (z) { - zooms.push(z); - conditions++; - } else if (fo) { - frame_offset = fo; - conditions++; - } else if (f) { - var err = filters.add(f); - if (err) { - throw makeError({ - message: err, - index: i - 1 - }); - } - conditions++; - } else if (attachment) { - throw makeError({ - message: 'Encountered second attachment name.', - index: i - 1 - }); - } else { - attachment = a; - } + } + return null; + } +}; - var c = input.charAt(i); - if (c === '{' || c === '}' || c === ';' || c === ',') { break; } - } - if (segments) { - return new tree.Selector(filters, zooms, frame_offset, elements, attachment, conditions, memo); - } - }, +carto.RendererJS = function (options) { + this.options = options || {}; + this.options.mapnik_version = this.options.mapnik_version || 'latest'; +}; - filter: function() { - save(); - var key, op, val; - if (! $('[')) return; - if (key = $(/^[a-zA-Z0-9\-_]+/) || - $(this.entities.quoted) || - $(this.entities.variable) || - $(this.entities.keyword) || - $(this.entities.field)) { - // TODO: remove at 1.0.0 - if (key instanceof tree.Quoted) { - key = new tree.Field(key.toString()); - } - if ((op = $(this.entities.comparison)) && - (val = $(this.entities.quoted) || - $(this.entities.variable) || - $(this.entities.dimension) || - $(this.entities.keyword) || - $(this.entities.field))) { - if (! $(']')) { - throw makeError({ - message: 'Missing closing ] of filter.', - index: memo - 1 - }); - } - if (!key.is) key = new tree.Field(key); - return new tree.Filter(key, op, val, memo, env.filename); - } - } - }, +// Prepare a javascript object which contains the layers +carto.RendererJS.prototype.render = function render(cartocss, callback) { + var reference = require('./torque-reference'); + tree.Reference.setData(reference.version.latest); + return new CartoCSS(cartocss, this.options); +} - frame_offset: function() { - save(); - var op, val; - if ($(/^\[\s*frame-offset/g) && - (op = $(this.entities.comparison)) && - (val = $(/^\d+/)) && - $(']')) { - return tree.FrameOffset(op, val, memo); - } - }, +if(typeof(module) !== 'undefined') { + module.exports = carto.RendererJS; +} - zoom: function() { - save(); - var op, val; - if ($(/^\[\s*zoom/g) && - (op = $(this.entities.comparison)) && - (val = $(this.entities.variable) || $(this.entities.dimension)) && $(']')) { - return new tree.Zoom(op, val, memo); - } else { - // backtrack - restore(); - } - }, - // The `block` rule is used by `ruleset` - // It's a wrapper around the `primary` rule, with added `{}`. - block: function() { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // div, .class, body > p {...} - ruleset: function() { - var selectors = [], s, f, l, rules, filters = []; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - while ($(this.comment)) {} - if (! $(',')) { break; } - while ($(this.comment)) {} - } - if (s) { - while ($(this.comment)) {} - } - - if (selectors.length > 0 && (rules = $(this.block))) { - if (selectors.length === 1 && - selectors[0].elements.length && - selectors[0].elements[0].value === 'Map') { - var rs = new tree.Ruleset(selectors, rules); - rs.isMap = true; - return rs; - } - return new tree.Ruleset(selectors, rules); - } else { - // Backtrack - restore(); - } - }, - - rule: function() { - var name, value, c = input.charAt(i); - save(); - - if (c === '.' || c === '#') { return; } - - if (name = $(this.variable) || $(this.property)) { - value = $(this.value); - - if (value && $(this.end)) { - return new tree.Rule(name, value, memo, env.filename); - } else { - furthest = i; - restore(); - } - } - }, - - font: function() { - var value = [], expression = [], weight, font, e; - - while (e = $(this.entity)) { - expression.push(e); - } - - value.push(new tree.Expression(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break; } - } - } - return new tree.Value(value); - }, - - // A Value is a comma-delimited list of Expressions - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - value: function() { - var e, expressions = []; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break; } - } - - if (expressions.length > 1) { - return new tree.Value(expressions.map(function(e) { - return e.value[0]; - })); - } else if (expressions.length === 1) { - return new tree.Value(expressions); - } - }, - // A sub-expression, contained by parenthensis - sub: function() { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - // This is a misnomer because it actually handles multiplication - // and division. - multiplication: function() { - var m, a, op, operation; - if (m = $(this.operand)) { - while ((op = ($('/') || $('*') || $('%'))) && (a = $(this.operand))) { - operation = new tree.Operation(op, [operation || m, a], memo); - } - return operation || m; - } - }, - addition: function() { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new tree.Operation(op, [operation || m, a], memo); - } - return operation || m; - } - }, - - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - operand: function() { - return $(this.sub) || $(this.entity); - }, - - // Expressions either represent mathematical operations, - // or white-space delimited Entities. @var * 2 - expression: function() { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - - if (entities.length > 0) { - return new tree.Expression(entities); - } - }, - property: function() { - var name = $(/^(([a-z][-a-z_0-9]*\/)?\*?-?[-a-z_0-9]+)\s*:/); - if (name) return name[1]; - } - } - }; - return parser; -}; +})(require('../carto')); }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./tree":41,"underscore":71}],38:[function(require,module,exports){ -(function (global){ -var _ = global._ || require('underscore'); -var carto = require('./index'); - -carto.Renderer = function Renderer(env, options) { - this.env = env || {}; - this.options = options || {}; - this.options.mapnik_version = this.options.mapnik_version || '3.0.0'; -}; - -/** - * Prepare a MSS document (given as an string) into a - * XML Style fragment (mostly useful for debugging) - * - * @param {String} data the mss contents as a string. - */ -carto.Renderer.prototype.renderMSS = function render(data) { - // effects is a container for side-effects, which currently - // are limited to FontSets. - var env = _(this.env).defaults({ - benchmark: false, - validation_data: false, - effects: [] - }); - - if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) { - throw new Error("Could not set mapnik version to " + this.options.mapnik_version); - } - - var output = []; - var styles = []; - - if (env.benchmark) console.time('Parsing MSS'); - var parser = (carto.Parser(env)).parse(data); - if (env.benchmark) console.timeEnd('Parsing MSS'); - - if (env.benchmark) console.time('Rule generation'); - var rule_list = parser.toList(env); - if (env.benchmark) console.timeEnd('Rule generation'); - - if (env.benchmark) console.time('Rule inheritance'); - var rules = inheritDefinitions(rule_list, env); - if (env.benchmark) console.timeEnd('Rule inheritance'); - - if (env.benchmark) console.time('Style sort'); - var sorted = sortStyles(rules,env); - if (env.benchmark) console.timeEnd('Style sort'); - - if (env.benchmark) console.time('Total Style generation'); - for (var k = 0, rule, style_name; k < sorted.length; k++) { - rule = sorted[k]; - style_name = 'style' + (rule.attachment !== '__default__' ? '-' + rule.attachment : ''); - styles.push(style_name); - var bench_name = '\tStyle "'+style_name+'" (#'+k+') toXML'; - if (env.benchmark) console.time(bench_name); - // env.effects can be modified by this call - output.push(carto.tree.StyleXML(style_name, rule.attachment, rule, env)); - if (env.benchmark) console.timeEnd(bench_name); - } - if (env.benchmark) console.timeEnd('Total Style generation'); - if (env.errors) throw env.errors; - return output.join('\n'); -}; - -/** - * Prepare a MML document (given as an object) into a - * fully-localized XML file ready for Mapnik2 consumption - * - * @param {String} m - the JSON file as a string. - */ -carto.Renderer.prototype.render = function render(m) { - // effects is a container for side-effects, which currently - // are limited to FontSets. - var env = _(this.env).defaults({ - benchmark: false, - validation_data: false, - effects: [], - ppi: 90.714 - }); - - if (!carto.tree.Reference.setVersion(this.options.mapnik_version)) { - throw new Error("Could not set mapnik version to " + this.options.mapnik_version); - } - - var output = []; - - // Transform stylesheets into definitions. - var definitions = _(m.Stylesheet).chain() - .map(function(s) { - if (typeof s == 'string') { - throw new Error("Stylesheet object is expected not a string: '" + s + "'"); - } - // Passing the environment from stylesheet to stylesheet, - // allows frames and effects to be maintained. - env = _(env).extend({filename:s.id}); - - var time = +new Date(), - root = (carto.Parser(env)).parse(s.data); - if (env.benchmark) - console.warn('Parsing time: ' + (new Date() - time) + 'ms'); - return root.toList(env); - }) - .flatten() - .value(); - - function appliesTo(name, classIndex) { - return function(definition) { - return definition.appliesTo(l.name, classIndex); - }; - } - - // Iterate through layers and create styles custom-built - // for each of them, and apply those styles to the layers. - var styles, l, classIndex, rules, sorted, matching; - for (var i = 0; i < m.Layer.length; i++) { - l = m.Layer[i]; - styles = []; - classIndex = {}; - - if (env.benchmark) console.warn('processing layer: ' + l.id); - // Classes are given as space-separated alphanumeric strings. - var classes = (l['class'] || '').split(/\s+/g); - for (var j = 0; j < classes.length; j++) { - classIndex[classes[j]] = true; - } - matching = definitions.filter(appliesTo(l.name, classIndex)); - rules = inheritDefinitions(matching, env); - sorted = sortStyles(rules, env); - - for (var k = 0, rule, style_name; k < sorted.length; k++) { - rule = sorted[k]; - style_name = l.name + (rule.attachment !== '__default__' ? '-' + rule.attachment : ''); - - // env.effects can be modified by this call - var styleXML = carto.tree.StyleXML(style_name, rule.attachment, rule, env); - - if (styleXML) { - output.push(styleXML); - styles.push(style_name); - } +},{"../carto":32,"./torque-reference":36,"./tree":37,"underscore":71}],36:[function(require,module,exports){ +var _mapnik_reference_latest = { + "version": "2.1.1", + "style": { + "filter-mode": { + "type": [ + "all", + "first" + ], + "doc": "Control the processing behavior of Rule filters within a Style. If 'all' is used then all Rules are processed sequentially independent of whether any previous filters matched. If 'first' is used then it means processing ends after the first match (a positive filter evaluation) and no further Rules in the Style are processed ('first' is usually the default for CSS implementations on top of Mapnik to simplify translation from CSS to Mapnik XML)", + "default-value": "all", + "default-meaning": "All Rules in a Style are processed whether they have filters or not and whether or not the filter conditions evaluate to true." + }, + "image-filters": { + "css": "image-filters", + "default-value": "none", + "default-meaning": "no filters", + "type": "functions", + "functions": [ + ["agg-stack-blur", 2], + ["emboss", 0], + ["blur", 0], + ["gray", 0], + ["sobel", 0], + ["edge-detect", 0], + ["x-gradient", 0], + ["y-gradient", 0], + ["invert", 0], + ["sharpen", 0], + ["colorize-alpha", -1], + ["color-to-alpha", 1], + ["scale-hsla", 8] + ], + "doc": "A list of image filters." + }, + "comp-op": { + "css": "comp-op", + "default-value": "src-over", + "default-meaning": "add the current layer on top of other layers", + "doc": "Composite operation. This defines how this layer should behave relative to layers atop or below it.", + "type": ["clear", + "src", + "dst", + "src-over", + "source-over", // added for torque + "dst-over", + "src-in", + "dst-in", + "src-out", + "dst-out", + "src-atop", + "dst-atop", + "xor", + "plus", + "minus", + "multiply", + "screen", + "overlay", + "darken", + "lighten", + "lighter", // added for torque + "color-dodge", + "color-burn", + "hard-light", + "soft-light", + "difference", + "exclusion", + "contrast", + "invert", + "invert-rgb", + "grain-merge", + "grain-extract", + "hue", + "saturation", + "color", + "value" + ] + }, + "opacity": { + "css": "opacity", + "type": "float", + "doc": "An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)", + "default-value": 1, + "default-meaning": "no separate buffer will be used and no alpha will be applied to the style after rendering" } - - output.push(carto.tree.LayerXML(l, styles)); - } - - output.unshift(env.effects.map(function(e) { - return e.toXML(env); - }).join('\n')); - - var map_properties = getMapProperties(m, definitions, env); - - // Exit on errors. - if (env.errors) throw env.errors; - - // Pass TileJSON and other custom parameters through to Mapnik XML. - var parameters = _(m).reduce(function(memo, v, k) { - if (!v && v !== 0) return memo; - - switch (k) { - // Known skippable properties. - case 'srs': - case 'Layer': - case 'Stylesheet': - break; - // Non URL-bound TileJSON properties. - case 'bounds': - case 'center': - case 'minzoom': - case 'maxzoom': - case 'version': - memo.push(' ' + v + ''); - break; - // Properties that require CDATA. - case 'name': - case 'description': - case 'legend': - case 'attribution': - case 'template': - memo.push(' '); - break; - // Mapnik image format. - case 'format': - memo.push(' ' + v + ''); - break; - // Mapnik interactivity settings. - case 'interactivity': - memo.push(' ' + v.layer + ''); - memo.push(' ' + v.fields + ''); - break; - // Support any additional scalar properties. - default: - if ('string' === typeof v) { - memo.push(' '); - } else if ('number' === typeof v) { - memo.push(' ' + v + ''); - } else if ('boolean' === typeof v) { - memo.push(' ' + v + ''); - } - break; + }, + "layer" : { + "name": { + "default-value": "", + "type":"string", + "required" : true, + "default-meaning": "No layer name has been provided", + "doc": "The name of a layer. Can be anything you wish and is not strictly validated, but ideally unique in the map" + }, + "srs": { + "default-value": "", + "type":"string", + "default-meaning": "No srs value is provided and the value will be inherited from the Map's srs", + "doc": "The spatial reference system definition for the layer, aka the projection. Can either be a proj4 literal string like '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' or, if the proper proj4 epsg/nad/etc identifier files are installed, a string that uses an id like: '+init=epsg:4326'" + }, + "status": { + "default-value": true, + "type":"boolean", + "default-meaning": "This layer will be marked as active and available for processing", + "doc": "A property that can be set to false to disable this layer from being processed" + }, + "minzoom": { + "default-value": "0", + "type":"float", + "default-meaning": "The layer will be visible at the minimum possible scale", + "doc": "The minimum scale denominator that this layer will be visible at. A layer's visibility is determined by whether its status is true and if the Map scale >= minzoom - 1e-6 and scale < maxzoom + 1e-6" + }, + "maxzoom": { + "default-value": "1.79769e+308", + "type":"float", + "default-meaning": "The layer will be visible at the maximum possible scale", + "doc": "The maximum scale denominator that this layer will be visible at. The default is the numeric limit of the C++ double type, which may vary slightly by system, but is likely a massive number like 1.79769e+308 and ensures that this layer will always be visible unless the value is reduced. A layer's visibility is determined by whether its status is true and if the Map scale >= minzoom - 1e-6 and scale < maxzoom + 1e-6" + }, + "queryable": { + "default-value": false, + "type":"boolean", + "default-meaning": "The layer will not be available for the direct querying of data values", + "doc": "This property was added for GetFeatureInfo/WMS compatibility and is rarely used. It is off by default meaning that in a WMS context the layer will not be able to be queried unless the property is explicitly set to true" + }, + "clear-label-cache": { + "default-value": false, + "type":"boolean", + "default-meaning": "The renderer's collision detector cache (used for avoiding duplicate labels and overlapping markers) will not be cleared immediately before processing this layer", + "doc": "This property, by default off, can be enabled to allow a user to clear the collision detector cache before a given layer is processed. This may be desirable to ensure that a given layers data shows up on the map even if it normally would not because of collisions with previously rendered labels or markers" + }, + "group-by": { + "default-value": "", + "type":"string", + "default-meaning": "No special layer grouping will be used during rendering", + "doc": "https://github.com/mapnik/mapnik/wiki/Grouped-rendering" + }, + "buffer-size": { + "default-value": "0", + "type":"float", + "default-meaning": "No buffer will be used", + "doc": "Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering" + }, + "maximum-extent": { + "default-value": "none", + "type":"bbox", + "default-meaning": "No clipping extent will be used", + "doc": "An extent to be used to limit the bounds used to query this specific layer data during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Layer." } - return memo; - }, []); - if (parameters.length) output.unshift( - '\n' + - parameters.join('\n') + - '\n\n' - ); - - var properties = _(map_properties).map(function(v) { return ' ' + v; }).join(''); - - output.unshift( - '\n' + - '\n' + - '\n'); - output.push(''); - return output.join('\n'); -}; - -/** - * This function currently modifies 'current' - * @param {Array} current current list of rules - * @param {Object} definition a Definition object to add to the rules - * @param {Object} byFilter an object/dictionary of existing filters. This is - * actually keyed `attachment->filter` - * @param {Object} env the current environment -*/ -function addRules(current, definition, byFilter, env) { - var newFilters = definition.filters, - newRules = definition.rules, - updatedFilters, clone, previous; - - // The current definition might have been split up into - // multiple definitions already. - for (var k = 0; k < current.length; k++) { - updatedFilters = current[k].filters.cloneWith(newFilters); - if (updatedFilters) { - previous = byFilter[updatedFilters]; - if (previous) { - // There's already a definition with those exact - // filters. Add the current definitions' rules - // and stop processing it as the existing rule - // has already gone down the inheritance chain. - previous.addRules(newRules); - } else { - clone = current[k].clone(updatedFilters); - // Make sure that we're only maintaining the clone - // when we did actually add rules. If not, there's - // no need to keep the clone around. - if (clone.addRules(newRules)) { - // We inserted an element before this one, so we need - // to make sure that in the next loop iteration, we're - // not performing the same task for this element again, - // hence the k++. - byFilter[updatedFilters] = clone; - current.splice(k, 0, clone); - k++; - } - } - } else if (updatedFilters === null) { - // if updatedFilters is null, then adding the filters doesn't - // invalidate or split the selector, so we addRules to the - // combined selector - - // Filters can be added, but they don't change the - // filters. This means we don't have to split the - // definition. - // - // this is cloned here because of shared classes, see - // sharedclass.mss - current[k] = current[k].clone(); - current[k].addRules(newRules); - } - // if updatedFeatures is false, then the filters split the rule, - // so they aren't the same inheritance chain - } - return current; -} - -/** - * Apply inherited styles from their ancestors to them. - * - * called either once per render (in the case of mss) or per layer - * (for mml) - * - * @param {Object} definitions - a list of definitions objects - * that contain .rules - * @param {Object} env - the environment - * @return {Array} an array of arrays is returned, - * in which each array refers to a specific attachment - */ -function inheritDefinitions(definitions, env) { - var inheritTime = +new Date(); - // definitions are ordered by specificity, - // high (index 0) to low - var byAttachment = {}, - byFilter = {}; - var result = []; - var current, previous, attachment; - - // Evaluate the filters specified by each definition with the given - // environment to correctly resolve variable references - definitions.forEach(function(d) { - d.filters.ev(env); - }); - - for (var i = 0; i < definitions.length; i++) { - - attachment = definitions[i].attachment; - current = [definitions[i]]; - - if (!byAttachment[attachment]) { - byAttachment[attachment] = []; - byAttachment[attachment].attachment = attachment; - byFilter[attachment] = {}; - result.push(byAttachment[attachment]); - } - - // Iterate over all subsequent rules. - for (var j = i + 1; j < definitions.length; j++) { - if (definitions[j].attachment === attachment) { - // Only inherit rules from the same attachment. - current = addRules(current, definitions[j], byFilter[attachment], env); + }, + "symbolizers" : { + "*": { + "image-filters": { + "css": "image-filters", + "default-value": "none", + "default-meaning": "no filters", + "type": "functions", + "functions": [ + ["agg-stack-blur", 2], + ["emboss", 0], + ["blur", 0], + ["gray", 0], + ["sobel", 0], + ["edge-detect", 0], + ["x-gradient", 0], + ["y-gradient", 0], + ["invert", 0], + ["sharpen", 0], + ["colorize-alpha", -1], + ["color-to-alpha", 1], + ["scale-hsla", 8], + ["ramp", -1] + ], + "doc": "A list of image filters." + }, + "comp-op": { + "css": "comp-op", + "default-value": "src-over", + "default-meaning": "add the current layer on top of other layers", + "doc": "Composite operation. This defines how this layer should behave relative to layers atop or below it.", + "type": ["clear", + "src", + "dst", + "src-over", + "source-over", // added for torque + "dst-over", + "src-in", + "dst-in", + "src-out", + "dst-out", + "src-atop", + "dst-atop", + "xor", + "plus", + "minus", + "multiply", + "screen", + "overlay", + "darken", + "lighten", + "lighter", // added for torque + "color-dodge", + "color-burn", + "hard-light", + "soft-light", + "difference", + "exclusion", + "contrast", + "invert", + "invert-rgb", + "grain-merge", + "grain-extract", + "hue", + "saturation", + "color", + "value" + ] + }, + "opacity": { + "css": "opacity", + "type": "float", + "doc": "An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)", + "default-value": 1, + "default-meaning": "no separate buffer will be used and no alpha will be applied to the style after rendering" } - } - - for (var k = 0; k < current.length; k++) { - byFilter[attachment][current[k].filters] = current[k]; - byAttachment[attachment].push(current[k]); - } - } - - if (env.benchmark) console.warn('Inheritance time: ' + ((new Date() - inheritTime)) + 'ms'); - - return result; - -} - -// Sort styles by the minimum index of their rules. -// This sorts a slice of the styles, so it returns a sorted -// array but does not change the input. -function sortStylesIndex(a, b) { return b.index - a.index; } -function sortStyles(styles, env) { - for (var i = 0; i < styles.length; i++) { - var style = styles[i]; - style.index = Infinity; - for (var b = 0; b < style.length; b++) { - var rules = style[b].rules; - for (var r = 0; r < rules.length; r++) { - var rule = rules[r]; - if (rule.index < style.index) { - style.index = rule.index; - } + }, + "map": { + "background-color": { + "css": "background-color", + "default-value": "none", + "default-meaning": "transparent", + "type": "color", + "doc": "Map Background color" + }, + "background-image": { + "css": "background-image", + "type": "uri", + "default-value": "", + "default-meaning": "transparent", + "doc": "An image that is repeated below all features on a map as a background.", + "description": "Map Background image" + }, + "srs": { + "css": "srs", + "type": "string", + "default-value": "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", + "default-meaning": "The proj4 literal of EPSG:4326 is assumed to be the Map's spatial reference and all data from layers within this map will be plotted using this coordinate system. If any layers do not declare an srs value then they will be assumed to be in the same srs as the Map and not transformations will be needed to plot them in the Map's coordinate space", + "doc": "Map spatial reference (proj4 string)" + }, + "buffer-size": { + "css": "buffer-size", + "default-value": "0", + "type":"float", + "default-meaning": "No buffer will be used", + "doc": "Extra tolerance around the map (in pixels) used to ensure labels crossing tile boundaries are equally rendered in each tile (e.g. cut in each tile). Not intended to be used in combination with \"avoid-edges\"." + }, + "maximum-extent": { + "css": "", + "default-value": "none", + "type":"bbox", + "default-meaning": "No clipping extent will be used", + "doc": "An extent to be used to limit the bounds used to query all layers during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Map." + }, + "base": { + "css": "base", + "default-value": "", + "default-meaning": "This base path defaults to an empty string meaning that any relative paths to files referenced in styles or layers will be interpreted relative to the application process.", + "type": "string", + "doc": "Any relative paths used to reference files will be understood as relative to this directory path if the map is loaded from an in memory object rather than from the filesystem. If the map is loaded from the filesystem and this option is not provided it will be set to the directory of the stylesheet." + }, + "paths-from-xml": { + "css": "", + "default-value": true, + "default-meaning": "Paths read from XML will be interpreted from the location of the XML", + "type": "boolean", + "doc": "value to control whether paths in the XML will be interpreted from the location of the XML or from the working directory of the program that calls load_map()" + }, + "minimum-version": { + "css": "", + "default-value": "none", + "default-meaning": "Mapnik version will not be detected and no error will be thrown about compatibility", + "type": "string", + "doc": "The minumum Mapnik version (e.g. 0.7.2) needed to use certain functionality in the stylesheet" + }, + "font-directory": { + "css": "font-directory", + "type": "uri", + "default-value": "none", + "default-meaning": "No map-specific fonts will be registered", + "doc": "Path to a directory which holds fonts which should be registered when the Map is loaded (in addition to any fonts that may be automatically registered)." } - } - } - - var result = styles.slice(); - result.sort(sortStylesIndex); - return result; -} - -/** - * Find a rule like Map { background-color: #fff; }, - * if any, and return a list of properties to be inserted - * into the = minzoom - 1e-6 and scale < maxzoom + 1e-6" - }, - "maxzoom": { - "default-value": "1.79769e+308", - "type":"float", - "default-meaning": "The layer will be visible at the maximum possible scale", - "doc": "The maximum scale denominator that this layer will be visible at. The default is the numeric limit of the C++ double type, which may vary slightly by system, but is likely a massive number like 1.79769e+308 and ensures that this layer will always be visible unless the value is reduced. A layer's visibility is determined by whether its status is true and if the Map scale >= minzoom - 1e-6 and scale < maxzoom + 1e-6" - }, - "queryable": { - "default-value": false, - "type":"boolean", - "default-meaning": "The layer will not be available for the direct querying of data values", - "doc": "This property was added for GetFeatureInfo/WMS compatibility and is rarely used. It is off by default meaning that in a WMS context the layer will not be able to be queried unless the property is explicitly set to true" - }, - "clear-label-cache": { - "default-value": false, - "type":"boolean", - "default-meaning": "The renderer's collision detector cache (used for avoiding duplicate labels and overlapping markers) will not be cleared immediately before processing this layer", - "doc": "This property, by default off, can be enabled to allow a user to clear the collision detector cache before a given layer is processed. This may be desirable to ensure that a given layers data shows up on the map even if it normally would not because of collisions with previously rendered labels or markers" - }, - "group-by": { - "default-value": "", - "type":"string", - "default-meaning": "No special layer grouping will be used during rendering", - "doc": "https://github.com/mapnik/mapnik/wiki/Grouped-rendering" - }, - "buffer-size": { - "default-value": "0", - "type":"float", - "default-meaning": "No buffer will be used", - "doc": "Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering" - }, - "maximum-extent": { - "default-value": "none", - "type":"bbox", - "default-meaning": "No clipping extent will be used", - "doc": "An extent to be used to limit the bounds used to query this specific layer data during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Layer." - } - }, - "symbolizers" : { - "*": { - "image-filters": { - "css": "image-filters", + "line": { + "stroke": { + "css": "line-color", + "default-value": "rgba(0,0,0,1)", + "type": "color", + "default-meaning": "black and fully opaque (alpha = 1), same as rgb(0,0,0)", + "doc": "The color of a drawn line", + "expression": true + }, + "stroke-width": { + "css": "line-width", + "default-value": 1, + "type": "float", + "doc": "The width of a line in pixels", + "expression": true + }, + "stroke-opacity": { + "css": "line-opacity", + "default-value": 1, + "type": "float", + "default-meaning": "opaque", + "doc": "The opacity of a line" + }, + "stroke-linejoin": { + "css": "line-join", + "default-value": "miter", + "type": [ + "miter", + "round", + "bevel" + ], + "doc": "The behavior of lines when joining" + }, + "stroke-linecap": { + "css": "line-cap", + "default-value": "butt", + "type": [ + "butt", + "round", + "square" + ], + "doc": "The display of line endings" + }, + "stroke-gamma": { + "css": "line-gamma", + "type": "float", + "default-value": 1, + "default-meaning": "fully antialiased", + "range": "0-1", + "doc": "Level of antialiasing of stroke line" + }, + "stroke-gamma-method": { + "css": "line-gamma-method", + "type": [ + "power", + "linear", + "none", + "threshold", + "multiply" + ], + "default-value": "power", + "default-meaning": "pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA", + "doc": "An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h" + }, + "stroke-dasharray": { + "css": "line-dasharray", + "type": "numbers", + "doc": "A pair of length values [a,b], where (a) is the dash length and (b) is the gap length respectively. More than two values are supported for more complex patterns.", "default-value": "none", - "default-meaning": "no filters", + "default-meaning": "solid line" + }, + "stroke-dashoffset": { + "css": "line-dash-offset", + "type": "numbers", + "doc": "valid parameter but not currently used in renderers (only exists for experimental svg support in Mapnik which is not yet enabled)", + "default-value": "none", + "default-meaning": "solid line" + }, + "stroke-miterlimit": { + "css": "line-miterlimit", + "type": "float", + "doc": "The limit on the ratio of the miter length to the stroke-width. Used to automatically convert miter joins to bevel joins for sharp angles to avoid the miter extending beyond the thickness of the stroking path. Normally will not need to be set, but a larger value can sometimes help avoid jaggy artifacts.", + "default-value": 4.0, + "default-meaning": "Will auto-convert miters to bevel line joins when theta is less than 29 degrees as per the SVG spec: 'miterLength / stroke-width = 1 / sin ( theta / 2 )'" + }, + "clip": { + "css": "line-clip", + "type": "boolean", + "default-value": true, + "default-meaning": "geometry will be clipped to map bounds before rendering", + "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." + }, + "smooth": { + "css": "line-smooth", + "type": "float", + "default-value": 0, + "default-meaning": "no smoothing", + "range": "0-1", + "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." + }, + "offset": { + "css": "line-offset", + "type": "float", + "default-value": 0, + "default-meaning": "no offset", + "doc": "Offsets a line a number of pixels parallel to its actual path. Postive values move the line left, negative values move it right (relative to the directionality of the line)." + }, + "rasterizer": { + "css": "line-rasterizer", + "type": [ + "full", + "fast" + ], + "default-value": "full", + "doc": "Exposes an alternate AGG rendering method that sacrifices some accuracy for speed." + }, + "geometry-transform": { + "css": "line-geometry-transform", "type": "functions", + "default-value": "none", + "default-meaning": "geometry will not be transformed", + "doc": "Allows transformation functions to be applied to the geometry.", "functions": [ - ["agg-stack-blur", 2], - ["emboss", 0], - ["blur", 0], - ["gray", 0], - ["sobel", 0], - ["edge-detect", 0], - ["x-gradient", 0], - ["y-gradient", 0], - ["invert", 0], - ["sharpen", 0], - ["colorize-alpha", -1], - ["color-to-alpha", 1], - ["scale-hsla", 8] - ], - "doc": "A list of image filters." + ["matrix", 6], + ["translate", 2], + ["scale", 2], + ["rotate", 3], + ["skewX", 1], + ["skewY", 1] + ] }, "comp-op": { - "css": "comp-op", + "css": "line-comp-op", "default-value": "src-over", - "default-meaning": "add the current layer on top of other layers", - "doc": "Composite operation. This defines how this layer should behave relative to layers atop or below it.", + "default-meaning": "add the current symbolizer on top of other symbolizer", + "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", "type": ["clear", "src", "dst", "src-over", - "source-over", // added for torque "dst-over", "src-in", "dst-in", @@ -8623,7 +8367,6 @@ var _mapnik_reference_latest = { "overlay", "darken", "lighten", - "lighter", // added for torque "color-dodge", "color-burn", "hard-light", @@ -8640,126 +8383,151 @@ var _mapnik_reference_latest = { "color", "value" ] - }, - "opacity": { - "css": "opacity", - "type": "float", - "doc": "An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)", - "default-value": 1, - "default-meaning": "no separate buffer will be used and no alpha will be applied to the style after rendering" } }, - "map": { - "background-color": { - "css": "background-color", - "default-value": "none", - "default-meaning": "transparent", - "type": "color", - "doc": "Map Background color" + "markers": { + "file": { + "css": "marker-file", + "doc": "An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.", + "default-value": "", + "default-meaning": "An ellipse or circle, if width equals height", + "type": "uri" }, - "background-image": { - "css": "background-image", - "type": "uri", - "default-value": "", - "default-meaning": "transparent", - "doc": "An image that is repeated below all features on a map as a background.", - "description": "Map Background image" + "opacity": { + "css": "marker-opacity", + "doc": "The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke", + "default-value": 1, + "default-meaning": "The stroke-opacity and fill-opacity will be used", + "type": "float" }, - "srs": { - "css": "srs", - "type": "string", - "default-value": "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - "default-meaning": "The proj4 literal of EPSG:4326 is assumed to be the Map's spatial reference and all data from layers within this map will be plotted using this coordinate system. If any layers do not declare an srs value then they will be assumed to be in the same srs as the Map and not transformations will be needed to plot them in the Map's coordinate space", - "doc": "Map spatial reference (proj4 string)" + "fill-opacity": { + "css": "marker-fill-opacity", + "doc": "The fill opacity of the marker", + "default-value": 1, + "default-meaning": "opaque", + "type": "float" }, - "buffer-size": { - "css": "buffer-size", - "default-value": "0", - "type":"float", - "default-meaning": "No buffer will be used", - "doc": "Extra tolerance around the map (in pixels) used to ensure labels crossing tile boundaries are equally rendered in each tile (e.g. cut in each tile). Not intended to be used in combination with \"avoid-edges\"." + "stroke": { + "css": "marker-line-color", + "doc": "The color of the stroke around a marker shape.", + "default-value": "black", + "type": "color" }, - "maximum-extent": { - "css": "", - "default-value": "none", - "type":"bbox", - "default-meaning": "No clipping extent will be used", - "doc": "An extent to be used to limit the bounds used to query all layers during rendering. Should be minx, miny, maxx, maxy in the coordinates of the Map." + "stroke-width": { + "css": "marker-line-width", + "doc": "The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.", + "type": "float" }, - "base": { - "css": "base", - "default-value": "", - "default-meaning": "This base path defaults to an empty string meaning that any relative paths to files referenced in styles or layers will be interpreted relative to the application process.", - "type": "string", - "doc": "Any relative paths used to reference files will be understood as relative to this directory path if the map is loaded from an in memory object rather than from the filesystem. If the map is loaded from the filesystem and this option is not provided it will be set to the directory of the stylesheet." + "stroke-opacity": { + "css": "marker-line-opacity", + "default-value": 1, + "default-meaning": "opaque", + "doc": "The opacity of a line", + "type": "float" }, - "paths-from-xml": { - "css": "", - "default-value": true, - "default-meaning": "Paths read from XML will be interpreted from the location of the XML", - "type": "boolean", - "doc": "value to control whether paths in the XML will be interpreted from the location of the XML or from the working directory of the program that calls load_map()" + "placement": { + "css": "marker-placement", + "type": [ + "point", + "line", + "interior" + ], + "default-value": "point", + "default-meaning": "Place markers at the center point (centroid) of the geometry", + "doc": "Attempt to place markers on a point, in the center of a polygon, or if markers-placement:line, then multiple times along a line. 'interior' placement can be used to ensure that points placed on polygons are forced to be inside the polygon interior" }, - "minimum-version": { - "css": "", - "default-value": "none", - "default-meaning": "Mapnik version will not be detected and no error will be thrown about compatibility", - "type": "string", - "doc": "The minumum Mapnik version (e.g. 0.7.2) needed to use certain functionality in the stylesheet" + "multi-policy": { + "css": "marker-multi-policy", + "type": [ + "each", + "whole", + "largest" + ], + "default-value": "each", + "default-meaning": "If a feature contains multiple geometries and the placement type is either point or interior then a marker will be rendered for each", + "doc": "A special setting to allow the user to control rendering behavior for 'multi-geometries' (when a feature contains multiple geometries). This setting does not apply to markers placed along lines. The 'each' policy is default and means all geometries will get a marker. The 'whole' policy means that the aggregate centroid between all geometries will be used. The 'largest' policy means that only the largest (by bounding box areas) feature will get a rendered marker (this is how text labeling behaves by default)." + }, + "marker-type": { + "css": "marker-type", + "type": [ + "arrow", + "ellipse", + "rectangle" + ], + "default-value": "ellipse", + "doc": "The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an arrow or an ellipse (a circle if height is equal to width)" + }, + "width": { + "css": "marker-width", + "default-value": 10, + "doc": "The width of the marker, if using one of the default types.", + "type": "float", + "expression": true + }, + "height": { + "css": "marker-height", + "default-value": 10, + "doc": "The height of the marker, if using one of the default types.", + "type": "float", + "expression": true }, - "font-directory": { - "css": "font-directory", - "type": "uri", - "default-value": "none", - "default-meaning": "No map-specific fonts will be registered", - "doc": "Path to a directory which holds fonts which should be registered when the Map is loaded (in addition to any fonts that may be automatically registered)." - } - }, - "polygon": { "fill": { - "css": "polygon-fill", + "css": "marker-fill", + "default-value": "blue", + "doc": "The color of the area of the marker.", "type": "color", - "default-value": "rgba(128,128,128,1)", - "default-meaning": "gray and fully opaque (alpha = 1), same as rgb(128,128,128)", - "doc": "Fill color to assign to a polygon" + "expression": true }, - "fill-opacity": { - "css": "polygon-opacity", - "type": "float", - "doc": "The opacity of the polygon", - "default-value": 1, - "default-meaning": "opaque" + "allow-overlap": { + "css": "marker-allow-overlap", + "type": "boolean", + "default-value": false, + "doc": "Control whether overlapping markers are shown or hidden.", + "default-meaning": "Do not allow makers to overlap with each other - overlapping markers will not be shown." }, - "gamma": { - "css": "polygon-gamma", + "ignore-placement": { + "css": "marker-ignore-placement", + "type": "boolean", + "default-value": false, + "default-meaning": "do not store the bbox of this geometry in the collision detector cache", + "doc": "value to control whether the placement of the feature will prevent the placement of other features" + }, + "spacing": { + "css": "marker-spacing", + "doc": "Space between repeated labels", + "default-value": 100, + "type": "float" + }, + "max-error": { + "css": "marker-max-error", "type": "float", - "default-value": 1, - "default-meaning": "fully antialiased", - "range": "0-1", - "doc": "Level of antialiasing of polygon edges" + "default-value": 0.2, + "doc": "The maximum difference between actual marker placement and the marker-spacing parameter. Setting a high value can allow the renderer to try to resolve placement conflicts with other symbolizers." }, - "gamma-method": { - "css": "polygon-gamma-method", - "type": [ - "power", - "linear", - "none", - "threshold", - "multiply" + "transform": { + "css": "marker-transform", + "type": "functions", + "functions": [ + ["matrix", 6], + ["translate", 2], + ["scale", 2], + ["rotate", 3], + ["skewX", 1], + ["skewY", 1] ], - "default-value": "power", - "default-meaning": "pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA", - "doc": "An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h" + "default-value": "", + "default-meaning": "No transformation", + "doc": "SVG transformation definition" }, "clip": { - "css": "polygon-clip", + "css": "marker-clip", "type": "boolean", "default-value": true, "default-meaning": "geometry will be clipped to map bounds before rendering", "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." }, "smooth": { - "css": "polygon-smooth", + "css": "marker-smooth", "type": "float", "default-value": 0, "default-meaning": "no smoothing", @@ -8767,7 +8535,7 @@ var _mapnik_reference_latest = { "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." }, "geometry-transform": { - "css": "polygon-geometry-transform", + "css": "marker-geometry-transform", "type": "functions", "default-value": "none", "default-meaning": "geometry will not be transformed", @@ -8782,7 +8550,7 @@ var _mapnik_reference_latest = { ] }, "comp-op": { - "css": "polygon-comp-op", + "css": "marker-comp-op", "default-value": "src-over", "default-meaning": "add the current symbolizer on top of other symbolizer", "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", @@ -8823,137 +8591,220 @@ var _mapnik_reference_latest = { ] } }, - "line": { - "stroke": { - "css": "line-color", - "default-value": "rgba(0,0,0,1)", - "type": "color", - "default-meaning": "black and fully opaque (alpha = 1), same as rgb(0,0,0)", - "doc": "The color of a drawn line" + "shield": { + "name": { + "css": "shield-name", + "type": "string", + "expression": true, + "serialization": "content", + "doc": "Value to use for a shield\"s text label. Data columns are specified using brackets like [column_name]" }, - "stroke-width": { - "css": "line-width", - "default-value": 1, - "type": "float", - "doc": "The width of a line in pixels" + "file": { + "css": "shield-file", + "required": true, + "type": "uri", + "default-value": "none", + "doc": "Image file to render behind the shield text" }, - "stroke-opacity": { - "css": "line-opacity", - "default-value": 1, + "face-name": { + "css": "shield-face-name", + "type": "string", + "validate": "font", + "doc": "Font name and style to use for the shield text", + "default-value": "", + "required": true + }, + "unlock-image": { + "css": "shield-unlock-image", + "type": "boolean", + "doc": "This parameter should be set to true if you are trying to position text beside rather than on top of the shield image", + "default-value": false, + "default-meaning": "text alignment relative to the shield image uses the center of the image as the anchor for text positioning." + }, + "size": { + "css": "shield-size", "type": "float", - "default-meaning": "opaque", - "doc": "The opacity of a line" + "doc": "The size of the shield text in pixels" }, - "stroke-linejoin": { - "css": "line-join", - "default-value": "miter", + "fill": { + "css": "shield-fill", + "type": "color", + "doc": "The color of the shield text" + }, + "placement": { + "css": "shield-placement", "type": [ - "miter", - "round", - "bevel" + "point", + "line", + "vertex", + "interior" ], - "doc": "The behavior of lines when joining" + "default-value": "point", + "doc": "How this shield should be placed. Point placement attempts to place it on top of points, line places along lines multiple times per feature, vertex places on the vertexes of polygons, and interior attempts to place inside of polygons." }, - "stroke-linecap": { - "css": "line-cap", - "default-value": "butt", - "type": [ - "butt", - "round", - "square" - ], - "doc": "The display of line endings" + "avoid-edges": { + "css": "shield-avoid-edges", + "doc": "Tell positioning algorithm to avoid labeling near intersection edges.", + "type": "boolean", + "default-value": false }, - "stroke-gamma": { - "css": "line-gamma", + "allow-overlap": { + "css": "shield-allow-overlap", + "type": "boolean", + "default-value": false, + "doc": "Control whether overlapping shields are shown or hidden.", + "default-meaning": "Do not allow shields to overlap with other map elements already placed." + }, + "minimum-distance": { + "css": "shield-min-distance", "type": "float", - "default-value": 1, - "default-meaning": "fully antialiased", - "range": "0-1", - "doc": "Level of antialiasing of stroke line" + "default-value": 0, + "doc": "Minimum distance to the next shield symbol, not necessarily the same shield." }, - "stroke-gamma-method": { - "css": "line-gamma-method", - "type": [ - "power", - "linear", - "none", - "threshold", - "multiply" - ], - "default-value": "power", - "default-meaning": "pow(x,gamma) is used to calculate pixel gamma, which produces slightly smoother line and polygon antialiasing than the 'linear' method, while other methods are usually only used to disable AA", - "doc": "An Antigrain Geometry specific rendering hint to control the quality of antialiasing. Under the hood in Mapnik this method is used in combination with the 'gamma' value (which defaults to 1). The methods are in the AGG source at https://github.com/mapnik/mapnik/blob/master/deps/agg/include/agg_gamma_functions.h" + "spacing": { + "css": "shield-spacing", + "type": "float", + "default-value": 0, + "doc": "The spacing between repeated occurrences of the same shield on a line" }, - "stroke-dasharray": { - "css": "line-dasharray", - "type": "numbers", - "doc": "A pair of length values [a,b], where (a) is the dash length and (b) is the gap length respectively. More than two values are supported for more complex patterns.", - "default-value": "none", - "default-meaning": "solid line" + "minimum-padding": { + "css": "shield-min-padding", + "default-value": 0, + "doc": "Determines the minimum amount of padding that a shield gets relative to other shields", + "type": "float" }, - "stroke-dashoffset": { - "css": "line-dash-offset", - "type": "numbers", - "doc": "valid parameter but not currently used in renderers (only exists for experimental svg support in Mapnik which is not yet enabled)", - "default-value": "none", - "default-meaning": "solid line" + "wrap-width": { + "css": "shield-wrap-width", + "type": "unsigned", + "default-value": 0, + "doc": "Length of a chunk of text in characters before wrapping text" }, - "stroke-miterlimit": { - "css": "line-miterlimit", + "wrap-before": { + "css": "shield-wrap-before", + "type": "boolean", + "default-value": false, + "doc": "Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width." + }, + "wrap-character": { + "css": "shield-wrap-character", + "type": "string", + "default-value": " ", + "doc": "Use this character instead of a space to wrap long names." + }, + "halo-fill": { + "css": "shield-halo-fill", + "type": "color", + "default-value": "#FFFFFF", + "default-meaning": "white", + "doc": "Specifies the color of the halo around the text." + }, + "halo-radius": { + "css": "shield-halo-radius", + "doc": "Specify the radius of the halo in pixels", + "default-value": 0, + "default-meaning": "no halo", + "type": "float" + }, + "character-spacing": { + "css": "shield-character-spacing", + "type": "unsigned", + "default-value": 0, + "doc": "Horizontal spacing between characters (in pixels). Currently works for point placement only, not line placement." + }, + "line-spacing": { + "css": "shield-line-spacing", + "doc": "Vertical spacing between lines of multiline labels (in pixels)", + "type": "unsigned" + }, + "dx": { + "css": "shield-text-dx", "type": "float", - "doc": "The limit on the ratio of the miter length to the stroke-width. Used to automatically convert miter joins to bevel joins for sharp angles to avoid the miter extending beyond the thickness of the stroking path. Normally will not need to be set, but a larger value can sometimes help avoid jaggy artifacts.", - "default-value": 4.0, - "default-meaning": "Will auto-convert miters to bevel line joins when theta is less than 29 degrees as per the SVG spec: 'miterLength / stroke-width = 1 / sin ( theta / 2 )'" + "doc": "Displace text within shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", + "default-value": 0 }, - "clip": { - "css": "line-clip", - "type": "boolean", - "default-value": true, - "default-meaning": "geometry will be clipped to map bounds before rendering", - "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." + "dy": { + "css": "shield-text-dy", + "type": "float", + "doc": "Displace text within shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", + "default-value": 0 }, - "smooth": { - "css": "line-smooth", + "shield-dx": { + "css": "shield-dx", "type": "float", - "default-value": 0, - "default-meaning": "no smoothing", - "range": "0-1", - "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." + "doc": "Displace shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", + "default-value": 0 }, - "offset": { - "css": "line-offset", + "shield-dy": { + "css": "shield-dy", "type": "float", - "default-value": 0, - "default-meaning": "no offset", - "doc": "Offsets a line a number of pixels parallel to its actual path. Postive values move the line left, negative values move it right (relative to the directionality of the line)." + "doc": "Displace shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", + "default-value": 0 }, - "rasterizer": { - "css": "line-rasterizer", + "opacity": { + "css": "shield-opacity", + "type": "float", + "doc": "(Default 1.0) - opacity of the image used for the shield", + "default-value": 1 + }, + "text-opacity": { + "css": "shield-text-opacity", + "type": "float", + "doc": "(Default 1.0) - opacity of the text placed on top of the shield", + "default-value": 1 + }, + "horizontal-alignment": { + "css": "shield-horizontal-alignment", "type": [ - "full", - "fast" + "left", + "middle", + "right", + "auto" ], - "default-value": "full", - "doc": "Exposes an alternate AGG rendering method that sacrifices some accuracy for speed." + "doc": "The shield's horizontal alignment from its centerpoint", + "default-value": "auto" }, - "geometry-transform": { - "css": "line-geometry-transform", - "type": "functions", - "default-value": "none", - "default-meaning": "geometry will not be transformed", - "doc": "Allows transformation functions to be applied to the geometry.", - "functions": [ - ["matrix", 6], - ["translate", 2], - ["scale", 2], - ["rotate", 3], - ["skewX", 1], - ["skewY", 1] - ] + "vertical-alignment": { + "css": "shield-vertical-alignment", + "type": [ + "top", + "middle", + "bottom", + "auto" + ], + "doc": "The shield's vertical alignment from its centerpoint", + "default-value": "middle" + }, + "text-transform": { + "css": "shield-text-transform", + "type": [ + "none", + "uppercase", + "lowercase", + "capitalize" + ], + "doc": "Transform the case of the characters", + "default-value": "none" + }, + "justify-alignment": { + "css": "shield-justify-alignment", + "type": [ + "left", + "center", + "right", + "auto" + ], + "doc": "Define how text in a shield's label is justified", + "default-value": "auto" + }, + "clip": { + "css": "shield-clip", + "type": "boolean", + "default-value": true, + "default-meaning": "geometry will be clipped to map bounds before rendering", + "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." }, "comp-op": { - "css": "line-comp-op", + "css": "shield-comp-op", "default-value": "src-over", "default-meaning": "add the current symbolizer on top of other symbolizer", "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", @@ -8994,127 +8845,35 @@ var _mapnik_reference_latest = { ] } }, - "markers": { + "line-pattern": { "file": { - "css": "marker-file", - "doc": "An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.", - "default-value": "", - "default-meaning": "An ellipse or circle, if width equals height", - "type": "uri" - }, - "opacity": { - "css": "marker-opacity", - "doc": "The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke", - "default-value": 1, - "default-meaning": "The stroke-opacity and fill-opacity will be used", - "type": "float" + "css": "line-pattern-file", + "type": "uri", + "default-value": "none", + "required": true, + "doc": "An image file to be repeated and warped along a line" }, - "fill-opacity": { - "css": "marker-fill-opacity", - "doc": "The fill opacity of the marker", - "default-value": 1, - "default-meaning": "opaque", - "type": "float" - }, - "stroke": { - "css": "marker-line-color", - "doc": "The color of the stroke around a marker shape.", - "default-value": "black", - "type": "color" - }, - "stroke-width": { - "css": "marker-line-width", - "doc": "The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.", - "type": "float" - }, - "stroke-opacity": { - "css": "marker-line-opacity", - "default-value": 1, - "default-meaning": "opaque", - "doc": "The opacity of a line", - "type": "float" - }, - "placement": { - "css": "marker-placement", - "type": [ - "point", - "line", - "interior" - ], - "default-value": "point", - "default-meaning": "Place markers at the center point (centroid) of the geometry", - "doc": "Attempt to place markers on a point, in the center of a polygon, or if markers-placement:line, then multiple times along a line. 'interior' placement can be used to ensure that points placed on polygons are forced to be inside the polygon interior" - }, - "multi-policy": { - "css": "marker-multi-policy", - "type": [ - "each", - "whole", - "largest" - ], - "default-value": "each", - "default-meaning": "If a feature contains multiple geometries and the placement type is either point or interior then a marker will be rendered for each", - "doc": "A special setting to allow the user to control rendering behavior for 'multi-geometries' (when a feature contains multiple geometries). This setting does not apply to markers placed along lines. The 'each' policy is default and means all geometries will get a marker. The 'whole' policy means that the aggregate centroid between all geometries will be used. The 'largest' policy means that only the largest (by bounding box areas) feature will get a rendered marker (this is how text labeling behaves by default)." - }, - "marker-type": { - "css": "marker-type", - "type": [ - "arrow", - "ellipse", - "rectangle" - ], - "default-value": "ellipse", - "doc": "The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an arrow or an ellipse (a circle if height is equal to width)" - }, - "width": { - "css": "marker-width", - "default-value": 10, - "doc": "The width of the marker, if using one of the default types.", - "type": "float", - "expression": true - }, - "height": { - "css": "marker-height", - "default-value": 10, - "doc": "The height of the marker, if using one of the default types.", - "type": "float", - "expression": true - }, - "fill": { - "css": "marker-fill", - "default-value": "blue", - "doc": "The color of the area of the marker.", - "type": "color" - }, - "allow-overlap": { - "css": "marker-allow-overlap", - "type": "boolean", - "default-value": false, - "doc": "Control whether overlapping markers are shown or hidden.", - "default-meaning": "Do not allow makers to overlap with each other - overlapping markers will not be shown." - }, - "ignore-placement": { - "css": "marker-ignore-placement", + "clip": { + "css": "line-pattern-clip", "type": "boolean", - "default-value": false, - "default-meaning": "do not store the bbox of this geometry in the collision detector cache", - "doc": "value to control whether the placement of the feature will prevent the placement of other features" - }, - "spacing": { - "css": "marker-spacing", - "doc": "Space between repeated labels", - "default-value": 100, - "type": "float" + "default-value": true, + "default-meaning": "geometry will be clipped to map bounds before rendering", + "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." }, - "max-error": { - "css": "marker-max-error", + "smooth": { + "css": "line-pattern-smooth", "type": "float", - "default-value": 0.2, - "doc": "The maximum difference between actual marker placement and the marker-spacing parameter. Setting a high value can allow the renderer to try to resolve placement conflicts with other symbolizers." + "default-value": 0, + "default-meaning": "no smoothing", + "range": "0-1", + "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." }, - "transform": { - "css": "marker-transform", + "geometry-transform": { + "css": "line-pattern-geometry-transform", "type": "functions", + "default-value": "none", + "default-meaning": "geometry will not be transformed", + "doc": "Allows transformation functions to be applied to the geometry.", "functions": [ ["matrix", 6], ["translate", 2], @@ -9122,20 +8881,91 @@ var _mapnik_reference_latest = { ["rotate", 3], ["skewX", 1], ["skewY", 1] + ] + }, + "comp-op": { + "css": "line-pattern-comp-op", + "default-value": "src-over", + "default-meaning": "add the current symbolizer on top of other symbolizer", + "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", + "type": ["clear", + "src", + "dst", + "src-over", + "dst-over", + "src-in", + "dst-in", + "src-out", + "dst-out", + "src-atop", + "dst-atop", + "xor", + "plus", + "minus", + "multiply", + "screen", + "overlay", + "darken", + "lighten", + "color-dodge", + "color-burn", + "hard-light", + "soft-light", + "difference", + "exclusion", + "contrast", + "invert", + "invert-rgb", + "grain-merge", + "grain-extract", + "hue", + "saturation", + "color", + "value" + ] + } + }, + "polygon-pattern": { + "file": { + "css": "polygon-pattern-file", + "type": "uri", + "default-value": "none", + "required": true, + "doc": "Image to use as a repeated pattern fill within a polygon" + }, + "alignment": { + "css": "polygon-pattern-alignment", + "type": [ + "local", + "global" ], - "default-value": "", - "default-meaning": "No transformation", - "doc": "SVG transformation definition" + "default-value": "local", + "doc": "Specify whether to align pattern fills to the layer or to the map." + }, + "gamma": { + "css": "polygon-pattern-gamma", + "type": "float", + "default-value": 1, + "default-meaning": "fully antialiased", + "range": "0-1", + "doc": "Level of antialiasing of polygon pattern edges" + }, + "opacity": { + "css": "polygon-pattern-opacity", + "type": "float", + "doc": "(Default 1.0) - Apply an opacity level to the image used for the pattern", + "default-value": 1, + "default-meaning": "The image is rendered without modifications" }, "clip": { - "css": "marker-clip", + "css": "polygon-pattern-clip", "type": "boolean", "default-value": true, "default-meaning": "geometry will be clipped to map bounds before rendering", "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." }, "smooth": { - "css": "marker-smooth", + "css": "polygon-pattern-smooth", "type": "float", "default-value": 0, "default-meaning": "no smoothing", @@ -9143,7 +8973,7 @@ var _mapnik_reference_latest = { "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." }, "geometry-transform": { - "css": "marker-geometry-transform", + "css": "polygon-pattern-geometry-transform", "type": "functions", "default-value": "none", "default-meaning": "geometry will not be transformed", @@ -9158,7 +8988,7 @@ var _mapnik_reference_latest = { ] }, "comp-op": { - "css": "marker-comp-op", + "css": "polygon-pattern-comp-op", "default-value": "src-over", "default-meaning": "add the current symbolizer on top of other symbolizer", "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", @@ -9199,220 +9029,56 @@ var _mapnik_reference_latest = { ] } }, - "shield": { - "name": { - "css": "shield-name", - "type": "string", - "expression": true, - "serialization": "content", - "doc": "Value to use for a shield\"s text label. Data columns are specified using brackets like [column_name]" - }, - "file": { - "css": "shield-file", - "required": true, - "type": "uri", - "default-value": "none", - "doc": "Image file to render behind the shield text" - }, - "face-name": { - "css": "shield-face-name", - "type": "string", - "validate": "font", - "doc": "Font name and style to use for the shield text", - "default-value": "", - "required": true - }, - "unlock-image": { - "css": "shield-unlock-image", - "type": "boolean", - "doc": "This parameter should be set to true if you are trying to position text beside rather than on top of the shield image", - "default-value": false, - "default-meaning": "text alignment relative to the shield image uses the center of the image as the anchor for text positioning." - }, - "size": { - "css": "shield-size", + "raster": { + "opacity": { + "css": "raster-opacity", + "default-value": 1, + "default-meaning": "opaque", "type": "float", - "doc": "The size of the shield text in pixels" + "doc": "The opacity of the raster symbolizer on top of other symbolizers." }, - "fill": { - "css": "shield-fill", - "type": "color", - "doc": "The color of the shield text" + "filter-factor": { + "css": "raster-filter-factor", + "default-value": -1, + "default-meaning": "Allow the datasource to choose appropriate downscaling.", + "type": "float", + "doc": "This is used by the Raster or Gdal datasources to pre-downscale images using overviews. Higher numbers can sometimes cause much better scaled image output, at the cost of speed." }, - "placement": { - "css": "shield-placement", + "scaling": { + "css": "raster-scaling", "type": [ - "point", - "line", - "vertex", - "interior" + "near", + "fast", + "bilinear", + "bilinear8", + "bicubic", + "spline16", + "spline36", + "hanning", + "hamming", + "hermite", + "kaiser", + "quadric", + "catrom", + "gaussian", + "bessel", + "mitchell", + "sinc", + "lanczos", + "blackman" ], - "default-value": "point", - "doc": "How this shield should be placed. Point placement attempts to place it on top of points, line places along lines multiple times per feature, vertex places on the vertexes of polygons, and interior attempts to place inside of polygons." - }, - "avoid-edges": { - "css": "shield-avoid-edges", - "doc": "Tell positioning algorithm to avoid labeling near intersection edges.", - "type": "boolean", - "default-value": false - }, - "allow-overlap": { - "css": "shield-allow-overlap", - "type": "boolean", - "default-value": false, - "doc": "Control whether overlapping shields are shown or hidden.", - "default-meaning": "Do not allow shields to overlap with other map elements already placed." - }, - "minimum-distance": { - "css": "shield-min-distance", - "type": "float", - "default-value": 0, - "doc": "Minimum distance to the next shield symbol, not necessarily the same shield." - }, - "spacing": { - "css": "shield-spacing", - "type": "float", - "default-value": 0, - "doc": "The spacing between repeated occurrences of the same shield on a line" - }, - "minimum-padding": { - "css": "shield-min-padding", - "default-value": 0, - "doc": "Determines the minimum amount of padding that a shield gets relative to other shields", - "type": "float" - }, - "wrap-width": { - "css": "shield-wrap-width", - "type": "unsigned", - "default-value": 0, - "doc": "Length of a chunk of text in characters before wrapping text" - }, - "wrap-before": { - "css": "shield-wrap-before", - "type": "boolean", - "default-value": false, - "doc": "Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width." - }, - "wrap-character": { - "css": "shield-wrap-character", - "type": "string", - "default-value": " ", - "doc": "Use this character instead of a space to wrap long names." - }, - "halo-fill": { - "css": "shield-halo-fill", - "type": "color", - "default-value": "#FFFFFF", - "default-meaning": "white", - "doc": "Specifies the color of the halo around the text." - }, - "halo-radius": { - "css": "shield-halo-radius", - "doc": "Specify the radius of the halo in pixels", - "default-value": 0, - "default-meaning": "no halo", - "type": "float" + "default-value": "near", + "doc": "The scaling algorithm used to making different resolution versions of this raster layer. Bilinear is a good compromise between speed and accuracy, while lanczos gives the highest quality." }, - "character-spacing": { - "css": "shield-character-spacing", + "mesh-size": { + "css": "raster-mesh-size", + "default-value": 16, + "default-meaning": "Reprojection mesh will be 1/16 of the resolution of the source image", "type": "unsigned", - "default-value": 0, - "doc": "Horizontal spacing between characters (in pixels). Currently works for point placement only, not line placement." - }, - "line-spacing": { - "css": "shield-line-spacing", - "doc": "Vertical spacing between lines of multiline labels (in pixels)", - "type": "unsigned" - }, - "dx": { - "css": "shield-text-dx", - "type": "float", - "doc": "Displace text within shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", - "default-value": 0 - }, - "dy": { - "css": "shield-text-dy", - "type": "float", - "doc": "Displace text within shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", - "default-value": 0 - }, - "shield-dx": { - "css": "shield-dx", - "type": "float", - "doc": "Displace shield by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", - "default-value": 0 - }, - "shield-dy": { - "css": "shield-dy", - "type": "float", - "doc": "Displace shield by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", - "default-value": 0 - }, - "opacity": { - "css": "shield-opacity", - "type": "float", - "doc": "(Default 1.0) - opacity of the image used for the shield", - "default-value": 1 - }, - "text-opacity": { - "css": "shield-text-opacity", - "type": "float", - "doc": "(Default 1.0) - opacity of the text placed on top of the shield", - "default-value": 1 - }, - "horizontal-alignment": { - "css": "shield-horizontal-alignment", - "type": [ - "left", - "middle", - "right", - "auto" - ], - "doc": "The shield's horizontal alignment from its centerpoint", - "default-value": "auto" - }, - "vertical-alignment": { - "css": "shield-vertical-alignment", - "type": [ - "top", - "middle", - "bottom", - "auto" - ], - "doc": "The shield's vertical alignment from its centerpoint", - "default-value": "middle" - }, - "text-transform": { - "css": "shield-text-transform", - "type": [ - "none", - "uppercase", - "lowercase", - "capitalize" - ], - "doc": "Transform the case of the characters", - "default-value": "none" - }, - "justify-alignment": { - "css": "shield-justify-alignment", - "type": [ - "left", - "center", - "right", - "auto" - ], - "doc": "Define how text in a shield's label is justified", - "default-value": "auto" - }, - "clip": { - "css": "shield-clip", - "type": "boolean", - "default-value": true, - "default-meaning": "geometry will be clipped to map bounds before rendering", - "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." + "doc": "A reduced resolution mesh is used for raster reprojection, and the total image size is divided by the mesh-size to determine the quality of that mesh. Values for mesh-size larger than the default will result in faster reprojection but might lead to distortion." }, "comp-op": { - "css": "shield-comp-op", + "css": "raster-comp-op", "default-value": "src-over", "default-meaning": "add the current symbolizer on top of other symbolizer", "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", @@ -9453,35 +9119,47 @@ var _mapnik_reference_latest = { ] } }, - "line-pattern": { + "point": { "file": { - "css": "line-pattern-file", + "css": "point-file", "type": "uri", + "required": false, "default-value": "none", - "required": true, - "doc": "An image file to be repeated and warped along a line" + "doc": "Image file to represent a point" }, - "clip": { - "css": "line-pattern-clip", + "allow-overlap": { + "css": "point-allow-overlap", "type": "boolean", - "default-value": true, - "default-meaning": "geometry will be clipped to map bounds before rendering", - "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." + "default-value": false, + "doc": "Control whether overlapping points are shown or hidden.", + "default-meaning": "Do not allow points to overlap with each other - overlapping markers will not be shown." }, - "smooth": { - "css": "line-pattern-smooth", + "ignore-placement": { + "css": "point-ignore-placement", + "type": "boolean", + "default-value": false, + "default-meaning": "do not store the bbox of this geometry in the collision detector cache", + "doc": "value to control whether the placement of the feature will prevent the placement of other features" + }, + "opacity": { + "css": "point-opacity", "type": "float", - "default-value": 0, - "default-meaning": "no smoothing", - "range": "0-1", - "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." + "default-value": 1.0, + "default-meaning": "Fully opaque", + "doc": "A value from 0 to 1 to control the opacity of the point" }, - "geometry-transform": { - "css": "line-pattern-geometry-transform", + "placement": { + "css": "point-placement", + "type": [ + "centroid", + "interior" + ], + "doc": "How this point should be placed. Centroid calculates the geometric center of a polygon, which can be outside of it, while interior always places inside of a polygon.", + "default-value": "centroid" + }, + "transform": { + "css": "point-transform", "type": "functions", - "default-value": "none", - "default-meaning": "geometry will not be transformed", - "doc": "Allows transformation functions to be applied to the geometry.", "functions": [ ["matrix", 6], ["translate", 2], @@ -9489,10 +9167,13 @@ var _mapnik_reference_latest = { ["rotate", 3], ["skewX", 1], ["skewY", 1] - ] + ], + "default-value": "", + "default-meaning": "No transformation", + "doc": "SVG transformation definition" }, "comp-op": { - "css": "line-pattern-comp-op", + "css": "point-comp-op", "default-value": "src-over", "default-meaning": "add the current symbolizer on top of other symbolizer", "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", @@ -9533,427 +9214,138 @@ var _mapnik_reference_latest = { ] } }, - "polygon-pattern": { - "file": { - "css": "polygon-pattern-file", - "type": "uri", - "default-value": "none", + "text": { + "name": { + "css": "text-name", + "type": "string", + "expression": true, "required": true, - "doc": "Image to use as a repeated pattern fill within a polygon" + "default-value": "", + "serialization": "content", + "doc": "Value to use for a text label. Data columns are specified using brackets like [column_name]" }, - "alignment": { - "css": "polygon-pattern-alignment", - "type": [ - "local", - "global" - ], - "default-value": "local", - "doc": "Specify whether to align pattern fills to the layer or to the map." + "face-name": { + "css": "text-face-name", + "type": "string", + "validate": "font", + "doc": "Font name and style to render a label in", + "required": true }, - "gamma": { - "css": "polygon-pattern-gamma", + "size": { + "css": "text-size", "type": "float", - "default-value": 1, - "default-meaning": "fully antialiased", - "range": "0-1", - "doc": "Level of antialiasing of polygon pattern edges" + "default-value": 10, + "doc": "Text size in pixels" }, - "opacity": { - "css": "polygon-pattern-opacity", - "type": "float", - "doc": "(Default 1.0) - Apply an opacity level to the image used for the pattern", - "default-value": 1, - "default-meaning": "The image is rendered without modifications" + "text-ratio": { + "css": "text-ratio", + "doc": "Define the amount of text (of the total) present on successive lines when wrapping occurs", + "default-value": 0, + "type": "unsigned" }, - "clip": { - "css": "polygon-pattern-clip", + "wrap-width": { + "css": "text-wrap-width", + "doc": "Length of a chunk of text in characters before wrapping text", + "default-value": 0, + "type": "unsigned" + }, + "wrap-before": { + "css": "text-wrap-before", "type": "boolean", - "default-value": true, - "default-meaning": "geometry will be clipped to map bounds before rendering", - "doc": "geometries are clipped to map bounds by default for best rendering performance. In some cases users may wish to disable this to avoid rendering artifacts." + "default-value": false, + "doc": "Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width." }, - "smooth": { - "css": "polygon-pattern-smooth", + "wrap-character": { + "css": "text-wrap-character", + "type": "string", + "default-value": " ", + "doc": "Use this character instead of a space to wrap long text." + }, + "spacing": { + "css": "text-spacing", + "type": "unsigned", + "doc": "Distance between repeated text labels on a line (aka. label-spacing)" + }, + "character-spacing": { + "css": "text-character-spacing", "type": "float", "default-value": 0, - "default-meaning": "no smoothing", - "range": "0-1", - "doc": "Smooths out geometry angles. 0 is no smoothing, 1 is fully smoothed. Values greater than 1 will produce wild, looping geometries." + "doc": "Horizontal spacing adjustment between characters in pixels" }, - "geometry-transform": { - "css": "polygon-pattern-geometry-transform", - "type": "functions", - "default-value": "none", - "default-meaning": "geometry will not be transformed", - "doc": "Allows transformation functions to be applied to the geometry.", - "functions": [ - ["matrix", 6], - ["translate", 2], - ["scale", 2], - ["rotate", 3], - ["skewX", 1], - ["skewY", 1] - ] + "line-spacing": { + "css": "text-line-spacing", + "default-value": 0, + "type": "unsigned", + "doc": "Vertical spacing adjustment between lines in pixels" + }, + "label-position-tolerance": { + "css": "text-label-position-tolerance", + "default-value": 0, + "type": "unsigned", + "doc": "Allows the label to be displaced from its ideal position by a number of pixels (only works with placement:line)" + }, + "max-char-angle-delta": { + "css": "text-max-char-angle-delta", + "type": "float", + "default-value": "22.5", + "doc": "The maximum angle change, in degrees, allowed between adjacent characters in a label. This value internally is converted to radians to the default is 22.5*math.pi/180.0. The higher the value the fewer labels will be placed around around sharp corners." + }, + "fill": { + "css": "text-fill", + "doc": "Specifies the color for the text", + "default-value": "#000000", + "type": "color" }, - "comp-op": { - "css": "polygon-pattern-comp-op", - "default-value": "src-over", - "default-meaning": "add the current symbolizer on top of other symbolizer", - "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", - "type": ["clear", - "src", - "dst", - "src-over", - "dst-over", - "src-in", - "dst-in", - "src-out", - "dst-out", - "src-atop", - "dst-atop", - "xor", - "plus", - "minus", - "multiply", - "screen", - "overlay", - "darken", - "lighten", - "color-dodge", - "color-burn", - "hard-light", - "soft-light", - "difference", - "exclusion", - "contrast", - "invert", - "invert-rgb", - "grain-merge", - "grain-extract", - "hue", - "saturation", - "color", - "value" - ] - } - }, - "raster": { "opacity": { - "css": "raster-opacity", - "default-value": 1, - "default-meaning": "opaque", + "css": "text-opacity", + "doc": "A number from 0 to 1 specifying the opacity for the text", + "default-value": 1.0, + "default-meaning": "Fully opaque", + "type": "float" + }, + "halo-fill": { + "css": "text-halo-fill", + "type": "color", + "default-value": "#FFFFFF", + "default-meaning": "white", + "doc": "Specifies the color of the halo around the text." + }, + "halo-radius": { + "css": "text-halo-radius", + "doc": "Specify the radius of the halo in pixels", + "default-value": 0, + "default-meaning": "no halo", + "type": "float" + }, + "dx": { + "css": "text-dx", "type": "float", - "doc": "The opacity of the raster symbolizer on top of other symbolizers." + "doc": "Displace text by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", + "default-value": 0 }, - "filter-factor": { - "css": "raster-filter-factor", - "default-value": -1, - "default-meaning": "Allow the datasource to choose appropriate downscaling.", + "dy": { + "css": "text-dy", "type": "float", - "doc": "This is used by the Raster or Gdal datasources to pre-downscale images using overviews. Higher numbers can sometimes cause much better scaled image output, at the cost of speed." + "doc": "Displace text by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", + "default-value": 0 }, - "scaling": { - "css": "raster-scaling", + "vertical-alignment": { + "css": "text-vertical-alignment", "type": [ - "near", - "fast", - "bilinear", - "bilinear8", - "bicubic", - "spline16", - "spline36", - "hanning", - "hamming", - "hermite", - "kaiser", - "quadric", - "catrom", - "gaussian", - "bessel", - "mitchell", - "sinc", - "lanczos", - "blackman" + "top", + "middle", + "bottom", + "auto" ], - "default-value": "near", - "doc": "The scaling algorithm used to making different resolution versions of this raster layer. Bilinear is a good compromise between speed and accuracy, while lanczos gives the highest quality." + "doc": "Position of label relative to point position.", + "default-value": "auto", + "default-meaning": "Default affected by value of dy; \"bottom\" for dy>0, \"top\" for dy<0." }, - "mesh-size": { - "css": "raster-mesh-size", - "default-value": 16, - "default-meaning": "Reprojection mesh will be 1/16 of the resolution of the source image", - "type": "unsigned", - "doc": "A reduced resolution mesh is used for raster reprojection, and the total image size is divided by the mesh-size to determine the quality of that mesh. Values for mesh-size larger than the default will result in faster reprojection but might lead to distortion." - }, - "comp-op": { - "css": "raster-comp-op", - "default-value": "src-over", - "default-meaning": "add the current symbolizer on top of other symbolizer", - "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", - "type": ["clear", - "src", - "dst", - "src-over", - "dst-over", - "src-in", - "dst-in", - "src-out", - "dst-out", - "src-atop", - "dst-atop", - "xor", - "plus", - "minus", - "multiply", - "screen", - "overlay", - "darken", - "lighten", - "color-dodge", - "color-burn", - "hard-light", - "soft-light", - "difference", - "exclusion", - "contrast", - "invert", - "invert-rgb", - "grain-merge", - "grain-extract", - "hue", - "saturation", - "color", - "value" - ] - } - }, - "point": { - "file": { - "css": "point-file", - "type": "uri", - "required": false, - "default-value": "none", - "doc": "Image file to represent a point" - }, - "allow-overlap": { - "css": "point-allow-overlap", - "type": "boolean", - "default-value": false, - "doc": "Control whether overlapping points are shown or hidden.", - "default-meaning": "Do not allow points to overlap with each other - overlapping markers will not be shown." - }, - "ignore-placement": { - "css": "point-ignore-placement", - "type": "boolean", - "default-value": false, - "default-meaning": "do not store the bbox of this geometry in the collision detector cache", - "doc": "value to control whether the placement of the feature will prevent the placement of other features" - }, - "opacity": { - "css": "point-opacity", - "type": "float", - "default-value": 1.0, - "default-meaning": "Fully opaque", - "doc": "A value from 0 to 1 to control the opacity of the point" - }, - "placement": { - "css": "point-placement", - "type": [ - "centroid", - "interior" - ], - "doc": "How this point should be placed. Centroid calculates the geometric center of a polygon, which can be outside of it, while interior always places inside of a polygon.", - "default-value": "centroid" - }, - "transform": { - "css": "point-transform", - "type": "functions", - "functions": [ - ["matrix", 6], - ["translate", 2], - ["scale", 2], - ["rotate", 3], - ["skewX", 1], - ["skewY", 1] - ], - "default-value": "", - "default-meaning": "No transformation", - "doc": "SVG transformation definition" - }, - "comp-op": { - "css": "point-comp-op", - "default-value": "src-over", - "default-meaning": "add the current symbolizer on top of other symbolizer", - "doc": "Composite operation. This defines how this symbolizer should behave relative to symbolizers atop or below it.", - "type": ["clear", - "src", - "dst", - "src-over", - "dst-over", - "src-in", - "dst-in", - "src-out", - "dst-out", - "src-atop", - "dst-atop", - "xor", - "plus", - "minus", - "multiply", - "screen", - "overlay", - "darken", - "lighten", - "color-dodge", - "color-burn", - "hard-light", - "soft-light", - "difference", - "exclusion", - "contrast", - "invert", - "invert-rgb", - "grain-merge", - "grain-extract", - "hue", - "saturation", - "color", - "value" - ] - } - }, - "text": { - "name": { - "css": "text-name", - "type": "string", - "expression": true, - "required": true, - "default-value": "", - "serialization": "content", - "doc": "Value to use for a text label. Data columns are specified using brackets like [column_name]" - }, - "face-name": { - "css": "text-face-name", - "type": "string", - "validate": "font", - "doc": "Font name and style to render a label in", - "required": true - }, - "size": { - "css": "text-size", - "type": "float", - "default-value": 10, - "doc": "Text size in pixels" - }, - "text-ratio": { - "css": "text-ratio", - "doc": "Define the amount of text (of the total) present on successive lines when wrapping occurs", - "default-value": 0, - "type": "unsigned" - }, - "wrap-width": { - "css": "text-wrap-width", - "doc": "Length of a chunk of text in characters before wrapping text", - "default-value": 0, - "type": "unsigned" - }, - "wrap-before": { - "css": "text-wrap-before", - "type": "boolean", - "default-value": false, - "doc": "Wrap text before wrap-width is reached. If false, wrapped lines will be a bit longer than wrap-width." - }, - "wrap-character": { - "css": "text-wrap-character", - "type": "string", - "default-value": " ", - "doc": "Use this character instead of a space to wrap long text." - }, - "spacing": { - "css": "text-spacing", - "type": "unsigned", - "doc": "Distance between repeated text labels on a line (aka. label-spacing)" - }, - "character-spacing": { - "css": "text-character-spacing", - "type": "float", - "default-value": 0, - "doc": "Horizontal spacing adjustment between characters in pixels" - }, - "line-spacing": { - "css": "text-line-spacing", - "default-value": 0, - "type": "unsigned", - "doc": "Vertical spacing adjustment between lines in pixels" - }, - "label-position-tolerance": { - "css": "text-label-position-tolerance", - "default-value": 0, - "type": "unsigned", - "doc": "Allows the label to be displaced from its ideal position by a number of pixels (only works with placement:line)" - }, - "max-char-angle-delta": { - "css": "text-max-char-angle-delta", - "type": "float", - "default-value": "22.5", - "doc": "The maximum angle change, in degrees, allowed between adjacent characters in a label. This value internally is converted to radians to the default is 22.5*math.pi/180.0. The higher the value the fewer labels will be placed around around sharp corners." - }, - "fill": { - "css": "text-fill", - "doc": "Specifies the color for the text", - "default-value": "#000000", - "type": "color" - }, - "opacity": { - "css": "text-opacity", - "doc": "A number from 0 to 1 specifying the opacity for the text", - "default-value": 1.0, - "default-meaning": "Fully opaque", - "type": "float" - }, - "halo-fill": { - "css": "text-halo-fill", - "type": "color", - "default-value": "#FFFFFF", - "default-meaning": "white", - "doc": "Specifies the color of the halo around the text." - }, - "halo-radius": { - "css": "text-halo-radius", - "doc": "Specify the radius of the halo in pixels", - "default-value": 0, - "default-meaning": "no halo", - "type": "float" - }, - "dx": { - "css": "text-dx", - "type": "float", - "doc": "Displace text by fixed amount, in pixels, +/- along the X axis. A positive value will shift the text right", - "default-value": 0 - }, - "dy": { - "css": "text-dy", - "type": "float", - "doc": "Displace text by fixed amount, in pixels, +/- along the Y axis. A positive value will shift the text down", - "default-value": 0 - }, - "vertical-alignment": { - "css": "text-vertical-alignment", - "type": [ - "top", - "middle", - "bottom", - "auto" - ], - "doc": "Position of label relative to point position.", - "default-value": "auto", - "default-meaning": "Default affected by value of dy; \"bottom\" for dy>0, \"top\" for dy<0." - }, - "avoid-edges": { - "css": "text-avoid-edges", - "doc": "Tell positioning algorithm to avoid labeling near intersection edges.", - "default-value": false, - "type": "boolean" + "avoid-edges": { + "css": "text-avoid-edges", + "doc": "Tell positioning algorithm to avoid labeling near intersection edges.", + "default-value": false, + "type": "boolean" }, "minimum-distance": { "css": "text-min-distance", @@ -10093,3922 +9485,5090 @@ var _mapnik_reference_latest = { "value" ] } - }, - "building": { - "fill": { - "css": "building-fill", - "default-value": "#FFFFFF", - "doc": "The color of the buildings walls.", - "type": "color" - }, - "fill-opacity": { - "css": "building-fill-opacity", - "type": "float", - "doc": "The opacity of the building as a whole, including all walls.", - "default-value": 1 - }, - "height": { - "css": "building-height", - "doc": "The height of the building in pixels.", - "type": "float", - "expression": true, - "default-value": "0" + }, + "building": { + "fill": { + "css": "building-fill", + "default-value": "#FFFFFF", + "doc": "The color of the buildings walls.", + "type": "color" + }, + "fill-opacity": { + "css": "building-fill-opacity", + "type": "float", + "doc": "The opacity of the building as a whole, including all walls.", + "default-value": 1 + }, + "height": { + "css": "building-height", + "doc": "The height of the building in pixels.", + "type": "float", + "expression": true, + "default-value": "0" + } + }, + "torque": { + "-torque-clear-color": { + "css": "-torque-clear-color", + "type": "color", + "default-value": "rgba(255, 255, 255, 0)", + "default-meaning": "full clear", + "doc": "color used to clear canvas on each frame" + }, + "-torque-frame-count": { + "css": "-torque-frame-count", + "default-value": "128", + "type":"float", + "default-meaning": "the data is broken into 128 time frames", + "doc": "Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used." + }, + "-torque-resolution": { + "css": "-torque-resolution", + "default-value": "2", + "type":"float", + "default-meaning": "", + "doc": "Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2" + }, + "-torque-animation-duration": { + "css": "-torque-animation-duration", + "default-value": "30", + "type":"float", + "default-meaning": "the animation lasts 30 seconds", + "doc": "Animation duration in seconds" + }, + "-torque-aggregation-function": { + "css": "-torque-aggregation-function", + "default-value": "count(cartodb_id)", + "type": "string", + "default-meaning": "the value for each cell is the count of points in that cell", + "doc": "A function used to calculate a value from the aggregate data for each cell. See -torque-resolution" + }, + "-torque-time-attribute": { + "css": "-torque-time-attribute", + "default-value": "time", + "type": "string", + "default-meaning": "the data column in your table that is of a time based type", + "doc": "The table column that contains the time information used create the animation" + }, + "-torque-data-aggregation": { + "css": "-torque-data-aggregation", + "default-value": "linear", + "type": [ + "linear", + "cumulative" + ], + "default-meaning": "previous values are discarded", + "doc": "A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts" + } + } + }, + "colors": { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255,235,205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "grey": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50], + "transparent": [0, 0, 0, 0] + }, + "filter": { + "value": [ + "true", + "false", + "null", + "point", + "linestring", + "polygon", + "collection" + ] + } +} + +module.exports = { + version: { + latest: _mapnik_reference_latest, + '2.1.1': _mapnik_reference_latest + } +}; + +},{}],37:[function(require,module,exports){ +/** + * TODO: document this. What does this do? + */ +if(typeof(module) !== "undefined") { + module.exports.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r; } + } + return null; + }; +} + +},{}],38:[function(require,module,exports){ +(function (global){ +(function(tree) { +var _ = global._ || require('underscore'); +tree.Call = function Call(name, args, index) { + this.name = name; + this.args = args; + this.index = index; +}; + +tree.Call.prototype = { + is: 'call', + // When evuating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // The *functions.js* file contains the built-in functions. + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + 'ev': function(env) { + var args = this.args.map(function(a) { return a.ev(env); }); + + for (var i = 0; i < args.length; i++) { + if (args[i].is === 'undefined') { + return { + is: 'undefined', + value: 'undefined' + }; + } + } + + if (this.name in tree.functions) { + if (tree.functions[this.name].length <= args.length) { + var val = tree.functions[this.name].apply(tree.functions, args); + if (val === null) { + env.error({ + message: 'incorrect arguments given to ' + this.name + '()', + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { is: 'undefined', value: 'undefined' }; + } + return val; + } else { + env.error({ + message: 'incorrect number of arguments for ' + this.name + + '(). ' + tree.functions[this.name].length + ' expected.', + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } + } else { + var fn = tree.Reference.mapnikFunctions[this.name]; + if (fn === undefined) { + var functions = _.pairs(tree.Reference.mapnikFunctions); + // cheap closest, needs improvement. + var name = this.name; + var mean = functions.map(function(f) { + return [f[0], tree.Reference.editDistance(name, f[0]), f[1]]; + }).sort(function(a, b) { + return a[1] - b[1]; + }); + env.error({ + message: 'unknown function ' + this.name + '(), did you mean ' + + mean[0][0] + '(' + mean[0][2] + ')', + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } + if (fn !== args.length && + !(Array.isArray(fn) && _.include(fn, args.length)) && + // support variable-arg functions like `colorize-alpha` + fn !== -1) { + env.error({ + message: 'function ' + this.name + '() takes ' + + fn + ' arguments and was given ' + args.length, + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } else { + // Save the evaluated versions of arguments + this.args = args; + return this; + } + } + }, + + toString: function(env, format) { + if (this.args.length) { + return this.name + '(' + this.args.join(',') + ')'; + } else { + return this.name; + } + } +}; + +})(require('../tree')); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"underscore":71}],39:[function(require,module,exports){ +(function(tree) { +// RGB Colors - #ff0014, #eee +// can be initialized with a 3 or 6 char string or a 3 or 4 element +// numerical array +tree.Color = function Color(rgb, a) { + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + if (Array.isArray(rgb)) { + this.rgb = rgb.slice(0, 3); + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function(c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function(c) { + return parseInt(c + c, 16); + }); + } + + if (typeof(a) === 'number') { + this.alpha = a; + } else if (rgb.length === 4) { + this.alpha = rgb[3]; + } else { + this.alpha = 1; + } +}; + +tree.Color.prototype = { + is: 'color', + 'ev': function() { return this; }, + + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + toString: function() { + if (this.alpha < 1.0) { + return 'rgba(' + this.rgb.map(function(c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ')'; + } else { + return '#' + this.rgb.map(function(i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } + }, + + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + operate: function(env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new tree.Color(result); + }, + + toHSL: function() { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + } +}; + +})(require('../tree')); + +},{"../tree":37}],40:[function(require,module,exports){ +(function(tree) { + +tree.Comment = function Comment(value, silent) { + this.value = value; + this.silent = !!silent; +}; + +tree.Comment.prototype = { + toString: function(env) { + return ''; + }, + 'ev': function() { return this; } +}; + +})(require('../tree')); + +},{"../tree":37}],41:[function(require,module,exports){ +(function (global){ +(function(tree) { +var assert = require('assert'), + _ = global._ || require('underscore'); + +// A definition is the combination of a selector and rules, like +// #foo { +// polygon-opacity:1.0; +// } +// +// The selector can have filters +tree.Definition = function Definition(selector, rules) { + this.elements = selector.elements; + assert.ok(selector.filters instanceof tree.Filterset); + this.rules = rules; + this.ruleIndex = {}; + for (var i = 0; i < this.rules.length; i++) { + if ('zoom' in this.rules[i]) this.rules[i] = this.rules[i].clone(); + this.rules[i].zoom = selector.zoom; + this.ruleIndex[this.rules[i].updateID()] = true; + } + this.filters = selector.filters; + this.zoom = selector.zoom; + this.frame_offset = selector.frame_offset; + this.attachment = selector.attachment || '__default__'; + this.specificity = selector.specificity(); +}; + +tree.Definition.prototype.toString = function() { + var str = this.filters.toString(); + for (var i = 0; i < this.rules.length; i++) { + str += '\n ' + this.rules[i]; + } + return str; +}; + +tree.Definition.prototype.clone = function(filters) { + if (filters) assert.ok(filters instanceof tree.Filterset); + var clone = Object.create(tree.Definition.prototype); + clone.rules = this.rules.slice(); + clone.ruleIndex = _.clone(this.ruleIndex); + clone.filters = filters ? filters : this.filters.clone(); + clone.attachment = this.attachment; + return clone; +}; + +tree.Definition.prototype.addRules = function(rules) { + var added = 0; + + // Add only unique rules. + for (var i = 0; i < rules.length; i++) { + if (!this.ruleIndex[rules[i].id]) { + this.rules.push(rules[i]); + this.ruleIndex[rules[i].id] = true; + added++; + } + } + + return added; +}; + +// Determine whether this selector matches a given id +// and array of classes, by determining whether +// all elements it contains match. +tree.Definition.prototype.appliesTo = function(id, classes) { + for (var i = 0, l = this.elements.length; i < l; i++) { + var elem = this.elements[i]; + if (!(elem.wildcard || + (elem.type === 'class' && classes[elem.clean]) || + (elem.type === 'id' && id === elem.clean))) return false; + } + return true; +}; + +function symbolizerName(symbolizer) { + function capitalize(str) { return str[1].toUpperCase(); } + return symbolizer.charAt(0).toUpperCase() + + symbolizer.slice(1).replace(/\-./, capitalize) + 'Symbolizer'; +} + +// Get a simple list of the symbolizers, in order +function symbolizerList(sym_order) { + return sym_order.sort(function(a, b) { return a[1] - b[1]; }) + .map(function(v) { return v[0]; }); +} + +tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { + var xml = zoom.toXML(env).join('') + this.filters.toXML(env); + + // Sort symbolizers by the index of their first property definition + var sym_order = [], indexes = []; + for (var key in symbolizers) { + indexes = []; + for (var prop in symbolizers[key]) { + indexes.push(symbolizers[key][prop].index); + } + var min_idx = Math.min.apply(Math, indexes); + sym_order.push([key, min_idx]); + } + + sym_order = symbolizerList(sym_order); + var sym_count = 0; + + for (var i = 0; i < sym_order.length; i++) { + var attributes = symbolizers[sym_order[i]]; + var symbolizer = sym_order[i].split('/').pop(); + + // Skip the magical * symbolizer which is used for universal properties + // which are bubbled up to Style elements intead of Symbolizer elements. + if (symbolizer === '*') continue; + sym_count++; + + var fail = tree.Reference.requiredProperties(symbolizer, attributes); + if (fail) { + var rule = attributes[Object.keys(attributes).shift()]; + env.error({ + message: fail, + index: rule.index, + filename: rule.filename + }); + } + + var name = symbolizerName(symbolizer); + + var selfclosing = true, tagcontent; + xml += ' <' + name + ' '; + for (var j in attributes) { + if (symbolizer === 'map') env.error({ + message: 'Map properties are not permitted in other rules', + index: attributes[j].index, + filename: attributes[j].filename + }); + var x = tree.Reference.selector(attributes[j].name); + if (x && x.serialization && x.serialization === 'content') { + selfclosing = false; + tagcontent = attributes[j].ev(env).toXML(env, true); + } else if (x && x.serialization && x.serialization === 'tag') { + selfclosing = false; + tagcontent = attributes[j].ev(env).toXML(env, true); + } else { + xml += attributes[j].ev(env).toXML(env) + ' '; + } + } + if (selfclosing) { + xml += '/>\n'; + } else if (typeof tagcontent !== "undefined") { + if (tagcontent.indexOf('<') != -1) { + xml += '>' + tagcontent + '\n'; + } else { + xml += '>\n'; } - }, - "torque": { - "-torque-clear-color": { - "css": "-torque-clear-color", - "type": "color", - "default-value": "rgba(255, 255, 255, 0)", - "default-meaning": "full clear", - "doc": "color used to clear canvas on each frame" - }, - "-torque-frame-count": { - "css": "-torque-frame-count", - "default-value": "128", - "type":"float", - "default-meaning": "the data is broken into 128 time frames", - "doc": "Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used." - }, - "-torque-resolution": { - "css": "-torque-resolution", - "default-value": "2", - "type":"float", - "default-meaning": "", - "doc": "Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2" - }, - "-torque-animation-duration": { - "css": "-torque-animation-duration", - "default-value": "30", - "type":"float", - "default-meaning": "the animation lasts 30 seconds", - "doc": "Animation duration in seconds" - }, - "-torque-aggregation-function": { - "css": "-torque-aggregation-function", - "default-value": "count(cartodb_id)", - "type": "string", - "default-meaning": "the value for each cell is the count of points in that cell", - "doc": "A function used to calculate a value from the aggregate data for each cell. See -torque-resolution" - }, - "-torque-time-attribute": { - "css": "-torque-time-attribute", - "default-value": "time", - "type": "string", - "default-meaning": "the data column in your table that is of a time based type", - "doc": "The table column that contains the time information used create the animation" - }, - "-torque-data-aggregation": { - "css": "-torque-data-aggregation", - "default-value": "linear", - "type": [ - "linear", - "cumulative" - ], - "default-meaning": "previous values are discarded", - "doc": "A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts" - } + } + } + if (!sym_count || !xml) return ''; + return ' \n' + xml + ' \n'; +}; + +// Take a zoom range of zooms and 'i', the index of a rule in this.rules, +// and finds all applicable symbolizers +tree.Definition.prototype.collectSymbolizers = function(zooms, i) { + var symbolizers = {}, child; + + for (var j = i; j < this.rules.length; j++) { + child = this.rules[j]; + var key = child.instance + '/' + child.symbolizer; + if (zooms.current & child.zoom && + (!(key in symbolizers) || + (!(child.name in symbolizers[key])))) { + zooms.current &= child.zoom; + if (!(key in symbolizers)) { + symbolizers[key] = {}; + } + symbolizers[key][child.name] = child; + } + } + + if (Object.keys(symbolizers).length) { + zooms.rule &= (zooms.available &= ~zooms.current); + return symbolizers; + } +}; + +// The tree.Zoom.toString function ignores the holes in zoom ranges and outputs +// scaledenominators that cover the whole range from the first to last bit set. +// This algorithm can produces zoom ranges that may have holes. However, +// when using the filter-mode="first", more specific zoom filters will always +// end up before broader ranges. The filter-mode will pick those first before +// resorting to the zoom range with the hole and stop processing further rules. +tree.Definition.prototype.toXML = function(env, existing) { + var filter = this.filters.toString(); + if (!(filter in existing)) existing[filter] = tree.Zoom.all; + + var available = tree.Zoom.all, xml = '', zoom, symbolizers, + zooms = { available: tree.Zoom.all }; + for (var i = 0; i < this.rules.length && available; i++) { + zooms.rule = this.rules[i].zoom; + if (!(existing[filter] & zooms.rule)) continue; + + while (zooms.current = zooms.rule & available) { + if (symbolizers = this.collectSymbolizers(zooms, i)) { + if (!(existing[filter] & zooms.current)) continue; + xml += this.symbolizersToXML(env, symbolizers, + (new tree.Zoom()).setZoom(existing[filter] & zooms.current)); + existing[filter] &= ~zooms.current; + } + } + } + + return xml; +}; + +tree.Definition.prototype.toJS = function(env) { + var shaderAttrs = {}; + + // merge conditions from filters with zoom condition of the + // definition + var zoom = "(" + this.zoom + " & (1 << ctx.zoom))"; + var frame_offset = this.frame_offset; + var _if = this.filters.toJS(env); + var filters = [zoom]; + if(_if) filters.push(_if); + if(frame_offset) filters.push('ctx["frame-offset"] === ' + frame_offset); + _if = filters.join(" && "); + _.each(this.rules, function(rule) { + if(rule instanceof tree.Rule) { + shaderAttrs[rule.name] = shaderAttrs[rule.name] || []; + + var r = { + index: rule.index, + symbolizer: rule.symbolizer + }; + + if (_if) { + r.js = "if(" + _if + "){" + rule.value.toJS(env) + "}" + } else { + r.js = rule.value.toJS(env); + } + + r.constant = rule.value.ev(env).is !== 'field'; + r.filtered = !!_if; + + shaderAttrs[rule.name].push(r); + } else { + throw new Error("Ruleset not supported"); + //if (rule instanceof tree.Ruleset) { + //var sh = rule.toJS(env); + //for(var v in sh) { + //shaderAttrs[v] = shaderAttrs[v] || []; + //for(var attr in sh[v]) { + //shaderAttrs[v].push(sh[v][attr]); + //} + //} + //} + } + }); + return shaderAttrs; +}; + + +})(require('../tree')); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"assert":29,"underscore":71}],42:[function(require,module,exports){ +(function (global){ +(function(tree) { +var _ = global._ || require('underscore'); +// +// A number with a unit +// +tree.Dimension = function Dimension(value, unit, index) { + this.value = parseFloat(value); + this.unit = unit || null; + this.index = index; +}; + +tree.Dimension.prototype = { + is: 'float', + physical_units: ['m', 'cm', 'in', 'mm', 'pt', 'pc'], + screen_units: ['px', '%'], + all_units: ['m', 'cm', 'in', 'mm', 'pt', 'pc', 'px', '%'], + densities: { + m: 0.0254, + mm: 25.4, + cm: 2.54, + pt: 72, + pc: 6 + }, + ev: function (env) { + if (this.unit && !_.contains(this.all_units, this.unit)) { + env.error({ + message: "Invalid unit: '" + this.unit + "'", + index: this.index + }); + return { is: 'undefined', value: 'undefined' }; + } + + // normalize units which are not px or % + if (this.unit && _.contains(this.physical_units, this.unit)) { + if (!env.ppi) { + env.error({ + message: "ppi is not set, so metric units can't be used", + index: this.index + }); + return { is: 'undefined', value: 'undefined' }; + } + // convert all units to inch + // convert inch to px using ppi + this.value = (this.value / this.densities[this.unit]) * env.ppi; + this.unit = 'px'; + } + + return this; + }, + round: function() { + this.value = Math.round(this.value); + return this; + }, + toColor: function() { + return new tree.Color([this.value, this.value, this.value]); + }, + round: function() { + this.value = Math.round(this.value); + return this; + }, + toString: function() { + return this.value.toString(); + }, + operate: function(env, op, other) { + if (this.unit === '%' && other.unit !== '%') { + env.error({ + message: 'If two operands differ, the first must not be %', + index: this.index + }); + return { + is: 'undefined', + value: 'undefined' + }; + } + + if (this.unit !== '%' && other.unit === '%') { + if (op === '*' || op === '/' || op === '%') { + env.error({ + message: 'Percent values can only be added or subtracted from other values', + index: this.index + }); + return { + is: 'undefined', + value: 'undefined' + }; + } + + return new tree.Dimension(tree.operate(op, + this.value, this.value * other.value * 0.01), + this.unit); + } + + //here the operands are either the same (% or undefined or px), or one is undefined and the other is px + return new tree.Dimension(tree.operate(op, this.value, other.value), + this.unit || other.unit); + } +}; + +})(require('../tree')); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"underscore":71}],43:[function(require,module,exports){ +(function(tree) { + +// An element is an id or class selector +tree.Element = function Element(value) { + this.value = value.trim(); + if (this.value[0] === '#') { + this.type = 'id'; + this.clean = this.value.replace(/^#/, ''); + } + if (this.value[0] === '.') { + this.type = 'class'; + this.clean = this.value.replace(/^\./, ''); + } + if (this.value.indexOf('*') !== -1) { + this.type = 'wildcard'; + } +}; + +// Determine the 'specificity matrix' of this +// specific selector +tree.Element.prototype.specificity = function() { + return [ + (this.type === 'id') ? 1 : 0, // a + (this.type === 'class') ? 1 : 0 // b + ]; +}; + +tree.Element.prototype.toString = function() { return this.value; }; + +})(require('../tree')); + +},{"../tree":37}],44:[function(require,module,exports){ +(function(tree) { + +tree.Expression = function Expression(value) { + this.value = value; +}; + +tree.Expression.prototype = { + is: 'expression', + ev: function(env) { + if (this.value.length > 1) { + return new tree.Expression(this.value.map(function(e) { + return e.ev(env); + })); + } else { + return this.value[0].ev(env); } }, - "colors": { - "aliceblue": [240, 248, 255], - "antiquewhite": [250, 235, 215], - "aqua": [0, 255, 255], - "aquamarine": [127, 255, 212], - "azure": [240, 255, 255], - "beige": [245, 245, 220], - "bisque": [255, 228, 196], - "black": [0, 0, 0], - "blanchedalmond": [255,235,205], - "blue": [0, 0, 255], - "blueviolet": [138, 43, 226], - "brown": [165, 42, 42], - "burlywood": [222, 184, 135], - "cadetblue": [95, 158, 160], - "chartreuse": [127, 255, 0], - "chocolate": [210, 105, 30], - "coral": [255, 127, 80], - "cornflowerblue": [100, 149, 237], - "cornsilk": [255, 248, 220], - "crimson": [220, 20, 60], - "cyan": [0, 255, 255], - "darkblue": [0, 0, 139], - "darkcyan": [0, 139, 139], - "darkgoldenrod": [184, 134, 11], - "darkgray": [169, 169, 169], - "darkgreen": [0, 100, 0], - "darkgrey": [169, 169, 169], - "darkkhaki": [189, 183, 107], - "darkmagenta": [139, 0, 139], - "darkolivegreen": [85, 107, 47], - "darkorange": [255, 140, 0], - "darkorchid": [153, 50, 204], - "darkred": [139, 0, 0], - "darksalmon": [233, 150, 122], - "darkseagreen": [143, 188, 143], - "darkslateblue": [72, 61, 139], - "darkslategrey": [47, 79, 79], - "darkturquoise": [0, 206, 209], - "darkviolet": [148, 0, 211], - "deeppink": [255, 20, 147], - "deepskyblue": [0, 191, 255], - "dimgray": [105, 105, 105], - "dimgrey": [105, 105, 105], - "dodgerblue": [30, 144, 255], - "firebrick": [178, 34, 34], - "floralwhite": [255, 250, 240], - "forestgreen": [34, 139, 34], - "fuchsia": [255, 0, 255], - "gainsboro": [220, 220, 220], - "ghostwhite": [248, 248, 255], - "gold": [255, 215, 0], - "goldenrod": [218, 165, 32], - "gray": [128, 128, 128], - "grey": [128, 128, 128], - "green": [0, 128, 0], - "greenyellow": [173, 255, 47], - "honeydew": [240, 255, 240], - "hotpink": [255, 105, 180], - "indianred": [205, 92, 92], - "indigo": [75, 0, 130], - "ivory": [255, 255, 240], - "khaki": [240, 230, 140], - "lavender": [230, 230, 250], - "lavenderblush": [255, 240, 245], - "lawngreen": [124, 252, 0], - "lemonchiffon": [255, 250, 205], - "lightblue": [173, 216, 230], - "lightcoral": [240, 128, 128], - "lightcyan": [224, 255, 255], - "lightgoldenrodyellow": [250, 250, 210], - "lightgray": [211, 211, 211], - "lightgreen": [144, 238, 144], - "lightgrey": [211, 211, 211], - "lightpink": [255, 182, 193], - "lightsalmon": [255, 160, 122], - "lightseagreen": [32, 178, 170], - "lightskyblue": [135, 206, 250], - "lightslategray": [119, 136, 153], - "lightslategrey": [119, 136, 153], - "lightsteelblue": [176, 196, 222], - "lightyellow": [255, 255, 224], - "lime": [0, 255, 0], - "limegreen": [50, 205, 50], - "linen": [250, 240, 230], - "magenta": [255, 0, 255], - "maroon": [128, 0, 0], - "mediumaquamarine": [102, 205, 170], - "mediumblue": [0, 0, 205], - "mediumorchid": [186, 85, 211], - "mediumpurple": [147, 112, 219], - "mediumseagreen": [60, 179, 113], - "mediumslateblue": [123, 104, 238], - "mediumspringgreen": [0, 250, 154], - "mediumturquoise": [72, 209, 204], - "mediumvioletred": [199, 21, 133], - "midnightblue": [25, 25, 112], - "mintcream": [245, 255, 250], - "mistyrose": [255, 228, 225], - "moccasin": [255, 228, 181], - "navajowhite": [255, 222, 173], - "navy": [0, 0, 128], - "oldlace": [253, 245, 230], - "olive": [128, 128, 0], - "olivedrab": [107, 142, 35], - "orange": [255, 165, 0], - "orangered": [255, 69, 0], - "orchid": [218, 112, 214], - "palegoldenrod": [238, 232, 170], - "palegreen": [152, 251, 152], - "paleturquoise": [175, 238, 238], - "palevioletred": [219, 112, 147], - "papayawhip": [255, 239, 213], - "peachpuff": [255, 218, 185], - "peru": [205, 133, 63], - "pink": [255, 192, 203], - "plum": [221, 160, 221], - "powderblue": [176, 224, 230], - "purple": [128, 0, 128], - "red": [255, 0, 0], - "rosybrown": [188, 143, 143], - "royalblue": [65, 105, 225], - "saddlebrown": [139, 69, 19], - "salmon": [250, 128, 114], - "sandybrown": [244, 164, 96], - "seagreen": [46, 139, 87], - "seashell": [255, 245, 238], - "sienna": [160, 82, 45], - "silver": [192, 192, 192], - "skyblue": [135, 206, 235], - "slateblue": [106, 90, 205], - "slategray": [112, 128, 144], - "slategrey": [112, 128, 144], - "snow": [255, 250, 250], - "springgreen": [0, 255, 127], - "steelblue": [70, 130, 180], - "tan": [210, 180, 140], - "teal": [0, 128, 128], - "thistle": [216, 191, 216], - "tomato": [255, 99, 71], - "turquoise": [64, 224, 208], - "violet": [238, 130, 238], - "wheat": [245, 222, 179], - "white": [255, 255, 255], - "whitesmoke": [245, 245, 245], - "yellow": [255, 255, 0], - "yellowgreen": [154, 205, 50], - "transparent": [0, 0, 0, 0] + + toString: function(env) { + return this.value.map(function(e) { + return e.toString(env); + }).join(' '); + } +}; + +})(require('../tree')); + +},{"../tree":37}],45:[function(require,module,exports){ +(function(tree) { + +tree.Field = function Field(content) { + this.value = content || ''; +}; + +tree.Field.prototype = { + is: 'field', + toString: function() { + return '[' + this.value + ']'; }, - "filter": { - "value": [ - "true", - "false", - "null", - "point", - "linestring", - "polygon", - "collection" - ] + 'ev': function() { + return this; } -} +}; + +})(require('../tree')); + +},{"../tree":37}],46:[function(require,module,exports){ +(function(tree) { + +tree.Filter = function Filter(key, op, val, index, filename) { + this.key = key; + this.op = op; + this.val = val; + this.index = index; + this.filename = filename; + + this.id = this.key + this.op + this.val; +}; + +// xmlsafe, numeric, suffix +var ops = { + '<': [' < ', 'numeric'], + '>': [' > ', 'numeric'], + '=': [' = ', 'both'], + '!=': [' != ', 'both'], + '<=': [' <= ', 'numeric'], + '>=': [' >= ', 'numeric'], + '=~': ['.match(', 'string', ')'] +}; + +tree.Filter.prototype.ev = function(env) { + this.key = this.key.ev(env); + this.val = this.val.ev(env); + return this; +}; + +tree.Filter.prototype.toXML = function(env) { + if (tree.Reference.data.filter) { + if (this.key.is === 'keyword' && -1 === tree.Reference.data.filter.value.indexOf(this.key.toString())) { + env.error({ + message: this.key.toString() + ' is not a valid keyword in a filter expression', + index: this.index, + filename: this.filename + }); + } + if (this.val.is === 'keyword' && -1 === tree.Reference.data.filter.value.indexOf(this.val.toString())) { + env.error({ + message: this.val.toString() + ' is not a valid keyword in a filter expression', + index: this.index, + filename: this.filename + }); + } + } + var key = this.key.toString(false); + var val = this.val.toString(this.val.is == 'string'); + + if ( + (ops[this.op][1] == 'numeric' && isNaN(val) && this.val.is !== 'field') || + (ops[this.op][1] == 'string' && (val)[0] != "'") + ) { + env.error({ + message: 'Cannot use operator "' + this.op + '" with value ' + this.val, + index: this.index, + filename: this.filename + }); + } + + return key + ops[this.op][0] + val + (ops[this.op][2] || ''); +}; + +tree.Filter.prototype.toString = function() { + return '[' + this.id + ']'; +}; + +})(require('../tree')); + +},{"../tree":37}],47:[function(require,module,exports){ +(function (global){ +var tree = require('../tree'); +var _ = global._ || require('underscore'); + +tree.Filterset = function Filterset() { + this.filters = {}; +}; + +tree.Filterset.prototype.toXML = function(env) { + var filters = []; + for (var id in this.filters) { + filters.push('(' + this.filters[id].toXML(env).trim() + ')'); + } + if (filters.length) { + return ' ' + filters.join(' and ') + '\n'; + } else { + return ''; + } +}; + +tree.Filterset.prototype.toString = function() { + var arr = []; + for (var id in this.filters) arr.push(this.filters[id].id); + return arr.sort().join('\t'); +}; + +tree.Filterset.prototype.ev = function(env) { + for (var i in this.filters) { + this.filters[i].ev(env); + } + return this; +}; + +tree.Filterset.prototype.clone = function() { + var clone = new tree.Filterset(); + for (var id in this.filters) { + clone.filters[id] = this.filters[id]; + } + return clone; +}; + +// Note: other has to be a tree.Filterset. +tree.Filterset.prototype.cloneWith = function(other) { + var additions = []; + for (var id in other.filters) { + var status = this.addable(other.filters[id]); + // status is true, false or null. if it's null we don't fail this + // clone nor do we add the filter. + if (status === false) { + return false; + } + if (status === true) { + // Adding the filter will override another value. + additions.push(other.filters[id]); + } + } + + // Adding the other filters doesn't make this filterset invalid, but it + // doesn't add anything to it either. + if (!additions.length) { + return null; + } + + // We can successfully add all filters. Now clone the filterset and add the + // new rules. + var clone = new tree.Filterset(); + + // We can add the rules that are already present without going through the + // add function as a Filterset is always in it's simplest canonical form. + for (id in this.filters) { + clone.filters[id] = this.filters[id]; + } + + // Only add new filters that actually change the filter. + while (id = additions.shift()) { + clone.add(id); + } + + return clone; +}; + +tree.Filterset.prototype.toJS = function(env) { + var opMap = { + '=': '===' + }; + return _.map(this.filters, function(filter) { + var op = filter.op; + if(op in opMap) { + op = opMap[op]; + } + var val = filter.val; + if(filter._val !== undefined) { + val = filter._val.toString(true); + } + var attrs = "data"; + return attrs + "['" + filter.key.value + "'] " + op + " " + (val.is === 'string' ? "'" + val.toString().replace(/'/g, "\\'") + "'" : val); + }).join(' && '); +}; + +// Returns true when the new filter can be added, false otherwise. +// It can also return null, and on the other side we test for === true or +// false +tree.Filterset.prototype.addable = function(filter) { + var key = filter.key.toString(), + value = filter.val.toString(); + + if (value.match(/^[0-9]+(\.[0-9]*)?$/)) value = parseFloat(value); + + switch (filter.op) { + case '=': + // if there is already foo= and we're adding foo= + if (this.filters[key + '='] !== undefined) { + if (this.filters[key + '='].val.toString() != value) { + return false; + } else { + return null; + } + } + if (this.filters[key + '!=' + value] !== undefined) return false; + if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return false; + if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return false; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return false; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return false; + return true; + + case '=~': + return true; + + case '!=': + if (this.filters[key + '='] !== undefined) return (this.filters[key + '='].val == value) ? false : null; + if (this.filters[key + '!=' + value] !== undefined) return null; + if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return null; + if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return null; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return null; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return null; + return true; + + case '>': + if (key + '=' in this.filters) { + if (this.filters[key + '='].val <= value) { + return false; + } else { + return null; + } + } + if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return false; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val <= value) return false; + if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return null; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return null; + return true; + + case '>=': + if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val < value) ? false : null; + if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return false; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return false; + if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return null; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val >= value) return null; + return true; + + case '<': + if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val >= value) ? false : null; + if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return false; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val >= value) return false; + if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return null; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return null; + return true; -module.exports = { - version: { - latest: _mapnik_reference_latest, - '2.1.1': _mapnik_reference_latest - } + case '<=': + if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val > value) ? false : null; + if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return false; + if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return false; + if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return null; + if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val <= value) return null; + return true; + } }; -},{}],41:[function(require,module,exports){ -/** - * TODO: document this. What does this do? - */ -if(typeof(module) !== "undefined") { - module.exports.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r; } - } - return null; - }; -} +// Does the new filter constitute a conflict? +tree.Filterset.prototype.conflict = function(filter) { + var key = filter.key.toString(), + value = filter.val.toString(); -},{}],42:[function(require,module,exports){ -(function (global){ -(function(tree) { -var _ = global._ || require('underscore'); -tree.Call = function Call(name, args, index) { - this.name = name; - this.args = args; - this.index = index; + if (!isNaN(parseFloat(value))) value = parseFloat(value); + + // if (a=b) && (a=c) + // if (a=b) && (a!=b) + // or (a!=b) && (a=b) + if ((filter.op === '=' && this.filters[key + '='] !== undefined && + value != this.filters[key + '='].val.toString()) || + (filter.op === '!=' && this.filters[key + '='] !== undefined && + value == this.filters[key + '='].val.toString()) || + (filter.op === '=' && this.filters[key + '!='] !== undefined && + value == this.filters[key + '!='].val.toString())) { + return filter.toString() + ' added to ' + this.toString() + ' produces an invalid filter'; + } + + return false; }; -tree.Call.prototype = { - is: 'call', - // When evuating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // The *functions.js* file contains the built-in functions. - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - 'ev': function(env) { - var args = this.args.map(function(a) { return a.ev(env); }); +// Only call this function for filters that have been cleared by .addable(). +tree.Filterset.prototype.add = function(filter, env) { + var key = filter.key.toString(), + id, + op = filter.op, + conflict = this.conflict(filter), + numval; - for (var i = 0; i < args.length; i++) { - if (args[i].is === 'undefined') { - return { - is: 'undefined', - value: 'undefined' - }; + if (conflict) return conflict; + + if (op === '=') { + for (var i in this.filters) { + if (this.filters[i].key == key) delete this.filters[i]; + } + this.filters[key + '='] = filter; + } else if (op === '!=') { + this.filters[key + '!=' + filter.val] = filter; + } else if (op === '=~') { + this.filters[key + '=~' + filter.val] = filter; + } else if (op === '>') { + // If there are other filters that are also > + // but are less than this one, they don't matter, so + // remove them. + for (var j in this.filters) { + if (this.filters[j].key == key && this.filters[j].val <= filter.val) { + delete this.filters[j]; } } - - if (this.name in tree.functions) { - if (tree.functions[this.name].length <= args.length) { - var val = tree.functions[this.name].apply(tree.functions, args); - if (val === null) { - env.error({ - message: 'incorrect arguments given to ' + this.name + '()', - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { is: 'undefined', value: 'undefined' }; - } - return val; - } else { - env.error({ - message: 'incorrect number of arguments for ' + this.name + - '(). ' + tree.functions[this.name].length + ' expected.', - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; + this.filters[key + '>'] = filter; + } else if (op === '>=') { + for (var k in this.filters) { + numval = (+this.filters[k].val.toString()); + if (this.filters[k].key == key && numval < filter.val) { + delete this.filters[k]; } - } else { - var fn = tree.Reference.mapnikFunctions[this.name]; - if (fn === undefined) { - var functions = _.pairs(tree.Reference.mapnikFunctions); - // cheap closest, needs improvement. - var name = this.name; - var mean = functions.map(function(f) { - return [f[0], tree.Reference.editDistance(name, f[0]), f[1]]; - }).sort(function(a, b) { - return a[1] - b[1]; - }); - env.error({ - message: 'unknown function ' + this.name + '(), did you mean ' + - mean[0][0] + '(' + mean[0][2] + ')', - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; + } + if (this.filters[key + '!=' + filter.val] !== undefined) { + delete this.filters[key + '!=' + filter.val]; + filter.op = '>'; + this.filters[key + '>'] = filter; + } + else { + this.filters[key + '>='] = filter; + } + } else if (op === '<') { + for (var l in this.filters) { + numval = (+this.filters[l].val.toString()); + if (this.filters[l].key == key && numval >= filter.val) { + delete this.filters[l]; } - if (fn !== args.length && - !(Array.isArray(fn) && _.include(fn, args.length)) && - // support variable-arg functions like `colorize-alpha` - fn !== -1) { - env.error({ - message: 'function ' + this.name + '() takes ' + - fn + ' arguments and was given ' + args.length, - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; - } else { - // Save the evaluated versions of arguments - this.args = args; - return this; + } + this.filters[key + '<'] = filter; + } else if (op === '<=') { + for (var m in this.filters) { + numval = (+this.filters[m].val.toString()); + if (this.filters[m].key == key && numval > filter.val) { + delete this.filters[m]; } } - }, + if (this.filters[key + '!=' + filter.val] !== undefined) { + delete this.filters[key + '!=' + filter.val]; + filter.op = '<'; + this.filters[key + '<'] = filter; + } + else { + this.filters[key + '<='] = filter; + } + } +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"underscore":71}],48:[function(require,module,exports){ +(function(tree) { + +tree._getFontSet = function(env, fonts) { + var fontKey = fonts.join(''); + if (env._fontMap && env._fontMap[fontKey]) { + return env._fontMap[fontKey]; + } + + var new_fontset = new tree.FontSet(env, fonts); + env.effects.push(new_fontset); + if (!env._fontMap) env._fontMap = {}; + env._fontMap[fontKey] = new_fontset; + return new_fontset; +}; + +tree.FontSet = function FontSet(env, fonts) { + this.fonts = fonts; + this.name = 'fontset-' + env.effects.length; +}; + +tree.FontSet.prototype.toXML = function(env) { + return '\n' + + this.fonts.map(function(f) { + return ' '; + }).join('\n') + + '\n'; +}; + +})(require('../tree')); + +},{"../tree":37}],49:[function(require,module,exports){ +var tree = require('../tree'); + +// Storage for Frame offset value +// and stores them as bit-sequences so that they can be combined, +// inverted, and compared quickly. +tree.FrameOffset = function(op, value, index) { + value = parseInt(value, 10); + if (value > tree.FrameOffset.max || value <= 0) { + throw { + message: 'Only frame-offset levels between 1 and ' + + tree.FrameOffset.max + ' supported.', + index: index + }; + } + + if (op !== '=') { + throw { + message: 'only = operator is supported for frame-offset', + index: index + }; + } + return value; +}; - toString: function(env, format) { - if (this.args.length) { - return this.name + '(' + this.args.join(',') + ')'; +tree.FrameOffset.max = 32; +tree.FrameOffset.none = 0; + + +},{"../tree":37}],50:[function(require,module,exports){ +(function(tree) { + +tree.ImageFilter = function ImageFilter(filter, args) { + this.filter = filter; + this.args = args || null; +}; + +tree.ImageFilter.prototype = { + is: 'imagefilter', + ev: function() { return this; }, + + toString: function() { + if (this.args) { + return this.filter + '(' + this.args.join(',') + ')'; } else { - return this.name; + return this.filter; } } }; + })(require('../tree')); -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"underscore":71}],43:[function(require,module,exports){ +},{"../tree":37}],51:[function(require,module,exports){ +(function (tree) { +tree.Invalid = function Invalid(chunk, index, message) { + this.chunk = chunk; + this.index = index; + this.type = 'syntax'; + this.message = message || "Invalid code: " + this.chunk; +}; + +tree.Invalid.prototype.is = 'invalid'; + +tree.Invalid.prototype.ev = function(env) { + env.error({ + chunk: this.chunk, + index: this.index, + type: 'syntax', + message: this.message || "Invalid code: " + this.chunk + }); + return { + is: 'undefined' + }; +}; +})(require('../tree')); + +},{"../tree":37}],52:[function(require,module,exports){ (function(tree) { -// RGB Colors - #ff0014, #eee -// can be initialized with a 3 or 6 char string or a 3 or 4 element -// numerical array -tree.Color = function Color(rgb, a) { - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - if (Array.isArray(rgb)) { - this.rgb = rgb.slice(0, 3); - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function(c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function(c) { - return parseInt(c + c, 16); - }); + +tree.Keyword = function Keyword(value) { + this.value = value; + var special = { + 'transparent': 'color', + 'true': 'boolean', + 'false': 'boolean' + }; + this.is = special[value] ? special[value] : 'keyword'; +}; +tree.Keyword.prototype = { + ev: function() { return this; }, + toString: function() { return this.value; } +}; + +})(require('../tree')); + +},{"../tree":37}],53:[function(require,module,exports){ +(function(tree) { + +tree.LayerXML = function(obj, styles) { + var dsoptions = []; + for (var i in obj.Datasource) { + dsoptions.push(''); } - if (typeof(a) === 'number') { - this.alpha = a; - } else if (rgb.length === 4) { - this.alpha = rgb[3]; - } else { - this.alpha = 1; + var prop_string = ''; + for (var prop in obj.properties) { + if (prop === 'minzoom') { + prop_string += ' maxzoom="' + tree.Zoom.ranges[obj.properties[prop]] + '"\n'; + } else if (prop === 'maxzoom') { + prop_string += ' minzoom="' + tree.Zoom.ranges[obj.properties[prop]+1] + '"\n'; + } else { + prop_string += ' ' + prop + '="' + obj.properties[prop] + '"\n'; + } } + + return '\n ' + + styles.reverse().map(function(s) { + return '' + s + ''; + }).join('\n ') + + (dsoptions.length ? + '\n \n ' + + dsoptions.join('\n ') + + '\n \n' + : '') + + ' \n'; }; -tree.Color.prototype = { - is: 'color', - 'ev': function() { return this; }, +})(require('../tree')); - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. +},{"../tree":37}],54:[function(require,module,exports){ +// A literal is a literal string for Mapnik - the +// result of the combination of a `tree.Field` with any +// other type. +(function(tree) { + +tree.Literal = function Field(content) { + this.value = content || ''; + this.is = 'field'; +}; + +tree.Literal.prototype = { toString: function() { - if (this.alpha < 1.0) { - return 'rgba(' + this.rgb.map(function(c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ')'; - } else { - return '#' + this.rgb.map(function(i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } + return this.value; }, + 'ev': function() { + return this; + } +}; - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - operate: function(env, op, other) { - var result = []; +})(require('../tree')); - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } +},{"../tree":37}],55:[function(require,module,exports){ +// An operation is an expression with an op in between two operands, +// like 2 + 1. +(function(tree) { - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new tree.Color(result); - }, +tree.Operation = function Operation(op, operands, index) { + this.op = op.trim(); + this.operands = operands; + this.index = index; +}; - toHSL: function() { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; +tree.Operation.prototype.is = 'operation'; - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; +tree.Operation.prototype.ev = function(env) { + var a = this.operands[0].ev(env), + b = this.operands[1].ev(env), + temp; - if (max === min) { - h = s = 0; + if (a.is === 'undefined' || b.is === 'undefined') { + return { + is: 'undefined', + value: 'undefined' + }; + } + + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + env.error({ + name: "OperationError", + message: "Can't substract or divide a color from a number", + index: this.index + }); + } + } + + // Only concatenate plain strings, because this is easily + // pre-processed + if (a instanceof tree.Quoted && b instanceof tree.Quoted && this.op !== '+') { + env.error({ + message: "Can't subtract, divide, or multiply strings.", + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } + + // Fields, literals, dimensions, and quoted strings can be combined. + if (a instanceof tree.Field || b instanceof tree.Field || + a instanceof tree.Literal || b instanceof tree.Literal) { + if (a.is === 'color' || b.is === 'color') { + env.error({ + message: "Can't subtract, divide, or multiply colors in expressions.", + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } else { + return new tree.Literal(a.ev(env).toString(true) + this.op + b.ev(env).toString(true)); + } + } + + if (a.operate === undefined) { + env.error({ + message: 'Cannot do math with type ' + a.is + '.', + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; + } - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; + return a.operate(env, this.op, b); +}; + +tree.operate = function(op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '%': return a % b; + case '/': return a / b; } }; })(require('../tree')); -},{"../tree":41}],44:[function(require,module,exports){ +},{"../tree":37}],56:[function(require,module,exports){ (function(tree) { -tree.Comment = function Comment(value, silent) { - this.value = value; - this.silent = !!silent; +tree.Quoted = function Quoted(content) { + this.value = content || ''; }; -tree.Comment.prototype = { - toString: function(env) { - return ''; +tree.Quoted.prototype = { + is: 'string', + + toString: function(quotes) { + var escapedValue = this.value + .replace(/&/g, '&') + var xmlvalue = escapedValue + .replace(/\'/g, '\\\'') + .replace(/\"/g, '"') + .replace(//g, '>'); + return (quotes === true) ? "'" + xmlvalue + "'" : escapedValue; }, - 'ev': function() { return this; } + + 'ev': function() { + return this; + }, + + operate: function(env, op, other) { + return new tree.Quoted(tree.operate(op, this.toString(), other.toString(this.contains_field))); + } }; })(require('../tree')); -},{"../tree":41}],45:[function(require,module,exports){ +},{"../tree":37}],57:[function(require,module,exports){ (function (global){ +// Carto pulls in a reference from the `mapnik-reference` +// module. This file builds indexes from that file for its various +// options, and provides validation methods for property: value +// combinations. (function(tree) { -var assert = require('assert'), - _ = global._ || require('underscore'); -// A definition is the combination of a selector and rules, like -// #foo { -// polygon-opacity:1.0; -// } -// -// The selector can have filters -tree.Definition = function Definition(selector, rules) { - this.elements = selector.elements; - assert.ok(selector.filters instanceof tree.Filterset); - this.rules = rules; - this.ruleIndex = {}; - for (var i = 0; i < this.rules.length; i++) { - if ('zoom' in this.rules[i]) this.rules[i] = this.rules[i].clone(); - this.rules[i].zoom = selector.zoom; - this.ruleIndex[this.rules[i].updateID()] = true; - } - this.filters = selector.filters; - this.zoom = selector.zoom; - this.frame_offset = selector.frame_offset; - this.attachment = selector.attachment || '__default__'; - this.specificity = selector.specificity(); +var _ = global._ || require('underscore'), + ref = {}; + +ref.setData = function(data) { + ref.data = data; + ref.selector_cache = generateSelectorCache(data); + ref.mapnikFunctions = generateMapnikFunctions(data); + + ref.mapnikFunctions.matrix = [6]; + ref.mapnikFunctions.translate = [1, 2]; + ref.mapnikFunctions.scale = [1, 2]; + ref.mapnikFunctions.rotate = [1, 3]; + ref.mapnikFunctions.skewX = [1]; + ref.mapnikFunctions.skewY = [1]; + + ref.required_cache = generateRequiredProperties(data); }; -tree.Definition.prototype.toString = function() { - var str = this.filters.toString(); - for (var i = 0; i < this.rules.length; i++) { - str += '\n ' + this.rules[i]; +ref.setVersion = function(version) { + var mapnik_reference = require('mapnik-reference'); + if (mapnik_reference.version.hasOwnProperty(version)) { + ref.setData(mapnik_reference.version[version]); + return true; + } else { + return false; } - return str; }; -tree.Definition.prototype.clone = function(filters) { - if (filters) assert.ok(filters instanceof tree.Filterset); - var clone = Object.create(tree.Definition.prototype); - clone.rules = this.rules.slice(); - clone.ruleIndex = _.clone(this.ruleIndex); - clone.filters = filters ? filters : this.filters.clone(); - clone.attachment = this.attachment; - return clone; +ref.selectorData = function(selector, i) { + if (ref.selector_cache[selector]) return ref.selector_cache[selector][i]; }; -tree.Definition.prototype.addRules = function(rules) { - var added = 0; +ref.validSelector = function(selector) { return !!ref.selector_cache[selector]; }; +ref.selectorName = function(selector) { return ref.selectorData(selector, 2); }; +ref.selector = function(selector) { return ref.selectorData(selector, 0); }; +ref.symbolizer = function(selector) { return ref.selectorData(selector, 1); }; - // Add only unique rules. - for (var i = 0; i < rules.length; i++) { - if (!this.ruleIndex[rules[i].id]) { - this.rules.push(rules[i]); - this.ruleIndex[rules[i].id] = true; - added++; +function generateSelectorCache(data) { + var index = {}; + for (var i in data.symbolizers) { + for (var j in data.symbolizers[i]) { + if (data.symbolizers[i][j].hasOwnProperty('css')) { + index[data.symbolizers[i][j].css] = [data.symbolizers[i][j], i, j]; + } } } + return index; +} - return added; -}; - -// Determine whether this selector matches a given id -// and array of classes, by determining whether -// all elements it contains match. -tree.Definition.prototype.appliesTo = function(id, classes) { - for (var i = 0, l = this.elements.length; i < l; i++) { - var elem = this.elements[i]; - if (!(elem.wildcard || - (elem.type === 'class' && classes[elem.clean]) || - (elem.type === 'id' && id === elem.clean))) return false; +function generateMapnikFunctions(data) { + var functions = {}; + for (var i in data.symbolizers) { + for (var j in data.symbolizers[i]) { + if (data.symbolizers[i][j].type === 'functions') { + for (var k = 0; k < data.symbolizers[i][j].functions.length; k++) { + var fn = data.symbolizers[i][j].functions[k]; + functions[fn[0]] = fn[1]; + } + } + } } - return true; -}; - -function symbolizerName(symbolizer) { - function capitalize(str) { return str[1].toUpperCase(); } - return symbolizer.charAt(0).toUpperCase() + - symbolizer.slice(1).replace(/\-./, capitalize) + 'Symbolizer'; + return functions; } -// Get a simple list of the symbolizers, in order -function symbolizerList(sym_order) { - return sym_order.sort(function(a, b) { return a[1] - b[1]; }) - .map(function(v) { return v[0]; }); +function generateRequiredProperties(data) { + var cache = {}; + for (var symbolizer_name in data.symbolizers) { + cache[symbolizer_name] = []; + for (var j in data.symbolizers[symbolizer_name]) { + if (data.symbolizers[symbolizer_name][j].required) { + cache[symbolizer_name].push(data.symbolizers[symbolizer_name][j].css); + } + } + } + return cache; } -tree.Definition.prototype.symbolizersToXML = function(env, symbolizers, zoom) { - var xml = zoom.toXML(env).join('') + this.filters.toXML(env); - - // Sort symbolizers by the index of their first property definition - var sym_order = [], indexes = []; - for (var key in symbolizers) { - indexes = []; - for (var prop in symbolizers[key]) { - indexes.push(symbolizers[key][prop].index); +ref.requiredProperties = function(symbolizer_name, rules) { + var req = ref.required_cache[symbolizer_name]; + for (var i in req) { + if (!(req[i] in rules)) { + return 'Property ' + req[i] + ' required for defining ' + + symbolizer_name + ' styles.'; } - var min_idx = Math.min.apply(Math, indexes); - sym_order.push([key, min_idx]); } +}; - sym_order = symbolizerList(sym_order); - var sym_count = 0; - - for (var i = 0; i < sym_order.length; i++) { - var attributes = symbolizers[sym_order[i]]; - var symbolizer = sym_order[i].split('/').pop(); - - // Skip the magical * symbolizer which is used for universal properties - // which are bubbled up to Style elements intead of Symbolizer elements. - if (symbolizer === '*') continue; - sym_count++; - - var fail = tree.Reference.requiredProperties(symbolizer, attributes); - if (fail) { - var rule = attributes[Object.keys(attributes).shift()]; - env.error({ - message: fail, - index: rule.index, - filename: rule.filename - }); +// TODO: finish implementation - this is dead code +ref._validateValue = { + 'font': function(env, value) { + if (env.validation_data && env.validation_data.fonts) { + return env.validation_data.fonts.indexOf(value) != -1; + } else { + return true; } + } +}; - var name = symbolizerName(symbolizer); +ref.isFont = function(selector) { + return ref.selector(selector).validate == 'font'; +}; - var selfclosing = true, tagcontent; - xml += ' <' + name + ' '; - for (var j in attributes) { - if (symbolizer === 'map') env.error({ - message: 'Map properties are not permitted in other rules', - index: attributes[j].index, - filename: attributes[j].filename - }); - var x = tree.Reference.selector(attributes[j].name); - if (x && x.serialization && x.serialization === 'content') { - selfclosing = false; - tagcontent = attributes[j].ev(env).toXML(env, true); - } else if (x && x.serialization && x.serialization === 'tag') { - selfclosing = false; - tagcontent = attributes[j].ev(env).toXML(env, true); - } else { - xml += attributes[j].ev(env).toXML(env) + ' '; - } - } - if (selfclosing) { - xml += '/>\n'; - } else if (typeof tagcontent !== "undefined") { - if (tagcontent.indexOf('<') != -1) { - xml += '>' + tagcontent + '\n'; +// https://gist.github.com/982927 +ref.editDistance = function(a, b){ + if (a.length === 0) return b.length; + if (b.length === 0) return a.length; + var matrix = []; + for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; } + for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; } + for (i = 1; i <= b.length; i++) { + for (j = 1; j <= a.length; j++) { + if (b.charAt(i-1) == a.charAt(j-1)) { + matrix[i][j] = matrix[i-1][j-1]; } else { - xml += '>\n'; + matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution + Math.min(matrix[i][j-1] + 1, // insertion + matrix[i-1][j] + 1)); // deletion } } } - if (!sym_count || !xml) return ''; - return ' \n' + xml + ' \n'; + return matrix[b.length][a.length]; }; -// Take a zoom range of zooms and 'i', the index of a rule in this.rules, -// and finds all applicable symbolizers -tree.Definition.prototype.collectSymbolizers = function(zooms, i) { - var symbolizers = {}, child; - - for (var j = i; j < this.rules.length; j++) { - child = this.rules[j]; - var key = child.instance + '/' + child.symbolizer; - if (zooms.current & child.zoom && - (!(key in symbolizers) || - (!(child.name in symbolizers[key])))) { - zooms.current &= child.zoom; - if (!(key in symbolizers)) { - symbolizers[key] = {}; +function validateFunctions(value, selector) { + if (value.value[0].is === 'string') return true; + for (var i in value.value) { + for (var j in value.value[i].value) { + if (value.value[i].value[j].is !== 'call') return false; + var f = _.find(ref + .selector(selector).functions, function(x) { + return x[0] == value.value[i].value[j].name; + }); + if (!(f && f[1] == -1)) { + // This filter is unknown or given an incorrect number of arguments + if (!f || f[1] !== value.value[i].value[j].args.length) return false; } - symbolizers[key][child.name] = child; } } + return true; +} - if (Object.keys(symbolizers).length) { - zooms.rule &= (zooms.available &= ~zooms.current); - return symbolizers; +function validateKeyword(value, selector) { + if (typeof ref.selector(selector).type === 'object') { + return ref.selector(selector).type + .indexOf(value.value[0].value) !== -1; + } else { + // allow unquoted keywords as strings + return ref.selector(selector).type === 'string'; } -}; - -// The tree.Zoom.toString function ignores the holes in zoom ranges and outputs -// scaledenominators that cover the whole range from the first to last bit set. -// This algorithm can produces zoom ranges that may have holes. However, -// when using the filter-mode="first", more specific zoom filters will always -// end up before broader ranges. The filter-mode will pick those first before -// resorting to the zoom range with the hole and stop processing further rules. -tree.Definition.prototype.toXML = function(env, existing) { - var filter = this.filters.toString(); - if (!(filter in existing)) existing[filter] = tree.Zoom.all; - - var available = tree.Zoom.all, xml = '', zoom, symbolizers, - zooms = { available: tree.Zoom.all }; - for (var i = 0; i < this.rules.length && available; i++) { - zooms.rule = this.rules[i].zoom; - if (!(existing[filter] & zooms.rule)) continue; +} - while (zooms.current = zooms.rule & available) { - if (symbolizers = this.collectSymbolizers(zooms, i)) { - if (!(existing[filter] & zooms.current)) continue; - xml += this.symbolizersToXML(env, symbolizers, - (new tree.Zoom()).setZoom(existing[filter] & zooms.current)); - existing[filter] &= ~zooms.current; +ref.validValue = function(env, selector, value) { + var i, j; + // TODO: handle in reusable way + if (!ref.selector(selector)) { + return false; + } else if (value.value[0].is == 'keyword') { + return validateKeyword(value, selector); + } else if (value.value[0].is == 'undefined') { + // caught earlier in the chain - ignore here so that + // error is not overridden + return true; + } else if (ref.selector(selector).type == 'numbers') { + for (i in value.value) { + if (value.value[i].is !== 'float') { + return false; + } + } + return true; + } else if (ref.selector(selector).type == 'tags') { + if (!value.value) return false; + if (!value.value[0].value) { + return value.value[0].is === 'tag'; + } + for (i = 0; i < value.value[0].value.length; i++) { + if (value.value[0].value[i].is !== 'tag') return false; + } + return true; + } else if (ref.selector(selector).type == 'functions') { + // For backwards compatibility, you can specify a string for `functions`-compatible + // values, though they will not be validated. + return validateFunctions(value, selector); + } else if (ref.selector(selector).type === 'unsigned') { + if (value.value[0].is === 'float') { + value.value[0].round(); + return true; + } else { + return false; + } + } else if ((ref.selector(selector).expression)) { + return true; + } else { + if (ref.selector(selector).validate) { + var valid = false; + for (i = 0; i < value.value.length; i++) { + if (ref.selector(selector).type == value.value[i].is && + ref + ._validateValue + [ref.selector(selector).validate] + (env, value.value[i].value)) { + return true; + } } + return valid; + } else { + return ref.selector(selector).type == value.value[0].is; } } +}; - return xml; +tree.Reference = ref; + +})(require('../tree')); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"mapnik-reference":68,"underscore":71}],58:[function(require,module,exports){ +(function(tree) { +// a rule is a single property and value combination, or variable +// name and value combination, like +// polygon-opacity: 1.0; or @opacity: 1.0; +tree.Rule = function Rule(name, value, index, filename) { + var parts = name.split('/'); + this.name = parts.pop(); + this.instance = parts.length ? parts[0] : '__default__'; + this.value = (value instanceof tree.Value) ? + value : new tree.Value([value]); + this.index = index; + this.symbolizer = tree.Reference.symbolizer(this.name); + this.filename = filename; + this.variable = (name.charAt(0) === '@'); }; -tree.Definition.prototype.toJS = function(env) { - var shaderAttrs = {}; +tree.Rule.prototype.is = 'rule'; - // merge conditions from filters with zoom condition of the - // definition - var zoom = "(" + this.zoom + " & (1 << ctx.zoom))"; - var frame_offset = this.frame_offset; - var _if = this.filters.toJS(env); - var filters = [zoom]; - if(_if) filters.push(_if); - if(frame_offset) filters.push('ctx["frame-offset"] === ' + frame_offset); - _if = filters.join(" && "); - _.each(this.rules, function(rule) { - if(rule instanceof tree.Rule) { - shaderAttrs[rule.name] = shaderAttrs[rule.name] || []; +tree.Rule.prototype.clone = function() { + var clone = Object.create(tree.Rule.prototype); + clone.name = this.name; + clone.value = this.value; + clone.index = this.index; + clone.instance = this.instance; + clone.symbolizer = this.symbolizer; + clone.filename = this.filename; + clone.variable = this.variable; + return clone; +}; - var r = { - index: rule.index, - symbolizer: rule.symbolizer - }; +tree.Rule.prototype.updateID = function() { + return this.id = this.zoom + '#' + this.instance + '#' + this.name; +}; - if (_if) { - r.js = "if(" + _if + "){" + rule.value.toJS(env) + "}" - } else { - r.js = rule.value.toJS(env); - } +tree.Rule.prototype.toString = function() { + return '[' + tree.Zoom.toString(this.zoom) + '] ' + this.name + ': ' + this.value; +}; - r.constant = rule.value.ev(env).is !== 'field'; - r.filtered = !!_if; +function getMean(name) { + return Object.keys(tree.Reference.selector_cache).map(function(f) { + return [f, tree.Reference.editDistance(name, f)]; + }).sort(function(a, b) { return a[1] - b[1]; }); +} - shaderAttrs[rule.name].push(r); - } else { - throw new Error("Ruleset not supported"); - //if (rule instanceof tree.Ruleset) { - //var sh = rule.toJS(env); - //for(var v in sh) { - //shaderAttrs[v] = shaderAttrs[v] || []; - //for(var attr in sh[v]) { - //shaderAttrs[v].push(sh[v][attr]); - //} - //} - //} - } - }); - return shaderAttrs; +// second argument, if true, outputs the value of this +// rule without the usual attribute="content" wrapping. Right +// now this is just for the TextSymbolizer, but applies to other +// properties in reference.json which specify serialization=content +tree.Rule.prototype.toXML = function(env, content, sep, format) { + if (!tree.Reference.validSelector(this.name)) { + var mean = getMean(this.name); + var mean_message = ''; + if (mean[0][1] < 3) { + mean_message = '. Did you mean ' + mean[0][0] + '?'; + } + return env.error({ + message: "Unrecognized rule: " + this.name + mean_message, + index: this.index, + type: 'syntax', + filename: this.filename + }); + } + + if ((this.value instanceof tree.Value) && + !tree.Reference.validValue(env, this.name, this.value)) { + if (!tree.Reference.selector(this.name)) { + return env.error({ + message: 'Unrecognized property: ' + + this.name, + index: this.index, + type: 'syntax', + filename: this.filename + }); + } else { + var typename; + if (tree.Reference.selector(this.name).validate) { + typename = tree.Reference.selector(this.name).validate; + } else if (typeof tree.Reference.selector(this.name).type === 'object') { + typename = 'keyword (options: ' + tree.Reference.selector(this.name).type.join(', ') + ')'; + } else { + typename = tree.Reference.selector(this.name).type; + } + return env.error({ + message: 'Invalid value for ' + + this.name + + ', the type ' + typename + + ' is expected. ' + this.value + + ' (of type ' + this.value.value[0].is + ') ' + + ' was given.', + index: this.index, + type: 'syntax', + filename: this.filename + }); + } + } + + if (this.variable) { + return ''; + } else if (tree.Reference.isFont(this.name) && this.value.value.length > 1) { + var f = tree._getFontSet(env, this.value.value); + return 'fontset-name="' + f.name + '"'; + } else if (content) { + return this.value.toString(env, this.name, sep); + } else { + return tree.Reference.selectorName(this.name) + + '="' + + this.value.toString(env, this.name) + + '"'; + } }; +// TODO: Rule ev chain should add fontsets to env.frames +tree.Rule.prototype.ev = function(context) { + return new tree.Rule(this.name, + this.value.ev(context), + this.index, + this.filename); +}; })(require('../tree')); -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"assert":29,"underscore":71}],46:[function(require,module,exports){ -(function (global){ +},{"../tree":37}],59:[function(require,module,exports){ (function(tree) { -var _ = global._ || require('underscore'); -// -// A number with a unit -// -tree.Dimension = function Dimension(value, unit, index) { - this.value = parseFloat(value); - this.unit = unit || null; - this.index = index; + +tree.Ruleset = function Ruleset(selectors, rules) { + this.selectors = selectors; + this.rules = rules; + // static cache of find() function + this._lookups = {}; }; +tree.Ruleset.prototype = { + is: 'ruleset', + 'ev': function(env) { + var i, + ruleset = new tree.Ruleset(this.selectors, this.rules.slice(0)); + ruleset.root = this.root; -tree.Dimension.prototype = { - is: 'float', - physical_units: ['m', 'cm', 'in', 'mm', 'pt', 'pc'], - screen_units: ['px', '%'], - all_units: ['m', 'cm', 'in', 'mm', 'pt', 'pc', 'px', '%'], - densities: { - m: 0.0254, - mm: 25.4, - cm: 2.54, - pt: 72, - pc: 6 - }, - ev: function (env) { - if (this.unit && !_.contains(this.all_units, this.unit)) { - env.error({ - message: "Invalid unit: '" + this.unit + "'", - index: this.index - }); - return { is: 'undefined', value: 'undefined' }; - } + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); - // normalize units which are not px or % - if (this.unit && _.contains(this.physical_units, this.unit)) { - if (!env.ppi) { - env.error({ - message: "ppi is not set, so metric units can't be used", - index: this.index - }); - return { is: 'undefined', value: 'undefined' }; - } - // convert all units to inch - // convert inch to px using ppi - this.value = (this.value / this.densities[this.unit]) * env.ppi; - this.unit = 'px'; + // Evaluate everything else + for (i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + ruleset.rules[i] = rule.ev ? rule.ev(env) : rule; } - return this; - }, - round: function() { - this.value = Math.round(this.value); - return this; + // Pop the stack + env.frames.shift(); + + return ruleset; }, - toColor: function() { - return new tree.Color([this.value, this.value, this.value]); + match: function(args) { + return !args || args.length === 0; }, - round: function() { - this.value = Math.round(this.value); - return this; + variables: function() { + if (this._variables) { return this._variables; } + else { + return this._variables = this.rules.reduce(function(hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } }, - toString: function() { - return this.value.toString(); + variable: function(name) { + return this.variables()[name]; }, - operate: function(env, op, other) { - if (this.unit === '%' && other.unit !== '%') { - env.error({ - message: 'If two operands differ, the first must not be %', - index: this.index + rulesets: function() { + if (this._rulesets) { return this._rulesets; } + else { + return this._rulesets = this.rules.filter(function(r) { + return (r instanceof tree.Ruleset); }); - return { - is: 'undefined', - value: 'undefined' - }; } + }, + find: function(selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toString(); - if (this.unit !== '%' && other.unit === '%') { - if (op === '*' || op === '/' || op === '%') { - env.error({ - message: 'Percent values can only be added or subtracted from other values', - index: this.index - }); - return { - is: 'undefined', - value: 'undefined' - }; - } + if (key in this._lookups) { return this._lookups[key]; } - return new tree.Dimension(tree.operate(op, - this.value, this.value * other.value * 0.01), - this.unit); + this.rulesets().forEach(function(rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + match = selector.match(rule.selectors[j]); + if (match) { + if (selector.elements.length > 1) { + Array.prototype.push.apply(rules, rule.find( + new tree.Selector(null, null, null, selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // Zooms can use variables. This replaces tree.Zoom objects on selectors + // with simple bit-arrays that we can compare easily. + evZooms: function(env) { + for (var i = 0; i < this.selectors.length; i++) { + var zval = tree.Zoom.all; + for (var z = 0; z < this.selectors[i].zoom.length; z++) { + zval = zval & this.selectors[i].zoom[z].ev(env).zoom; + } + this.selectors[i].zoom = zval; } + }, + flatten: function(result, parents, env) { + var selectors = [], i, j; + if (this.selectors.length === 0) { + env.frames = env.frames.concat(this.rules); + } + // evaluate zoom variables on this object. + this.evZooms(env); + for (i = 0; i < this.selectors.length; i++) { + var child = this.selectors[i]; - //here the operands are either the same (% or undefined or px), or one is undefined and the other is px - return new tree.Dimension(tree.operate(op, this.value, other.value), - this.unit || other.unit); - } -}; - -})(require('../tree')); - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"underscore":71}],47:[function(require,module,exports){ -(function(tree) { - -// An element is an id or class selector -tree.Element = function Element(value) { - this.value = value.trim(); - if (this.value[0] === '#') { - this.type = 'id'; - this.clean = this.value.replace(/^#/, ''); - } - if (this.value[0] === '.') { - this.type = 'class'; - this.clean = this.value.replace(/^\./, ''); - } - if (this.value.indexOf('*') !== -1) { - this.type = 'wildcard'; - } -}; - -// Determine the 'specificity matrix' of this -// specific selector -tree.Element.prototype.specificity = function() { - return [ - (this.type === 'id') ? 1 : 0, // a - (this.type === 'class') ? 1 : 0 // b - ]; -}; - -tree.Element.prototype.toString = function() { return this.value; }; - -})(require('../tree')); + if (!child.filters) { + // TODO: is this internal inconsistency? + // This is an invalid filterset. + continue; + } -},{"../tree":41}],48:[function(require,module,exports){ -(function(tree) { + if (parents.length) { + for (j = 0; j < parents.length; j++) { + var parent = parents[j]; -tree.Expression = function Expression(value) { - this.value = value; -}; + var mergedFilters = parent.filters.cloneWith(child.filters); + if (mergedFilters === null) { + // Filters could be added, but they didn't change the + // filters. This means that we only have to clone when + // the zoom levels or the attachment is different too. + if (parent.zoom === (parent.zoom & child.zoom) && + parent.frame_offset === child.frame_offset && + parent.attachment === child.attachment && + parent.elements.join() === child.elements.join()) { + selectors.push(parent); + continue; + } else { + mergedFilters = parent.filters; + } + } else if (!mergedFilters) { + // The merged filters are invalid, that means we don't + // have to clone. + continue; + } -tree.Expression.prototype = { - is: 'expression', - ev: function(env) { - if (this.value.length > 1) { - return new tree.Expression(this.value.map(function(e) { - return e.ev(env); - })); - } else { - return this.value[0].ev(env); + var clone = Object.create(tree.Selector.prototype); + clone.filters = mergedFilters; + clone.zoom = parent.zoom & child.zoom; + clone.frame_offset = child.frame_offset; + clone.elements = parent.elements.concat(child.elements); + if (parent.attachment && child.attachment) { + clone.attachment = parent.attachment + '/' + child.attachment; + } + else clone.attachment = child.attachment || parent.attachment; + clone.conditions = parent.conditions + child.conditions; + clone.index = child.index; + selectors.push(clone); + } + } else { + selectors.push(child); + } } - }, - - toString: function(env) { - return this.value.map(function(e) { - return e.toString(env); - }).join(' '); - } -}; -})(require('../tree')); + var rules = []; + for (i = 0; i < this.rules.length; i++) { + var rule = this.rules[i]; -},{"../tree":41}],49:[function(require,module,exports){ -(function(tree) { + // Recursively flatten any nested rulesets + if (rule instanceof tree.Ruleset) { + rule.flatten(result, selectors, env); + } else if (rule instanceof tree.Rule) { + rules.push(rule); + } else if (rule instanceof tree.Invalid) { + env.error(rule); + } + } -tree.Field = function Field(content) { - this.value = content || ''; -}; + var index = rules.length ? rules[0].index : false; + for (i = 0; i < selectors.length; i++) { + // For specificity sort, use the position of the first rule to allow + // defining attachments that are under current element as a descendant + // selector. + if (index !== false) { + selectors[i].index = index; + } + result.push(new tree.Definition(selectors[i], rules.slice())); + } -tree.Field.prototype = { - is: 'field', - toString: function() { - return '[' + this.value + ']'; - }, - 'ev': function() { - return this; + return result; } }; - })(require('../tree')); -},{"../tree":41}],50:[function(require,module,exports){ +},{"../tree":37}],60:[function(require,module,exports){ (function(tree) { -tree.Filter = function Filter(key, op, val, index, filename) { - this.key = key; - this.op = op; - this.val = val; +tree.Selector = function Selector(filters, zoom, frame_offset, elements, attachment, conditions, index) { + this.elements = elements || []; + this.attachment = attachment; + this.filters = filters || {}; + this.frame_offset = frame_offset; + this.zoom = typeof zoom !== 'undefined' ? zoom : tree.Zoom.all; + this.conditions = conditions; this.index = index; - this.filename = filename; - - this.id = this.key + this.op + this.val; -}; - -// xmlsafe, numeric, suffix -var ops = { - '<': [' < ', 'numeric'], - '>': [' > ', 'numeric'], - '=': [' = ', 'both'], - '!=': [' != ', 'both'], - '<=': [' <= ', 'numeric'], - '>=': [' >= ', 'numeric'], - '=~': ['.match(', 'string', ')'] -}; - -tree.Filter.prototype.ev = function(env) { - this.key = this.key.ev(env); - this.val = this.val.ev(env); - return this; -}; - -tree.Filter.prototype.toXML = function(env) { - if (tree.Reference.data.filter) { - if (this.key.is === 'keyword' && -1 === tree.Reference.data.filter.value.indexOf(this.key.toString())) { - env.error({ - message: this.key.toString() + ' is not a valid keyword in a filter expression', - index: this.index, - filename: this.filename - }); - } - if (this.val.is === 'keyword' && -1 === tree.Reference.data.filter.value.indexOf(this.val.toString())) { - env.error({ - message: this.val.toString() + ' is not a valid keyword in a filter expression', - index: this.index, - filename: this.filename - }); - } - } - var key = this.key.toString(false); - var val = this.val.toString(this.val.is == 'string'); - - if ( - (ops[this.op][1] == 'numeric' && isNaN(val) && this.val.is !== 'field') || - (ops[this.op][1] == 'string' && (val)[0] != "'") - ) { - env.error({ - message: 'Cannot use operator "' + this.op + '" with value ' + this.val, - index: this.index, - filename: this.filename - }); - } - - return key + ops[this.op][0] + val + (ops[this.op][2] || ''); }; -tree.Filter.prototype.toString = function() { - return '[' + this.id + ']'; +// Determine the specificity of this selector +// based on the specificity of its elements - calling +// Element.specificity() in order to do so +// +// [ID, Class, Filters, Position in document] +tree.Selector.prototype.specificity = function() { + return this.elements.reduce(function(memo, e) { + var spec = e.specificity(); + memo[0] += spec[0]; + memo[1] += spec[1]; + return memo; + }, [0, 0, this.conditions, this.index]); }; })(require('../tree')); -},{"../tree":41}],51:[function(require,module,exports){ +},{"../tree":37}],61:[function(require,module,exports){ (function (global){ -var tree = require('../tree'); +(function(tree) { var _ = global._ || require('underscore'); -tree.Filterset = function Filterset() { - this.filters = {}; -}; - -tree.Filterset.prototype.toXML = function(env) { - var filters = []; - for (var id in this.filters) { - filters.push('(' + this.filters[id].toXML(env).trim() + ')'); - } - if (filters.length) { - return ' ' + filters.join(' and ') + '\n'; - } else { - return ''; - } -}; - -tree.Filterset.prototype.toString = function() { - var arr = []; - for (var id in this.filters) arr.push(this.filters[id].id); - return arr.sort().join('\t'); -}; - -tree.Filterset.prototype.ev = function(env) { - for (var i in this.filters) { - this.filters[i].ev(env); - } - return this; -}; - -tree.Filterset.prototype.clone = function() { - var clone = new tree.Filterset(); - for (var id in this.filters) { - clone.filters[id] = this.filters[id]; - } - return clone; -}; +// Given a style's name, attachment, definitions, and an environment object, +// return a stringified style for Mapnik +tree.StyleXML = function(name, attachment, definitions, env) { + var existing = {}; + var image_filters = [], image_filters_inflate = [], direct_image_filters = [], comp_op = [], opacity = []; -// Note: other has to be a tree.Filterset. -tree.Filterset.prototype.cloneWith = function(other) { - var additions = []; - for (var id in other.filters) { - var status = this.addable(other.filters[id]); - // status is true, false or null. if it's null we don't fail this - // clone nor do we add the filter. - if (status === false) { - return false; - } - if (status === true) { - // Adding the filter will override another value. - additions.push(other.filters[id]); + for (var i = 0; i < definitions.length; i++) { + for (var j = 0; j < definitions[i].rules.length; j++) { + if (definitions[i].rules[j].name === 'image-filters') { + image_filters.push(definitions[i].rules[j]); + } + if (definitions[i].rules[j].name === 'image-filters-inflate') { + image_filters_inflate.push(definitions[i].rules[j]); + } + if (definitions[i].rules[j].name === 'direct-image-filters') { + direct_image_filters.push(definitions[i].rules[j]); + } + if (definitions[i].rules[j].name === 'comp-op') { + comp_op.push(definitions[i].rules[j]); + } + if (definitions[i].rules[j].name === 'opacity') { + opacity.push(definitions[i].rules[j]); + } } } - // Adding the other filters doesn't make this filterset invalid, but it - // doesn't add anything to it either. - if (!additions.length) { - return null; - } + var rules = definitions.map(function(definition) { + return definition.toXML(env, existing); + }); - // We can successfully add all filters. Now clone the filterset and add the - // new rules. - var clone = new tree.Filterset(); + var attrs_xml = ''; - // We can add the rules that are already present without going through the - // add function as a Filterset is always in it's simplest canonical form. - for (id in this.filters) { - clone.filters[id] = this.filters[id]; + if (image_filters.length) { + attrs_xml += ' image-filters="' + _.chain(image_filters) + // prevent identical filters from being duplicated in the style + .uniq(function(i) { return i.id; }).map(function(f) { + return f.ev(env).toXML(env, true, ',', 'image-filter'); + }).value().join(',') + '"'; } - // Only add new filters that actually change the filter. - while (id = additions.shift()) { - clone.add(id); + if (image_filters_inflate.length) { + attrs_xml += ' image-filters-inflate="' + image_filters_inflate[0].value.ev(env).toString() + '"'; } - return clone; -}; + if (direct_image_filters.length) { + attrs_xml += ' direct-image-filters="' + _.chain(direct_image_filters) + // prevent identical filters from being duplicated in the style + .uniq(function(i) { return i.id; }).map(function(f) { + return f.ev(env).toXML(env, true, ',', 'direct-image-filter'); + }).value().join(',') + '"'; + } -tree.Filterset.prototype.toJS = function(env) { - var opMap = { - '=': '===' - }; - return _.map(this.filters, function(filter) { - var op = filter.op; - if(op in opMap) { - op = opMap[op]; + if (comp_op.length && comp_op[0].value.ev(env).value != 'src-over') { + attrs_xml += ' comp-op="' + comp_op[0].value.ev(env).toString() + '"'; } - var val = filter.val; - if(filter._val !== undefined) { - val = filter._val.toString(true); + + if (opacity.length && opacity[0].value.ev(env).value != 1) { + attrs_xml += ' opacity="' + opacity[0].value.ev(env).toString() + '"'; } - var attrs = "data"; - return attrs + "." + filter.key.value + " " + op + " " + (val.is === 'string' ? "'"+ val +"'" : val); - }).join(' && '); + var rule_string = rules.join(''); + if (!attrs_xml && !rule_string) return ''; + return ''; }; -// Returns true when the new filter can be added, false otherwise. -// It can also return null, and on the other side we test for === true or -// false -tree.Filterset.prototype.addable = function(filter) { - var key = filter.key.toString(), - value = filter.val.toString(); - - if (value.match(/^[0-9]+(\.[0-9]*)?$/)) value = parseFloat(value); - - switch (filter.op) { - case '=': - // if there is already foo= and we're adding foo= - if (this.filters[key + '='] !== undefined) { - if (this.filters[key + '='].val.toString() != value) { - return false; - } else { - return null; - } - } - if (this.filters[key + '!=' + value] !== undefined) return false; - if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return false; - if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return false; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return false; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return false; - return true; +})(require('../tree')); - case '=~': - return true; +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"../tree":37,"underscore":71}],62:[function(require,module,exports){ +(function(tree) { - case '!=': - if (this.filters[key + '='] !== undefined) return (this.filters[key + '='].val == value) ? false : null; - if (this.filters[key + '!=' + value] !== undefined) return null; - if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return null; - if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return null; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return null; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return null; - return true; +tree.URL = function URL(val, paths) { + this.value = val; + this.paths = paths; +}; - case '>': - if (key + '=' in this.filters) { - if (this.filters[key + '='].val <= value) { - return false; - } else { - return null; - } - } - if (this.filters[key + '<'] !== undefined && this.filters[key + '<'].val <= value) return false; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val <= value) return false; - if (this.filters[key + '>'] !== undefined && this.filters[key + '>'].val >= value) return null; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return null; - return true; +tree.URL.prototype = { + is: 'uri', + toString: function() { + return this.value.toString(); + }, + ev: function(ctx) { + return new tree.URL(this.value.ev(ctx), this.paths); + } +}; - case '>=': - if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val < value) ? false : null; - if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return false; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return false; - if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return null; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val >= value) return null; - return true; +})(require('../tree')); - case '<': - if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val >= value) ? false : null; - if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return false; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val >= value) return false; - if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return null; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val < value) return null; - return true; +},{"../tree":37}],63:[function(require,module,exports){ +(function(tree) { - case '<=': - if (this.filters[key + '=' ] !== undefined) return (this.filters[key + '='].val > value) ? false : null; - if (this.filters[key + '>' ] !== undefined && this.filters[key + '>'].val >= value) return false; - if (this.filters[key + '>='] !== undefined && this.filters[key + '>='].val > value) return false; - if (this.filters[key + '<' ] !== undefined && this.filters[key + '<'].val <= value) return null; - if (this.filters[key + '<='] !== undefined && this.filters[key + '<='].val <= value) return null; - return true; - } +tree.Value = function Value(value) { + this.value = value; }; -// Does the new filter constitute a conflict? -tree.Filterset.prototype.conflict = function(filter) { - var key = filter.key.toString(), - value = filter.val.toString(); - - if (!isNaN(parseFloat(value))) value = parseFloat(value); +tree.Value.prototype = { + is: 'value', + ev: function(env) { + if (this.value.length === 1) { + return this.value[0].ev(env); + } else { + return new tree.Value(this.value.map(function(v) { + return v.ev(env); + })); + } + }, + toString: function(env, selector, sep, format) { + return this.value.map(function(e) { + return e.toString(env, format); + }).join(sep || ', '); + }, + clone: function() { + var obj = Object.create(tree.Value.prototype); + if (Array.isArray(obj)) obj.value = this.value.slice(); + else obj.value = this.value; + obj.is = this.is; + return obj; + }, - // if (a=b) && (a=c) - // if (a=b) && (a!=b) - // or (a!=b) && (a=b) - if ((filter.op === '=' && this.filters[key + '='] !== undefined && - value != this.filters[key + '='].val.toString()) || - (filter.op === '!=' && this.filters[key + '='] !== undefined && - value == this.filters[key + '='].val.toString()) || - (filter.op === '=' && this.filters[key + '!='] !== undefined && - value == this.filters[key + '!='].val.toString())) { - return filter.toString() + ' added to ' + this.toString() + ' produces an invalid filter'; + toJS: function(env) { + //var v = this.value[0].value[0]; + var val = this.ev(env); + var v = val.toString(); + if(val.is === "color" || val.is === 'uri' || val.is === 'string' || val.is === 'keyword') { + v = "'" + v + "'"; + } else if (val.is === 'field') { + // replace [variable] by ctx['variable'] + v = v.replace(/\[(.*)\]/g, "data['$1']"); + }else if (val.is === 'call') { + v = JSON.stringify({ + name: val.name, + args: val.args + }) + } + return "_value = " + v + ";"; } - return false; }; -// Only call this function for filters that have been cleared by .addable(). -tree.Filterset.prototype.add = function(filter, env) { - var key = filter.key.toString(), - id, - op = filter.op, - conflict = this.conflict(filter), - numval; +})(require('../tree')); - if (conflict) return conflict; +},{"../tree":37}],64:[function(require,module,exports){ +(function(tree) { - if (op === '=') { - for (var i in this.filters) { - if (this.filters[i].key == key) delete this.filters[i]; - } - this.filters[key + '='] = filter; - } else if (op === '!=') { - this.filters[key + '!=' + filter.val] = filter; - } else if (op === '=~') { - this.filters[key + '=~' + filter.val] = filter; - } else if (op === '>') { - // If there are other filters that are also > - // but are less than this one, they don't matter, so - // remove them. - for (var j in this.filters) { - if (this.filters[j].key == key && this.filters[j].val <= filter.val) { - delete this.filters[j]; - } - } - this.filters[key + '>'] = filter; - } else if (op === '>=') { - for (var k in this.filters) { - numval = (+this.filters[k].val.toString()); - if (this.filters[k].key == key && numval < filter.val) { - delete this.filters[k]; - } - } - if (this.filters[key + '!=' + filter.val] !== undefined) { - delete this.filters[key + '!=' + filter.val]; - filter.op = '>'; - this.filters[key + '>'] = filter; - } - else { - this.filters[key + '>='] = filter; - } - } else if (op === '<') { - for (var l in this.filters) { - numval = (+this.filters[l].val.toString()); - if (this.filters[l].key == key && numval >= filter.val) { - delete this.filters[l]; - } - } - this.filters[key + '<'] = filter; - } else if (op === '<=') { - for (var m in this.filters) { - numval = (+this.filters[m].val.toString()); - if (this.filters[m].key == key && numval > filter.val) { - delete this.filters[m]; - } - } - if (this.filters[key + '!=' + filter.val] !== undefined) { - delete this.filters[key + '!=' + filter.val]; - filter.op = '<'; - this.filters[key + '<'] = filter; - } - else { - this.filters[key + '<='] = filter; +tree.Variable = function Variable(name, index, filename) { + this.name = name; + this.index = index; + this.filename = filename; +}; + +tree.Variable.prototype = { + is: 'variable', + toString: function() { + return this.name; + }, + ev: function(env) { + var variable, + v, + name = this.name; + + if (this._css) return this._css; + + var thisframe = env.frames.filter(function(f) { + return f.name == this.name; + }.bind(this)); + if (thisframe.length) { + return thisframe[0].value.ev(env); + } else { + env.error({ + message: 'variable ' + this.name + ' is undefined', + index: this.index, + type: 'runtime', + filename: this.filename + }); + return { + is: 'undefined', + value: 'undefined' + }; } } }; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"underscore":71}],52:[function(require,module,exports){ -(function(tree) { +})(require('../tree')); -tree._getFontSet = function(env, fonts) { - var fontKey = fonts.join(''); - if (env._fontMap && env._fontMap[fontKey]) { - return env._fontMap[fontKey]; - } +},{"../tree":37}],65:[function(require,module,exports){ +var tree = require('../tree'); - var new_fontset = new tree.FontSet(env, fonts); - env.effects.push(new_fontset); - if (!env._fontMap) env._fontMap = {}; - env._fontMap[fontKey] = new_fontset; - return new_fontset; +// Storage for zoom ranges. Only supports continuous ranges, +// and stores them as bit-sequences so that they can be combined, +// inverted, and compared quickly. +tree.Zoom = function(op, value, index) { + this.op = op; + this.value = value; + this.index = index; }; -tree.FontSet = function FontSet(env, fonts) { - this.fonts = fonts; - this.name = 'fontset-' + env.effects.length; +tree.Zoom.prototype.setZoom = function(zoom) { + this.zoom = zoom; + return this; }; -tree.FontSet.prototype.toXML = function(env) { - return '\n' + - this.fonts.map(function(f) { - return ' '; - }).join('\n') + - '\n'; +tree.Zoom.prototype.ev = function(env) { + var start = 0, + end = Infinity, + value = parseInt(this.value.ev(env).toString(), 10), + zoom = 0; + + if (value > tree.Zoom.maxZoom || value < 0) { + env.error({ + message: 'Only zoom levels between 0 and ' + + tree.Zoom.maxZoom + ' supported.', + index: this.index + }); + } + + switch (this.op) { + case '=': + this.zoom = 1 << value; + return this; + case '>': + start = value + 1; + break; + case '>=': + start = value; + break; + case '<': + end = value - 1; + break; + case '<=': + end = value; + break; + } + for (var i = 0; i <= tree.Zoom.maxZoom; i++) { + if (i >= start && i <= end) { + zoom |= (1 << i); + } + } + this.zoom = zoom; + return this; }; -})(require('../tree')); +tree.Zoom.prototype.toString = function() { + return this.zoom; +}; -},{"../tree":41}],53:[function(require,module,exports){ -var tree = require('../tree'); +// Covers all zoomlevels from 0 to 22 +tree.Zoom.all = 0x7FFFFF; -// Storage for Frame offset value -// and stores them as bit-sequences so that they can be combined, -// inverted, and compared quickly. -tree.FrameOffset = function(op, value, index) { - value = parseInt(value, 10); - if (value > tree.FrameOffset.max || value <= 0) { - throw { - message: 'Only frame-offset levels between 1 and ' + - tree.FrameOffset.max + ' supported.', - index: index - }; +tree.Zoom.maxZoom = 22; + +tree.Zoom.ranges = { + 0: 1000000000, + 1: 500000000, + 2: 200000000, + 3: 100000000, + 4: 50000000, + 5: 25000000, + 6: 12500000, + 7: 6500000, + 8: 3000000, + 9: 1500000, + 10: 750000, + 11: 400000, + 12: 200000, + 13: 100000, + 14: 50000, + 15: 25000, + 16: 12500, + 17: 5000, + 18: 2500, + 19: 1500, + 20: 750, + 21: 500, + 22: 250, + 23: 100 +}; + +// Only works for single range zooms. `[XXX....XXXXX.........]` is invalid. +tree.Zoom.prototype.toXML = function() { + var conditions = []; + if (this.zoom != tree.Zoom.all) { + var start = null, end = null; + for (var i = 0; i <= tree.Zoom.maxZoom; i++) { + if (this.zoom & (1 << i)) { + if (start === null) start = i; + end = i; + } + } + if (start > 0) conditions.push(' ' + + tree.Zoom.ranges[start] + '\n'); + if (end < 22) conditions.push(' ' + + tree.Zoom.ranges[end + 1] + '\n'); } + return conditions; +}; - if (op !== '=') { - throw { - message: 'only = operator is supported for frame-offset', - index: index - }; +tree.Zoom.prototype.toString = function() { + var str = ''; + for (var i = 0; i <= tree.Zoom.maxZoom; i++) { + str += (this.zoom & (1 << i)) ? 'X' : '.'; } - return value; + return str; }; -tree.FrameOffset.max = 32; -tree.FrameOffset.none = 0; +},{"../tree":37}],66:[function(require,module,exports){ +module.exports={ + "_args": [ + [ + "carto@https://github.com/CartoDB/carto/archive/master.tar.gz", + "/home/daniel/Dev/torque" + ] + ], + "_from": "https://github.com/CartoDB/carto/archive/master.tar.gz", + "_id": "carto@0.15.1-cdb1", + "_inCache": true, + "_installable": true, + "_location": "/carto", + "_phantomChildren": {}, + "_requested": { + "name": "carto", + "raw": "carto@https://github.com/CartoDB/carto/archive/master.tar.gz", + "rawSpec": "https://github.com/CartoDB/carto/archive/master.tar.gz", + "scope": null, + "spec": "https://github.com/CartoDB/carto/archive/master.tar.gz", + "type": "remote" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://github.com/CartoDB/carto/archive/master.tar.gz", + "_shasum": "c88ee6c0e6da9a71870a73020d15cbf768e4c68c", + "_shrinkwrap": null, + "_spec": "carto@https://github.com/CartoDB/carto/archive/master.tar.gz", + "_where": "/home/daniel/Dev/torque", + "author": { + "name": "CartoDB", + "url": "http://cartodb.com/" + }, + "bin": { + "carto": "./bin/carto" + }, + "bugs": { + "url": "https://github.com/cartodb/carto/issues" + }, + "contributors": [ + { + "name": "Tom MacWright", + "email": "macwright@gmail.com" + }, + { + "name": "Konstantin Käfer" + }, + { + "name": "Alexis Sellier", + "email": "self@cloudhead.net" + }, + { + "name": "Raul Ochoa", + "email": "rochoa@cartodb.com" + }, + { + "name": "Javi Santana", + "email": "jsantana@cartodb.com" + } + ], + "dependencies": { + "mapnik-reference": "~6.0.2", + "optimist": "~0.6.0", + "underscore": "1.8.3" + }, + "description": "CartoCSS Stylesheet Compiler", + "devDependencies": { + "browserify": "~7.0.0", + "coveralls": "~2.10.1", + "istanbul": "~0.2.14", + "jshint": "0.2.x", + "mocha": "1.12.x", + "sax": "0.1.x", + "uglify-js": "1.3.3" + }, + "engines": { + "node": ">=0.4.x" + }, + "homepage": "https://github.com/cartodb/carto#readme", + "keywords": [ + "css", + "maps", + "stylesheets" + ], + "licenses": [ + { + "type": "Apache" + } + ], + "main": "./lib/carto/index", + "man": [ + "./man/carto.1" + ], + "name": "carto", + "optionalDependencies": {}, + "readme": "# CartoCSS\n\n[![Build Status](https://travis-ci.org/CartoDB/carto.png?branch=master)](https://travis-ci.org/CartoDB/carto)\n\nIs as stylesheet renderer for javascript, It's an evolution of the Mapnik renderer from Mapbox.\nPlease, see original [Mapbox repo](http://github.com/mapbox/carto) for more information and credits\n\n## Quick Start\n\n```javascript\n// shader is a CartoCSS object\n\nvar cartocss = [\n '#layer {',\n ' marker-width: [property]',\n ' marker-fill: red',\n '}'\n].join('')\nvar shader = new carto.RendererJS().render(cartocss);\nvar layers = shader.getLayers()\nfor (var i = 0; i < layers.length; ++i) {\n var layer = layers[i];\n console.log(\"layer name: \", layer.fullName())\n console.log(\"- frames: \", layer.frames())\n console.log(\"- attachment: \", layer.attachment())\n\n var layerShader = layer.getStyle({ property: 1 }, { zoom: 10 })\n console.log(layerShader['marker-width']) // 1\n console.log(layerShader['marker-fill']) // #FF0000\n}\n\n```\n\n# API\n\n## RendererJS\n\n### render(cartocss)\n\n## CartoCSS\n\ncompiled cartocss object\n\n### getLayers\n\nreturn the layers, an array of ``CartoCSS.Layer`` object\n\n### getDefault\n\nreturn the default layer (``CartoCSS.Layer``), usually the Map layer\n\n\n### findLayer(where)\n\nfind a layer using where object.\n\n```\nshader.findLayer({ name: 'test' })\n```\n\n## CartoCSS.Layer\n\n### getStyle(props, context)\n\nreturn the evaluated style:\n - props: object containing properties needed to render the style. If the cartocss style uses\n some variables they should be passed in this object\n - context: rendering context variables like ``zoom`` or animation ``frame``\n\n\n\n\n\n\n\n\n\n\n## Reference Documentation\n\n* [mapbox.com/carto](http://mapbox.com/carto/)\n\n\n", + "readmeFilename": "README.md", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/cartodb/carto.git" + }, + "scripts": { + "coverage": "istanbul cover ./node_modules/.bin/_mocha && coveralls < ./coverage/lcov.info", + "pretest": "npm install", + "test": "mocha -R spec" + }, + "url": "https://github.com/cartodb/carto", + "version": "0.15.1-cdb1" +} +},{}],67:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} -},{"../tree":41}],54:[function(require,module,exports){ -(function(tree) { +},{}],68:[function(require,module,exports){ +(function (__dirname){ +var fs = require('fs'), + path = require('path'), + existsSync = require('fs').existsSync || require('path').existsSync; -tree.ImageFilter = function ImageFilter(filter, args) { - this.filter = filter; - this.args = args || null; -}; +// Load all stated versions into the module exports +module.exports.version = {}; -tree.ImageFilter.prototype = { - is: 'imagefilter', - ev: function() { return this; }, +var refs = [ + '2.0.0', + '2.0.1', + '2.0.2', + '2.1.0', + '2.1.1', + '2.2.0', + '2.3.0', + '3.0.0' +]; - toString: function() { - if (this.args) { - return this.filter + '(' + this.args.join(',') + ')'; - } else { - return this.filter; - } +refs.map(function(version) { + module.exports.version[version] = require(path.join(__dirname, version, 'reference.json')); + var ds_path = path.join(__dirname, version, 'datasources.json'); + if (existsSync(ds_path)) { + module.exports.version[version].datasources = require(ds_path).datasources; } -}; - - -})(require('../tree')); +}); -},{"../tree":41}],55:[function(require,module,exports){ -(function (tree) { -tree.Invalid = function Invalid(chunk, index, message) { - this.chunk = chunk; - this.index = index; - this.type = 'syntax'; - this.message = message || "Invalid code: " + this.chunk; -}; +}).call(this,"/node_modules/mapnik-reference") +},{"fs":30,"path":69}],69:[function(require,module,exports){ +(function (process){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. -tree.Invalid.prototype.is = 'invalid'; +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } -tree.Invalid.prototype.ev = function(env) { - env.error({ - chunk: this.chunk, - index: this.index, - type: 'syntax', - message: this.message || "Invalid code: " + this.chunk - }); - return { - is: 'undefined' - }; -}; -})(require('../tree')); + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } -},{"../tree":41}],56:[function(require,module,exports){ -(function(tree) { + return parts; +} -tree.Keyword = function Keyword(value) { - this.value = value; - var special = { - 'transparent': 'color', - 'true': 'boolean', - 'false': 'boolean' - }; - this.is = special[value] ? special[value] : 'keyword'; -}; -tree.Keyword.prototype = { - ev: function() { return this; }, - toString: function() { return this.value; } +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); }; -})(require('../tree')); - -},{"../tree":41}],57:[function(require,module,exports){ -(function(tree) { +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; -tree.LayerXML = function(obj, styles) { - var dsoptions = []; - for (var i in obj.Datasource) { - dsoptions.push(''); - } + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); - var prop_string = ''; - for (var prop in obj.properties) { - if (prop === 'minzoom') { - prop_string += ' maxzoom="' + tree.Zoom.ranges[obj.properties[prop]] + '"\n'; - } else if (prop === 'maxzoom') { - prop_string += ' minzoom="' + tree.Zoom.ranges[obj.properties[prop]+1] + '"\n'; - } else { - prop_string += ' ' + prop + '="' + obj.properties[prop] + '"\n'; - } + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; } - return '\n ' + - styles.reverse().map(function(s) { - return '' + s + ''; - }).join('\n ') + - (dsoptions.length ? - '\n \n ' + - dsoptions.join('\n ') + - '\n \n' - : '') + - ' \n'; -}; + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } -})(require('../tree')); + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) -},{"../tree":41}],58:[function(require,module,exports){ -// A literal is a literal string for Mapnik - the -// result of the combination of a `tree.Field` with any -// other type. -(function(tree) { + // Normalize the path + resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); -tree.Literal = function Field(content) { - this.value = content || ''; - this.is = 'field'; + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; -tree.Literal.prototype = { - toString: function() { - return this.value; - }, - 'ev': function() { - return this; - } -}; +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = substr(path, -1) === '/'; -})(require('../tree')); + // Normalize the path + path = normalizeArray(filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); -},{"../tree":41}],59:[function(require,module,exports){ -// An operation is an expression with an op in between two operands, -// like 2 + 1. -(function(tree) { + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } -tree.Operation = function Operation(op, operands, index) { - this.op = op.trim(); - this.operands = operands; - this.index = index; + return (isAbsolute ? '/' : '') + path; }; -tree.Operation.prototype.is = 'operation'; - -tree.Operation.prototype.ev = function(env) { - var a = this.operands[0].ev(env), - b = this.operands[1].ev(env), - temp; +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; - if (a.is === 'undefined' || b.is === 'undefined') { - return { - is: 'undefined', - value: 'undefined' - }; +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(filter(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); } + return p; + }).join('/')); +}; - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - env.error({ - name: "OperationError", - message: "Can't substract or divide a color from a number", - index: this.index - }); - } - } - // Only concatenate plain strings, because this is easily - // pre-processed - if (a instanceof tree.Quoted && b instanceof tree.Quoted && this.op !== '+') { - env.error({ - message: "Can't subtract, divide, or multiply strings.", - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; - } +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); - // Fields, literals, dimensions, and quoted strings can be combined. - if (a instanceof tree.Field || b instanceof tree.Field || - a instanceof tree.Literal || b instanceof tree.Literal) { - if (a.is === 'color' || b.is === 'color') { - env.error({ - message: "Can't subtract, divide, or multiply colors in expressions.", - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; - } else { - return new tree.Literal(a.ev(env).toString(true) + this.op + b.ev(env).toString(true)); - } + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; } - if (a.operate === undefined) { - env.error({ - message: 'Cannot do math with type ' + a.is + '.', - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; } - return a.operate(env, this.op, b); -}; + if (start > end) return []; + return arr.slice(start, end - start + 1); + } -tree.operate = function(op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '%': return a % b; - case '/': return a / b; + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; } -}; + } -})(require('../tree')); + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } -},{"../tree":41}],60:[function(require,module,exports){ -(function(tree) { + outputParts = outputParts.concat(toParts.slice(samePartsLength)); -tree.Quoted = function Quoted(content) { - this.value = content || ''; + return outputParts.join('/'); }; -tree.Quoted.prototype = { - is: 'string', +exports.sep = '/'; +exports.delimiter = ':'; - toString: function(quotes) { - var escapedValue = this.value - .replace(/&/g, '&') - var xmlvalue = escapedValue - .replace(/\'/g, '\\\'') - .replace(/\"/g, '"') - .replace(//g, '>'); - return (quotes === true) ? "'" + xmlvalue + "'" : escapedValue; - }, +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; - 'ev': function() { - return this; - }, + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } - operate: function(env, op, other) { - return new tree.Quoted(tree.operate(op, this.toString(), other.toString(this.contains_field))); - } + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; }; -})(require('../tree')); -},{"../tree":41}],61:[function(require,module,exports){ -(function (global){ -// Carto pulls in a reference from the `mapnik-reference` -// module. This file builds indexes from that file for its various -// options, and provides validation methods for property: value -// combinations. -(function(tree) { +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; -var _ = global._ || require('underscore'), - ref = {}; -ref.setData = function(data) { - ref.data = data; - ref.selector_cache = generateSelectorCache(data); - ref.mapnikFunctions = generateMapnikFunctions(data); +exports.extname = function(path) { + return splitPath(path)[3]; +}; - ref.mapnikFunctions.matrix = [6]; - ref.mapnikFunctions.translate = [1, 2]; - ref.mapnikFunctions.scale = [1, 2]; - ref.mapnikFunctions.rotate = [1, 3]; - ref.mapnikFunctions.skewX = [1]; - ref.mapnikFunctions.skewY = [1]; +function filter (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; +} - ref.required_cache = generateRequiredProperties(data); -}; +// String.prototype.substr - negative index don't work in IE8 +var substr = 'ab'.substr(-1) === 'b' + ? function (str, start, len) { return str.substr(start, len) } + : function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } +; -ref.setVersion = function(version) { - var mapnik_reference = require('mapnik-reference'); - if (mapnik_reference.version.hasOwnProperty(version)) { - ref.setData(mapnik_reference.version[version]); - return true; - } else { - return false; +}).call(this,require('_process')) +},{"_process":70}],70:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canMutationObserver = typeof window !== 'undefined' + && window.MutationObserver; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; } -}; -ref.selectorData = function(selector, i) { - if (ref.selector_cache[selector]) return ref.selector_cache[selector][i]; -}; + var queue = []; -ref.validSelector = function(selector) { return !!ref.selector_cache[selector]; }; -ref.selectorName = function(selector) { return ref.selectorData(selector, 2); }; -ref.selector = function(selector) { return ref.selectorData(selector, 0); }; -ref.symbolizer = function(selector) { return ref.selectorData(selector, 1); }; + if (canMutationObserver) { + var hiddenDiv = document.createElement("div"); + var observer = new MutationObserver(function () { + var queueList = queue.slice(); + queue.length = 0; + queueList.forEach(function (fn) { + fn(); + }); + }); -function generateSelectorCache(data) { - var index = {}; - for (var i in data.symbolizers) { - for (var j in data.symbolizers[i]) { - if (data.symbolizers[i][j].hasOwnProperty('css')) { - index[data.symbolizers[i][j].css] = [data.symbolizers[i][j], i, j]; + observer.observe(hiddenDiv, { attributes: true }); + + return function nextTick(fn) { + if (!queue.length) { + hiddenDiv.setAttribute('yes', 'no'); } - } + queue.push(fn); + }; } - return index; -} -function generateMapnikFunctions(data) { - var functions = {}; - for (var i in data.symbolizers) { - for (var j in data.symbolizers[i]) { - if (data.symbolizers[i][j].type === 'functions') { - for (var k = 0; k < data.symbolizers[i][j].functions.length; k++) { - var fn = data.symbolizers[i][j].functions[k]; - functions[fn[0]] = fn[1]; + if (canPost) { + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); } } - } - } - return functions; -} + }, true); -function generateRequiredProperties(data) { - var cache = {}; - for (var symbolizer_name in data.symbolizers) { - cache[symbolizer_name] = []; - for (var j in data.symbolizers[symbolizer_name]) { - if (data.symbolizers[symbolizer_name][j].required) { - cache[symbolizer_name].push(data.symbolizers[symbolizer_name][j].css); - } - } + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; } - return cache; -} -ref.requiredProperties = function(symbolizer_name, rules) { - var req = ref.required_cache[symbolizer_name]; - for (var i in req) { - if (!(req[i] in rules)) { - return 'Property ' + req[i] + ' required for defining ' + - symbolizer_name + ' styles.'; - } - } -}; + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); -// TODO: finish implementation - this is dead code -ref._validateValue = { - 'font': function(env, value) { - if (env.validation_data && env.validation_data.fonts) { - return env.validation_data.fonts.indexOf(value) != -1; - } else { - return true; - } - } -}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; -ref.isFont = function(selector) { - return ref.selector(selector).validate == 'font'; +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); }; -// https://gist.github.com/982927 -ref.editDistance = function(a, b){ - if (a.length === 0) return b.length; - if (b.length === 0) return a.length; - var matrix = []; - for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; } - for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; } - for (i = 1; i <= b.length; i++) { - for (j = 1; j <= a.length; j++) { - if (b.charAt(i-1) == a.charAt(j-1)) { - matrix[i][j] = matrix[i-1][j-1]; - } else { - matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution - Math.min(matrix[i][j-1] + 1, // insertion - matrix[i-1][j] + 1)); // deletion - } - } - } - return matrix[b.length][a.length]; +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); }; -function validateFunctions(value, selector) { - if (value.value[0].is === 'string') return true; - for (var i in value.value) { - for (var j in value.value[i].value) { - if (value.value[i].value[j].is !== 'call') return false; - var f = _.find(ref - .selector(selector).functions, function(x) { - return x[0] == value.value[i].value[j].name; - }); - if (!(f && f[1] == -1)) { - // This filter is unknown or given an incorrect number of arguments - if (!f || f[1] !== value.value[i].value[j].args.length) return false; - } - } - } - return true; -} +},{}],71:[function(require,module,exports){ +// Underscore.js 1.8.3 +// http://underscorejs.org +// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. -function validateKeyword(value, selector) { - if (typeof ref.selector(selector).type === 'object') { - return ref.selector(selector).type - .indexOf(value.value[0].value) !== -1; - } else { - // allow unquoted keywords as strings - return ref.selector(selector).type === 'string'; - } -} +(function() { -ref.validValue = function(env, selector, value) { - var i, j; - // TODO: handle in reusable way - if (!ref.selector(selector)) { - return false; - } else if (value.value[0].is == 'keyword') { - return validateKeyword(value, selector); - } else if (value.value[0].is == 'undefined') { - // caught earlier in the chain - ignore here so that - // error is not overridden - return true; - } else if (ref.selector(selector).type == 'numbers') { - for (i in value.value) { - if (value.value[i].is !== 'float') { - return false; - } - } - return true; - } else if (ref.selector(selector).type == 'tags') { - if (!value.value) return false; - if (!value.value[0].value) { - return value.value[0].is === 'tag'; - } - for (i = 0; i < value.value[0].value.length; i++) { - if (value.value[0].value[i].is !== 'tag') return false; - } - return true; - } else if (ref.selector(selector).type == 'functions') { - // For backwards compatibility, you can specify a string for `functions`-compatible - // values, though they will not be validated. - return validateFunctions(value, selector); - } else if (ref.selector(selector).type === 'unsigned') { - if (value.value[0].is === 'float') { - value.value[0].round(); - return true; - } else { - return false; - } - } else if ((ref.selector(selector).expression)) { - return true; - } else { - if (ref.selector(selector).validate) { - var valid = false; - for (i = 0; i < value.value.length; i++) { - if (ref.selector(selector).type == value.value[i].is && - ref - ._validateValue - [ref.selector(selector).validate] - (env, value.value[i].value)) { - return true; - } - } - return valid; - } else { - return ref.selector(selector).type == value.value[0].is; - } - } -}; + // Baseline setup + // -------------- -tree.Reference = ref; + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; -})(require('../tree')); + // Save the previous value of the `_` variable. + var previousUnderscore = root._; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"mapnik-reference":70,"underscore":71}],62:[function(require,module,exports){ -(function(tree) { -// a rule is a single property and value combination, or variable -// name and value combination, like -// polygon-opacity: 1.0; or @opacity: 1.0; -tree.Rule = function Rule(name, value, index, filename) { - var parts = name.split('/'); - this.name = parts.pop(); - this.instance = parts.length ? parts[0] : '__default__'; - this.value = (value instanceof tree.Value) ? - value : new tree.Value([value]); - this.index = index; - this.symbolizer = tree.Reference.symbolizer(this.name); - this.filename = filename; - this.variable = (name.charAt(0) === '@'); -}; + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; -tree.Rule.prototype.is = 'rule'; + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; -tree.Rule.prototype.clone = function() { - var clone = Object.create(tree.Rule.prototype); - clone.name = this.name; - clone.value = this.value; - clone.index = this.index; - clone.instance = this.instance; - clone.symbolizer = this.symbolizer; - clone.filename = this.filename; - clone.variable = this.variable; - return clone; -}; + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind, + nativeCreate = Object.create; + + // Naked function reference for surrogate-prototype-swapping. + var Ctor = function(){}; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.8.3'; + + // Internal function that returns an efficient (for current engines) version + // of the passed-in callback, to be repeatedly applied in other Underscore + // functions. + var optimizeCb = function(func, context, argCount) { + if (context === void 0) return func; + switch (argCount == null ? 3 : argCount) { + case 1: return function(value) { + return func.call(context, value); + }; + case 2: return function(value, other) { + return func.call(context, value, other); + }; + case 3: return function(value, index, collection) { + return func.call(context, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(context, accumulator, value, index, collection); + }; + } + return function() { + return func.apply(context, arguments); + }; + }; + + // A mostly-internal function to generate callbacks that can be applied + // to each element in a collection, returning the desired result — either + // identity, an arbitrary callback, a property matcher, or a property accessor. + var cb = function(value, context, argCount) { + if (value == null) return _.identity; + if (_.isFunction(value)) return optimizeCb(value, context, argCount); + if (_.isObject(value)) return _.matcher(value); + return _.property(value); + }; + _.iteratee = function(value, context) { + return cb(value, context, Infinity); + }; -tree.Rule.prototype.updateID = function() { - return this.id = this.zoom + '#' + this.instance + '#' + this.name; -}; + // An internal function for creating assigner functions. + var createAssigner = function(keysFunc, undefinedOnly) { + return function(obj) { + var length = arguments.length; + if (length < 2 || obj == null) return obj; + for (var index = 1; index < length; index++) { + var source = arguments[index], + keys = keysFunc(source), + l = keys.length; + for (var i = 0; i < l; i++) { + var key = keys[i]; + if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; + } + } + return obj; + }; + }; -tree.Rule.prototype.toString = function() { - return '[' + tree.Zoom.toString(this.zoom) + '] ' + this.name + ': ' + this.value; -}; + // An internal function for creating a new object that inherits from another. + var baseCreate = function(prototype) { + if (!_.isObject(prototype)) return {}; + if (nativeCreate) return nativeCreate(prototype); + Ctor.prototype = prototype; + var result = new Ctor; + Ctor.prototype = null; + return result; + }; -function getMean(name) { - return Object.keys(tree.Reference.selector_cache).map(function(f) { - return [f, tree.Reference.editDistance(name, f)]; - }).sort(function(a, b) { return a[1] - b[1]; }); -} + var property = function(key) { + return function(obj) { + return obj == null ? void 0 : obj[key]; + }; + }; -// second argument, if true, outputs the value of this -// rule without the usual attribute="content" wrapping. Right -// now this is just for the TextSymbolizer, but applies to other -// properties in reference.json which specify serialization=content -tree.Rule.prototype.toXML = function(env, content, sep, format) { - if (!tree.Reference.validSelector(this.name)) { - var mean = getMean(this.name); - var mean_message = ''; - if (mean[0][1] < 3) { - mean_message = '. Did you mean ' + mean[0][0] + '?'; - } - return env.error({ - message: "Unrecognized rule: " + this.name + mean_message, - index: this.index, - type: 'syntax', - filename: this.filename - }); - } + // Helper for collection methods to determine whether a collection + // should be iterated as an array or as an object + // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength + // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 + var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; + var getLength = property('length'); + var isArrayLike = function(collection) { + var length = getLength(collection); + return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; + }; - if ((this.value instanceof tree.Value) && - !tree.Reference.validValue(env, this.name, this.value)) { - if (!tree.Reference.selector(this.name)) { - return env.error({ - message: 'Unrecognized property: ' + - this.name, - index: this.index, - type: 'syntax', - filename: this.filename - }); - } else { - var typename; - if (tree.Reference.selector(this.name).validate) { - typename = tree.Reference.selector(this.name).validate; - } else if (typeof tree.Reference.selector(this.name).type === 'object') { - typename = 'keyword (options: ' + tree.Reference.selector(this.name).type.join(', ') + ')'; - } else { - typename = tree.Reference.selector(this.name).type; - } - return env.error({ - message: 'Invalid value for ' + - this.name + - ', the type ' + typename + - ' is expected. ' + this.value + - ' (of type ' + this.value.value[0].is + ') ' + - ' was given.', - index: this.index, - type: 'syntax', - filename: this.filename - }); - } - } + // Collection Functions + // -------------------- - if (this.variable) { - return ''; - } else if (tree.Reference.isFont(this.name) && this.value.value.length > 1) { - var f = tree._getFontSet(env, this.value.value); - return 'fontset-name="' + f.name + '"'; - } else if (content) { - return this.value.toString(env, this.name, sep); + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles raw objects in addition to array-likes. Treats all + // sparse array-likes as if they were dense. + _.each = _.forEach = function(obj, iteratee, context) { + iteratee = optimizeCb(iteratee, context); + var i, length; + if (isArrayLike(obj)) { + for (i = 0, length = obj.length; i < length; i++) { + iteratee(obj[i], i, obj); + } } else { - return tree.Reference.selectorName(this.name) + - '="' + - this.value.toString(env, this.name) + - '"'; + var keys = _.keys(obj); + for (i = 0, length = keys.length; i < length; i++) { + iteratee(obj[keys[i]], keys[i], obj); + } } -}; - -// TODO: Rule ev chain should add fontsets to env.frames -tree.Rule.prototype.ev = function(context) { - return new tree.Rule(this.name, - this.value.ev(context), - this.index, - this.filename); -}; - -})(require('../tree')); - -},{"../tree":41}],63:[function(require,module,exports){ -(function(tree) { + return obj; + }; -tree.Ruleset = function Ruleset(selectors, rules) { - this.selectors = selectors; - this.rules = rules; - // static cache of find() function - this._lookups = {}; -}; -tree.Ruleset.prototype = { - is: 'ruleset', - 'ev': function(env) { - var i, - ruleset = new tree.Ruleset(this.selectors, this.rules.slice(0)); - ruleset.root = this.root; + // Return the results of applying the iteratee to each element. + _.map = _.collect = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + results = Array(length); + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + results[index] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); + // Create a reducing function iterating left or right. + function createReduce(dir) { + // Optimized iterator function as using arguments.length + // in the main function will deoptimize the, see #1991. + function iterator(obj, iteratee, memo, keys, index, length) { + for (; index >= 0 && index < length; index += dir) { + var currentKey = keys ? keys[index] : index; + memo = iteratee(memo, obj[currentKey], currentKey, obj); + } + return memo; + } - // Evaluate everything else - for (i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - ruleset.rules[i] = rule.ev ? rule.ev(env) : rule; - } + return function(obj, iteratee, memo, context) { + iteratee = optimizeCb(iteratee, context, 4); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length, + index = dir > 0 ? 0 : length - 1; + // Determine the initial value if none is provided. + if (arguments.length < 3) { + memo = obj[keys ? keys[index] : index]; + index += dir; + } + return iterator(obj, iteratee, memo, keys, index, length); + }; + } - // Pop the stack - env.frames.shift(); + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. + _.reduce = _.foldl = _.inject = createReduce(1); - return ruleset; - }, - match: function(args) { - return !args || args.length === 0; - }, - variables: function() { - if (this._variables) { return this._variables; } - else { - return this._variables = this.rules.reduce(function(hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function(name) { - return this.variables()[name]; - }, - rulesets: function() { - if (this._rulesets) { return this._rulesets; } - else { - return this._rulesets = this.rules.filter(function(r) { - return (r instanceof tree.Ruleset); - }); - } - }, - find: function(selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toString(); + // The right-associative version of reduce, also known as `foldr`. + _.reduceRight = _.foldr = createReduce(-1); - if (key in this._lookups) { return this._lookups[key]; } + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var key; + if (isArrayLike(obj)) { + key = _.findIndex(obj, predicate, context); + } else { + key = _.findKey(obj, predicate, context); + } + if (key !== void 0 && key !== -1) return obj[key]; + }; - this.rulesets().forEach(function(rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - match = selector.match(rule.selectors[j]); - if (match) { - if (selector.elements.length > 1) { - Array.prototype.push.apply(rules, rule.find( - new tree.Selector(null, null, null, selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // Zooms can use variables. This replaces tree.Zoom objects on selectors - // with simple bit-arrays that we can compare easily. - evZooms: function(env) { - for (var i = 0; i < this.selectors.length; i++) { - var zval = tree.Zoom.all; - for (var z = 0; z < this.selectors[i].zoom.length; z++) { - zval = zval & this.selectors[i].zoom[z].ev(env).zoom; - } - this.selectors[i].zoom = zval; - } - }, - flatten: function(result, parents, env) { - var selectors = [], i, j; - if (this.selectors.length === 0) { - env.frames = env.frames.concat(this.rules); - } - // evaluate zoom variables on this object. - this.evZooms(env); - for (i = 0; i < this.selectors.length; i++) { - var child = this.selectors[i]; + // Return all the elements that pass a truth test. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + predicate = cb(predicate, context); + _.each(obj, function(value, index, list) { + if (predicate(value, index, list)) results.push(value); + }); + return results; + }; - if (!child.filters) { - // TODO: is this internal inconsistency? - // This is an invalid filterset. - continue; - } + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, _.negate(cb(predicate)), context); + }; - if (parents.length) { - for (j = 0; j < parents.length; j++) { - var parent = parents[j]; + // Determine whether all of the elements match a truth test. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (!predicate(obj[currentKey], currentKey, obj)) return false; + } + return true; + }; - var mergedFilters = parent.filters.cloneWith(child.filters); - if (mergedFilters === null) { - // Filters could be added, but they didn't change the - // filters. This means that we only have to clone when - // the zoom levels or the attachment is different too. - if (parent.zoom === (parent.zoom & child.zoom) && - parent.frame_offset === child.frame_offset && - parent.attachment === child.attachment && - parent.elements.join() === child.elements.join()) { - selectors.push(parent); - continue; - } else { - mergedFilters = parent.filters; - } - } else if (!mergedFilters) { - // The merged filters are invalid, that means we don't - // have to clone. - continue; - } + // Determine if at least one element in the object matches a truth test. + // Aliased as `any`. + _.some = _.any = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = !isArrayLike(obj) && _.keys(obj), + length = (keys || obj).length; + for (var index = 0; index < length; index++) { + var currentKey = keys ? keys[index] : index; + if (predicate(obj[currentKey], currentKey, obj)) return true; + } + return false; + }; - var clone = Object.create(tree.Selector.prototype); - clone.filters = mergedFilters; - clone.zoom = parent.zoom & child.zoom; - clone.frame_offset = child.frame_offset; - clone.elements = parent.elements.concat(child.elements); - if (parent.attachment && child.attachment) { - clone.attachment = parent.attachment + '/' + child.attachment; - } - else clone.attachment = child.attachment || parent.attachment; - clone.conditions = parent.conditions + child.conditions; - clone.index = child.index; - selectors.push(clone); - } - } else { - selectors.push(child); - } - } + // Determine if the array or object contains a given item (using `===`). + // Aliased as `includes` and `include`. + _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + if (typeof fromIndex != 'number' || guard) fromIndex = 0; + return _.indexOf(obj, item, fromIndex) >= 0; + }; - var rules = []; - for (i = 0; i < this.rules.length; i++) { - var rule = this.rules[i]; + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + var func = isFunc ? method : value[method]; + return func == null ? func : func.apply(value, args); + }); + }; - // Recursively flatten any nested rulesets - if (rule instanceof tree.Ruleset) { - rule.flatten(result, selectors, env); - } else if (rule instanceof tree.Rule) { - rules.push(rule); - } else if (rule instanceof tree.Invalid) { - env.error(rule); - } + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matcher(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matcher(attrs)); + }; + + // Return the maximum element (or element-based computation). + _.max = function(obj, iteratee, context) { + var result = -Infinity, lastComputed = -Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value > result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed > lastComputed || computed === -Infinity && result === -Infinity) { + result = value; + lastComputed = computed; } + }); + } + return result; + }; - var index = rules.length ? rules[0].index : false; - for (i = 0; i < selectors.length; i++) { - // For specificity sort, use the position of the first rule to allow - // defining attachments that are under current element as a descendant - // selector. - if (index !== false) { - selectors[i].index = index; - } - result.push(new tree.Definition(selectors[i], rules.slice())); + // Return the minimum element (or element-based computation). + _.min = function(obj, iteratee, context) { + var result = Infinity, lastComputed = Infinity, + value, computed; + if (iteratee == null && obj != null) { + obj = isArrayLike(obj) ? obj : _.values(obj); + for (var i = 0, length = obj.length; i < length; i++) { + value = obj[i]; + if (value < result) { + result = value; + } + } + } else { + iteratee = cb(iteratee, context); + _.each(obj, function(value, index, list) { + computed = iteratee(value, index, list); + if (computed < lastComputed || computed === Infinity && result === Infinity) { + result = value; + lastComputed = computed; } + }); + } + return result; + }; - return result; + // Shuffle a collection, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var set = isArrayLike(obj) ? obj : _.values(obj); + var length = set.length; + var shuffled = Array(length); + for (var index = 0, rand; index < length; index++) { + rand = _.random(0, index); + if (rand !== index) shuffled[index] = shuffled[rand]; + shuffled[rand] = set[index]; } -}; -})(require('../tree')); + return shuffled; + }; -},{"../tree":41}],64:[function(require,module,exports){ -(function(tree) { + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (!isArrayLike(obj)) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; -tree.Selector = function Selector(filters, zoom, frame_offset, elements, attachment, conditions, index) { - this.elements = elements || []; - this.attachment = attachment; - this.filters = filters || {}; - this.frame_offset = frame_offset; - this.zoom = typeof zoom !== 'undefined' ? zoom : tree.Zoom.all; - this.conditions = conditions; - this.index = index; -}; + // Sort the object's values by a criterion produced by an iteratee. + _.sortBy = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iteratee(value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; -// Determine the specificity of this selector -// based on the specificity of its elements - calling -// Element.specificity() in order to do so -// -// [ID, Class, Filters, Position in document] -tree.Selector.prototype.specificity = function() { - return this.elements.reduce(function(memo, e) { - var spec = e.specificity(); - memo[0] += spec[0]; - memo[1] += spec[1]; - return memo; - }, [0, 0, this.conditions, this.index]); -}; + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iteratee, context) { + var result = {}; + iteratee = cb(iteratee, context); + _.each(obj, function(value, index) { + var key = iteratee(value, index, obj); + behavior(result, value, key); + }); + return result; + }; + }; -})(require('../tree')); + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, value, key) { + if (_.has(result, key)) result[key].push(value); else result[key] = [value]; + }); -},{"../tree":41}],65:[function(require,module,exports){ -(function (global){ -(function(tree) { -var _ = global._ || require('underscore'); + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, value, key) { + result[key] = value; + }); -// Given a style's name, attachment, definitions, and an environment object, -// return a stringified style for Mapnik -tree.StyleXML = function(name, attachment, definitions, env) { - var existing = {}; - var image_filters = [], image_filters_inflate = [], direct_image_filters = [], comp_op = [], opacity = []; + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, value, key) { + if (_.has(result, key)) result[key]++; else result[key] = 1; + }); - for (var i = 0; i < definitions.length; i++) { - for (var j = 0; j < definitions[i].rules.length; j++) { - if (definitions[i].rules[j].name === 'image-filters') { - image_filters.push(definitions[i].rules[j]); - } - if (definitions[i].rules[j].name === 'image-filters-inflate') { - image_filters_inflate.push(definitions[i].rules[j]); - } - if (definitions[i].rules[j].name === 'direct-image-filters') { - direct_image_filters.push(definitions[i].rules[j]); - } - if (definitions[i].rules[j].name === 'comp-op') { - comp_op.push(definitions[i].rules[j]); - } - if (definitions[i].rules[j].name === 'opacity') { - opacity.push(definitions[i].rules[j]); - } - } - } + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (isArrayLike(obj)) return _.map(obj, _.identity); + return _.values(obj); + }; - var rules = definitions.map(function(definition) { - return definition.toXML(env, existing); + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return isArrayLike(obj) ? obj.length : _.keys(obj).length; + }; + + // Split a collection into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(obj, predicate, context) { + predicate = cb(predicate, context); + var pass = [], fail = []; + _.each(obj, function(value, key, obj) { + (predicate(value, key, obj) ? pass : fail).push(value); }); + return [pass, fail]; + }; - var attrs_xml = ''; + // Array Functions + // --------------- - if (image_filters.length) { - attrs_xml += ' image-filters="' + _.chain(image_filters) - // prevent identical filters from being duplicated in the style - .uniq(function(i) { return i.id; }).map(function(f) { - return f.ev(env).toXML(env, true, ',', 'image-filter'); - }).value().join(',') + '"'; - } + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[0]; + return _.initial(array, array.length - n); + }; - if (image_filters_inflate.length) { - attrs_xml += ' image-filters-inflate="' + image_filters_inflate[0].value.ev(env).toString() + '"'; + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. + _.initial = function(array, n, guard) { + return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if (n == null || guard) return array[array.length - 1]; + return _.rest(array, Math.max(0, array.length - n)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, n == null || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, strict, startIndex) { + var output = [], idx = 0; + for (var i = startIndex || 0, length = getLength(input); i < length; i++) { + var value = input[i]; + if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { + //flatten current level of array or arguments object + if (!shallow) value = flatten(value, shallow, strict); + var j = 0, len = value.length; + output.length += len; + while (j < len) { + output[idx++] = value[j++]; + } + } else if (!strict) { + output[idx++] = value; + } } + return output; + }; - if (direct_image_filters.length) { - attrs_xml += ' direct-image-filters="' + _.chain(direct_image_filters) - // prevent identical filters from being duplicated in the style - .uniq(function(i) { return i.id; }).map(function(f) { - return f.ev(env).toXML(env, true, ',', 'direct-image-filter'); - }).value().join(',') + '"'; + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, false); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iteratee, context) { + if (!_.isBoolean(isSorted)) { + context = iteratee; + iteratee = isSorted; + isSorted = false; } - - if (comp_op.length && comp_op[0].value.ev(env).value != 'src-over') { - attrs_xml += ' comp-op="' + comp_op[0].value.ev(env).toString() + '"'; + if (iteratee != null) iteratee = cb(iteratee, context); + var result = []; + var seen = []; + for (var i = 0, length = getLength(array); i < length; i++) { + var value = array[i], + computed = iteratee ? iteratee(value, i, array) : value; + if (isSorted) { + if (!i || seen !== computed) result.push(value); + seen = computed; + } else if (iteratee) { + if (!_.contains(seen, computed)) { + seen.push(computed); + result.push(value); + } + } else if (!_.contains(result, value)) { + result.push(value); + } } + return result; + }; - if (opacity.length && opacity[0].value.ev(env).value != 1) { - attrs_xml += ' opacity="' + opacity[0].value.ev(env).toString() + '"'; + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(flatten(arguments, true, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var result = []; + var argsLength = arguments.length; + for (var i = 0, length = getLength(array); i < length; i++) { + var item = array[i]; + if (_.contains(result, item)) continue; + for (var j = 1; j < argsLength; j++) { + if (!_.contains(arguments[j], item)) break; + } + if (j === argsLength) result.push(item); } - var rule_string = rules.join(''); - if (!attrs_xml && !rule_string) return ''; - return ''; -}; + return result; + }; -})(require('../tree')); + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = flatten(arguments, true, true, 1); + return _.filter(array, function(value){ + return !_.contains(rest, value); + }); + }; -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../tree":41,"underscore":71}],66:[function(require,module,exports){ -(function(tree) { + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + return _.unzip(arguments); + }; -tree.URL = function URL(val, paths) { - this.value = val; - this.paths = paths; -}; + // Complement of _.zip. Unzip accepts an array of arrays and groups + // each array's elements on shared indices + _.unzip = function(array) { + var length = array && _.max(array, getLength).length || 0; + var result = Array(length); -tree.URL.prototype = { - is: 'uri', - toString: function() { - return this.value.toString(); - }, - ev: function(ctx) { - return new tree.URL(this.value.ev(ctx), this.paths); + for (var index = 0; index < length; index++) { + result[index] = _.pluck(array, index); } -}; + return result; + }; -})(require('../tree')); + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + var result = {}; + for (var i = 0, length = getLength(list); i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; -},{"../tree":41}],67:[function(require,module,exports){ -(function(tree) { + // Generator function to create the findIndex and findLastIndex functions + function createPredicateIndexFinder(dir) { + return function(array, predicate, context) { + predicate = cb(predicate, context); + var length = getLength(array); + var index = dir > 0 ? 0 : length - 1; + for (; index >= 0 && index < length; index += dir) { + if (predicate(array[index], index, array)) return index; + } + return -1; + }; + } -tree.Value = function Value(value) { - this.value = value; -}; + // Returns the first index on an array-like that passes a predicate test + _.findIndex = createPredicateIndexFinder(1); + _.findLastIndex = createPredicateIndexFinder(-1); -tree.Value.prototype = { - is: 'value', - ev: function(env) { - if (this.value.length === 1) { - return this.value[0].ev(env); + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iteratee, context) { + iteratee = cb(iteratee, context, 1); + var value = iteratee(obj); + var low = 0, high = getLength(array); + while (low < high) { + var mid = Math.floor((low + high) / 2); + if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; + } + return low; + }; + + // Generator function to create the indexOf and lastIndexOf functions + function createIndexFinder(dir, predicateFind, sortedIndex) { + return function(array, item, idx) { + var i = 0, length = getLength(array); + if (typeof idx == 'number') { + if (dir > 0) { + i = idx >= 0 ? idx : Math.max(idx + length, i); } else { - return new tree.Value(this.value.map(function(v) { - return v.ev(env); - })); + length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; } - }, - toString: function(env, selector, sep, format) { - return this.value.map(function(e) { - return e.toString(env, format); - }).join(sep || ', '); - }, - clone: function() { - var obj = Object.create(tree.Value.prototype); - if (Array.isArray(obj)) obj.value = this.value.slice(); - else obj.value = this.value; - obj.is = this.is; - return obj; - }, - - toJS: function(env) { - //var v = this.value[0].value[0]; - var val = this.ev(env); - var v = val.toString(); - if(val.is === "color" || val.is === 'uri' || val.is === 'string' || val.is === 'keyword') { - v = "'" + v + "'"; - } else if (val.is === 'field') { - // replace [variable] by ctx['variable'] - v = v.replace(/\[(.*)\]/g, "data['$1']"); - }else if (val.is === 'call') { - v = JSON.stringify({ - name: val.name, - args: val.args - }) + } else if (sortedIndex && idx && length) { + idx = sortedIndex(array, item); + return array[idx] === item ? idx : -1; } - return "_value = " + v + ";"; - } - -}; - -})(require('../tree')); - -},{"../tree":41}],68:[function(require,module,exports){ -(function(tree) { + if (item !== item) { + idx = predicateFind(slice.call(array, i, length), _.isNaN); + return idx >= 0 ? idx + i : -1; + } + for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { + if (array[idx] === item) return idx; + } + return -1; + }; + } -tree.Variable = function Variable(name, index, filename) { - this.name = name; - this.index = index; - this.filename = filename; -}; + // Return the position of the first occurrence of an item in an array, + // or -1 if the item is not included in the array. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); + _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); -tree.Variable.prototype = { - is: 'variable', - toString: function() { - return this.name; - }, - ev: function(env) { - var variable, - v, - name = this.name; + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (stop == null) { + stop = start || 0; + start = 0; + } + step = step || 1; - if (this._css) return this._css; + var length = Math.max(Math.ceil((stop - start) / step), 0); + var range = Array(length); - var thisframe = env.frames.filter(function(f) { - return f.name == this.name; - }.bind(this)); - if (thisframe.length) { - return thisframe[0].value.ev(env); - } else { - env.error({ - message: 'variable ' + this.name + ' is undefined', - index: this.index, - type: 'runtime', - filename: this.filename - }); - return { - is: 'undefined', - value: 'undefined' - }; - } + for (var idx = 0; idx < length; idx++, start += step) { + range[idx] = start; } -}; -})(require('../tree')); + return range; + }; -},{"../tree":41}],69:[function(require,module,exports){ -var tree = require('../tree'); + // Function (ahem) Functions + // ------------------ -// Storage for zoom ranges. Only supports continuous ranges, -// and stores them as bit-sequences so that they can be combined, -// inverted, and compared quickly. -tree.Zoom = function(op, value, index) { - this.op = op; - this.value = value; - this.index = index; -}; + // Determines whether to execute a function as a constructor + // or a normal function with the provided arguments + var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { + if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); + var self = baseCreate(sourceFunc.prototype); + var result = sourceFunc.apply(self, args); + if (_.isObject(result)) return result; + return self; + }; -tree.Zoom.prototype.setZoom = function(zoom) { - this.zoom = zoom; - return this; -}; + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); + var args = slice.call(arguments, 2); + var bound = function() { + return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); + }; + return bound; + }; -tree.Zoom.prototype.ev = function(env) { - var start = 0, - end = Infinity, - value = parseInt(this.value.ev(env).toString(), 10), - zoom = 0; + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + var bound = function() { + var position = 0, length = boundArgs.length; + var args = Array(length); + for (var i = 0; i < length; i++) { + args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; + } + while (position < arguments.length) args.push(arguments[position++]); + return executeBound(func, bound, this, this, args); + }; + return bound; + }; - if (value > tree.Zoom.maxZoom || value < 0) { - env.error({ - message: 'Only zoom levels between 0 and ' + - tree.Zoom.maxZoom + ' supported.', - index: this.index - }); + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var i, length = arguments.length, key; + if (length <= 1) throw new Error('bindAll must be passed function names'); + for (i = 1; i < length; i++) { + key = arguments[i]; + obj[key] = _.bind(obj[key], obj); } + return obj; + }; - switch (this.op) { - case '=': - this.zoom = 1 << value; - return this; - case '>': - start = value + 1; - break; - case '>=': - start = value; - break; - case '<': - end = value - 1; - break; - case '<=': - end = value; - break; - } - for (var i = 0; i <= tree.Zoom.maxZoom; i++) { - if (i >= start && i <= end) { - zoom |= (1 << i); - } - } - this.zoom = zoom; - return this; -}; + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memoize = function(key) { + var cache = memoize.cache; + var address = '' + (hasher ? hasher.apply(this, arguments) : key); + if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); + return cache[address]; + }; + memoize.cache = {}; + return memoize; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ + return func.apply(null, args); + }, wait); + }; -tree.Zoom.prototype.toString = function() { - return this.zoom; -}; + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = _.partial(_.delay, _, 1); -// Covers all zoomlevels from 0 to 22 -tree.Zoom.all = 0x7FFFFF; + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + if (!options) options = {}; + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + if (!timeout) context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0 || remaining > wait) { + if (timeout) { + clearTimeout(timeout); + timeout = null; + } + previous = now; + result = func.apply(context, args); + if (!timeout) context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; -tree.Zoom.maxZoom = 22; + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; -tree.Zoom.ranges = { - 0: 1000000000, - 1: 500000000, - 2: 200000000, - 3: 100000000, - 4: 50000000, - 5: 25000000, - 6: 12500000, - 7: 6500000, - 8: 3000000, - 9: 1500000, - 10: 750000, - 11: 400000, - 12: 200000, - 13: 100000, - 14: 50000, - 15: 25000, - 16: 12500, - 17: 5000, - 18: 2500, - 19: 1500, - 20: 750, - 21: 500, - 22: 250, - 23: 100 -}; + var later = function() { + var last = _.now() - timestamp; -// Only works for single range zooms. `[XXX....XXXXX.........]` is invalid. -tree.Zoom.prototype.toXML = function() { - var conditions = []; - if (this.zoom != tree.Zoom.all) { - var start = null, end = null; - for (var i = 0; i <= tree.Zoom.maxZoom; i++) { - if (this.zoom & (1 << i)) { - if (start === null) start = i; - end = i; - } + if (last < wait && last >= 0) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + if (!timeout) context = args = null; } - if (start > 0) conditions.push(' ' + - tree.Zoom.ranges[start] + '\n'); - if (end < 22) conditions.push(' ' + - tree.Zoom.ranges[end + 1] + '\n'); - } - return conditions; -}; + } + }; -tree.Zoom.prototype.toString = function() { - var str = ''; - for (var i = 0; i <= tree.Zoom.maxZoom; i++) { - str += (this.zoom & (1 << i)) ? 'X' : '.'; - } - return str; -}; + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + context = args = null; + } -},{"../tree":41}],70:[function(require,module,exports){ -(function (__dirname){ -var fs = require('fs'), - path = require('path'), - existsSync = require('fs').existsSync || require('path').existsSync; + return result; + }; + }; -// Load all stated versions into the module exports -module.exports.version = {}; + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; -var refs = [ - '2.0.0', - '2.0.1', - '2.0.2', - '2.1.0', - '2.1.1', - '2.2.0', - '2.3.0', - '3.0.0' -]; + // Returns a negated version of the passed-in predicate. + _.negate = function(predicate) { + return function() { + return !predicate.apply(this, arguments); + }; + }; -refs.map(function(version) { - module.exports.version[version] = require(path.join(__dirname, version, 'reference.json')); - var ds_path = path.join(__dirname, version, 'datasources.json'); - if (existsSync(ds_path)) { - module.exports.version[version].datasources = require(ds_path).datasources; - } -}); + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var args = arguments; + var start = args.length - 1; + return function() { + var i = start; + var result = args[start].apply(this, arguments); + while (i--) result = args[i].call(this, result); + return result; + }; + }; -}).call(this,"/node_modules/carto/node_modules/mapnik-reference") -},{"fs":28,"path":31}],71:[function(require,module,exports){ -// Underscore.js 1.6.0 -// http://underscorejs.org -// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. + // Returns a function that will only be executed on and after the Nth call. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; -(function() { + // Returns a function that will only be executed up to (but not including) the Nth call. + _.before = function(times, func) { + var memo; + return function() { + if (--times > 0) { + memo = func.apply(this, arguments); + } + if (times <= 1) func = null; + return memo; + }; + }; - // Baseline setup - // -------------- + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = _.partial(_.before, 2); - // Establish the root object, `window` in the browser, or `exports` on the server. - var root = this; + // Object Functions + // ---------------- - // Save the previous value of the `_` variable. - var previousUnderscore = root._; + // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. + var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); + var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', + 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - // Establish the object that gets returned to break out of a loop iteration. - var breaker = {}; + function collectNonEnumProps(obj, keys) { + var nonEnumIdx = nonEnumerableProps.length; + var constructor = obj.constructor; + var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + // Constructor is a special case. + var prop = 'constructor'; + if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - // Create quick reference variables for speed access to core prototypes. - var - push = ArrayProto.push, - slice = ArrayProto.slice, - concat = ArrayProto.concat, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; + while (nonEnumIdx--) { + prop = nonEnumerableProps[nonEnumIdx]; + if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { + keys.push(prop); + } + } + } - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeForEach = ArrayProto.forEach, - nativeMap = ArrayProto.map, - nativeReduce = ArrayProto.reduce, - nativeReduceRight = ArrayProto.reduceRight, - nativeFilter = ArrayProto.filter, - nativeEvery = ArrayProto.every, - nativeSome = ArrayProto.some, - nativeIndexOf = ArrayProto.indexOf, - nativeLastIndexOf = ArrayProto.lastIndexOf, - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind; + // Retrieve the names of an object's own properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; + }; - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; + // Retrieve all the property names of an object. + _.allKeys = function(obj) { + if (!_.isObject(obj)) return []; + var keys = []; + for (var key in obj) keys.push(key); + // Ahem, IE < 9. + if (hasEnumBug) collectNonEnumProps(obj, keys); + return keys; }; - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object via a string identifier, - // for Closure Compiler "advanced" mode. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; } - exports._ = _; - } else { - root._ = _; - } + return values; + }; - // Current version. - _.VERSION = '1.6.0'; + // Returns the results of applying the iteratee to each element of the object + // In contrast to _.map it returns an object + _.mapObject = function(obj, iteratee, context) { + iteratee = cb(iteratee, context); + var keys = _.keys(obj), + length = keys.length, + results = {}, + currentKey; + for (var index = 0; index < length; index++) { + currentKey = keys[index]; + results[currentKey] = iteratee(obj[currentKey], currentKey, obj); + } + return results; + }; - // Collection Functions - // -------------------- + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles objects with the built-in `forEach`, arrays, and raw objects. - // Delegates to **ECMAScript 5**'s native `forEach` if available. - var each = _.each = _.forEach = function(obj, iterator, context) { - if (obj == null) return obj; - if (nativeForEach && obj.forEach === nativeForEach) { - obj.forEach(iterator, context); - } else if (obj.length === +obj.length) { - for (var i = 0, length = obj.length; i < length; i++) { - if (iterator.call(context, obj[i], i, obj) === breaker) return; - } - } else { - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; - } + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; } - return obj; + return result; }; - // Return the results of applying the iterator to each element. - // Delegates to **ECMAScript 5**'s native `map` if available. - _.map = _.collect = function(obj, iterator, context) { - var results = []; - if (obj == null) return results; - if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); - each(obj, function(value, index, list) { - results.push(iterator.call(context, value, index, list)); - }); - return results; + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); }; - var reduceError = 'Reduce of empty array with no initial value'; + // Extend a given object with all the properties in passed-in object(s). + _.extend = createAssigner(_.allKeys); - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. - _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduce && obj.reduce === nativeReduce) { - if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); - } - each(obj, function(value, index, list) { - if (!initial) { - memo = value; - initial = true; - } else { - memo = iterator.call(context, memo, value, index, list); - } - }); - if (!initial) throw new TypeError(reduceError); - return memo; - }; + // Assigns a given object with all the own properties in the passed-in object(s) + // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) + _.extendOwn = _.assign = createAssigner(_.keys); - // The right-associative version of reduce, also known as `foldr`. - // Delegates to **ECMAScript 5**'s native `reduceRight` if available. - _.reduceRight = _.foldr = function(obj, iterator, memo, context) { - var initial = arguments.length > 2; - if (obj == null) obj = []; - if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { - if (context) iterator = _.bind(iterator, context); - return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); - } - var length = obj.length; - if (length !== +length) { - var keys = _.keys(obj); - length = keys.length; + // Returns the first key on an object that passes a predicate test + _.findKey = function(obj, predicate, context) { + predicate = cb(predicate, context); + var keys = _.keys(obj), key; + for (var i = 0, length = keys.length; i < length; i++) { + key = keys[i]; + if (predicate(obj[key], key, obj)) return key; } - each(obj, function(value, index, list) { - index = keys ? keys[--length] : --length; - if (!initial) { - memo = obj[index]; - initial = true; - } else { - memo = iterator.call(context, memo, obj[index], index, list); - } - }); - if (!initial) throw new TypeError(reduceError); - return memo; }; - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var result; - any(obj, function(value, index, list) { - if (predicate.call(context, value, index, list)) { - result = value; - return true; - } - }); + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(object, oiteratee, context) { + var result = {}, obj = object, iteratee, keys; + if (obj == null) return result; + if (_.isFunction(oiteratee)) { + keys = _.allKeys(obj); + iteratee = optimizeCb(oiteratee, context); + } else { + keys = flatten(arguments, false, false, 1); + iteratee = function(value, key, obj) { return key in obj; }; + obj = Object(obj); + } + for (var i = 0, length = keys.length; i < length; i++) { + var key = keys[i]; + var value = obj[key]; + if (iteratee(value, key, obj)) result[key] = value; + } return result; }; - // Return all the elements that pass a truth test. - // Delegates to **ECMAScript 5**'s native `filter` if available. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - if (obj == null) return results; - if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); - each(obj, function(value, index, list) { - if (predicate.call(context, value, index, list)) results.push(value); - }); - return results; + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj, iteratee, context) { + if (_.isFunction(iteratee)) { + iteratee = _.negate(iteratee); + } else { + var keys = _.map(flatten(arguments, false, false, 1), String); + iteratee = function(value, key) { + return !_.contains(keys, key); + }; + } + return _.pick(obj, iteratee, context); }; - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, function(value, index, list) { - return !predicate.call(context, value, index, list); - }, context); + // Fill in a given object with default properties. + _.defaults = createAssigner(_.allKeys, true); + + // Creates an object that inherits from the given prototype object. + // If additional properties are provided then they will be added to the + // created object. + _.create = function(prototype, props) { + var result = baseCreate(prototype); + if (props) _.extendOwn(result, props); + return result; }; - // Determine whether all of the elements match a truth test. - // Delegates to **ECMAScript 5**'s native `every` if available. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - predicate || (predicate = _.identity); - var result = true; - if (obj == null) return result; - if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); - each(obj, function(value, index, list) { - if (!(result = result && predicate.call(context, value, index, list))) return breaker; - }); - return !!result; + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); }; - // Determine if at least one element in the object matches a truth test. - // Delegates to **ECMAScript 5**'s native `some` if available. - // Aliased as `any`. - var any = _.some = _.any = function(obj, predicate, context) { - predicate || (predicate = _.identity); - var result = false; - if (obj == null) return result; - if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); - each(obj, function(value, index, list) { - if (result || (result = predicate.call(context, value, index, list))) return breaker; - }); - return !!result; + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; }; - // Determine if the array or object contains a given value (using `===`). - // Aliased as `include`. - _.contains = _.include = function(obj, target) { - if (obj == null) return false; - if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; - return any(obj, function(value) { - return value === target; - }); + // Returns whether an object has a given set of `key:value` pairs. + _.isMatch = function(object, attrs) { + var keys = _.keys(attrs), length = keys.length; + if (object == null) return !length; + var obj = Object(object); + for (var i = 0; i < length; i++) { + var key = keys[i]; + if (attrs[key] !== obj[key] || !(key in obj)) return false; + } + return true; }; - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - return (isFunc ? method : value[method]).apply(value, args); - }); - }; - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a === 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className !== toString.call(b)) return false; + switch (className) { + // Strings, numbers, regular expressions, dates, and booleans are compared by value. + case '[object RegExp]': + // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return '' + a === '' + b; + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. + // Object(NaN) is equivalent to NaN + if (+a !== +a) return +b !== +b; + // An `egal` comparison is performed for other numeric values. + return +a === 0 ? 1 / +a === 1 / b : +a === +b; + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a === +b; + } - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matches(attrs)); - }; + var areArrays = className === '[object Array]'; + if (!areArrays) { + if (typeof a != 'object' || typeof b != 'object') return false; - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matches(attrs)); - }; + // Objects with different constructors are not equivalent, but `Object`s or `Array`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && + _.isFunction(bCtor) && bCtor instanceof bCtor) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + } + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - // Return the maximum element or (element-based computation). - // Can't optimize arrays of integers longer than 65,535 elements. - // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) - _.max = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.max.apply(Math, obj); + // Initializing stack of traversed objects. + // It's done here since we only need them for objects and arrays comparison. + aStack = aStack || []; + bStack = bStack || []; + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] === a) return bStack[length] === b; } - var result = -Infinity, lastComputed = -Infinity; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - if (computed > lastComputed) { - result = value; - lastComputed = computed; + + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + + // Recursively compare objects and arrays. + if (areArrays) { + // Compare array lengths to determine if a deep comparison is necessary. + length = a.length; + if (length !== b.length) return false; + // Deep compare the contents, ignoring non-numeric properties. + while (length--) { + if (!eq(a[length], b[length], aStack, bStack)) return false; } - }); - return result; + } else { + // Deep compare objects. + var keys = _.keys(a), key; + length = keys.length; + // Ensure that both objects contain the same number of properties before comparing deep equality. + if (_.keys(b).length !== length) return false; + while (length--) { + // Deep compare each member + key = keys[length]; + if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return true; }; - // Return the minimum element (or element-based computation). - _.min = function(obj, iterator, context) { - if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { - return Math.min.apply(Math, obj); - } - var result = Infinity, lastComputed = Infinity; - each(obj, function(value, index, list) { - var computed = iterator ? iterator.call(context, value, index, list) : value; - if (computed < lastComputed) { - result = value; - lastComputed = computed; - } - }); - return result; + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b); }; - // Shuffle an array, using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). - _.shuffle = function(obj) { - var rand; - var index = 0; - var shuffled = []; - each(obj, function(value) { - rand = _.random(index++); - shuffled[index - 1] = shuffled[rand]; - shuffled[rand] = value; - }); - return shuffled; + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; + return _.keys(obj).length === 0; }; - // Sample **n** random values from a collection. - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (obj.length !== +obj.length) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; - } - return _.shuffle(obj).slice(0, Math.max(0, n)); + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); }; - // An internal function to generate lookup iterators. - var lookupIterator = function(value) { - if (value == null) return _.identity; - if (_.isFunction(value)) return value; - return _.property(value); + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) === '[object Array]'; }; - // Sort the object's values by a criterion produced by an iterator. - _.sortBy = function(obj, iterator, context) { - iterator = lookupIterator(iterator); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iterator.call(context, value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); + // Is a given variable an object? + _.isObject = function(obj) { + var type = typeof obj; + return type === 'function' || type === 'object' && !!obj; }; - // An internal function used for aggregate "group by" operations. - var group = function(behavior) { - return function(obj, iterator, context) { - var result = {}; - iterator = lookupIterator(iterator); - each(obj, function(value, index) { - var key = iterator.call(context, value, index, obj); - behavior(result, key, value); - }); - return result; + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. + _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) === '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE < 9), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return _.has(obj, 'callee'); + }; + } + + // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, + // IE 11 (#1621), and in Safari 8 (#1929). + if (typeof /./ != 'function' && typeof Int8Array != 'object') { + _.isFunction = function(obj) { + return typeof obj == 'function' || false; }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); }; - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, key, value) { - _.has(result, key) ? result[key].push(value) : result[key] = [value]; - }); + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj !== +obj; + }; - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, key, value) { - result[key] = value; - }); + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; + }; - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, key) { - _.has(result, key) ? result[key]++ : result[key] = 1; - }); + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iterator, context) { - iterator = lookupIterator(iterator); - var value = iterator.call(context, obj); - var low = 0, high = array.length; - while (low < high) { - var mid = (low + high) >>> 1; - iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; - } - return low; + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; }; - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (obj.length === +obj.length) return _.map(obj, _.identity); - return _.values(obj); + // Keep the identity function around for default iteratees. + _.identity = function(value) { + return value; }; - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + // Predicate-generating functions. Often useful outside of Underscore. + _.constant = function(value) { + return function() { + return value; + }; }; - // Array Functions - // --------------- + _.noop = function(){}; - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if ((n == null) || guard) return array[0]; - if (n < 0) return []; - return slice.call(array, 0, n); + _.property = property; + + // Generates a function for a given object that returns a given property. + _.propertyOf = function(obj) { + return obj == null ? function(){} : function(key) { + return obj[key]; + }; }; - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. The **guard** check allows it to work with - // `_.map`. - _.initial = function(array, n, guard) { - return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + // Returns a predicate for checking whether an object has a given set of + // `key:value` pairs. + _.matcher = _.matches = function(attrs) { + attrs = _.extendOwn({}, attrs); + return function(obj) { + return _.isMatch(obj, attrs); + }; }; - // Get the last element of an array. Passing **n** will return the last N - // values in the array. The **guard** check allows it to work with `_.map`. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if ((n == null) || guard) return array[array.length - 1]; - return slice.call(array, Math.max(array.length - n, 0)); + // Run a function **n** times. + _.times = function(n, iteratee, context) { + var accum = Array(Math.max(0, n)); + iteratee = optimizeCb(iteratee, context, 1); + for (var i = 0; i < n; i++) accum[i] = iteratee(i); + return accum; }; - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. The **guard** - // check allows it to work with `_.map`. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, (n == null) || guard ? 1 : n); + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); }; - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { + return new Date().getTime(); }; - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, output) { - if (shallow && _.every(input, _.isArray)) { - return concat.apply(output, input); + // List of HTML entities for escaping. + var escapeMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + var unescapeMap = _.invert(escapeMap); + + // Functions for escaping and unescaping strings to/from HTML interpolation. + var createEscaper = function(map) { + var escaper = function(match) { + return map[match]; + }; + // Regexes for identifying a key that needs to be escaped + var source = '(?:' + _.keys(map).join('|') + ')'; + var testRegexp = RegExp(source); + var replaceRegexp = RegExp(source, 'g'); + return function(string) { + string = string == null ? '' : '' + string; + return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; + }; + }; + _.escape = createEscaper(escapeMap); + _.unescape = createEscaper(unescapeMap); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property, fallback) { + var value = object == null ? void 0 : object[property]; + if (value === void 0) { + value = fallback; } - each(input, function(value) { - if (_.isArray(value) || _.isArguments(value)) { - shallow ? push.apply(output, value) : flatten(value, shallow, output); - } else { - output.push(value); - } - }); - return output; + return _.isFunction(value) ? value.call(object) : value; }; - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, []); + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; }; - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g }; - // Split an array into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = function(array, predicate) { - var pass = [], fail = []; - each(array, function(elem) { - (predicate(elem) ? pass : fail).push(elem); - }); - return [pass, fail]; + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\u2028': 'u2028', + '\u2029': 'u2029' }; - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iterator, context) { - if (_.isFunction(isSorted)) { - context = iterator; - iterator = isSorted; - isSorted = false; - } - var initial = iterator ? _.map(array, iterator, context) : array; - var results = []; - var seen = []; - each(initial, function(value, index) { - if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { - seen.push(value); - results.push(array[index]); + var escaper = /\\|'|\r|\n|\u2028|\u2029/g; + + var escapeChar = function(match) { + return '\\' + escapes[match]; + }; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + // NB: `oldSettings` only exists for backwards compatibility. + _.template = function(text, settings, oldSettings) { + if (!settings && oldSettings) settings = oldSettings; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset).replace(escaper, escapeChar); + index = offset + match.length; + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } else if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } else if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; } + + // Adobe VMs need the match returned to produce the correct offest. + return match; }); - return results; - }; + source += "';\n"; - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(_.flatten(arguments, true)); + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + 'return __p;\n'; + + try { + var render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled source as a convenience for precompilation. + var argument = settings.variable || 'obj'; + template.source = 'function(' + argument + '){\n' + source + '}'; + + return template; }; - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var rest = slice.call(arguments, 1); - return _.filter(_.uniq(array), function(item) { - return _.every(rest, function(other) { - return _.contains(other, item); - }); - }); + // Add a "chain" function. Start chaining a wrapped Underscore object. + _.chain = function(obj) { + var instance = _(obj); + instance._chain = true; + return instance; }; - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); - return _.filter(array, function(value){ return !_.contains(rest, value); }); + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(instance, obj) { + return instance._chain ? _(obj).chain() : obj; }; - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - var length = _.max(_.pluck(arguments, 'length').concat(0)); - var results = new Array(length); - for (var i = 0; i < length; i++) { - results[i] = _.pluck(arguments, '' + i); - } - return results; + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + _.each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result(this, func.apply(_, args)); + }; + }); }; - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - if (list == null) return {}; - var result = {}; - for (var i = 0, length = list.length; i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; + return result(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + _.each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result(this, method.apply(this._wrapped, arguments)); + }; + }); + + // Extracts the result from a wrapped and chained object. + _.prototype.value = function() { + return this._wrapped; }; - // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), - // we need this function. Return the position of the first occurrence of an - // item in an array, or -1 if the item is not included in the array. - // Delegates to **ECMAScript 5**'s native `indexOf` if available. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = function(array, item, isSorted) { - if (array == null) return -1; - var i = 0, length = array.length; - if (isSorted) { - if (typeof isSorted == 'number') { - i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); - } else { - i = _.sortedIndex(array, item); - return array[i] === item ? i : -1; - } - } - if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); - for (; i < length; i++) if (array[i] === item) return i; - return -1; + // Provide unwrapping proxy for some methods used in engine operations + // such as arithmetic and JSON stringification. + _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; + + _.prototype.toString = function() { + return '' + this._wrapped; }; - // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. - _.lastIndexOf = function(array, item, from) { - if (array == null) return -1; - var hasIndex = from != null; - if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { - return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}.call(this)); + +},{}],72:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],73:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); } - var i = (hasIndex ? from : array.length); - while (i--) if (array[i] === item) return i; - return -1; - }; + return objects.join(' '); + } - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (arguments.length <= 1) { - stop = start || 0; - start = 0; + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; } - step = arguments[2] || 1; - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var idx = 0; - var range = new Array(length); - - while(idx < length) { - range[idx++] = start; - start += step; + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); } + } + return str; +}; - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Reusable constructor function for prototype setting. - var ctor = function(){}; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - var args, bound; - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError; - args = slice.call(arguments, 2); - return bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - ctor.prototype = func.prototype; - var self = new ctor; - ctor.prototype = null; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (Object(result) === result) return result; - return self; - }; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder, allowing any combination of arguments to be pre-filled. - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - return function() { - var position = 0; - var args = boundArgs.slice(); - for (var i = 0, length = args.length; i < length; i++) { - if (args[i] === _) args[i] = arguments[position++]; - } - while (position < arguments.length) args.push(arguments[position++]); - return func.apply(this, args); - }; - }; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = function(obj) { - var funcs = slice.call(arguments, 1); - if (funcs.length === 0) throw new Error('bindAll must be passed function names'); - each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); - return obj; - }; - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memo = {}; - hasher || (hasher = _.identity); +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { return function() { - var key = hasher.apply(this, arguments); - return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + return exports.deprecate(fn, msg).apply(this, arguments); }; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ return func.apply(null, args); }, wait); - }; + } - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = function(func) { - return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); - }; + if (process.noDeprecation === true) { + return fn; + } - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - options || (options = {}); - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0) { - clearTimeout(timeout); - timeout = null; - previous = now; - result = func.apply(context, args); - context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); } - return result; - }; - }; + warned = true; + } + return fn.apply(this, arguments); + } - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; + return deprecated; +}; - var later = function() { - var last = _.now() - timestamp; - if (last < wait) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - context = args = null; - } - } - }; - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) { - timeout = setTimeout(later, wait); - } - if (callNow) { - result = func.apply(context, args); - context = args = null; - } +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; - return result; - }; - }; - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = function(func) { - var ran = false, memo; - return function() { - if (ran) return memo; - ran = true; - memo = func.apply(this, arguments); - func = null; - return memo; - }; +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var funcs = arguments; - return function() { - var args = arguments; - for (var i = funcs.length - 1; i >= 0; i--) { - args = [funcs[i].apply(this, args)]; - } - return args[0]; - }; - }; +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; - // Returns a function that will only be executed after being called N times. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - // Object Functions - // ---------------- +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; - // Retrieve the names of an object's properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - return keys; - }; + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = new Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = new Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; +function stylizeNoColor(str, styleType) { + return str; +} - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; +function arrayToHash(array) { + var hash = {}; - // Extend a given object with all the properties in passed-in object(s). - _.extend = function(obj) { - each(slice.call(arguments, 1), function(source) { - if (source) { - for (var prop in source) { - obj[prop] = source[prop]; - } - } - }); - return obj; - }; + array.forEach(function(val, idx) { + hash[val] = true; + }); - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - each(keys, function(key) { - if (key in obj) copy[key] = obj[key]; - }); - return copy; - }; + return hash; +} - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj) { - var copy = {}; - var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); - for (var key in obj) { - if (!_.contains(keys, key)) copy[key] = obj[key]; + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); } - return copy; - }; + return ret; + } - // Fill in a given object with default properties. - _.defaults = function(obj) { - each(slice.call(arguments, 1), function(source) { - if (source) { - for (var prop in source) { - if (obj[prop] === void 0) obj[prop] = source[prop]; - } - } - }); - return obj; - }; + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a == 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className != toString.call(b)) return false; - switch (className) { - // Strings, numbers, dates, and booleans are compared by value. - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return a == String(b); - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a == +b; - // RegExps are compared by their source patterns and flags. - case '[object RegExp]': - return a.source == b.source && - a.global == b.global && - a.multiline == b.multiline && - a.ignoreCase == b.ignoreCase; + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); } - if (typeof a != 'object' || typeof b != 'object') return false; - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] == a) return bStack[length] == b; - } - // Objects with different constructors are not equivalent, but `Object`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && - _.isFunction(bCtor) && (bCtor instanceof bCtor)) - && ('constructor' in a && 'constructor' in b)) { - return false; + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size = 0, result = true; - // Recursively compare objects and arrays. - if (className == '[object Array]') { - // Compare array lengths to determine if a deep comparison is necessary. - size = a.length; - result = size == b.length; - if (result) { - // Deep compare the contents, ignoring non-numeric properties. - while (size--) { - if (!(result = eq(a[size], b[size], aStack, bStack))) break; - } - } - } else { - // Deep compare objects. - for (var key in a) { - if (_.has(a, key)) { - // Count the expected number of properties. - size++; - // Deep compare each member. - if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; - } - } - // Ensure that both objects contain the same number of properties. - if (result) { - for (key in b) { - if (_.has(b, key) && !(size--)) break; - } - result = !size; - } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return result; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b, [], []); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; - for (var key in obj) if (_.has(obj, key)) return false; - return true; - }; + if (isError(value)) { + return formatError(value); + } + } - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; + var base = '', array = false, braces = ['{', '}']; - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) == '[object Array]'; - }; + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } - // Is a given variable an object? - _.isObject = function(obj) { - return obj === Object(obj); - }; + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. - each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) == '[object ' + name + ']'; - }; - }); + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } - // Define a fallback version of the method in browsers (ahem, IE), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return !!(obj && _.has(obj, 'callee')); - }; + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); } - // Optimize `isFunction` if appropriate. - if (typeof (/./) !== 'function') { - _.isFunction = function(obj) { - return typeof obj === 'function'; - }; + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); } - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj != +obj; - }; + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; - }; + ctx.seen.push(value); - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; + ctx.seen.pop(); - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return hasOwnProperty.call(obj, key); - }; + return reduceToSingleString(output, base, braces); +} - // Utility Functions - // ----------------- - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} - // Keep the identity function around for default iterators. - _.identity = function(value) { - return value; - }; - _.constant = function(value) { - return function () { - return value; - }; - }; +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} - _.property = function(key) { - return function(obj) { - return obj[key]; - }; - }; - // Returns a predicate for checking whether an object has a given set of `key:value` pairs. - _.matches = function(attrs) { - return function(obj) { - if (obj === attrs) return true; //avoid comparing an object to itself. - for (var key in attrs) { - if (attrs[key] !== obj[key]) - return false; - } - return true; +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); } - }; + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} - // Run a function **n** times. - _.times = function(n, iterator, context) { - var accum = Array(Math.max(0, n)); - for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); - return accum; - }; - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); } - return min + Math.floor(Math.random() * (max - min + 1)); - }; + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { return new Date().getTime(); }; + return name + ': ' + str; +} - // List of HTML entities for escaping. - var entityMap = { - escape: { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - } - }; - entityMap.unescape = _.invert(entityMap.escape); - // Regexes containing the keys and values listed immediately above. - var entityRegexes = { - escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), - unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') - }; +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); - // Functions for escaping and unescaping strings to/from HTML interpolation. - _.each(['escape', 'unescape'], function(method) { - _[method] = function(string) { - if (string == null) return ''; - return ('' + string).replace(entityRegexes[method], function(match) { - return entityMap[method][match]; - }); - }; - }); + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, property) { - if (object == null) return void 0; - var value = object[property]; - return _.isFunction(value) ? value.call(object) : value; - }; + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result.call(this, func.apply(_, args)); - }; - }); - }; - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\t': 't', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; - var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - _.template = function(text, data, settings) { - var render; - settings = _.defaults({}, settings, _.templateSettings); +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; - // Combine delimiters into one regular expression via alternation. - var matcher = new RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset) - .replace(escaper, function(match) { return '\\' + escapes[match]; }); +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } - if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } - if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - index = offset + match.length; - return match; - }); - source += "';\n"; +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + "return __p;\n"; +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; - try { - render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; - if (data) return render(data, _); - var template = function(data) { - return render.call(this, data, _); - }; +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; - // Provide the compiled function source as a convenience for precompilation. - template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; +exports.isBuffer = require('./support/isBuffer'); - return template; - }; +function objectToString(o) { + return Object.prototype.toString.call(o); +} - // Add a "chain" function, which will delegate to the wrapper. - _.chain = function(obj) { - return _(obj).chain(); - }; - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} - // Helper function to continue chaining intermediate results. - var result = function(obj) { - return this._chain ? _(obj).chain() : obj; - }; - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; - // Add all mutator Array functions to the wrapper. - each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; - return result.call(this, obj); - }; - }); +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} - // Add all accessor Array functions to the wrapper. - each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result.call(this, method.apply(this._wrapped, arguments)); - }; - }); - _.extend(_.prototype, { +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; - // Start chaining a wrapped Underscore object. - chain: function() { - this._chain = true; - return this; - }, - // Extracts the result from a wrapped and chained object. - value: function() { - return this._wrapped; - } +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); - }); +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof define === 'function' && define.amd) { - define('underscore', [], function() { - return _; - }); + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; } -}).call(this); + return origin; +}; -},{}],72:[function(require,module,exports){ -module.exports={ - "name": "carto", - "version": "0.15.1-cdb1", - "description": "CartoCSS Stylesheet Compiler", - "url": "https://github.com/cartodb/carto", - "repository": { - "type": "git", - "url": "http://github.com/cartodb/carto.git" - }, - "author": { - "name": "CartoDB", - "url": "http://cartodb.com/" - }, - "keywords": [ - "maps", - "css", - "stylesheets" - ], - "contributors": [ - { - "name": "Tom MacWright", - "email": "macwright@gmail.com" - }, - { - "name": "Konstantin Käfer" - }, - { - "name": "Alexis Sellier", - "email": "self@cloudhead.net" - }, - { - "name": "Raul Ochoa", - "email": "rochoa@cartodb.com" - }, - { - "name": "Javi Santana", - "email": "jsantana@cartodb.com" - } - ], - "licenses": [ - { - "type": "Apache" - } - ], - "bin": { - "carto": "./bin/carto" - }, - "man": [ - "./man/carto.1" - ], - "main": "./lib/carto/index", - "engines": { - "node": ">=0.4.x" - }, - "dependencies": { - "underscore": "~1.6.0", - "mapnik-reference": "~6.0.2", - "optimist": "~0.6.0" - }, - "devDependencies": { - "mocha": "1.12.x", - "jshint": "0.2.x", - "sax": "0.1.x", - "istanbul": "~0.2.14", - "coveralls": "~2.10.1", - "browserify": "~7.0.0", - "uglify-js": "1.3.3" - }, - "scripts": { - "pretest": "npm install", - "test": "mocha -R spec", - "coverage": "istanbul cover ./node_modules/.bin/_mocha && coveralls < ./coverage/lcov.info" - }, - "readme": "# CartoCSS\n\n[![Build Status](https://secure.travis-ci.org/mapbox/carto.png)](http://travis-ci.org/mapbox/carto)\n\nIs as stylesheet renderer for javascript, It's an evolution of the Mapnik renderer from Mapbox.\nPlease, see original [Mapbox repo](http://github.com/mapbox/carto) for more information and credits\n\n## Quick Start\n\n```javascript\n// shader is a CartoCSS object\n\nvar cartocss = [\n '#layer {',\n ' marker-width: [property]',\n ' marker-fill: red',\n '}'\n].join('')\nvar shader = new carto.RendererJS().render(cartocss);\nvar layers = shader.getLayers()\nfor (var i = 0; i < layers.length; ++i) {\n var layer = layers[i];\n console.log(\"layer name: \", layer.fullName())\n console.log(\"- frames: \", layer.frames())\n console.log(\"- attachment: \", layer.attachment())\n\n var layerShader = layer.getStyle({ property: 1 }, { zoom: 10 })\n console.log(layerShader['marker-width']) // 1\n console.log(layerShader['marker-fill']) // #FF0000\n}\n\n```\n\n# API\n\n## RendererJS\n\n### render(cartocss)\n\n## CartoCSS\n\ncompiled cartocss object\n\n### getLayers\n\nreturn the layers, an array of ``CartoCSS.Layer`` object\n\n### getDefault\n\nreturn the default layer (``CartoCSS.Layer``), usually the Map layer\n\n\n### findLayer(where)\n\nfind a layer using where object.\n\n```\nshader.findLayer({ name: 'test' })\n```\n\n## CartoCSS.Layer\n\n### getStyle(props, context)\n\nreturn the evaluated style:\n - props: object containing properties needed to render the style. If the cartocss style uses\n some variables they should be passed in this object\n - context: rendering context variables like ``zoom`` or animation ``frame``\n\n\n\n\n\n\n\n\n\n\n## Reference Documentation\n\n* [mapbox.com/carto](http://mapbox.com/carto/)\n\n\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/cartodb/carto/issues" - }, - "homepage": "https://github.com/cartodb/carto", - "_id": "carto@0.15.1-cdb1", - "_shasum": "62534c2975cbee073f10c6c14a0c7e889c9469e7", - "_resolved": "https://github.com/CartoDB/carto/archive/master.tar.gz", - "_from": "https://github.com/CartoDB/carto/archive/master.tar.gz" +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); } -},{}]},{},[10])(10) +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":72,"_process":70,"inherits":67}]},{},[10])(10) }); \ No newline at end of file diff --git a/dist/torque.js b/dist/torque.js index fbad17c6..ff97d066 100644 --- a/dist/torque.js +++ b/dist/torque.js @@ -1,3 +1,3 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.torque=e()}}(function(){var e,t,n;return function i(e,t,n){function r(o,u){if(!t[o]){if(!e[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=t[o]={exports:{}};e[o][0].call(l.exports,function(t){var n=e[o][1][t];return r(n?n:t)},l,l.exports,i,e,t,n)}return t[o].exports}var s=typeof require=="function"&&require;for(var o=0;oe&&this.time(0),this.rescale(),this):this.options.animationDuration},steps:function(e){return this.options.steps=e,this.rescale()},step:function(e){if(arguments.length===0)return this.range(this.domain(this._time));this._time=this.domainInv(this.rangeInv(e))},pause:function(){this.running=!1,s(this._tick),this.options.onPause&&this.options.onPause()},_tick:function(){var e=+(new Date),t=(e-this._t0)*.001;t=Math.min(this.options.maxDelta,t),this._t0=e,this._time+=t,this.step()>=this.options.steps&&(this.options.loop?this._time=0:(this.time(this.options.animationDuration),this.pause())),this.running&&(this.time(this._time),i(this._tick))}},t.exports=o}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./":10}],2:[function(e,t,n){var r={version:"1.0.0",style:{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]}},layer:{"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"number","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"number","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"number","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}},symbolizers:{"*":{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},trail:{steps:{css:"trail-steps",type:"float","default-value":1,"default-meaning":"no trail steps",doc:"How many steps of trails are going to be rendered"}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon"},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line"},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels"},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color"},"marker-type":{css:"marker-type",type:["rectangle","ellipse"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)"},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float"}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]}};t.exports={version:{latest:r,"1.0.0":r}}},{}],3:[function(e,t,n){(function(n){function i(){}var r=n.carto||e("carto");i.prototype={},i.optionsFromLayer=function(e){var t={};if(!e)return t;var n={"buffer-size":"buffer-size","-torque-frame-count":"steps","-torque-resolution":"resolution","-torque-animation-duration":"animationDuration","-torque-aggregation-function":"countby","-torque-time-attribute":"column","-torque-data-aggregation":"data_aggregation"};for(var r in n){var i=e.eval(r);if(i!==undefined){var s=n[r];t[s]=i}}return t},i.optionsFromCartoCSS=function(e){var t=(new r.RendererJS).render(e),n=t.findLayer({name:"Map"});return i.optionsFromLayer(n)},t.exports.TorqueLayer=i}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{carto:undefined}],4:[function(e,t,n){(function(e){function r(){var e=arguments,t=e[0];for(var n=1;ni&&(n.x-=i),this.canvas.style[r.CSS_TRANSFORM_]="translate("+Math.round(n.x)+"px,"+Math.round(n.y)+"px)",this.scheduleUpdate()},r.prototype.update_=function(){this.requestAnimationFrameId_=null;if(!this.isAdded_)return;this.isAnimated_&&this.scheduleUpdate(),this.needsResize_&&this.resizeHandler_&&(this.needsResize_=!1,this.resizeHandler_()),this.updateHandler_&&this.updateHandler_()},r.prototype.getTopLeft=function(){return this.topLeft_},r.prototype.scheduleUpdate=function(){this.isAdded_&&!this.requestAnimationFrameId_&&(this.requestAnimationFrameId_=this.requestAnimFrame_.call(window,this.requestUpdateFunction_))},t.exports=r},{}],6:[function(e,t,n){function r(e,t){this.tileSize=new google.maps.Size(256,256),this.maxZoom=19,this.name="Tile #s",this.alt="Canvas tile layer",this.tiles={},this.canvas_setup=e,this.render=t,t||(this.render=e)}r.prototype.create_tile_canvas=function(e,t,n){var r=n.createElement("canvas"),i=n.createElement("canvas");r.style.border=i.style.border="none",r.style.margin=i.style.margin="0",r.style.padding=i.style.padding="0";var s=r.getContext("2d");s.width=r.width=this.tileSize.width,s.height=r.height=this.tileSize.height;var o=i.getContext("2d");i.width=o.width=this.tileSize.width,i.height=o.height=this.tileSize.height;var u=e.x+"_"+e.y+"_"+t;return r.setAttribute("id",u),i.setAttribute("id",u),u in this.tiles&&delete this.tiles[u],this.tiles[u]={canvas:r,ctx:s,hit_canvas:i,hit_ctx:o,coord:e,zoom:t,primitives:null},this.canvas_setup&&this.canvas_setup(this.tiles[u],e,t),r},r.prototype.each=function(e){for(var t in this.tiles){var n=this.tiles[t];e(n)}},r.prototype.recreate=function(){for(var e in this.tiles){var t=this.tiles[e];this.canvas_setup(t,t.coord,t.zoom)}},r.prototype.redraw_tile=function(e){this.render(e,e.coord,e.zoom)},r.prototype.redraw=function(){for(var e in this.tiles){var t=this.tiles[e];this.render(t,t.coord,t.zoom)}},r.prototype.getTile=function(e,t,n){return this.create_tile_canvas(e,t,n)},r.prototype.releaseTile=function(e){var t=e.getAttribute("id");delete this.tiles[t]},t.exports=r},{}],7:[function(e,t,n){function r(){}r.prototype={_initTileLoader:function(e,t){this._map=e,this._projection=t,this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._updateTiles=this._updateTiles.bind(this),this._listeners=[],this._listeners.push(google.maps.event.addListener(this._map,"dragend",this._updateTiles),google.maps.event.addListener(this._map,"zoom_changed",this._updateTiles)),this.tileSize=256,this._updateTiles()},_removeTileLoader:function(){this._listeners.forEach(function(e){google.maps.event.removeListener(e)}),this._removeTiles()},_removeTiles:function(){for(var e in this._tiles)this._removeTile(e)},_reloadTiles:function(){this._removeTiles(),this._updateTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getBounds(),t=this._map.getZoom(),n=this.tileSize,r=1<t.x||it.y)&&this._removeTile(s))},_removeTile:function(e){this.onTileRemoved&&this.onTileRemoved(this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.onTilesLoaded&&this.onTilesLoaded()},getTilePos:function(e){var t=1<=0&&a>=0&&u=0&&this.cancelAnimationFrame.call(window,this.currentAnimationFrame),this.currentAnimationFrame=this.requestAnimationFrame.call(window,this.render)},redraw:function(e){var t=L.DomUtil.getPosition(this._map.getPanes().mapPane);t&&L.DomUtil.setPosition(this._canvas,{x:-t.x,y:-t.y}),e?this.render():this._render()},onResize:function(){},render:function(){throw new Error("render function should be implemented")}})},{"./leaflet_tileloader_mixin":13}],12:[function(e,t,n){typeof L!="undefined"&&e("./torque")},{"./torque":14}],13:[function(e,t,n){L.Mixin.TileLoader={_initTileLoader:function(){this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._map.on({moveend:this._updateTiles},this),this._updateTiles()},_removeTileLoader:function(){this._map.off({moveend:this._updateTiles},this),this._removeTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getPixelBounds(),t=this._map.getZoom(),n=this.options.tileSize;if(t>this.options.maxZoom||te.max.x||re.max.y)&&this._removeTile(s))},_removeTile:function(e){this.fire("tileRemoved",this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.fire("tilesLoaded")},getTilePos:function(e){e=new L.Point(e.x,e.y);var t=this._map._getNewTopLeftPoint(this._map.getCenter()),n=this.options.tileSize;return e.multiplyBy(n).subtract(t)},_addTilesFromCenterOut:function(e){var t=[],n=e.getCenter(),r=this._map.getZoom(),i,s,o;for(i=e.min.y;i<=e.max.y;i++)for(s=e.min.x;s<=e.max.x;s++)o=new L.Point(s,i),o.zoom=r,this._tileShouldBeLoaded(o)&&t.push(o);var u=t.length;if(u===0)return;t.sort(function(e,t){return e.distanceTo(n)-t.distanceTo(n)}),this._tilesToLoad+=u;for(s=0;s0&&l>0&&o.getContext("2d").drawImage(this.getCanvas(),u,a,f,l,u-n.x,a-n.y,f,l)}}}this.prevRenderedKey=this.key},setKey:function(e,t){this.key=e,this.animator.step(e),this._clearTileCaches(),this.redraw(t&&t.direct),this.fire("change:time",{time:this.getTime(),step:this.key})},setStep:function(e){if(e===undefined||e.length!==undefined)throw new Error("setTime only accept scalars");this.setKey(e)},stepToTime:function(e){var t=this.provider.getKeySpan(),n=t.start+(t.end-t.start)*(e/this.provider.getSteps());return new Date(n)},timeToStep:function(e){typeof e=="Date"&&(e=e.getTime());if(!this.provider)return 0;var t=this.provider.getKeySpan(),n=this.provider.getSteps()*(e-t.start)/(t.end-t.start);return n},getStep:function(){return this.key},getTime:function(){return this.stepToTime(this.key)},getTimeSpan:function(){return this.provider.getKeySpan()},setCartoCSS:function(e){if(this.provider.options.named_map)throw new Error("CartoCSS style on named maps is read-only");if(!this.renderer)throw new Error("renderer is not valid");var t=(new n.RendererJS).render(e);this.renderer.setShader(t);var i=r.common.TorqueLayer.optionsFromLayer(t.findLayer({name:"Map"}));return this.provider.setCartoCSS&&this.provider.setCartoCSS(e),this.provider.setOptions(i)&&this._reloadTiles(),r.extend(this.options,i),i.animationDuration&&this.animator.duration(i.animationDuration),this._clearCaches(),this.redraw(),this},getActivePointsBBox:function(e){var t=[];for(var n in this._tiles){var r=this._tiles[n];t=t.concat(this.renderer.getActivePointsBBox(r,e))}return t},getValueForPos:function(e,t,n){n=n===undefined?this.key:n;var r,i,s,o=null,u,a;for(r in this._tiles){i=this._tiles[r],s=this.getTilePos(i.coord),u=e-s.x,a=t-s.y,u>=0&&a>=0&&u1&&(i.new_value(this.name,this.count),this.count=0,this.start())}},i.metric=function(e){return new s(e)},t.exports=i},{}],18:[function(e,t,n){t.exports={json:e("./json"),JsonArray:e("./jsonarray"),windshaft:e("./windshaft")}},{"./json":19,"./jsonarray":20,"./windshaft":21}],19:[function(e,t,n){function a(e){for(var t=1;t>0),e.options.data_steps=t.num_steps>>0,e.options.step=e.options.step||1,e.options.bounds=[[t.ymin,t.xmin],[t.ymax,t.xmax]],e._setReady(!0)},{parseJSON:!0,no_cdn:!0})},{parseJSON:!0,no_cdn:!0})}},t.exports=f},{"../":10,"../profiler":17}],20:[function(e,t,n){function f(e,t){for(var n=1;n=0?t["marker-fill-opacity"]:1,e.globalAlpha>0&&e.fill()),t["marker-line-color"]&&t["marker-line-width"]&&t["marker-line-width"]>i&&(e.globalAlpha=t["marker-line-opacity"]>=0?t["marker-line-opacity"]:1,t["marker-line-width"]!==undefined&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.stroke())}function u(e,t){e.fillStyle=t["marker-fill"];var n=t["marker-width"],r=n*2;if(t["marker-fill"]){if(t["marker-fill-opacity"]!==undefined||t["marker-opacity"]!==undefined)e.globalAlpha=t["marker-fill-opacity"]||t["marker-opacity"];e.fillRect(-n,-n,r,r)}e.globalAlpha=1,t["marker-line-color"]&&t["marker-line-width"]&&(t["marker-line-opacity"]&&(e.globalAlpha=t["marker-line-opacity"]),t["marker-line-width"]&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.strokeRect(-n,-n,r,r))}function a(e,t,n){if(t.complete){if(n["marker-fill-opacity"]!==undefined||n["marker-opacity"]!==undefined)e.globalAlpha=n["marker-fill-opacity"]||n["marker-opacity"];e.drawImage(t,0,0,Math.min(t.width,s),Math.min(t.height,s))}}var r=Math.PI*2,i=.05,s=255;t.exports={renderPoint:o,renderSprite:a,renderRectangle:u,MAX_SPRITE_RADIUS:s}},{}],23:[function(e,t,n){t.exports={cartocss:e("./cartocss_render"),Point:e("./point"),Rectangle:e("./rectangle")}},{"./cartocss_render":22,"./point":24,"./rectangle":25}],24:[function(e,t,n){(function(n){function c(e){return l[e]||e}function h(e,t){if(!e)throw new Error("canvas can't be undefined");this.options=t,this._canvas=e,this._ctx=e.getContext("2d"),this._sprites=[],this._shader=null,this._icons={},this._iconsToLoad=0,this._filters=new u(this._canvas,{canvasClass:t.canvasClass}),this.setCartoCSS(this.options.cartocss||f),this.TILE_SIZE=256,this._style=null,this._gradients={},this._forcePoints=!1}var r=e("../"),i=e("./cartocss_render"),s=e("../profiler"),o=n.carto||e("carto"),u=e("./torque_filters"),a=Math.PI*2,f=["#layer {"," marker-fill: #662506;"," marker-width: 4;"," [value > 1] { marker-fill: #FEE391; }"," [value > 2] { marker-fill: #FEC44F; }"," [value > 3] { marker-fill: #FE9929; }"," [value > 4] { marker-fill: #EC7014; }"," [value > 5] { marker-fill: #CC4C02; }"," [value > 6] { marker-fill: #993404; }"," [value > 7] { marker-fill: #662506; }","}"].join("\n"),l={src:"source-over","src-over":"source-over","dst-over":"destination-over","src-in":"source-in","dst-in":"destination-in","src-out":"source-out","dst-out":"destination-out","src-atop":"source-atop","dst-atop":"destination-atop",xor:"xor",darken:"darken",lighten:"lighten"};r.extend(h.prototype,r.Event,{clearCanvas:function(){var e=this._canvas,t=this._Map["-torque-clear-color"];if(t==="rgba(255, 255, 255, 0)"||!t)this._canvas.width=this._canvas.width;else{var n=this._ctx;n.setTransform(1,0,0,1,0,0);var r=this._Map["comp-op"];n.globalCompositeOperation=c(r),n.fillStyle=t,n.fillRect(0,0,e.width,e.height)}},setCanvas:function(e){this._canvas=e,this._ctx=e.getContext("2d")},setCartoCSS:function(e){this.setShader((new o.RendererJS).render(e))},setShader:function(e){this._sprites=[],this._shader=e,this._Map=this._shader.getDefault().getStyle({},{zoom:0});var t=this._shader.getImageURLs();this._preloadIcons(t)},clearSpriteCache:function(){this._sprites=[]},generateSprite:function(e,t,n){var o=this,u=s.metric("torque.renderer.point.generateSprite").start(),a=e.getStyle({value:t},n);if(this._style===null||this._style!==a)this._style=a;var f=a["marker-width"];if(!f)return null;if(a["marker-opacity"]===0&&!a["marker-line-opacity"])return null;var l=this._createCanvas(),c=l.getContext("2d"),h=a["marker-file"]||a["point-file"],p=h&&this._qualifyURL(h);if(p&&this._iconsToLoad<=0&&this._icons[p]){var d=this._icons[p],v=Math.min(a["marker-width"]*2||d.width,i.MAX_SPRITE_RADIUS*2),m=Math.min((a["marker-height"]||v)*(d.width/d.height),i.MAX_SPRITE_RADIUS*2);l.width=c.width=v,l.height=c.height=m,c.scale(v/d.width,m/d.height),i.renderSprite(c,d,a)}else{var g=(a["marker-line-width"]||0)+f*2,y=c.width=l.width=c.height=l.height=Math.ceil(g);c.translate(y/2,y/2);var b=a["marker-type"];b&&b==="rectangle"?i.renderRectangle(c,a):i.renderPoint(c,a)}u.end(!0);if(r.flags.sprites_to_images){var w=this._createImage();return w.src=l.toDataURL(),w}return l},renderTile:function(e,t,n){if(this._iconsToLoad>0)return this.on("allIconsLoaded",function(){this.renderTile.apply(this,[e,t,n])}),!1;var r=s.metric("torque.renderer.point.renderLayers").start(),i=this._shader.getLayers();for(var o=0,u=i.length;oe.maxDate&&(t=e.maxDate);var h=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),p=e.timeCount[t],d=this.options.resolution/2;if(p){var v=e.timeIndex[t];for(var m=0;m>1)+d,E=h-e.y[g]+d;f.drawImage(b,w,E-(b.height>>1))}}}}a.end(!0)},setBlendMode:function(e){this.options.blendmode=e},getActivePointsBBox:function(e,t){var n=[],i=new r.Mercator,s=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),o=e.timeCount[t],u=e.timeIndex[t];for(var a=0;a>1,a=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),f=e.timeCount[t],l=e.timeIndex[t];for(var c=0;c=0&&m=0&&g0&&!this._forcePoints){var n=Object.keys(e.reduce(function(e,n){var r=t._qualifyURL(n);return t._icons[r]||(e[r]=!0),e},{})),r=t._shader.getLayers().some(function(e){return typeof e.shader["image-filters"]!="undefined"});this._iconsToLoad+=n.length,n.forEach(function(e){t._icons[e]=null;var n=t._createImage();r&&(n.crossOrigin="Anonymous"),t._setImageSrc(n,e,function(i){i?(t._forcePoints=!0,t.clearSpriteCache(),t._iconsToLoad=0,t.fire("allIconsLoaded"),r&&console.info("Only CORS-enabled, or same domain image-files can be used in combination with image-filters"),console.error("Couldn't get marker-file "+e)):(t._icons[e]=n,t._iconsToLoad--,t._iconsToLoad<=0&&(t.clearSpriteCache(),t.fire("allIconsLoaded")))})})}else this.fire("allIconsLoaded")},applyFilters:function(){if(this._style&&this._style["image-filters"]){function e(e){var t="";for(var n=0;n 10] { polygon-fill: #FFFF00; }"," [value > 100] { polygon-fill: #FFCC00; }"," [value > 1000] { polygon-fill: #FE9929; }"," [value > 10000] { polygon-fill: #FF6600; }"," [value > 100000] { polygon-fill: #FF3300; }","}"].join("\n"),s=Math.PI*2;o.prototype={setCartoCSS:function(e){this._cartoCssStyle=(new r.RendererJS).render(e);if(this._cartoCssStyle.getLayers().length>1)throw new Error("only one CartoCSS layer is supported");this._shader=this._cartoCssStyle.getLayers()[0].shader},setCanvas:function(e){if(!e)return;this._canvas=e,this._ctx=e.getContext("2d")},accumulate:function(e,t){var n=Profiler.metric("RectangleRender:accumulate").start(),r,i,s,o,u,a,f,l,c=this.options.resolution,h=256/c,p=new Float32Array(h*h);typeof t!="object"&&(t=[t]);for(u=0;u=200&&e<300||e===304?t(o):t(null)}r=r||{method:"GET",data:null,responseType:"text"},i={url:e,callback:t};var s=XMLHttpRequest;n.XDomainRequest&&!("withCredentials"in s)&&/^(http(s)?:)?\/\//.test(e)&&(s=XDomainRequest);var o=new s;return o.open(r.method,e,!0),"onload"in o?o.onload=o.onerror=u:o.onreadystatechange=function(){o.readyState>3&&u()},o.onprogress=function(){},o.responseType=r.responseType,r.data&&(o.setRequestHeader("Content-type","application/json"),o.setRequestHeader("Accept","*")),o.send(r.data),o}function u(e,t,n){return o(e,n,{data:t,method:"POST"})}var r=e("./core"),i=null;t.exports={get:o,post:u,jsonp:s,lastCall:function(){return i}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./core":4}]},{},[10])(10)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.torque=e()}}(function(){var e,t,n;return function i(e,t,n){function r(o,u){if(!t[o]){if(!e[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(s)return s(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=t[o]={exports:{}};e[o][0].call(l.exports,function(t){var n=e[o][1][t];return r(n?n:t)},l,l.exports,i,e,t,n)}return t[o].exports}var s=typeof require=="function"&&require;for(var o=0;oe&&this.time(0),this.rescale(),this):this.options.animationDuration},steps:function(e){return this.options.steps=e,this.rescale()},step:function(e){if(arguments.length===0)return this.range(this.domain(this._time));this._time=this.domainInv(this.rangeInv(e))},pause:function(){this.running=!1,s(this._tick),this.options.onPause&&this.options.onPause()},_tick:function(){var e=+(new Date),t=(e-this._t0)*.001;t=Math.min(this.options.maxDelta,t),this._t0=e,this._time+=t,this.step()>=this.options.steps&&(this.options.loop?this._time=0:(this.time(this.options.animationDuration),this.pause())),this.running&&(this.time(this._time),i(this._tick))}},t.exports=o}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./":10}],2:[function(e,t,n){var r={version:"1.0.0",style:{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]}},layer:{"buffer-size":{"default-value":"0",type:"float","default-meaning":"No buffer will be used",doc:"Extra tolerance around the Layer extent (in pixels) used to when querying and (potentially) clipping the layer data during rendering"},"-torque-clear-color":{css:"-torque-clear-color",type:"color","default-value":"rgba(255, 255, 255, 0)","default-meaning":"full clear",doc:"color used to clear canvas on each frame"},"-torque-frame-count":{css:"-torque-frame-count","default-value":"128",type:"number","default-meaning":"the data is broken into 128 time frames",doc:"Number of animation steps/frames used in the animation. If the data contains a fewere number of total frames, the lesser value will be used."},"-torque-resolution":{css:"-torque-resolution","default-value":"2",type:"number","default-meaning":"",doc:"Spatial resolution in pixels. A resolution of 1 means no spatial aggregation of the data. Any other resolution of N results in spatial aggregation into cells of NxN pixels. The value N must be power of 2"},"-torque-animation-duration":{css:"-torque-animation-duration","default-value":"30",type:"number","default-meaning":"the animation lasts 30 seconds",doc:"Animation duration in seconds"},"-torque-aggregation-function":{css:"-torque-aggregation-function","default-value":"count(cartodb_id)",type:"string","default-meaning":"the value for each cell is the count of points in that cell",doc:"A function used to calculate a value from the aggregate data for each cell. See -torque-resolution"},"-torque-time-attribute":{css:"-torque-time-attribute","default-value":"time",type:"string","default-meaning":"the data column in your table that is of a time based type",doc:"The table column that contains the time information used create the animation"},"-torque-data-aggregation":{css:"-torque-data-aggregation","default-value":"linear",type:["cumulative"],"default-meaning":"previous values are discarded",doc:"A linear animation will discard previous values while a cumulative animation will accumulate them until it restarts"}},symbolizers:{"*":{"comp-op":{css:"comp-op","default-value":"src-over","default-meaning":"add the current layer on top of other layers",doc:"Composite operation. This defines how this layer should behave relative to layers atop or below it.",type:["src","src-over","dst-over","src-in","dst-in","src-out","dst-out","src-atop","dst-atop","xor","darken","lighten"]},opacity:{css:"opacity",type:"float",doc:"An alpha value for the style (which means an alpha applied to all features in separate buffer and then composited back to main buffer)","default-value":1,"default-meaning":"no separate buffer will be used and no alpha will be applied to the style after rendering"}},trail:{steps:{css:"trail-steps",type:"float","default-value":1,"default-meaning":"no trail steps",doc:"How many steps of trails are going to be rendered"}},polygon:{fill:{css:"polygon-fill",type:"color","default-value":"rgba(128,128,128,1)","default-meaning":"gray and fully opaque (alpha = 1), same as rgb(128,128,128)",doc:"Fill color to assign to a polygon"},"fill-opacity":{css:"polygon-opacity",type:"float",doc:"The opacity of the polygon","default-value":1,"default-meaning":"opaque"}},line:{stroke:{css:"line-color","default-value":"rgba(0,0,0,1)",type:"color","default-meaning":"black and fully opaque (alpha = 1), same as rgb(0,0,0)",doc:"The color of a drawn line"},"stroke-width":{css:"line-width","default-value":1,type:"float",doc:"The width of a line in pixels"},"stroke-opacity":{css:"line-opacity","default-value":1,type:"float","default-meaning":"opaque",doc:"The opacity of a line"},"stroke-linejoin":{css:"line-join","default-value":"miter",type:["miter","round","bevel"],doc:"The behavior of lines when joining"},"stroke-linecap":{css:"line-cap","default-value":"butt",type:["butt","round","square"],doc:"The display of line endings"}},markers:{file:{css:"marker-file",doc:"An SVG file that this marker shows at each placement. If no file is given, the marker will show an ellipse.","default-value":"","default-meaning":"An ellipse or circle, if width equals height",type:"uri"},opacity:{css:"marker-opacity",doc:"The overall opacity of the marker, if set, overrides both the opacity of both the fill and stroke","default-value":1,"default-meaning":"The stroke-opacity and fill-opacity will be used",type:"float"},"fill-opacity":{css:"marker-fill-opacity",doc:"The fill opacity of the marker","default-value":1,"default-meaning":"opaque",type:"float"},stroke:{css:"marker-line-color",doc:"The color of the stroke around a marker shape.","default-value":"black",type:"color"},"stroke-width":{css:"marker-line-width",doc:"The width of the stroke around a marker shape, in pixels. This is positioned on the boundary, so high values can cover the area itself.",type:"float"},"stroke-opacity":{css:"marker-line-opacity","default-value":1,"default-meaning":"opaque",doc:"The opacity of a line",type:"float"},fill:{css:"marker-fill","default-value":"blue",doc:"The color of the area of the marker.",type:"color"},"marker-type":{css:"marker-type",type:["rectangle","ellipse"],"default-value":"ellipse",doc:"The default marker-type. If a SVG file is not given as the marker-file parameter, the renderer provides either an rectangle or an ellipse (a circle if height is equal to width)"},width:{css:"marker-width","default-value":10,doc:"The width of the marker, if using one of the default types.",type:"float"}},point:{file:{css:"point-file",type:"uri",required:!1,"default-value":"none",doc:"Image file to represent a point"},opacity:{css:"point-opacity",type:"float","default-value":1,"default-meaning":"Fully opaque",doc:"A value from 0 to 1 to control the opacity of the point"}}},colors:{aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50],transparent:[0,0,0,0]}};t.exports={version:{latest:r,"1.0.0":r}}},{}],3:[function(e,t,n){(function(n){function i(){}var r=n.carto||e("carto");i.prototype={},i.optionsFromLayer=function(e){var t={};if(!e)return t;var n={"buffer-size":"buffer-size","-torque-frame-count":"steps","-torque-resolution":"resolution","-torque-animation-duration":"animationDuration","-torque-aggregation-function":"countby","-torque-time-attribute":"column","-torque-data-aggregation":"data_aggregation"};for(var r in n){var i=e.eval(r);if(i!==undefined){var s=n[r];t[s]=i}}return t},i.optionsFromCartoCSS=function(e){var t=(new r.RendererJS).render(e),n=t.findLayer({name:"Map"});return i.optionsFromLayer(n)},t.exports.TorqueLayer=i}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{carto:undefined}],4:[function(e,t,n){(function(e){function r(){var e=arguments,t=e[0];for(var n=1;ni&&(n.x-=i),this.canvas.style[r.CSS_TRANSFORM_]="translate("+Math.round(n.x)+"px,"+Math.round(n.y)+"px)",this.scheduleUpdate()},r.prototype.update_=function(){this.requestAnimationFrameId_=null;if(!this.isAdded_)return;this.isAnimated_&&this.scheduleUpdate(),this.needsResize_&&this.resizeHandler_&&(this.needsResize_=!1,this.resizeHandler_()),this.updateHandler_&&this.updateHandler_()},r.prototype.getTopLeft=function(){return this.topLeft_},r.prototype.scheduleUpdate=function(){this.isAdded_&&!this.requestAnimationFrameId_&&(this.requestAnimationFrameId_=this.requestAnimFrame_.call(window,this.requestUpdateFunction_))},t.exports=r},{}],6:[function(e,t,n){function r(e,t){this.tileSize=new google.maps.Size(256,256),this.maxZoom=19,this.name="Tile #s",this.alt="Canvas tile layer",this.tiles={},this.canvas_setup=e,this.render=t,t||(this.render=e)}r.prototype.create_tile_canvas=function(e,t,n){var r=n.createElement("canvas"),i=n.createElement("canvas");r.style.border=i.style.border="none",r.style.margin=i.style.margin="0",r.style.padding=i.style.padding="0";var s=r.getContext("2d");s.width=r.width=this.tileSize.width,s.height=r.height=this.tileSize.height;var o=i.getContext("2d");i.width=o.width=this.tileSize.width,i.height=o.height=this.tileSize.height;var u=e.x+"_"+e.y+"_"+t;return r.setAttribute("id",u),i.setAttribute("id",u),u in this.tiles&&delete this.tiles[u],this.tiles[u]={canvas:r,ctx:s,hit_canvas:i,hit_ctx:o,coord:e,zoom:t,primitives:null},this.canvas_setup&&this.canvas_setup(this.tiles[u],e,t),r},r.prototype.each=function(e){for(var t in this.tiles){var n=this.tiles[t];e(n)}},r.prototype.recreate=function(){for(var e in this.tiles){var t=this.tiles[e];this.canvas_setup(t,t.coord,t.zoom)}},r.prototype.redraw_tile=function(e){this.render(e,e.coord,e.zoom)},r.prototype.redraw=function(){for(var e in this.tiles){var t=this.tiles[e];this.render(t,t.coord,t.zoom)}},r.prototype.getTile=function(e,t,n){return this.create_tile_canvas(e,t,n)},r.prototype.releaseTile=function(e){var t=e.getAttribute("id");delete this.tiles[t]},t.exports=r},{}],7:[function(e,t,n){function r(){}r.prototype={_initTileLoader:function(e,t){this._map=e,this._projection=t,this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._updateTiles=this._updateTiles.bind(this),this._listeners=[],this._listeners.push(google.maps.event.addListener(this._map,"dragend",this._updateTiles),google.maps.event.addListener(this._map,"zoom_changed",this._updateTiles)),this.tileSize=256,this._updateTiles()},_removeTileLoader:function(){this._listeners.forEach(function(e){google.maps.event.removeListener(e)}),this._removeTiles()},_removeTiles:function(){for(var e in this._tiles)this._removeTile(e)},_reloadTiles:function(){this._removeTiles(),this._updateTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getBounds(),t=this._map.getZoom(),n=this.tileSize,r=1<t.x||it.y)&&this._removeTile(s))},_removeTile:function(e){this.onTileRemoved&&this.onTileRemoved(this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.onTilesLoaded&&this.onTilesLoaded()},getTilePos:function(e){var t=1<=0&&a>=0&&u=0&&this.cancelAnimationFrame.call(window,this.currentAnimationFrame),this.currentAnimationFrame=this.requestAnimationFrame.call(window,this.render)},redraw:function(e){var t=L.DomUtil.getPosition(this._map.getPanes().mapPane);t&&L.DomUtil.setPosition(this._canvas,{x:-t.x,y:-t.y}),e?this.render():this._render()},onResize:function(){},render:function(){throw new Error("render function should be implemented")}})},{"./leaflet_tileloader_mixin":13}],12:[function(e,t,n){typeof L!="undefined"&&e("./torque")},{"./torque":14}],13:[function(e,t,n){L.Mixin.TileLoader={_initTileLoader:function(){this._tiles={},this._tilesLoading={},this._tilesToLoad=0,this._map.on({moveend:this._updateTiles},this),this._updateTiles()},_removeTileLoader:function(){this._map.off({moveend:this._updateTiles},this),this._removeTiles()},_updateTiles:function(){if(!this._map)return;var e=this._map.getPixelBounds(),t=this._map.getZoom(),n=this.options.tileSize;if(t>this.options.maxZoom||te.max.x||re.max.y)&&this._removeTile(s))},_removeTile:function(e){this.fire("tileRemoved",this._tiles[e]),delete this._tiles[e],delete this._tilesLoading[e]},_tileKey:function(e){return e.x+":"+e.y+":"+e.zoom},_tileShouldBeLoaded:function(e){var t=this._tileKey(e);return!(t in this._tiles)&&!(t in this._tilesLoading)},_tileLoaded:function(e,t){this._tilesToLoad--;var n=e.x+":"+e.y+":"+e.zoom;this._tiles[n]=t,delete this._tilesLoading[n],this._tilesToLoad===0&&this.fire("tilesLoaded")},getTilePos:function(e){e=new L.Point(e.x,e.y);var t=this._map._getNewTopLeftPoint(this._map.getCenter()),n=this.options.tileSize;return e.multiplyBy(n).subtract(t)},_addTilesFromCenterOut:function(e){var t=[],n=e.getCenter(),r=this._map.getZoom(),i,s,o;for(i=e.min.y;i<=e.max.y;i++)for(s=e.min.x;s<=e.max.x;s++)o=new L.Point(s,i),o.zoom=r,this._tileShouldBeLoaded(o)&&t.push(o);var u=t.length;if(u===0)return;t.sort(function(e,t){return e.distanceTo(n)-t.distanceTo(n)}),this._tilesToLoad+=u;for(s=0;s0&&l>0&&o.getContext("2d").drawImage(this.getCanvas(),u,a,f,l,u-n.x,a-n.y,f,l)}}}this.prevRenderedKey=this.key},setKey:function(e,t){this.key=e,this.animator.step(e),this._clearTileCaches(),this.redraw(t&&t.direct),this.fire("change:time",{time:this.getTime(),step:this.key})},setStep:function(e){if(e===undefined||e.length!==undefined)throw new Error("setTime only accept scalars");this.setKey(e)},stepToTime:function(e){var t=this.provider.getKeySpan(),n=t.start+(t.end-t.start)*(e/this.provider.getSteps());return new Date(n)},timeToStep:function(e){typeof e=="Date"&&(e=e.getTime());if(!this.provider)return 0;var t=this.provider.getKeySpan(),n=this.provider.getSteps()*(e-t.start)/(t.end-t.start);return n},getStep:function(){return this.key},getTime:function(){return this.stepToTime(this.key)},getTimeSpan:function(){return this.provider.getKeySpan()},setCartoCSS:function(e){if(this.provider.options.named_map)throw new Error("CartoCSS style on named maps is read-only");if(!this.renderer)throw new Error("renderer is not valid");var t=(new n.RendererJS).render(e);this.renderer.setShader(t);var i=r.common.TorqueLayer.optionsFromLayer(t.findLayer({name:"Map"}));return this.provider.setCartoCSS&&this.provider.setCartoCSS(e),this.provider.setOptions(i)&&this._reloadTiles(),r.extend(this.options,i),i.animationDuration&&this.animator.duration(i.animationDuration),this._clearCaches(),this.redraw(),this},getActivePointsBBox:function(e){var t=[];for(var n in this._tiles){var r=this._tiles[n];t=t.concat(this.renderer.getActivePointsBBox(r,e))}return t},getValueForPos:function(e,t,n){n=n===undefined?this.key:n;var r,i,s,o=null,u,a;for(r in this._tiles){i=this._tiles[r],s=this.getTilePos(i.coord),u=e-s.x,a=t-s.y,u>=0&&a>=0&&u1&&(i.new_value(this.name,this.count),this.count=0,this.start())}},i.metric=function(e){return new s(e)},t.exports=i},{}],18:[function(e,t,n){t.exports={json:e("./json"),JsonArray:e("./jsonarray"),windshaft:e("./windshaft"),internal:e("./internal")}},{"./internal":19,"./json":20,"./jsonarray":21,"./windshaft":22}],19:[function(e,t,n){var r=e("../"),i=new r.Mercator,s=function(e){this.setReady(!1),this.options=e,this.options.data_aggregation&&(this.options.cumulative=this.options.data_aggregation==="cumulative"),this.points=[],this._tileQueue=[],this.options.bounds=[[Number.MAX_VALUE,Number.MAX_VALUE],[Number.MIN_VALUE,Number.MIN_VALUE]]};s.prototype={addPoint:function(e,t,n,r){typeof n=="number"?(n=parseInt(n),this.timestampType===undefined&&(this.timestampType="number")):(n=new Date(Date.parse(n)),this.timestampType===undefined&&(this.timestampType="date")),this.points.push({lat:parseFloat(e),lon:parseFloat(t),time:n,value:parseFloat(r)||r})},getBounds:function(){return this.options.bounds},getCategories:function(){if(!this.options.countby)return[];var e=this,t=function(t){return t.name==e.points[r].value},n=[];for(var r=0;rthis.options.bounds[1][0]&&(this.options.bounds[1][0]=e.latLonBounds.maxLat),e.latLonBounds.minLatthis.options.bounds[1][1]&&(this.options.bounds[1][1]=e.latLonBounds.maxLon),e.latLonBounds.minLone.latLonBounds.minLat&&t.lone.latLonBounds.minLon}},getPointsInTile:function(e){var t=[];for(var n=0;n0){l[d]===undefined&&(l[d]=[]),l[d][v]===undefined&&(l[d][v]=0),l[d][v]+=h.value,h.value=l[d][v];for(var g=m;g>0),e.options.data_steps=t.num_steps>>0,e.options.step=e.options.step||1,e.options.bounds=[[t.ymin,t.xmin],[t.ymax,t.xmax]],e._setReady(!0)},{parseJSON:!0,no_cdn:!0})},{parseJSON:!0,no_cdn:!0})}},t.exports=f},{"../":10,"../profiler":17}],21:[function(e,t,n){function f(e,t){for(var n=1;n=0?t["marker-fill-opacity"]:1,e.globalAlpha>0&&e.fill()),t["marker-line-color"]&&t["marker-line-width"]&&t["marker-line-width"]>i&&(e.globalAlpha=t["marker-line-opacity"]>=0?t["marker-line-opacity"]:1,t["marker-line-width"]!==undefined&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.stroke())}function u(e,t){e.fillStyle=t["marker-fill"];var n=t["marker-width"],r=n*2;if(t["marker-fill"]){if(t["marker-fill-opacity"]!==undefined||t["marker-opacity"]!==undefined)e.globalAlpha=t["marker-fill-opacity"]||t["marker-opacity"];e.fillRect(-n,-n,r,r)}e.globalAlpha=1,t["marker-line-color"]&&t["marker-line-width"]&&(t["marker-line-opacity"]&&(e.globalAlpha=t["marker-line-opacity"]),t["marker-line-width"]&&(e.lineWidth=t["marker-line-width"]),e.strokeStyle=t["marker-line-color"],e.globalAlpha>0&&e.strokeRect(-n,-n,r,r))}function a(e,t,n){if(t.complete){if(n["marker-fill-opacity"]!==undefined||n["marker-opacity"]!==undefined)e.globalAlpha=n["marker-fill-opacity"]||n["marker-opacity"];e.drawImage(t,0,0,Math.min(t.width,s),Math.min(t.height,s))}}var r=Math.PI*2,i=.05,s=255;t.exports={renderPoint:o,renderSprite:a,renderRectangle:u,MAX_SPRITE_RADIUS:s}},{}],24:[function(e,t,n){t.exports={cartocss:e("./cartocss_render"),Point:e("./point"),Rectangle:e("./rectangle")}},{"./cartocss_render":23,"./point":25,"./rectangle":26}],25:[function(e,t,n){(function(n){function c(e){return l[e]||e}function h(e,t){if(!e)throw new Error("canvas can't be undefined");this.options=t,this._canvas=e,this._ctx=e.getContext("2d"),this._sprites=[],this._shader=null,this._icons={},this._iconsToLoad=0,this._filters=new u(this._canvas,{canvasClass:t.canvasClass}),this.setCartoCSS(this.options.cartocss||f),this.TILE_SIZE=256,this._style=null,this._gradients={},this._forcePoints=!1}var r=e("../"),i=e("./cartocss_render"),s=e("../profiler"),o=n.carto||e("carto"),u=e("./torque_filters"),a=Math.PI*2,f=["#layer {"," marker-fill: #662506;"," marker-width: 4;"," [value > 1] { marker-fill: #FEE391; }"," [value > 2] { marker-fill: #FEC44F; }"," [value > 3] { marker-fill: #FE9929; }"," [value > 4] { marker-fill: #EC7014; }"," [value > 5] { marker-fill: #CC4C02; }"," [value > 6] { marker-fill: #993404; }"," [value > 7] { marker-fill: #662506; }","}"].join("\n"),l={src:"source-over","src-over":"source-over","dst-over":"destination-over","src-in":"source-in","dst-in":"destination-in","src-out":"source-out","dst-out":"destination-out","src-atop":"source-atop","dst-atop":"destination-atop",xor:"xor",darken:"darken",lighten:"lighten"};r.extend(h.prototype,r.Event,{clearCanvas:function(){var e=this._canvas,t=this._Map["-torque-clear-color"];if(t==="rgba(255, 255, 255, 0)"||!t)this._canvas.width=this._canvas.width;else{var n=this._ctx;n.setTransform(1,0,0,1,0,0);var r=this._Map["comp-op"];n.globalCompositeOperation=c(r),n.fillStyle=t,n.fillRect(0,0,e.width,e.height)}},setCanvas:function(e){this._canvas=e,this._ctx=e.getContext("2d")},setCartoCSS:function(e){this.setShader((new o.RendererJS).render(e))},setShader:function(e){this._sprites=[],this._shader=e,this._Map=this._shader.getDefault().getStyle({},{zoom:0});var t=this._shader.getImageURLs();this._preloadIcons(t)},clearSpriteCache:function(){this._sprites=[]},generateSprite:function(e,t,n){var o=this,u=s.metric("torque.renderer.point.generateSprite").start(),a=e.getStyle({value:t},n);if(this._style===null||this._style!==a)this._style=a;var f=a["marker-width"];if(!f)return null;if(a["marker-opacity"]===0&&!a["marker-line-opacity"])return null;var l=this._createCanvas(),c=l.getContext("2d"),h=a["marker-file"]||a["point-file"],p=h&&this._qualifyURL(h);if(p&&this._iconsToLoad<=0&&this._icons[p]){var d=this._icons[p],v=Math.min(a["marker-width"]*2||d.width,i.MAX_SPRITE_RADIUS*2),m=Math.min((a["marker-height"]||v)*(d.width/d.height),i.MAX_SPRITE_RADIUS*2);l.width=c.width=v,l.height=c.height=m,c.scale(v/d.width,m/d.height),i.renderSprite(c,d,a)}else{var g=(a["marker-line-width"]||0)+f*2,y=c.width=l.width=c.height=l.height=Math.ceil(g);c.translate(y/2,y/2);var b=a["marker-type"];b&&b==="rectangle"?i.renderRectangle(c,a):i.renderPoint(c,a)}u.end(!0);if(r.flags.sprites_to_images){var w=this._createImage();return w.src=l.toDataURL(),w}return l},renderTile:function(e,t,n){if(this._iconsToLoad>0)return this.on("allIconsLoaded",function(){this.renderTile.apply(this,[e,t,n])}),!1;var r=s.metric("torque.renderer.point.renderLayers").start(),i=this._shader.getLayers();for(var o=0,u=i.length;oe.maxDate&&(t=e.maxDate);var h=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),p=e.timeCount[t],d=this.options.resolution/2;if(p){var v=e.timeIndex[t];for(var m=0;m>1)+d,E=h-e.y[g]+d;f.drawImage(b,w,E-(b.height>>1))}}}}a.end(!0)},setBlendMode:function(e){this.options.blendmode=e},getActivePointsBBox:function(e,t){var n=[],i=new r.Mercator,s=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),o=e.timeCount[t],u=e.timeIndex[t];for(var a=0;a>1,a=this.options.resolution*(this.TILE_SIZE/this.options.resolution-1),f=e.timeCount[t],l=e.timeIndex[t];for(var c=0;c=0&&m=0&&g0&&!this._forcePoints){var n=Object.keys(e.reduce(function(e,n){var r=t._qualifyURL(n);return t._icons[r]||(e[r]=!0),e},{})),r=t._shader.getLayers().some(function(e){return typeof e.shader["image-filters"]!="undefined"});this._iconsToLoad+=n.length,n.forEach(function(e){t._icons[e]=null;var n=t._createImage();r&&(n.crossOrigin="Anonymous"),t._setImageSrc(n,e,function(i){i?(t._forcePoints=!0,t.clearSpriteCache(),t._iconsToLoad=0,t.fire("allIconsLoaded"),r&&console.info("Only CORS-enabled, or same domain image-files can be used in combination with image-filters"),console.error("Couldn't get marker-file "+e)):(t._icons[e]=n,t._iconsToLoad--,t._iconsToLoad<=0&&(t.clearSpriteCache(),t.fire("allIconsLoaded")))})})}else this.fire("allIconsLoaded")},applyFilters:function(){if(this._style&&this._style["image-filters"]){function e(e){var t="";for(var n=0;n 10] { polygon-fill: #FFFF00; }"," [value > 100] { polygon-fill: #FFCC00; }"," [value > 1000] { polygon-fill: #FE9929; }"," [value > 10000] { polygon-fill: #FF6600; }"," [value > 100000] { polygon-fill: #FF3300; }","}"].join("\n"),s=Math.PI*2;o.prototype={setCartoCSS:function(e){this._cartoCssStyle=(new r.RendererJS).render(e);if(this._cartoCssStyle.getLayers().length>1)throw new Error("only one CartoCSS layer is supported");this._shader=this._cartoCssStyle.getLayers()[0].shader},setCanvas:function(e){if(!e)return;this._canvas=e,this._ctx=e.getContext("2d")},accumulate:function(e,t){var n=Profiler.metric("RectangleRender:accumulate").start(),r,i,s,o,u,a,f,l,c=this.options.resolution,h=256/c,p=new Float32Array(h*h);typeof t!="object"&&(t=[t]);for(u=0;u=200&&e<300||e===304?t(o):t(null)}r=r||{method:"GET",data:null,responseType:"text"},i={url:e,callback:t};var s=XMLHttpRequest;n.XDomainRequest&&!("withCredentials"in s)&&/^(http(s)?:)?\/\//.test(e)&&(s=XDomainRequest);var o=new s;return o.open(r.method,e,!0),"onload"in o?o.onload=o.onerror=u:o.onreadystatechange=function(){o.readyState>3&&u()},o.onprogress=function(){},o.responseType=r.responseType,r.data&&(o.setRequestHeader("Content-type","application/json"),o.setRequestHeader("Accept","*")),o.send(r.data),o}function u(e,t,n){return o(e,n,{data:t,method:"POST"})}var r=e("./core"),i=null;t.exports={get:o,post:u,jsonp:s,lastCall:function(){return i}}}).call(this,typeof global!="undefined"?global:typeof self!="undefined"?self:typeof window!="undefined"?window:{})},{"./core":4}]},{},[10])(10)}); \ No newline at end of file diff --git a/dist/torque.uncompressed.js b/dist/torque.uncompressed.js index f76b445c..0df8ee6e 100644 --- a/dist/torque.uncompressed.js +++ b/dist/torque.uncompressed.js @@ -2000,7 +2000,7 @@ module.exports.GMapsTileLoader = gmaps.GMapsTileLoader; module.exports.GMapsTorqueLayer = gmaps.GMapsTorqueLayer; module.exports.GMapsTiledTorqueLayer = gmaps.GMapsTiledTorqueLayer; -},{"./animator":1,"./cartocss_reference":2,"./common":3,"./core":4,"./gmaps":8,"./leaflet":12,"./math":15,"./mercator":16,"./provider":18,"./renderer":23,"./request":27}],11:[function(require,module,exports){ +},{"./animator":1,"./cartocss_reference":2,"./common":3,"./core":4,"./gmaps":8,"./leaflet":12,"./math":15,"./mercator":16,"./provider":18,"./renderer":24,"./request":28}],11:[function(require,module,exports){ require('./leaflet_tileloader_mixin'); /** @@ -2425,7 +2425,8 @@ L.TorqueLayer = L.CanvasLayer.extend({ providers: { 'sql_api': torque.providers.json, 'url_template': torque.providers.JsonArray, - 'windshaft': torque.providers.windshaft + 'windshaft': torque.providers.windshaft, + 'internal': torque.providers.internal }, renderers: { @@ -2949,7 +2950,7 @@ MercatorProjection.prototype.latLonToTilePoint = function(lat, lon, tileX, tileY var worldCoordinate = this._fromLatLonToPoint(lat, lon); var pixelCoordinate = new Point(worldCoordinate.x*numTiles, worldCoordinate.y*numTiles); var tilePixelPos = this._tilePixelPos(tileX, tileY); - return new Point(Math.round(pixelCoordinate.x-tilePixelPos.x), Math.round(pixelCoordinate.y-tilePixelPos.y)); + return new Point(Math.round(pixelCoordinate.x-tilePixelPos.x), this._tileSize - Math.round(pixelCoordinate.y-tilePixelPos.y)); }; module.exports = MercatorProjection; @@ -3102,10 +3103,320 @@ module.exports = Profiler; module.exports = { json: require('./json'), JsonArray: require('./jsonarray'), - windshaft: require('./windshaft') + windshaft: require('./windshaft'), + internal: require('./internal') +}; + +},{"./internal":19,"./json":20,"./jsonarray":21,"./windshaft":22}],19:[function(require,module,exports){ +var torque = require('../'); + +var mercatorUtils = new torque.Mercator(); + +/* + * Options: + * steps: + */ +var internal = function (options) { + this.setReady(false); + this.options = options; + if (this.options.data_aggregation) { + this.options.cumulative = this.options.data_aggregation === 'cumulative'; + } + this.points = []; + this._tileQueue = []; + this.options.bounds = [ + [Number.MAX_VALUE, Number.MAX_VALUE], + [Number.MIN_VALUE, Number.MIN_VALUE] + ]; +}; + + +internal.prototype = { + addPoint: function (lat, lon, time, value) { + if (typeof(time) == "number") { + time = parseInt(time); + if (this.timestampType === undefined) { + this.timestampType = "number"; + } + } else { + time = new Date(Date.parse(time)); + if (this.timestampType === undefined) { + this.timestampType = "date"; + } + } + this.points.push({lat: parseFloat(lat), lon: parseFloat(lon), time: time, value: parseFloat(value) || value}); + }, + getBounds: function () { + return this.options.bounds; + }, + getCategories: function () { + if (!this.options.countby) { + return []; + } + + var self = this; + + var checkCategoryExists = function (category) { + return category.name == self.points[i].value; + }; + + var categories = []; + for (var i = 0; i < this.points.length; i++) { + if (!categories.some(checkCategoryExists)) { + var randomColor = 0x1000000 + Math.floor(Math.random() * 0xffffff); + randomColor = "#" + randomColor.toString(16).slice(1, 7); + categories.push({ + value: this.points[i].value, + name: this.points[i].value, + color: randomColor + }); + } + } + + return categories; + }, + setOptions: function(opt) { + var refresh = false; + + if (opt.resolution !== undefined && opt.resolution !== this.options.resolution) { + this.options.resolution = opt.resolution; + refresh = true; + } + + if (opt.steps !== undefined && opt.steps !== this.options.steps) { + this.setSteps(opt.steps, { silent: true }); + refresh = true; + } + + if (opt.column !== undefined && opt.column !== this.options.column) { + this.options.column = opt.column; + refresh = true; + } + + if (opt.countby !== undefined && opt.countby !== this.options.countby) { + this.options.countby = opt.countby; + refresh = true; + } + + if (opt.data_aggregation !== undefined) { + var c = opt.data_aggregation === 'cumulative'; + if (this.options.cumulative !== c) { + this.options.cumulative = c; + refresh = true; + } + } + + if (refresh) { + this.reload(); + } + + return refresh; + }, + setReady: function (ready) { + if (ready == false) { + this._ready = false; + } else { + var self = this; + + this.options.data_steps = this.points.length; + + this.points.sort(function (point1, point2) { + return point1.time - point2.time; + }); + + if (this.timestampType == "number") { + this.options.start = this.points[0].time; + this.options.end = this.points[this.points.length - 1].time; + } else { + this.options.start = this.points[0].time.getTime(); + this.options.end = this.points[this.points.length - 1].time.getTime(); + } + + this.timestamps = {}; // {date: timestamp_id} + for (var i = 0; i < this.points.length; i++) { + var point = this.points[i]; + if ((this.options.end - this.options.start) != 0) { + this.timestamps[point.time] || (this.timestamps[point.time] = parseInt(this.getSteps() * (point.time - this.options.start) / (this.options.end - this.options.start))); + } else { + this.timestamps[point.time] || (this.timestamps[point.time] = 0); + } + } + + this.maxTimestamp = this.timestamps[this.points[this.points.length - 1].time]; + + this._ready = true; + this._processQueue(); + this.options.ready && this.options.ready(); + } + }, + getTileData: function (coord, zoom, callback) { + if(!this._ready) { + this._tileQueue.push([coord, callback]); + } else { + this._getTileData(coord, callback); + } + }, + _getTileData: function (tile, callback) { + this.prepareTile(tile); + + var pointsInTile = this.getPointsInTile(tile); + + callback(this.processTile(tile, pointsInTile)); + }, + _processQueue: function() { + var item; + while (item = this._tileQueue.pop()) { + this._getTileData.apply(this, item); + } + }, + prepareTile: function (tile) { + /* Calculate tile bounds in lat/lon */ + var bounds = mercatorUtils.tileBBox(tile.x, tile.y, tile.zoom); + + tile.latLonBounds = { + minLat: bounds[0].lat, + maxLat: bounds[1].lat, + minLon: bounds[0].lon, + maxLon: bounds[1].lon + }; + + /* Update total bounds */ + if (tile.latLonBounds.maxLat > this.options.bounds[1][0]) this.options.bounds[1][0] = tile.latLonBounds.maxLat; + if (tile.latLonBounds.minLat < this.options.bounds[0][0]) this.options.bounds[0][0] = tile.latLonBounds.minLat; + if (tile.latLonBounds.maxLon > this.options.bounds[1][1]) this.options.bounds[1][1] = tile.latLonBounds.maxLon; + if (tile.latLonBounds.minLon < this.options.bounds[0][1]) this.options.bounds[0][1] = tile.latLonBounds.minLon; + + /* Function to find out if a point falls into this tile */ + tile.contains = function (point) { + return point.lat < tile.latLonBounds.maxLat && point.lat > tile.latLonBounds.minLat && point.lon < tile.latLonBounds.maxLon && point.lon > tile.latLonBounds.minLon; + } + }, + /* + * Get the all the data points, no matter their timestamp, that fall into the tile + */ + getPointsInTile: function (tile) { + var pointsInTile = []; + + for (var i = 0; i < this.points.length; i++) { + if (tile.contains(this.points[i])) { + pointsInTile.push(this.points[i]); + } + } + + return pointsInTile; + }, + processTile: function (tile, pointsInThisTile) { + /* + * For each this.points[i], x[i] and y[i] are the offsets in pixels from the tile boundaries. + */ + var x = []; + var y = []; + + /* + * pointsInTilePerTimestamp: + */ + var pointsInThisTileByTimestamp = []; + + var timeCount = []; + var timeIndex = []; + var renderData = []; + var renderDataPos = []; + + var accumulatedValues = []; + + for (var pointIdx = 0; pointIdx < pointsInThisTile.length; pointIdx++) { + var point = pointsInThisTile[pointIdx]; + + var tileXY = mercatorUtils.latLonToTilePoint(point.lat, point.lon, tile.x, tile.y, tile.zoom); + + var xInTile = tileXY.x; + var yInTile = tileXY.y; + x[pointIdx] = xInTile; + y[pointIdx] = yInTile; + + var pointTimestamp = this.timestamps[point.time]; + + if (this.options.cumulative && this.maxTimestamp > 0) { + if (accumulatedValues[xInTile] === undefined) { + accumulatedValues[xInTile] = []; + } + if (accumulatedValues[xInTile][yInTile] === undefined) { + accumulatedValues[xInTile][yInTile] = 0; + } + accumulatedValues[xInTile][yInTile] += point.value; + point.value = accumulatedValues[xInTile][yInTile]; + for (var futureTimestamps = pointTimestamp; futureTimestamps < this.maxTimestamp; futureTimestamps++) { + var pointsInTileForFutureTimestamp = pointsInThisTileByTimestamp[futureTimestamps] || (pointsInThisTileByTimestamp[futureTimestamps] = []); + pointsInTileForFutureTimestamp.push({idx: pointIdx, value: point.value}); + } + } else { + var pointsInTileForThisTimestamp = pointsInThisTileByTimestamp[pointTimestamp] || (pointsInThisTileByTimestamp[pointTimestamp] = []); + pointsInTileForThisTimestamp.push({idx: pointIdx, value: point.value}); + } + } + + var pointsInThisTileByTimestamp_keys = Object.keys(pointsInThisTileByTimestamp); + var maxTileTimestamp = pointsInThisTileByTimestamp_keys[pointsInThisTileByTimestamp_keys.length - 1] || 0; + + var renderDataIndex = 0; + var timeStampIndex = 0; + for (var timestamp = 0; timestamp <= maxTileTimestamp; timestamp++) { + var pointsInThisTileForThisTimestamp = pointsInThisTileByTimestamp[timestamp]; + if (pointsInThisTileForThisTimestamp) { + for (var i = 0; i < pointsInThisTileForThisTimestamp.length; i++) { + var point = pointsInThisTileForThisTimestamp[i]; + renderDataPos[renderDataIndex] = point.idx; + renderData[renderDataIndex] = point.value; + ++renderDataIndex; + } + } + timeIndex[timestamp] = timeStampIndex; + var increase = pointsInThisTileForThisTimestamp ? pointsInThisTileForThisTimestamp.length : 0; + timeCount[timestamp] = increase; + timeStampIndex += increase; + } + return { + x: x, + y: y, + z: tile.zoom, + coord: { + x: tile.x, + y: tile.y, + z: tile.zoom + }, + timeCount: timeCount, + timeIndex: timeIndex, + renderDataPos: renderDataPos, + renderData: renderData, + maxDate: maxTileTimestamp + }; + }, + getKeySpan: function () { + return { + start: this.options.start, + end: this.options.end, + step: this.options.step || ((this.options.end - this.options.start) / this.getSteps()), + steps: this.getSteps(), + columnType: this.timestampType + }; + }, + getSteps: function () { + return this.options.steps; + }, + setSteps: function(steps, opt) { + opt = opt || {}; + if (this.options.steps !== steps) { + this.options.steps = steps; + this.options.step = (this.options.end - this.options.start) / this.getSteps(); + this.options.step = this.options.step || 1; + if (!opt.silent) this.reload(); + } + } }; -},{"./json":19,"./jsonarray":20,"./windshaft":21}],19:[function(require,module,exports){ +module.exports = internal; + +},{"../":10}],20:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -3684,7 +3995,7 @@ var Profiler = require('../profiler'); module.exports = json; -},{"../":10,"../profiler":17}],20:[function(require,module,exports){ +},{"../":10,"../profiler":17}],21:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -3914,7 +4225,7 @@ var Profiler = require('../profiler'); module.exports = json; -},{"../":10,"../profiler":17}],21:[function(require,module,exports){ +},{"../":10,"../profiler":17}],22:[function(require,module,exports){ var torque = require('../'); var Profiler = require('../profiler'); @@ -4404,7 +4715,7 @@ var Profiler = require('../profiler'); module.exports = windshaft; -},{"../":10,"../profiler":17}],22:[function(require,module,exports){ +},{"../":10,"../profiler":17}],23:[function(require,module,exports){ var TAU = Math.PI*2; // min value to render a line. // it does not make sense to render a line of a width is not even visible @@ -4497,13 +4808,13 @@ module.exports = { MAX_SPRITE_RADIUS: MAX_SPRITE_RADIUS }; -},{}],23:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ module.exports = { cartocss: require('./cartocss_render'), Point: require('./point'), Rectangle: require('./rectangle') }; -},{"./cartocss_render":22,"./point":24,"./rectangle":25}],24:[function(require,module,exports){ +},{"./cartocss_render":23,"./point":25,"./rectangle":26}],25:[function(require,module,exports){ (function (global){ var torque = require('../'); var cartocss = require('./cartocss_render'); @@ -4954,7 +5265,7 @@ var Filters = require('./torque_filters'); module.exports = PointRenderer; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../":10,"../profiler":17,"./cartocss_render":22,"./torque_filters":26,"carto":undefined}],25:[function(require,module,exports){ +},{"../":10,"../profiler":17,"./cartocss_render":23,"./torque_filters":27,"carto":undefined}],26:[function(require,module,exports){ (function (global){ var carto = global.carto || require('carto'); @@ -5118,7 +5429,7 @@ var carto = global.carto || require('carto'); module.exports = RectanbleRenderer; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"carto":undefined}],26:[function(require,module,exports){ +},{"carto":undefined}],27:[function(require,module,exports){ /* Based on simpleheat, a tiny JavaScript library for drawing heatmaps with Canvas, by Vladimir Agafonkin @@ -5210,7 +5521,7 @@ torque_filters.prototype = { module.exports = torque_filters; -},{}],27:[function(require,module,exports){ +},{}],28:[function(require,module,exports){ (function (global){ var torque = require('./core'); diff --git a/examples/csv.html b/examples/csv.html new file mode 100644 index 00000000..b3ca83e6 --- /dev/null +++ b/examples/csv.html @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + + + +
+
+
+
+
+

Column definition

+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+

First column in file is #0

+
+
+
+
+
+
+

Animation parameters

+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+

File selector

+
+
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + diff --git a/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css new file mode 100644 index 00000000..74ed8970 --- /dev/null +++ b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css @@ -0,0 +1,222 @@ +/*! + * Bootstrap Colorpicker v2.3.3 + * http://mjolnic.github.io/bootstrap-colorpicker/ + * + * Originally written by (c) 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + */ +.colorpicker-saturation { + width: 100px; + height: 100px; + background-image: url("../img/bootstrap-colorpicker/saturation.png"); + cursor: crosshair; + float: left; +} +.colorpicker-saturation i { + display: block; + height: 5px; + width: 5px; + border: 1px solid #000; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + position: absolute; + top: 0; + left: 0; + margin: -4px 0 0 -4px; +} +.colorpicker-saturation i b { + display: block; + height: 5px; + width: 5px; + border: 1px solid #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} +.colorpicker-hue, +.colorpicker-alpha { + width: 15px; + height: 100px; + float: left; + cursor: row-resize; + margin-left: 4px; + margin-bottom: 4px; +} +.colorpicker-hue i, +.colorpicker-alpha i { + display: block; + height: 1px; + background: #000; + border-top: 1px solid #fff; + position: absolute; + top: 0; + left: 0; + width: 100%; + margin-top: -1px; +} +.colorpicker-hue { + background-image: url("../img/bootstrap-colorpicker/hue.png"); +} +.colorpicker-alpha { + background-image: url("../img/bootstrap-colorpicker/alpha.png"); + display: none; +} +.colorpicker-saturation, +.colorpicker-hue, +.colorpicker-alpha { + background-size: contain; +} +.colorpicker { + padding: 4px; + min-width: 130px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + z-index: 2500; +} +.colorpicker:before, +.colorpicker:after { + display: table; + content: ""; + line-height: 0; +} +.colorpicker:after { + clear: both; +} +.colorpicker:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.colorpicker:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.colorpicker div { + position: relative; +} +.colorpicker.colorpicker-with-alpha { + min-width: 140px; +} +.colorpicker.colorpicker-with-alpha .colorpicker-alpha { + display: block; +} +.colorpicker-color { + height: 10px; + margin-top: 5px; + clear: both; + background-image: url("../img/bootstrap-colorpicker/alpha.png"); + background-position: 0 100%; +} +.colorpicker-color div { + height: 10px; +} +.colorpicker-selectors { + display: none; + height: 10px; + margin-top: 5px; + clear: both; +} +.colorpicker-selectors i { + cursor: pointer; + float: left; + height: 10px; + width: 10px; +} +.colorpicker-selectors i + i { + margin-left: 3px; +} +.colorpicker-element .input-group-addon i, +.colorpicker-element .add-on i { + display: inline-block; + cursor: pointer; + height: 16px; + vertical-align: text-top; + width: 16px; +} +.colorpicker.colorpicker-inline { + position: relative; + display: inline-block; + float: none; + z-index: auto; +} +.colorpicker.colorpicker-horizontal { + width: 110px; + min-width: 110px; + height: auto; +} +.colorpicker.colorpicker-horizontal .colorpicker-saturation { + margin-bottom: 4px; +} +.colorpicker.colorpicker-horizontal .colorpicker-color { + width: 100px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue, +.colorpicker.colorpicker-horizontal .colorpicker-alpha { + width: 100px; + height: 15px; + float: left; + cursor: col-resize; + margin-left: 0px; + margin-bottom: 4px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue i, +.colorpicker.colorpicker-horizontal .colorpicker-alpha i { + display: block; + height: 15px; + background: #ffffff; + position: absolute; + top: 0; + left: 0; + width: 1px; + border: none; + margin-top: 0px; +} +.colorpicker.colorpicker-horizontal .colorpicker-hue { + background-image: url("../img/bootstrap-colorpicker/hue-horizontal.png"); +} +.colorpicker.colorpicker-horizontal .colorpicker-alpha { + background-image: url("../img/bootstrap-colorpicker/alpha-horizontal.png"); +} +.colorpicker.colorpicker-hidden { + display: none; +} +.colorpicker.colorpicker-visible { + display: block; +} +.colorpicker-inline.colorpicker-visible { + display: inline-block; +} +.colorpicker-right:before { + left: auto; + right: 6px; +} +.colorpicker-right:after { + left: auto; + right: 7px; +} +.colorpicker-no-arrow:before { + border-right: 0; + border-left: 0; +} +.colorpicker-no-arrow:after { + border-right: 0; + border-left: 0; +} +/*# sourceMappingURL=bootstrap-colorpicker.css.map */ \ No newline at end of file diff --git a/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map new file mode 100644 index 00000000..e61413ad --- /dev/null +++ b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/less/colorpicker.less"],"names":[],"mappings":";;;;;;;;;AAqBA;EACE,YAAA;EACA,aAAA;EAXA,sBAAsB,8CAAtB;EAaA,iBAAA;EACA,WAAA;;AALF,uBAME;EACE,cAAA;EACA,WAAA;EACA,UAAA;EACA,sBAAA;EAfF,0BAAA;EACA,uBAAA;EACA,kBAAA;EAeE,kBAAA;EACA,MAAA;EACA,OAAA;EACA,qBAAA;;AAfJ,uBAME,EAUE;EACE,cAAA;EACA,WAAA;EACA,UAAA;EACA,sBAAA;EAzBJ,0BAAA;EACA,uBAAA;EACA,kBAAA;;AA6BF;AACA;EACE,WAAA;EACA,aAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,kBAAA;;AAGF,gBAAiB;AACjB,kBAAmB;EACjB,cAAA;EACA,WAAA;EACA,gBAAA;EACA,0BAAA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,WAAA;EACA,gBAAA;;AAGF;EA1DE,sBAAsB,uCAAtB;;AA8DF;EA9DE,sBAAsB,yCAAtB;EAgEA,aAAA;;AAGF;AACA;AACA;EACE,wBAAA;;AAGF;EACE,YAAA;EACA,gBAAA;EACA,eAAA;EAxEA,0BAAA;EACA,uBAAA;EACA,kBAAA;EAwEA,aAAA;;AAGF,YAAY;AACZ,YAAY;EACV,cAAA;EACA,SAAS,EAAT;EACA,cAAA;;AAGF,YAAY;EACV,WAAA;;AAGF,YAAY;EACV,SAAS,EAAT;EACA,qBAAA;EACA,kCAAA;EACA,mCAAA;EACA,6BAAA;EACA,uCAAA;EACA,kBAAA;EACA,SAAA;EACA,SAAA;;AAGF,YAAY;EACV,SAAS,EAAT;EACA,qBAAA;EACA,kCAAA;EACA,mCAAA;EACA,gCAAA;EACA,kBAAA;EACA,SAAA;EACA,SAAA;;AAGF,YAAa;EACX,kBAAA;;AAGF,YAAY;EACV,gBAAA;;AAGF,YAAY,uBAAwB;EAClC,cAAA;;AAGF;EACE,YAAA;EACA,eAAA;EACA,WAAA;EAlIA,sBAAsB,yCAAtB;EAoIA,2BAAA;;AAGF,kBAAmB;EACjB,YAAA;;AAGF;EACE,aAAA;EACA,YAAA;EACA,eAAA;EACA,WAAA;;AAGF,sBAAuB;EACrB,eAAA;EACA,WAAA;EACA,YAAA;EACA,WAAA;;AAGF,sBAAuB,EAAE;EACvB,gBAAA;;AAGF,oBAAqB,mBAAmB;AACxC,oBAAqB,QAAQ;EAC3B,qBAAA;EACA,eAAA;EACA,YAAA;EACA,wBAAA;EACA,WAAA;;AAGF,YAAY;EACV,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,aAAA;;AAGF,YAAY;EACV,YAAA;EACA,gBAAA;EACA,YAAA;;AAGF,YAAY,uBAAwB;EAClC,kBAAA;;AAGF,YAAY,uBAAwB;EAClC,YAAA;;AAGF,YAAY,uBAAwB;AACpC,YAAY,uBAAwB;EAClC,YAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,kBAAA;;AAGF,YAAY,uBAAwB,iBAAiB;AACrD,YAAY,uBAAwB,mBAAmB;EACrD,cAAA;EACA,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,UAAA;EACA,YAAA;EACA,eAAA;;AAGF,YAAY,uBAAwB;EAlNlC,sBAAsB,kDAAtB;;AAsNF,YAAY,uBAAwB;EAtNlC,sBAAsB,oDAAtB;;AA0NF,YAAY;EACV,aAAA;;AAGF,YAAY;EACV,cAAA;;AAGF,mBAAmB;EACjB,qBAAA;;AAGF,kBAAkB;EAChB,UAAA;EACA,UAAA;;AAGF,kBAAkB;EAChB,UAAA;EACA,UAAA;;AAGF,qBAAqB;EACnB,eAAA;EACA,cAAA;;AAGF,qBAAqB;EACnB,eAAA;EACA,cAAA","sourcesContent":["/*!\n * Bootstrap Colorpicker v2.3.3\n * http://mjolnic.github.io/bootstrap-colorpicker/\n *\n * Originally written by (c) 2012 Stefan Petre\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0.txt\n *\n */\n@imgPath: \"../img/bootstrap-colorpicker/\";\n\n.bgImg(@imgFilename) {\n background-image: url(\"@{imgPath}@{imgFilename}\");\n}\n\n.borderRadius(@size) {\n -webkit-border-radius: @size;\n -moz-border-radius: @size;\n border-radius: @size;\n}\n\n.colorpicker-saturation {\n width: 100px;\n height: 100px;\n .bgImg('saturation.png');\n cursor: crosshair;\n float: left;\n i {\n display: block;\n height: 5px;\n width: 5px;\n border: 1px solid #000;\n .borderRadius(5px);\n position: absolute;\n top: 0;\n left: 0;\n margin: -4px 0 0 -4px;\n b {\n display: block;\n height: 5px;\n width: 5px;\n border: 1px solid #fff;\n .borderRadius(5px);\n }\n }\n}\n\n.colorpicker-hue,\n.colorpicker-alpha {\n width: 15px;\n height: 100px;\n float: left;\n cursor: row-resize;\n margin-left: 4px;\n margin-bottom: 4px;\n}\n\n.colorpicker-hue i,\n.colorpicker-alpha i {\n display: block;\n height: 1px;\n background: #000;\n border-top: 1px solid #fff;\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n margin-top: -1px;\n}\n\n.colorpicker-hue {\n .bgImg('hue.png');\n}\n\n.colorpicker-alpha {\n .bgImg('alpha.png');\n display: none;\n}\n\n.colorpicker-saturation,\n.colorpicker-hue,\n.colorpicker-alpha {\n background-size: contain;\n}\n\n.colorpicker {\n padding: 4px;\n min-width: 130px;\n margin-top: 1px;\n .borderRadius(4px);\n z-index: 2500;\n}\n\n.colorpicker:before,\n.colorpicker:after {\n display: table;\n content: \"\";\n line-height: 0;\n}\n\n.colorpicker:after {\n clear: both;\n}\n\n.colorpicker:before {\n content: '';\n display: inline-block;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-bottom: 7px solid #ccc;\n border-bottom-color: rgba(0, 0, 0, 0.2);\n position: absolute;\n top: -7px;\n left: 6px;\n}\n\n.colorpicker:after {\n content: '';\n display: inline-block;\n border-left: 6px solid transparent;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #ffffff;\n position: absolute;\n top: -6px;\n left: 7px;\n}\n\n.colorpicker div {\n position: relative;\n}\n\n.colorpicker.colorpicker-with-alpha {\n min-width: 140px;\n}\n\n.colorpicker.colorpicker-with-alpha .colorpicker-alpha {\n display: block;\n}\n\n.colorpicker-color {\n height: 10px;\n margin-top: 5px;\n clear: both;\n .bgImg('alpha.png');\n background-position: 0 100%;\n}\n\n.colorpicker-color div {\n height: 10px;\n}\n\n.colorpicker-selectors {\n display: none;\n height: 10px;\n margin-top: 5px;\n clear: both;\n}\n\n.colorpicker-selectors i {\n cursor: pointer;\n float: left;\n height: 10px;\n width: 10px;\n}\n\n.colorpicker-selectors i + i {\n margin-left: 3px;\n}\n\n.colorpicker-element .input-group-addon i,\n.colorpicker-element .add-on i {\n display: inline-block;\n cursor: pointer;\n height: 16px;\n vertical-align: text-top;\n width: 16px;\n}\n\n.colorpicker.colorpicker-inline {\n position: relative;\n display: inline-block;\n float: none;\n z-index: auto;\n}\n\n.colorpicker.colorpicker-horizontal {\n width: 110px;\n min-width: 110px;\n height: auto;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-saturation {\n margin-bottom: 4px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-color {\n width: 100px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue,\n.colorpicker.colorpicker-horizontal .colorpicker-alpha {\n width: 100px;\n height: 15px;\n float: left;\n cursor: col-resize;\n margin-left: 0px;\n margin-bottom: 4px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue i,\n.colorpicker.colorpicker-horizontal .colorpicker-alpha i {\n display: block;\n height: 15px;\n background: #ffffff;\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n border: none;\n margin-top: 0px;\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-hue {\n .bgImg('hue-horizontal.png');\n}\n\n.colorpicker.colorpicker-horizontal .colorpicker-alpha {\n .bgImg('alpha-horizontal.png');\n}\n\n.colorpicker.colorpicker-hidden {\n display: none;\n}\n\n.colorpicker.colorpicker-visible {\n display: block;\n}\n\n.colorpicker-inline.colorpicker-visible {\n display: inline-block;\n}\n\n.colorpicker-right:before {\n left: auto;\n right: 6px;\n}\n\n.colorpicker-right:after {\n left: auto;\n right: 7px;\n}\n\n.colorpicker-no-arrow:before {\n border-right: 0;\n border-left: 0;\n}\n\n.colorpicker-no-arrow:after {\n border-right: 0;\n border-left: 0;\n}\n"]} \ No newline at end of file diff --git a/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css new file mode 100644 index 00000000..22e5c37a --- /dev/null +++ b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css @@ -0,0 +1,10 @@ +/*! + * Bootstrap Colorpicker v2.3.3 + * http://mjolnic.github.io/bootstrap-colorpicker/ + * + * Originally written by (c) 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + */.colorpicker-saturation{width:100px;height:100px;background-image:url(../img/bootstrap-colorpicker/saturation.png);cursor:crosshair;float:left}.colorpicker-saturation i{display:block;height:5px;width:5px;border:1px solid #000;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;position:absolute;top:0;left:0;margin:-4px 0 0 -4px}.colorpicker-saturation i b{display:block;height:5px;width:5px;border:1px solid #fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.colorpicker-alpha,.colorpicker-hue{width:15px;height:100px;float:left;cursor:row-resize;margin-left:4px;margin-bottom:4px}.colorpicker-alpha i,.colorpicker-hue i{display:block;height:1px;background:#000;border-top:1px solid #fff;position:absolute;top:0;left:0;width:100%;margin-top:-1px}.colorpicker-hue{background-image:url(../img/bootstrap-colorpicker/hue.png)}.colorpicker-alpha{background-image:url(../img/bootstrap-colorpicker/alpha.png);display:none}.colorpicker-alpha,.colorpicker-hue,.colorpicker-saturation{background-size:contain}.colorpicker{padding:4px;min-width:130px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;z-index:2500}.colorpicker:after,.colorpicker:before{display:table;content:"";line-height:0}.colorpicker:after{clear:both}.colorpicker:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:6px}.colorpicker:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:7px}.colorpicker div{position:relative}.colorpicker.colorpicker-with-alpha{min-width:140px}.colorpicker.colorpicker-with-alpha .colorpicker-alpha{display:block}.colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url(../img/bootstrap-colorpicker/alpha.png);background-position:0 100%}.colorpicker-color div{height:10px}.colorpicker-selectors{display:none;height:10px;margin-top:5px;clear:both}.colorpicker-selectors i{cursor:pointer;float:left;height:10px;width:10px}.colorpicker-selectors i+i{margin-left:3px}.colorpicker-element .add-on i,.colorpicker-element .input-group-addon i{display:inline-block;cursor:pointer;height:16px;vertical-align:text-top;width:16px}.colorpicker.colorpicker-inline{position:relative;display:inline-block;float:none;z-index:auto}.colorpicker.colorpicker-horizontal{width:110px;min-width:110px;height:auto}.colorpicker.colorpicker-horizontal .colorpicker-saturation{margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-color{width:100px}.colorpicker.colorpicker-horizontal .colorpicker-alpha,.colorpicker.colorpicker-horizontal .colorpicker-hue{width:100px;height:15px;float:left;cursor:col-resize;margin-left:0;margin-bottom:4px}.colorpicker.colorpicker-horizontal .colorpicker-alpha i,.colorpicker.colorpicker-horizontal .colorpicker-hue i{display:block;height:15px;background:#fff;position:absolute;top:0;left:0;width:1px;border:none;margin-top:0}.colorpicker.colorpicker-horizontal .colorpicker-hue{background-image:url(../img/bootstrap-colorpicker/hue-horizontal.png)}.colorpicker.colorpicker-horizontal .colorpicker-alpha{background-image:url(../img/bootstrap-colorpicker/alpha-horizontal.png)}.colorpicker.colorpicker-hidden{display:none}.colorpicker.colorpicker-visible{display:block}.colorpicker-inline.colorpicker-visible{display:inline-block}.colorpicker-right:before{left:auto;right:6px}.colorpicker-right:after{left:auto;right:7px}.colorpicker-no-arrow:before{border-right:0;border-left:0}.colorpicker-no-arrow:after{border-right:0;border-left:0} +/*# sourceMappingURL=bootstrap-colorpicker.min.css.map */ \ No newline at end of file diff --git a/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map new file mode 100644 index 00000000..f61ccb3e --- /dev/null +++ b/examples/vendor/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/less/colorpicker.less"],"names":[],"mappings":";;;;;;;;AAqBA,wBACE,MAAA,MACA,OAAA,MAXA,iBAAsB,iDAatB,OAAA,UACA,MAAA,KACA,0BACE,QAAA,MACA,OAAA,IACA,MAAA,IACA,OAAA,IAAA,MAAA,KAfF,sBAAA,IACA,mBAAA,IACA,cAAA,IAeE,SAAA,SACA,IAAA,EACA,KAAA,EACA,OAAA,KAAA,EAAA,EAAA,KACA,4BACE,QAAA,MACA,OAAA,IACA,MAAA,IACA,OAAA,IAAA,MAAA,KAzBJ,sBAAA,IACA,mBAAA,IACA,cAAA,IA8BF,mBADA,iBAEE,MAAA,KACA,OAAA,MACA,MAAA,KACA,OAAA,WACA,YAAA,IACA,cAAA,IAIiB,qBADF,mBAEf,QAAA,MACA,OAAA,IACA,WAAA,KACA,WAAA,IAAA,MAAA,KACA,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,KACA,WAAA,KAGF,iBA1DE,iBAAsB,0CA8DxB,mBA9DE,iBAAsB,4CAgEtB,QAAA,KAKF,mBADA,iBADA,wBAGE,gBAAA,QAGF,aACE,QAAA,IACA,UAAA,MACA,WAAA,IAxEA,sBAAA,IACA,mBAAA,IACA,cAAA,IAwEA,QAAA,KAIU,mBADA,oBAEV,QAAA,MACA,QAAA,GACA,YAAA,EAGU,mBACV,MAAA,KAGU,oBACV,QAAA,GACA,QAAA,aACA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,KACA,oBAAA,eACA,SAAA,SACA,IAAA,KACA,KAAA,IAGU,mBACV,QAAA,GACA,QAAA,aACA,YAAA,IAAA,MAAA,YACA,aAAA,IAAA,MAAA,YACA,cAAA,IAAA,MAAA,KACA,SAAA,SACA,IAAA,KACA,KAAA,IAGW,iBACX,SAAA,SAGU,oCACV,UAAA,MAGkC,uDAClC,QAAA,MAGF,mBACE,OAAA,KACA,WAAA,IACA,MAAA,KAlIA,iBAAsB,4CAoItB,oBAAA,EAAA,KAGiB,uBACjB,OAAA,KAGF,uBACE,QAAA,KACA,OAAA,KACA,WAAA,IACA,MAAA,KAGqB,yBACrB,OAAA,QACA,MAAA,KACA,OAAA,KACA,MAAA,KAGuB,2BACvB,YAAA,IAI2B,+BADW,0CAEtC,QAAA,aACA,OAAA,QACA,OAAA,KACA,eAAA,SACA,MAAA,KAGU,gCACV,SAAA,SACA,QAAA,aACA,MAAA,KACA,QAAA,KAGU,oCACV,MAAA,MACA,UAAA,MACA,OAAA,KAGkC,4DAClC,cAAA,IAGkC,uDAClC,MAAA,MAIkC,uDADA,qDAElC,MAAA,MACA,OAAA,KACA,MAAA,KACA,OAAA,WACA,YAAA,EACA,cAAA,IAIqD,yDADF,uDAEnD,QAAA,MACA,OAAA,KACA,WAAA,KACA,SAAA,SACA,IAAA,EACA,KAAA,EACA,MAAA,IACA,OAAA,KACA,WAAA,EAGkC,qDAlNlC,iBAAsB,qDAsNY,uDAtNlC,iBAAsB,uDA0NZ,gCACV,QAAA,KAGU,iCACV,QAAA,MAGiB,wCACjB,QAAA,aAGgB,0BAChB,KAAA,KACA,MAAA,IAGgB,yBAChB,KAAA,KACA,MAAA,IAGmB,6BACnB,aAAA,EACA,YAAA,EAGmB,4BACnB,aAAA,EACA,YAAA"} \ No newline at end of file diff --git a/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png new file mode 100644 index 00000000..f8318895 Binary files /dev/null and b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha-horizontal.png differ diff --git a/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png new file mode 100644 index 00000000..2e53a30e Binary files /dev/null and b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png differ diff --git a/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png new file mode 100644 index 00000000..3dcd5946 Binary files /dev/null and b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue-horizontal.png differ diff --git a/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png new file mode 100644 index 00000000..6f5ec2e5 Binary files /dev/null and b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png differ diff --git a/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png new file mode 100644 index 00000000..170841cb Binary files /dev/null and b/examples/vendor/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png differ diff --git a/examples/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js b/examples/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js new file mode 100644 index 00000000..758ebc38 --- /dev/null +++ b/examples/vendor/bootstrap-colorpicker/js/bootstrap-colorpicker.js @@ -0,0 +1,1106 @@ +/*! + * Bootstrap Colorpicker v2.3.3 + * http://mjolnic.github.io/bootstrap-colorpicker/ + * + * Originally written by (c) 2012 Stefan Petre + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + */ + +(function(factory) { + "use strict"; + if (typeof exports === 'object') { + module.exports = factory(window.jQuery); + } else if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else if (window.jQuery && !window.jQuery.fn.colorpicker) { + factory(window.jQuery); + } +}(function($) { + 'use strict'; + + /** + * Color manipulation helper class + * + * @param {Object|String} val + * @param {Object} predefinedColors + * @constructor + */ + var Color = function(val, predefinedColors) { + this.value = { + h: 0, + s: 0, + b: 0, + a: 1 + }; + this.origFormat = null; // original string format + if (predefinedColors) { + $.extend(this.colors, predefinedColors); + } + if (val) { + if (val.toLowerCase !== undefined) { + // cast to string + val = val + ''; + this.setColor(val); + } else if (val.h !== undefined) { + this.value = val; + } + } + }; + + Color.prototype = { + constructor: Color, + // 140 predefined colors from the HTML Colors spec + colors: { + "aliceblue": "#f0f8ff", + "antiquewhite": "#faebd7", + "aqua": "#00ffff", + "aquamarine": "#7fffd4", + "azure": "#f0ffff", + "beige": "#f5f5dc", + "bisque": "#ffe4c4", + "black": "#000000", + "blanchedalmond": "#ffebcd", + "blue": "#0000ff", + "blueviolet": "#8a2be2", + "brown": "#a52a2a", + "burlywood": "#deb887", + "cadetblue": "#5f9ea0", + "chartreuse": "#7fff00", + "chocolate": "#d2691e", + "coral": "#ff7f50", + "cornflowerblue": "#6495ed", + "cornsilk": "#fff8dc", + "crimson": "#dc143c", + "cyan": "#00ffff", + "darkblue": "#00008b", + "darkcyan": "#008b8b", + "darkgoldenrod": "#b8860b", + "darkgray": "#a9a9a9", + "darkgreen": "#006400", + "darkkhaki": "#bdb76b", + "darkmagenta": "#8b008b", + "darkolivegreen": "#556b2f", + "darkorange": "#ff8c00", + "darkorchid": "#9932cc", + "darkred": "#8b0000", + "darksalmon": "#e9967a", + "darkseagreen": "#8fbc8f", + "darkslateblue": "#483d8b", + "darkslategray": "#2f4f4f", + "darkturquoise": "#00ced1", + "darkviolet": "#9400d3", + "deeppink": "#ff1493", + "deepskyblue": "#00bfff", + "dimgray": "#696969", + "dodgerblue": "#1e90ff", + "firebrick": "#b22222", + "floralwhite": "#fffaf0", + "forestgreen": "#228b22", + "fuchsia": "#ff00ff", + "gainsboro": "#dcdcdc", + "ghostwhite": "#f8f8ff", + "gold": "#ffd700", + "goldenrod": "#daa520", + "gray": "#808080", + "green": "#008000", + "greenyellow": "#adff2f", + "honeydew": "#f0fff0", + "hotpink": "#ff69b4", + "indianred": "#cd5c5c", + "indigo": "#4b0082", + "ivory": "#fffff0", + "khaki": "#f0e68c", + "lavender": "#e6e6fa", + "lavenderblush": "#fff0f5", + "lawngreen": "#7cfc00", + "lemonchiffon": "#fffacd", + "lightblue": "#add8e6", + "lightcoral": "#f08080", + "lightcyan": "#e0ffff", + "lightgoldenrodyellow": "#fafad2", + "lightgrey": "#d3d3d3", + "lightgreen": "#90ee90", + "lightpink": "#ffb6c1", + "lightsalmon": "#ffa07a", + "lightseagreen": "#20b2aa", + "lightskyblue": "#87cefa", + "lightslategray": "#778899", + "lightsteelblue": "#b0c4de", + "lightyellow": "#ffffe0", + "lime": "#00ff00", + "limegreen": "#32cd32", + "linen": "#faf0e6", + "magenta": "#ff00ff", + "maroon": "#800000", + "mediumaquamarine": "#66cdaa", + "mediumblue": "#0000cd", + "mediumorchid": "#ba55d3", + "mediumpurple": "#9370d8", + "mediumseagreen": "#3cb371", + "mediumslateblue": "#7b68ee", + "mediumspringgreen": "#00fa9a", + "mediumturquoise": "#48d1cc", + "mediumvioletred": "#c71585", + "midnightblue": "#191970", + "mintcream": "#f5fffa", + "mistyrose": "#ffe4e1", + "moccasin": "#ffe4b5", + "navajowhite": "#ffdead", + "navy": "#000080", + "oldlace": "#fdf5e6", + "olive": "#808000", + "olivedrab": "#6b8e23", + "orange": "#ffa500", + "orangered": "#ff4500", + "orchid": "#da70d6", + "palegoldenrod": "#eee8aa", + "palegreen": "#98fb98", + "paleturquoise": "#afeeee", + "palevioletred": "#d87093", + "papayawhip": "#ffefd5", + "peachpuff": "#ffdab9", + "peru": "#cd853f", + "pink": "#ffc0cb", + "plum": "#dda0dd", + "powderblue": "#b0e0e6", + "purple": "#800080", + "red": "#ff0000", + "rosybrown": "#bc8f8f", + "royalblue": "#4169e1", + "saddlebrown": "#8b4513", + "salmon": "#fa8072", + "sandybrown": "#f4a460", + "seagreen": "#2e8b57", + "seashell": "#fff5ee", + "sienna": "#a0522d", + "silver": "#c0c0c0", + "skyblue": "#87ceeb", + "slateblue": "#6a5acd", + "slategray": "#708090", + "snow": "#fffafa", + "springgreen": "#00ff7f", + "steelblue": "#4682b4", + "tan": "#d2b48c", + "teal": "#008080", + "thistle": "#d8bfd8", + "tomato": "#ff6347", + "turquoise": "#40e0d0", + "violet": "#ee82ee", + "wheat": "#f5deb3", + "white": "#ffffff", + "whitesmoke": "#f5f5f5", + "yellow": "#ffff00", + "yellowgreen": "#9acd32", + "transparent": "transparent" + }, + _sanitizeNumber: function(val) { + if (typeof val === 'number') { + return val; + } + if (isNaN(val) || (val === null) || (val === '') || (val === undefined)) { + return 1; + } + if (val === '') { + return 0; + } + if (val.toLowerCase !== undefined) { + if (val.match(/^\./)) { + val = "0" + val; + } + return Math.ceil(parseFloat(val) * 100) / 100; + } + return 1; + }, + isTransparent: function(strVal) { + if (!strVal) { + return false; + } + strVal = strVal.toLowerCase().trim(); + return (strVal === 'transparent') || (strVal.match(/#?00000000/)) || (strVal.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/)); + }, + rgbaIsTransparent: function(rgba) { + return ((rgba.r === 0) && (rgba.g === 0) && (rgba.b === 0) && (rgba.a === 0)); + }, + //parse a string to HSB + setColor: function(strVal) { + strVal = strVal.toLowerCase().trim(); + if (strVal) { + if (this.isTransparent(strVal)) { + this.value = { + h: 0, + s: 0, + b: 0, + a: 0 + }; + } else { + this.value = this.stringToHSB(strVal) || { + h: 0, + s: 0, + b: 0, + a: 1 + }; // if parser fails, defaults to black + } + } + }, + stringToHSB: function(strVal) { + strVal = strVal.toLowerCase(); + var alias; + if (typeof this.colors[strVal] !== 'undefined') { + strVal = this.colors[strVal]; + alias = 'alias'; + } + var that = this, + result = false; + $.each(this.stringParsers, function(i, parser) { + var match = parser.re.exec(strVal), + values = match && parser.parse.apply(that, [match]), + format = alias || parser.format || 'rgba'; + if (values) { + if (format.match(/hsla?/)) { + result = that.RGBtoHSB.apply(that, that.HSLtoRGB.apply(that, values)); + } else { + result = that.RGBtoHSB.apply(that, values); + } + that.origFormat = format; + return false; + } + return true; + }); + return result; + }, + setHue: function(h) { + this.value.h = 1 - h; + }, + setSaturation: function(s) { + this.value.s = s; + }, + setBrightness: function(b) { + this.value.b = 1 - b; + }, + setAlpha: function(a) { + this.value.a = Math.round((parseInt((1 - a) * 100, 10) / 100) * 100) / 100; + }, + toRGB: function(h, s, b, a) { + if (!h) { + h = this.value.h; + s = this.value.s; + b = this.value.b; + } + h *= 360; + var R, G, B, X, C; + h = (h % 360) / 60; + C = b * s; + X = C * (1 - Math.abs(h % 2 - 1)); + R = G = B = b - C; + + h = ~~h; + R += [C, X, 0, 0, X, C][h]; + G += [X, C, C, X, 0, 0][h]; + B += [0, 0, X, C, C, X][h]; + return { + r: Math.round(R * 255), + g: Math.round(G * 255), + b: Math.round(B * 255), + a: a || this.value.a + }; + }, + toHex: function(h, s, b, a) { + var rgb = this.toRGB(h, s, b, a); + if (this.rgbaIsTransparent(rgb)) { + return 'transparent'; + } + return '#' + ((1 << 24) | (parseInt(rgb.r) << 16) | (parseInt(rgb.g) << 8) | parseInt(rgb.b)).toString(16).substr(1); + }, + toHSL: function(h, s, b, a) { + h = h || this.value.h; + s = s || this.value.s; + b = b || this.value.b; + a = a || this.value.a; + + var H = h, + L = (2 - s) * b, + S = s * b; + if (L > 0 && L <= 1) { + S /= L; + } else { + S /= 2 - L; + } + L /= 2; + if (S > 1) { + S = 1; + } + return { + h: isNaN(H) ? 0 : H, + s: isNaN(S) ? 0 : S, + l: isNaN(L) ? 0 : L, + a: isNaN(a) ? 0 : a + }; + }, + toAlias: function(r, g, b, a) { + var rgb = this.toHex(r, g, b, a); + for (var alias in this.colors) { + if (this.colors[alias] === rgb) { + return alias; + } + } + return false; + }, + RGBtoHSB: function(r, g, b, a) { + r /= 255; + g /= 255; + b /= 255; + + var H, S, V, C; + V = Math.max(r, g, b); + C = V - Math.min(r, g, b); + H = (C === 0 ? null : + V === r ? (g - b) / C : + V === g ? (b - r) / C + 2 : + (r - g) / C + 4 + ); + H = ((H + 360) % 6) * 60 / 360; + S = C === 0 ? 0 : C / V; + return { + h: this._sanitizeNumber(H), + s: S, + b: V, + a: this._sanitizeNumber(a) + }; + }, + HueToRGB: function(p, q, h) { + if (h < 0) { + h += 1; + } else if (h > 1) { + h -= 1; + } + if ((h * 6) < 1) { + return p + (q - p) * h * 6; + } else if ((h * 2) < 1) { + return q; + } else if ((h * 3) < 2) { + return p + (q - p) * ((2 / 3) - h) * 6; + } else { + return p; + } + }, + HSLtoRGB: function(h, s, l, a) { + if (s < 0) { + s = 0; + } + var q; + if (l <= 0.5) { + q = l * (1 + s); + } else { + q = l + s - (l * s); + } + + var p = 2 * l - q; + + var tr = h + (1 / 3); + var tg = h; + var tb = h - (1 / 3); + + var r = Math.round(this.HueToRGB(p, q, tr) * 255); + var g = Math.round(this.HueToRGB(p, q, tg) * 255); + var b = Math.round(this.HueToRGB(p, q, tb) * 255); + return [r, g, b, this._sanitizeNumber(a)]; + }, + toString: function(format) { + format = format || 'rgba'; + var c = false; + switch (format) { + case 'rgb': + { + c = this.toRGB(); + if (this.rgbaIsTransparent(c)) { + return 'transparent'; + } + return 'rgb(' + c.r + ',' + c.g + ',' + c.b + ')'; + } + break; + case 'rgba': + { + c = this.toRGB(); + return 'rgba(' + c.r + ',' + c.g + ',' + c.b + ',' + c.a + ')'; + } + break; + case 'hsl': + { + c = this.toHSL(); + return 'hsl(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%)'; + } + break; + case 'hsla': + { + c = this.toHSL(); + return 'hsla(' + Math.round(c.h * 360) + ',' + Math.round(c.s * 100) + '%,' + Math.round(c.l * 100) + '%,' + c.a + ')'; + } + break; + case 'hex': + { + return this.toHex(); + } + break; + case 'alias': + return this.toAlias() || this.toHex(); + default: + { + return c; + } + break; + } + }, + // a set of RE's that can match strings and generate color tuples. + // from John Resig color plugin + // https://github.com/jquery/jquery-color/ + stringParsers: [{ + re: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/, + format: 'rgb', + parse: function(execResult) { + return [ + execResult[1], + execResult[2], + execResult[3], + 1 + ]; + } + }, { + re: /rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/, + format: 'rgb', + parse: function(execResult) { + return [ + 2.55 * execResult[1], + 2.55 * execResult[2], + 2.55 * execResult[3], + 1 + ]; + } + }, { + re: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/, + format: 'rgba', + parse: function(execResult) { + return [ + execResult[1], + execResult[2], + execResult[3], + execResult[4] + ]; + } + }, { + re: /rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/, + format: 'rgba', + parse: function(execResult) { + return [ + 2.55 * execResult[1], + 2.55 * execResult[2], + 2.55 * execResult[3], + execResult[4] + ]; + } + }, { + re: /hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/, + format: 'hsl', + parse: function(execResult) { + return [ + execResult[1] / 360, + execResult[2] / 100, + execResult[3] / 100, + execResult[4] + ]; + } + }, { + re: /hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/, + format: 'hsla', + parse: function(execResult) { + return [ + execResult[1] / 360, + execResult[2] / 100, + execResult[3] / 100, + execResult[4] + ]; + } + }, { + re: /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, + format: 'hex', + parse: function(execResult) { + return [ + parseInt(execResult[1], 16), + parseInt(execResult[2], 16), + parseInt(execResult[3], 16), + 1 + ]; + } + }, { + re: /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/, + format: 'hex', + parse: function(execResult) { + return [ + parseInt(execResult[1] + execResult[1], 16), + parseInt(execResult[2] + execResult[2], 16), + parseInt(execResult[3] + execResult[3], 16), + 1 + ]; + } + }], + colorNameToHex: function(name) { + if (typeof this.colors[name.toLowerCase()] !== 'undefined') { + return this.colors[name.toLowerCase()]; + } + return false; + } + }; + + /* + * Default plugin options + */ + var defaults = { + horizontal: false, // horizontal mode layout ? + inline: false, //forces to show the colorpicker as an inline element + color: false, //forces a color + format: false, //forces a format + input: 'input', // children input selector + container: false, // container selector + component: '.add-on, .input-group-addon', // children component selector + sliders: { + saturation: { + maxLeft: 100, + maxTop: 100, + callLeft: 'setSaturation', + callTop: 'setBrightness' + }, + hue: { + maxLeft: 0, + maxTop: 100, + callLeft: false, + callTop: 'setHue' + }, + alpha: { + maxLeft: 0, + maxTop: 100, + callLeft: false, + callTop: 'setAlpha' + } + }, + slidersHorz: { + saturation: { + maxLeft: 100, + maxTop: 100, + callLeft: 'setSaturation', + callTop: 'setBrightness' + }, + hue: { + maxLeft: 100, + maxTop: 0, + callLeft: 'setHue', + callTop: false + }, + alpha: { + maxLeft: 100, + maxTop: 0, + callLeft: 'setAlpha', + callTop: false + } + }, + template: '