├── LICENSE.txt ├── README.md ├── app ├── index.html └── mapbox-gl │ ├── mapbox-gl.css │ ├── mapbox-gl.js │ ├── mapbox-gl.js.map │ └── style_spec.js ├── gulpfile.js ├── package.json ├── style.js ├── style.json ├── style.json5 ├── style.toml └── style.yml /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | ISC License 3 | 4 | Copyright (c) 2017, Mapbox 5 | 6 | Permission to use, copy, modify, and/or distribute this software for any 7 | purpose with or without fee is hereby granted, provided that the above 8 | copyright notice and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [Mapbox GL](https://www.mapbox.com/mapbox-gl/) Code Flow Example 2 | 3 | This repository is a simple example of a development environment for Mapbox GL 4 | styles that is based on editing raw code with a text editor. This style 5 | of editing is similar to [TileMill](https://www.mapbox.com/tilemill/) 6 | or the [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) desktop 7 | tools. 8 | 9 | This example is based on [Gulp](http://gulpjs.com/) as a framework for its 10 | basic utilities: 11 | 12 | * A [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/)-powered page for 13 | previewing the style 14 | * Support for [JSON](http://json.org/), [JSON5](http://json5.org/), 15 | [YAML](http://yaml.org/), and [TOML](https://github.com/toml-lang/toml) 16 | files as input. You can also specify an executable JavaScript file with a `.js` extension 17 | and hashbang and the file will be run and its output piped into the style 18 | definition. 19 | * Live-reloading when the style is changed 20 | 21 | ## Install 22 | 23 | First, clone this git repository: 24 | 25 | git clone https://github.com/mapbox/mapbox-gl-codeflow-example.git 26 | cd mapbox-gl-codeflow-example 27 | 28 | And then install the dependencies: 29 | 30 | npm install 31 | 32 | And then start up: 33 | 34 | gulp --style=style.json 35 | 36 | You can also specify `style.json5`, `style.yml`, or `style.toml` as your 37 | inputs. Unlike JSON, these alternative formats support commenting, so you 38 | can annotate your styles. Note that this is a one-way conversion, like the conversion 39 | from [CartoCSS](https://www.mapbox.com/tilemill/docs/manual/carto/) 40 | to [Mapnik XML](https://github.com/mapnik/mapnik/wiki/XMLConfigReference) 41 | was. 42 | 43 | ## Example 44 | 45 | This project is an _example_ of one such flow: you could do the same 46 | with a bare-bones node.js script, or Python or any other environment. You could 47 | also skip some of the fancier features, like live reloading, or add others, 48 | like a more complex debugging view. 49 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mapbox GL 6 | 7 | 8 | 9 | 10 | 27 | 28 | 29 |
30 |
31 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/mapbox-gl/mapbox-gl.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'mapboxgl'; 3 | src:url('font/icon.eot?v=1'); 4 | src:url('font/icon.eot?v=1#iefix-lwq1d6') format('embedded-opentype'), 5 | url('font/icon.woff?v=1') format('woff'); 6 | font-weight: normal; 7 | font-style: normal; 8 | } 9 | 10 | .mapboxgl-map { 11 | font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif; 12 | overflow: hidden; 13 | position: relative; 14 | -webkit-tap-highlight-color: rgba(0,0,0,0); 15 | } 16 | 17 | .mapboxgl-canvas-container.mapboxgl-interactive, 18 | .mapboxgl-ctrl-nav-compass { 19 | cursor: -webkit-grab; 20 | cursor: -moz-grab; 21 | cursor: grab; 22 | } 23 | .mapboxgl-canvas-container.mapboxgl-interactive:active, 24 | .mapboxgl-ctrl-nav-compass:active { 25 | cursor: -webkit-grabbing; 26 | cursor: -moz-grabbing; 27 | cursor: grabbing; 28 | } 29 | 30 | .mapboxgl-ctrl-top-left, 31 | .mapboxgl-ctrl-top-right, 32 | .mapboxgl-ctrl-bottom-left, 33 | .mapboxgl-ctrl-bottom-right { position:absolute; } 34 | .mapboxgl-ctrl-top-left { top:0; left:0; } 35 | .mapboxgl-ctrl-top-right { top:0; right:0; } 36 | .mapboxgl-ctrl-bottom-left { bottom:0; left:0; } 37 | .mapboxgl-ctrl-bottom-right { right:0; bottom:0; } 38 | 39 | .mapboxgl-ctrl { clear:both; } 40 | .mapboxgl-ctrl-top-left .mapboxgl-ctrl { margin:10px 0 0 10px; float:left; } 41 | .mapboxgl-ctrl-top-right .mapboxgl-ctrl{ margin:10px 10px 0 0; float:right; } 42 | .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl { margin:0 0 10px 10px; float:left; } 43 | .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl { margin:0 10px 10px 0; float:right; } 44 | 45 | .mapboxgl-ctrl-group { 46 | border-radius: 4px; 47 | border: 1px solid #ccc; 48 | overflow: hidden; 49 | background: #fff; 50 | } 51 | .mapboxgl-ctrl-group > button { 52 | width: 30px; 53 | height: 30px; 54 | display: block; 55 | padding: 0; 56 | outline: none; 57 | border: none; 58 | border-bottom: 1px solid #ddd; 59 | box-sizing: border-box; 60 | background-color: rgba(0,0,0,0); 61 | cursor: pointer; 62 | } 63 | /* https://bugzilla.mozilla.org/show_bug.cgi?id=140562 */ 64 | .mapboxgl-ctrl > button::-moz-focus-inner { 65 | border: 0; 66 | padding: 0; 67 | } 68 | .mapboxgl-ctrl > button:last-child { 69 | border-bottom: 0; 70 | } 71 | .mapboxgl-ctrl > button:hover { 72 | background-color: rgba(0,0,0,0.05); 73 | } 74 | .mapboxgl-ctrl-icon:before { 75 | font-family: 'mapboxgl'; 76 | speak: none; 77 | font-style: normal; 78 | font-weight: normal; 79 | font-variant: normal; 80 | text-transform: none; 81 | font-size: 20px; 82 | line-height: 1; 83 | -webkit-font-smoothing: antialiased; 84 | -moz-osx-font-smoothing: grayscale; 85 | } 86 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out:before { content: '\e600'; } 87 | .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-in:before { content: '\e601'; } 88 | 89 | .mapboxgl-ctrl.mapboxgl-ctrl-attrib { 90 | padding: 0 5px; 91 | background-color: rgba(255,255,255,0.5); 92 | margin: 0; 93 | } 94 | .mapboxgl-ctrl-attrib a { 95 | color: rgba(0,0,0,0.75); 96 | text-decoration: none; 97 | } 98 | .mapboxgl-ctrl-attrib a:hover { 99 | color: inherit; 100 | text-decoration: underline; 101 | } 102 | .mapboxgl-ctrl-attrib .mapbox-improve-map { 103 | font-weight: bold; 104 | margin-left: 2px; 105 | } 106 | 107 | .mapboxgl-popup { 108 | position: absolute; 109 | display: -webkit-flex; 110 | display: flex; 111 | will-change: transform; 112 | pointer-events: none; 113 | } 114 | .mapboxgl-popup-anchor-top, 115 | .mapboxgl-popup-anchor-top-left, 116 | .mapboxgl-popup-anchor-top-right { 117 | -webkit-flex-direction: column; 118 | flex-direction: column; 119 | } 120 | .mapboxgl-popup-anchor-bottom, 121 | .mapboxgl-popup-anchor-bottom-left, 122 | .mapboxgl-popup-anchor-bottom-right { 123 | -webkit-flex-direction: column-reverse; 124 | flex-direction: column-reverse; 125 | } 126 | .mapboxgl-popup-anchor-left { 127 | -webkit-flex-direction: row; 128 | flex-direction: row; 129 | } 130 | .mapboxgl-popup-anchor-right { 131 | -webkit-flex-direction: row-reverse; 132 | flex-direction: row-reverse; 133 | } 134 | .mapboxgl-popup-tip { 135 | width: 0; 136 | height: 0; 137 | border: 10px solid transparent; 138 | z-index: 1; 139 | } 140 | .mapboxgl-popup-anchor-top .mapboxgl-popup-tip { 141 | -webkit-align-self: center; 142 | align-self: center; 143 | border-top: none; 144 | border-bottom-color: #fff; 145 | } 146 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip { 147 | -webkit-align-self: flex-start; 148 | align-self: flex-start; 149 | border-top: none; 150 | border-left: none; 151 | border-bottom-color: #fff; 152 | } 153 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip { 154 | -webkit-align-self: flex-end; 155 | align-self: flex-end; 156 | border-top: none; 157 | border-right: none; 158 | border-bottom-color: #fff; 159 | } 160 | .mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip { 161 | -webkit-align-self: center; 162 | align-self: center; 163 | border-bottom: none; 164 | border-top-color: #fff; 165 | } 166 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip { 167 | -webkit-align-self: flex-start; 168 | align-self: flex-start; 169 | border-bottom: none; 170 | border-left: none; 171 | border-top-color: #fff; 172 | } 173 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip { 174 | -webkit-align-self: flex-end; 175 | align-self: flex-end; 176 | border-bottom: none; 177 | border-right: none; 178 | border-top-color: #fff; 179 | } 180 | .mapboxgl-popup-anchor-left .mapboxgl-popup-tip { 181 | -webkit-align-self: center; 182 | align-self: center; 183 | border-left: none; 184 | border-right-color: #fff; 185 | } 186 | .mapboxgl-popup-anchor-right .mapboxgl-popup-tip { 187 | -webkit-align-self: center; 188 | align-self: center; 189 | border-right: none; 190 | border-left-color: #fff; 191 | } 192 | .mapboxgl-popup-close-button { 193 | position: absolute; 194 | right: 0; 195 | top: 0; 196 | border: none; 197 | border-radius: 0 3px 0 0; 198 | cursor: pointer; 199 | background-color: rgba(0,0,0,0); 200 | } 201 | .mapboxgl-popup-close-button:hover { 202 | background-color: rgba(0,0,0,0.05); 203 | } 204 | .mapboxgl-popup-content { 205 | position: relative; 206 | background: #fff; 207 | border-radius: 3px; 208 | box-shadow: 0 1px 2px rgba(0,0,0,0.10); 209 | padding: 10px 10px 15px; 210 | pointer-events: auto; 211 | } 212 | .mapboxgl-popup-anchor-top-left .mapboxgl-popup-content { 213 | border-top-left-radius: 0; 214 | } 215 | .mapboxgl-popup-anchor-top-right .mapboxgl-popup-content { 216 | border-top-right-radius: 0; 217 | } 218 | .mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-content { 219 | border-bottom-left-radius: 0; 220 | } 221 | .mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-content { 222 | border-bottom-right-radius: 0; 223 | } 224 | 225 | .mapboxgl-crosshair, 226 | .mapboxgl-crosshair .mapboxgl-interactive, 227 | .mapboxgl-crosshair .mapboxgl-interactive:active { 228 | cursor: crosshair; 229 | } 230 | .mapboxgl-boxzoom { 231 | position: absolute; 232 | top: 0; 233 | left: 0; 234 | width: 0; 235 | height: 0; 236 | background: #fff; 237 | border: 2px dotted #202020; 238 | opacity: 0.5; 239 | } 240 | @media print { 241 | .mapbox-improve-map { 242 | display:none; 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /app/mapbox-gl/style_spec.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.validate = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(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 s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { 72 | for (var i = 1; i < arguments.length; i++) { 73 | args[i - 1] = arguments[i]; 74 | } 75 | } 76 | queue.push(new Item(fun, args)); 77 | if (queue.length === 1 && !draining) { 78 | setTimeout(drainQueue, 0); 79 | } 80 | }; 81 | 82 | // v8 likes predictible objects 83 | function Item(fun, array) { 84 | this.fun = fun; 85 | this.array = array; 86 | } 87 | Item.prototype.run = function () { 88 | this.fun.apply(null, this.array); 89 | }; 90 | process.title = 'browser'; 91 | process.browser = true; 92 | process.env = {}; 93 | process.argv = []; 94 | process.version = ''; // empty string to avoid regexp issues 95 | process.versions = {}; 96 | 97 | function noop() {} 98 | 99 | process.on = noop; 100 | process.addListener = noop; 101 | process.once = noop; 102 | process.off = noop; 103 | process.removeListener = noop; 104 | process.removeAllListeners = noop; 105 | process.emit = noop; 106 | 107 | process.binding = function (name) { 108 | throw new Error('process.binding is not supported'); 109 | }; 110 | 111 | // TODO(shtylman) 112 | process.cwd = function () { return '/' }; 113 | process.chdir = function (dir) { 114 | throw new Error('process.chdir is not supported'); 115 | }; 116 | process.umask = function() { return 0; }; 117 | 118 | },{}],3:[function(require,module,exports){ 119 | module.exports = function isBuffer(arg) { 120 | return arg && typeof arg === 'object' 121 | && typeof arg.copy === 'function' 122 | && typeof arg.fill === 'function' 123 | && typeof arg.readUInt8 === 'function'; 124 | } 125 | },{}],4:[function(require,module,exports){ 126 | (function (process,global){ 127 | // Copyright Joyent, Inc. and other Node contributors. 128 | // 129 | // Permission is hereby granted, free of charge, to any person obtaining a 130 | // copy of this software and associated documentation files (the 131 | // "Software"), to deal in the Software without restriction, including 132 | // without limitation the rights to use, copy, modify, merge, publish, 133 | // distribute, sublicense, and/or sell copies of the Software, and to permit 134 | // persons to whom the Software is furnished to do so, subject to the 135 | // following conditions: 136 | // 137 | // The above copyright notice and this permission notice shall be included 138 | // in all copies or substantial portions of the Software. 139 | // 140 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 141 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 142 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 143 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 144 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 145 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 146 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 147 | 148 | var formatRegExp = /%[sdj%]/g; 149 | exports.format = function(f) { 150 | if (!isString(f)) { 151 | var objects = []; 152 | for (var i = 0; i < arguments.length; i++) { 153 | objects.push(inspect(arguments[i])); 154 | } 155 | return objects.join(' '); 156 | } 157 | 158 | var i = 1; 159 | var args = arguments; 160 | var len = args.length; 161 | var str = String(f).replace(formatRegExp, function(x) { 162 | if (x === '%%') return '%'; 163 | if (i >= len) return x; 164 | switch (x) { 165 | case '%s': return String(args[i++]); 166 | case '%d': return Number(args[i++]); 167 | case '%j': 168 | try { 169 | return JSON.stringify(args[i++]); 170 | } catch (_) { 171 | return '[Circular]'; 172 | } 173 | default: 174 | return x; 175 | } 176 | }); 177 | for (var x = args[i]; i < len; x = args[++i]) { 178 | if (isNull(x) || !isObject(x)) { 179 | str += ' ' + x; 180 | } else { 181 | str += ' ' + inspect(x); 182 | } 183 | } 184 | return str; 185 | }; 186 | 187 | 188 | // Mark that a method should not be used. 189 | // Returns a modified function which warns once by default. 190 | // If --no-deprecation is set, then it is a no-op. 191 | exports.deprecate = function(fn, msg) { 192 | // Allow for deprecating things in the process of starting up. 193 | if (isUndefined(global.process)) { 194 | return function() { 195 | return exports.deprecate(fn, msg).apply(this, arguments); 196 | }; 197 | } 198 | 199 | if (process.noDeprecation === true) { 200 | return fn; 201 | } 202 | 203 | var warned = false; 204 | function deprecated() { 205 | if (!warned) { 206 | if (process.throwDeprecation) { 207 | throw new Error(msg); 208 | } else if (process.traceDeprecation) { 209 | console.trace(msg); 210 | } else { 211 | console.error(msg); 212 | } 213 | warned = true; 214 | } 215 | return fn.apply(this, arguments); 216 | } 217 | 218 | return deprecated; 219 | }; 220 | 221 | 222 | var debugs = {}; 223 | var debugEnviron; 224 | exports.debuglog = function(set) { 225 | if (isUndefined(debugEnviron)) 226 | debugEnviron = process.env.NODE_DEBUG || ''; 227 | set = set.toUpperCase(); 228 | if (!debugs[set]) { 229 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { 230 | var pid = process.pid; 231 | debugs[set] = function() { 232 | var msg = exports.format.apply(exports, arguments); 233 | console.error('%s %d: %s', set, pid, msg); 234 | }; 235 | } else { 236 | debugs[set] = function() {}; 237 | } 238 | } 239 | return debugs[set]; 240 | }; 241 | 242 | 243 | /** 244 | * Echos the value of a value. Trys to print the value out 245 | * in the best way possible given the different types. 246 | * 247 | * @param {Object} obj The object to print out. 248 | * @param {Object} opts Optional options object that alters the output. 249 | */ 250 | /* legacy: obj, showHidden, depth, colors*/ 251 | function inspect(obj, opts) { 252 | // default options 253 | var ctx = { 254 | seen: [], 255 | stylize: stylizeNoColor 256 | }; 257 | // legacy... 258 | if (arguments.length >= 3) ctx.depth = arguments[2]; 259 | if (arguments.length >= 4) ctx.colors = arguments[3]; 260 | if (isBoolean(opts)) { 261 | // legacy... 262 | ctx.showHidden = opts; 263 | } else if (opts) { 264 | // got an "options" object 265 | exports._extend(ctx, opts); 266 | } 267 | // set default options 268 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false; 269 | if (isUndefined(ctx.depth)) ctx.depth = 2; 270 | if (isUndefined(ctx.colors)) ctx.colors = false; 271 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true; 272 | if (ctx.colors) ctx.stylize = stylizeWithColor; 273 | return formatValue(ctx, obj, ctx.depth); 274 | } 275 | exports.inspect = inspect; 276 | 277 | 278 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics 279 | inspect.colors = { 280 | 'bold' : [1, 22], 281 | 'italic' : [3, 23], 282 | 'underline' : [4, 24], 283 | 'inverse' : [7, 27], 284 | 'white' : [37, 39], 285 | 'grey' : [90, 39], 286 | 'black' : [30, 39], 287 | 'blue' : [34, 39], 288 | 'cyan' : [36, 39], 289 | 'green' : [32, 39], 290 | 'magenta' : [35, 39], 291 | 'red' : [31, 39], 292 | 'yellow' : [33, 39] 293 | }; 294 | 295 | // Don't use 'blue' not visible on cmd.exe 296 | inspect.styles = { 297 | 'special': 'cyan', 298 | 'number': 'yellow', 299 | 'boolean': 'yellow', 300 | 'undefined': 'grey', 301 | 'null': 'bold', 302 | 'string': 'green', 303 | 'date': 'magenta', 304 | // "name": intentionally not styling 305 | 'regexp': 'red' 306 | }; 307 | 308 | 309 | function stylizeWithColor(str, styleType) { 310 | var style = inspect.styles[styleType]; 311 | 312 | if (style) { 313 | return '\u001b[' + inspect.colors[style][0] + 'm' + str + 314 | '\u001b[' + inspect.colors[style][1] + 'm'; 315 | } else { 316 | return str; 317 | } 318 | } 319 | 320 | 321 | function stylizeNoColor(str, styleType) { 322 | return str; 323 | } 324 | 325 | 326 | function arrayToHash(array) { 327 | var hash = {}; 328 | 329 | array.forEach(function(val, idx) { 330 | hash[val] = true; 331 | }); 332 | 333 | return hash; 334 | } 335 | 336 | 337 | function formatValue(ctx, value, recurseTimes) { 338 | // Provide a hook for user-specified inspect functions. 339 | // Check that value is an object with an inspect function on it 340 | if (ctx.customInspect && 341 | value && 342 | isFunction(value.inspect) && 343 | // Filter out the util module, it's inspect function is special 344 | value.inspect !== exports.inspect && 345 | // Also filter out any prototype objects using the circular check. 346 | !(value.constructor && value.constructor.prototype === value)) { 347 | var ret = value.inspect(recurseTimes, ctx); 348 | if (!isString(ret)) { 349 | ret = formatValue(ctx, ret, recurseTimes); 350 | } 351 | return ret; 352 | } 353 | 354 | // Primitive types cannot have properties 355 | var primitive = formatPrimitive(ctx, value); 356 | if (primitive) { 357 | return primitive; 358 | } 359 | 360 | // Look up the keys of the object. 361 | var keys = Object.keys(value); 362 | var visibleKeys = arrayToHash(keys); 363 | 364 | if (ctx.showHidden) { 365 | keys = Object.getOwnPropertyNames(value); 366 | } 367 | 368 | // IE doesn't make error fields non-enumerable 369 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx 370 | if (isError(value) 371 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { 372 | return formatError(value); 373 | } 374 | 375 | // Some type of object without properties can be shortcutted. 376 | if (keys.length === 0) { 377 | if (isFunction(value)) { 378 | var name = value.name ? ': ' + value.name : ''; 379 | return ctx.stylize('[Function' + name + ']', 'special'); 380 | } 381 | if (isRegExp(value)) { 382 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 383 | } 384 | if (isDate(value)) { 385 | return ctx.stylize(Date.prototype.toString.call(value), 'date'); 386 | } 387 | if (isError(value)) { 388 | return formatError(value); 389 | } 390 | } 391 | 392 | var base = '', array = false, braces = ['{', '}']; 393 | 394 | // Make Array say that they are Array 395 | if (isArray(value)) { 396 | array = true; 397 | braces = ['[', ']']; 398 | } 399 | 400 | // Make functions say that they are functions 401 | if (isFunction(value)) { 402 | var n = value.name ? ': ' + value.name : ''; 403 | base = ' [Function' + n + ']'; 404 | } 405 | 406 | // Make RegExps say that they are RegExps 407 | if (isRegExp(value)) { 408 | base = ' ' + RegExp.prototype.toString.call(value); 409 | } 410 | 411 | // Make dates with properties first say the date 412 | if (isDate(value)) { 413 | base = ' ' + Date.prototype.toUTCString.call(value); 414 | } 415 | 416 | // Make error with message first say the error 417 | if (isError(value)) { 418 | base = ' ' + formatError(value); 419 | } 420 | 421 | if (keys.length === 0 && (!array || value.length == 0)) { 422 | return braces[0] + base + braces[1]; 423 | } 424 | 425 | if (recurseTimes < 0) { 426 | if (isRegExp(value)) { 427 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); 428 | } else { 429 | return ctx.stylize('[Object]', 'special'); 430 | } 431 | } 432 | 433 | ctx.seen.push(value); 434 | 435 | var output; 436 | if (array) { 437 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); 438 | } else { 439 | output = keys.map(function(key) { 440 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); 441 | }); 442 | } 443 | 444 | ctx.seen.pop(); 445 | 446 | return reduceToSingleString(output, base, braces); 447 | } 448 | 449 | 450 | function formatPrimitive(ctx, value) { 451 | if (isUndefined(value)) 452 | return ctx.stylize('undefined', 'undefined'); 453 | if (isString(value)) { 454 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') 455 | .replace(/'/g, "\\'") 456 | .replace(/\\"/g, '"') + '\''; 457 | return ctx.stylize(simple, 'string'); 458 | } 459 | if (isNumber(value)) 460 | return ctx.stylize('' + value, 'number'); 461 | if (isBoolean(value)) 462 | return ctx.stylize('' + value, 'boolean'); 463 | // For some reason typeof null is "object", so special case here. 464 | if (isNull(value)) 465 | return ctx.stylize('null', 'null'); 466 | } 467 | 468 | 469 | function formatError(value) { 470 | return '[' + Error.prototype.toString.call(value) + ']'; 471 | } 472 | 473 | 474 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { 475 | var output = []; 476 | for (var i = 0, l = value.length; i < l; ++i) { 477 | if (hasOwnProperty(value, String(i))) { 478 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 479 | String(i), true)); 480 | } else { 481 | output.push(''); 482 | } 483 | } 484 | keys.forEach(function(key) { 485 | if (!key.match(/^\d+$/)) { 486 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, 487 | key, true)); 488 | } 489 | }); 490 | return output; 491 | } 492 | 493 | 494 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { 495 | var name, str, desc; 496 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; 497 | if (desc.get) { 498 | if (desc.set) { 499 | str = ctx.stylize('[Getter/Setter]', 'special'); 500 | } else { 501 | str = ctx.stylize('[Getter]', 'special'); 502 | } 503 | } else { 504 | if (desc.set) { 505 | str = ctx.stylize('[Setter]', 'special'); 506 | } 507 | } 508 | if (!hasOwnProperty(visibleKeys, key)) { 509 | name = '[' + key + ']'; 510 | } 511 | if (!str) { 512 | if (ctx.seen.indexOf(desc.value) < 0) { 513 | if (isNull(recurseTimes)) { 514 | str = formatValue(ctx, desc.value, null); 515 | } else { 516 | str = formatValue(ctx, desc.value, recurseTimes - 1); 517 | } 518 | if (str.indexOf('\n') > -1) { 519 | if (array) { 520 | str = str.split('\n').map(function(line) { 521 | return ' ' + line; 522 | }).join('\n').substr(2); 523 | } else { 524 | str = '\n' + str.split('\n').map(function(line) { 525 | return ' ' + line; 526 | }).join('\n'); 527 | } 528 | } 529 | } else { 530 | str = ctx.stylize('[Circular]', 'special'); 531 | } 532 | } 533 | if (isUndefined(name)) { 534 | if (array && key.match(/^\d+$/)) { 535 | return str; 536 | } 537 | name = JSON.stringify('' + key); 538 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { 539 | name = name.substr(1, name.length - 2); 540 | name = ctx.stylize(name, 'name'); 541 | } else { 542 | name = name.replace(/'/g, "\\'") 543 | .replace(/\\"/g, '"') 544 | .replace(/(^"|"$)/g, "'"); 545 | name = ctx.stylize(name, 'string'); 546 | } 547 | } 548 | 549 | return name + ': ' + str; 550 | } 551 | 552 | 553 | function reduceToSingleString(output, base, braces) { 554 | var numLinesEst = 0; 555 | var length = output.reduce(function(prev, cur) { 556 | numLinesEst++; 557 | if (cur.indexOf('\n') >= 0) numLinesEst++; 558 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; 559 | }, 0); 560 | 561 | if (length > 60) { 562 | return braces[0] + 563 | (base === '' ? '' : base + '\n ') + 564 | ' ' + 565 | output.join(',\n ') + 566 | ' ' + 567 | braces[1]; 568 | } 569 | 570 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; 571 | } 572 | 573 | 574 | // NOTE: These type checking functions intentionally don't use `instanceof` 575 | // because it is fragile and can be easily faked with `Object.create()`. 576 | function isArray(ar) { 577 | return Array.isArray(ar); 578 | } 579 | exports.isArray = isArray; 580 | 581 | function isBoolean(arg) { 582 | return typeof arg === 'boolean'; 583 | } 584 | exports.isBoolean = isBoolean; 585 | 586 | function isNull(arg) { 587 | return arg === null; 588 | } 589 | exports.isNull = isNull; 590 | 591 | function isNullOrUndefined(arg) { 592 | return arg == null; 593 | } 594 | exports.isNullOrUndefined = isNullOrUndefined; 595 | 596 | function isNumber(arg) { 597 | return typeof arg === 'number'; 598 | } 599 | exports.isNumber = isNumber; 600 | 601 | function isString(arg) { 602 | return typeof arg === 'string'; 603 | } 604 | exports.isString = isString; 605 | 606 | function isSymbol(arg) { 607 | return typeof arg === 'symbol'; 608 | } 609 | exports.isSymbol = isSymbol; 610 | 611 | function isUndefined(arg) { 612 | return arg === void 0; 613 | } 614 | exports.isUndefined = isUndefined; 615 | 616 | function isRegExp(re) { 617 | return isObject(re) && objectToString(re) === '[object RegExp]'; 618 | } 619 | exports.isRegExp = isRegExp; 620 | 621 | function isObject(arg) { 622 | return typeof arg === 'object' && arg !== null; 623 | } 624 | exports.isObject = isObject; 625 | 626 | function isDate(d) { 627 | return isObject(d) && objectToString(d) === '[object Date]'; 628 | } 629 | exports.isDate = isDate; 630 | 631 | function isError(e) { 632 | return isObject(e) && 633 | (objectToString(e) === '[object Error]' || e instanceof Error); 634 | } 635 | exports.isError = isError; 636 | 637 | function isFunction(arg) { 638 | return typeof arg === 'function'; 639 | } 640 | exports.isFunction = isFunction; 641 | 642 | function isPrimitive(arg) { 643 | return arg === null || 644 | typeof arg === 'boolean' || 645 | typeof arg === 'number' || 646 | typeof arg === 'string' || 647 | typeof arg === 'symbol' || // ES6 symbol 648 | typeof arg === 'undefined'; 649 | } 650 | exports.isPrimitive = isPrimitive; 651 | 652 | exports.isBuffer = require('./support/isBuffer'); 653 | 654 | function objectToString(o) { 655 | return Object.prototype.toString.call(o); 656 | } 657 | 658 | 659 | function pad(n) { 660 | return n < 10 ? '0' + n.toString(10) : n.toString(10); 661 | } 662 | 663 | 664 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 665 | 'Oct', 'Nov', 'Dec']; 666 | 667 | // 26 Feb 16:19:34 668 | function timestamp() { 669 | var d = new Date(); 670 | var time = [pad(d.getHours()), 671 | pad(d.getMinutes()), 672 | pad(d.getSeconds())].join(':'); 673 | return [d.getDate(), months[d.getMonth()], time].join(' '); 674 | } 675 | 676 | 677 | // log is just a thin wrapper to console.log that prepends a timestamp 678 | exports.log = function() { 679 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); 680 | }; 681 | 682 | 683 | /** 684 | * Inherit the prototype methods from one constructor into another. 685 | * 686 | * The Function.prototype.inherits from lang.js rewritten as a standalone 687 | * function (not on Function.prototype). NOTE: If this file is to be loaded 688 | * during bootstrapping this function needs to be rewritten using some native 689 | * functions as prototype setup using normal JavaScript does not work as 690 | * expected during bootstrapping (see mirror.js in r114903). 691 | * 692 | * @param {function} ctor Constructor function which needs to inherit the 693 | * prototype. 694 | * @param {function} superCtor Constructor function to inherit prototype from. 695 | */ 696 | exports.inherits = require('inherits'); 697 | 698 | exports._extend = function(origin, add) { 699 | // Don't do anything if add isn't an object 700 | if (!add || !isObject(add)) return origin; 701 | 702 | var keys = Object.keys(add); 703 | var i = keys.length; 704 | while (i--) { 705 | origin[keys[i]] = add[keys[i]]; 706 | } 707 | return origin; 708 | }; 709 | 710 | function hasOwnProperty(obj, prop) { 711 | return Object.prototype.hasOwnProperty.call(obj, prop); 712 | } 713 | 714 | }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 715 | },{"./support/isBuffer":3,"_process":2,"inherits":1}],5:[function(require,module,exports){ 716 | 'use strict'; 717 | 718 | var parseCSSColor = require('csscolorparser').parseCSSColor; 719 | var format = require('util').format; 720 | 721 | module.exports = function(style, reference) { 722 | 723 | var constants = style.constants || {}, 724 | layers = {}, 725 | errors = []; 726 | 727 | function error(key, val /*, message, ...*/) { 728 | var err = { 729 | message: (key ? key + ': ' : '') + 730 | format.apply(format, Array.prototype.slice.call(arguments, 2)) 731 | }; 732 | 733 | if (val !== null && val !== undefined && val.__line__) { 734 | err.line = val.__line__; 735 | } 736 | 737 | errors.push(err); 738 | } 739 | 740 | // Main recursive validation function. Tracks: 741 | // 742 | // - key: string representing location of validation in style tree. Used only 743 | // for more informative error reporting. 744 | // - val: current value from style being evaluated. May be anything from a 745 | // high level object that needs to be descended into deeper or a simple 746 | // scalar value. 747 | // - spec: current spec being evaluated. Tracks val. 748 | // 749 | function validate(key, val, spec) { 750 | var type = typeof_(val); 751 | 752 | // Constants 753 | if (type === 'string' && val[0] === '@') { 754 | if (!(val in constants)) { 755 | return error(key, val, 'constant "%s" not found', val); 756 | } 757 | val = constants[val]; 758 | type = typeof_(val); 759 | } 760 | 761 | // Functions 762 | if (spec.function && type === 'object') { 763 | return validate.function(key, val, spec); 764 | } 765 | 766 | if (spec.type) { 767 | var validator = validate[spec.type]; 768 | if (validator) { 769 | return validator(key, val, spec); 770 | } 771 | spec = reference[spec.type]; 772 | } 773 | 774 | validate.object(key, val, spec); 775 | } 776 | 777 | validate.constants = function(key, val) { 778 | var type = typeof_(val); 779 | if (type !== 'object') { 780 | return error(key, val, 'object expected, %s found', type); 781 | } 782 | 783 | for (var k in val) { 784 | if (k[0] !== '@') { 785 | error(key + '.' + k, val[k], 'constants must start with "@"'); 786 | } 787 | } 788 | }; 789 | 790 | validate.source = function(key, val) { 791 | if (!val.type) { 792 | error(key, val, '"type" is required'); 793 | return; 794 | } 795 | 796 | var type = unbundle(val.type); 797 | switch (type) { 798 | case 'vector': 799 | case 'raster': 800 | validate.object(key, val, reference.source_tile); 801 | 802 | if ('url' in val) { 803 | for (var prop in val) { 804 | if (['type', 'url', 'tileSize'].indexOf(prop) < 0) { 805 | error(key + '.' + prop, val[prop], 'a source with a "url" property may not include a "%s" property', prop); 806 | } 807 | } 808 | } 809 | 810 | break; 811 | case 'geojson': 812 | validate.object(key, val, reference.source_geojson); 813 | break; 814 | case 'video': 815 | validate.object(key, val, reference.source_video); 816 | break; 817 | default: 818 | validate.enum(key + '.type', val.type, {values: ['vector', 'raster', 'geojson', 'video']}); 819 | } 820 | }; 821 | 822 | validate.layer = function(key, val) { 823 | if (!val.type && !val.ref) { 824 | error(key, val, 'either "type" or "ref" is required'); 825 | } 826 | 827 | var type = unbundle(val.type), 828 | ref = unbundle(val.ref); 829 | 830 | if (val.id) { 831 | if (layers[val.id]) { 832 | error(key, val.id, 'duplicate layer id "%s", previously used at line %d', val.id, layers[val.id]); 833 | } else { 834 | layers[val.id] = val.id.__line__; 835 | } 836 | } 837 | 838 | if ('ref' in val) { 839 | ['type', 'source', 'source-layer', 'filter', 'layout'].forEach(function (p) { 840 | if (p in val) { 841 | error(key, val[p], '"%s" is prohibited for ref layers', p); 842 | } 843 | }); 844 | 845 | var parent; 846 | 847 | style.layers.forEach(function(layer) { 848 | if (layer.id == ref) parent = layer; 849 | }); 850 | 851 | if (!parent) { 852 | error(key, val.ref, 'ref layer "%s" not found', ref); 853 | } else if (parent.ref) { 854 | error(key, val.ref, 'ref cannot reference another ref layer'); 855 | } else { 856 | type = parent.type; 857 | } 858 | } else if (type !== 'background') { 859 | if (!val.source) { 860 | error(key, val, 'missing required property "source"'); 861 | } else { 862 | var source = style.sources[val.source]; 863 | if (!source) { 864 | error(key, val.source, 'source "%s" not found', val.source); 865 | } else if (source.type == 'vector' && type == 'raster') { 866 | error(key, val.source, 'layer "%s" requires a raster source', val.id); 867 | } else if (source.type == 'raster' && type != 'raster') { 868 | error(key, val.source, 'layer "%s" requires a vector source', val.id); 869 | } 870 | } 871 | } 872 | 873 | validate.object(key, val, reference.layer, { 874 | filter: validate.filter, 875 | layout: function(key, val) { 876 | var spec = reference['layout_' + type]; 877 | return type && spec && validate(key, val, spec); 878 | }, 879 | paint: function(key, val) { 880 | var spec = reference['paint_' + type]; 881 | return type && spec && validate(key, val, spec); 882 | } 883 | }); 884 | }; 885 | 886 | validate.object = function (key, val, spec, validators) { 887 | validators = validators || {}; 888 | 889 | var type = typeof_(val); 890 | if (type !== 'object') { 891 | return error(key, val, 'object expected, %s found', type); 892 | } 893 | 894 | for (var k in val) { 895 | var speckey = k.split('.')[0]; // treat 'paint.*' as 'paint' 896 | var def = spec[speckey] || spec['*']; 897 | var transition = speckey.match(/^(.*)-transition$/); 898 | 899 | if (def) { 900 | (validators[speckey] || validate)((key ? key + '.' : key) + k, val[k], def); 901 | } else if (transition && spec[transition[1]] && spec[transition[1]].transition) { 902 | validate((key ? key + '.' : key) + k, val[k], reference.transition); 903 | // tolerate root-level extra keys & arbitrary layer properties 904 | } else if (key !== '' && key.split('.').length !== 1) { 905 | error(key, val[k], 'unknown property "%s"', k); 906 | } 907 | } 908 | 909 | for (var l in spec) { 910 | if (spec[l].required && spec[l]['default'] === undefined && val[l] === undefined) { 911 | error(key, val, 'missing required property "%s"', l); 912 | } 913 | } 914 | }; 915 | 916 | validate.array = function (key, val, spec, validator) { 917 | if (typeof_(val) !== 'array') { 918 | return error(key, val, 'array expected, %s found', typeof_(val)); 919 | } 920 | 921 | if (spec.length && val.length !== spec.length) { 922 | return error(key, val, 'array length %d expected, length %d found', spec.length, val.length); 923 | } 924 | 925 | var value = { 926 | "type": spec.value 927 | }; 928 | 929 | if (style.version < 7) { 930 | value.function = spec.function; 931 | } 932 | 933 | if (typeof_(spec.value) === 'object') { 934 | value = spec.value; 935 | } 936 | 937 | for (var i = 0; i < val.length; i++) { 938 | (validator || validate)(key + '[' + i + ']', val[i], value); 939 | } 940 | }; 941 | 942 | validate.filter = function(key, val) { 943 | var type; 944 | 945 | if (typeof_(val) !== 'array') { 946 | return error(key, val, 'array expected, %s found', typeof_(val)); 947 | } 948 | 949 | if (val.length < 1) { 950 | return error(key, val, 'filter array must have at least 1 element'); 951 | } 952 | 953 | validate.enum(key + '[0]', val[0], reference.filter_operator); 954 | 955 | switch (unbundle(val[0])) { 956 | case '<': 957 | case '<=': 958 | case '>': 959 | case '>=': 960 | if (val.length >= 2 && val[1] == '$type') { 961 | error(key, val, '"$type" cannot be use with operator "%s"', val[0]); 962 | } 963 | /* falls through */ 964 | case '==': 965 | case '!=': 966 | if (val.length != 3) { 967 | error(key, val, 'filter array for operator "%s" must have 3 elements', val[0]); 968 | } 969 | /* falls through */ 970 | case 'in': 971 | case '!in': 972 | if (val.length >= 2) { 973 | type = typeof_(val[1]); 974 | if (type !== 'string') { 975 | error(key + '[1]', val[1], 'string expected, %s found', type); 976 | } else if (val[1][0] === '@') { 977 | error(key + '[1]', val[1], 'filter key cannot be a constant'); 978 | } 979 | } 980 | for (var i = 2; i < val.length; i++) { 981 | type = typeof_(val[i]); 982 | if (val[1] == '$type') { 983 | validate.enum(key + '[' + i + ']', val[i], reference.geometry_type); 984 | } else if (type === 'string' && val[i][0] === '@') { 985 | error(key + '[' + i + ']', val[i], 'filter value cannot be a constant'); 986 | } else if (type !== 'string' && type !== 'number' && type !== 'boolean') { 987 | error(key + '[' + i + ']', val[i], 'string, number, or boolean expected, %s found', type); 988 | } 989 | } 990 | break; 991 | 992 | case 'any': 993 | case 'all': 994 | case 'none': 995 | for (i = 1; i < val.length; i++) { 996 | validate.filter(key + '[' + i + ']', val[i]); 997 | } 998 | break; 999 | } 1000 | }; 1001 | 1002 | validate.function = function(key, val, spec) { 1003 | validate.object(key, val, reference.function, { 1004 | stops: function (key, val, arraySpec) { 1005 | var lastStop = -Infinity; 1006 | validate.array(key, val, arraySpec, function validateStop(key, val) { 1007 | if (typeof_(val) !== 'array') { 1008 | return error(key, val, 'array expected, %s found', typeof_(val)); 1009 | } 1010 | 1011 | if (val.length !== 2) { 1012 | return error(key, val, 'array length %d expected, length %d found', 2, val.length); 1013 | } 1014 | 1015 | validate(key + '[0]', val[0], {type: 'number'}); 1016 | validate(key + '[1]', val[1], spec); 1017 | 1018 | if (typeof_(val[0]) === 'number') { 1019 | if (spec.function === 'piecewise-constant' && val[0] % 1 !== 0) { 1020 | error(key + '[0]', val[0], 'zoom level for piecewise-constant functions must be an integer'); 1021 | } 1022 | 1023 | if (val[0] < lastStop) { 1024 | error(key + '[0]', val[0], 'array stops must appear in ascending order'); 1025 | } 1026 | 1027 | lastStop = val[0]; 1028 | } 1029 | }); 1030 | 1031 | if (typeof_(val) === 'array' && val.length === 0) { 1032 | error(key, val, 'array must have at least one stop'); 1033 | } 1034 | } 1035 | }); 1036 | }; 1037 | 1038 | validate.enum = function (key, val, spec) { 1039 | if (spec.values.indexOf(unbundle(val)) === -1) { 1040 | error(key, val, 'expected one of [%s], %s found', spec.values.join(', '), val); 1041 | } 1042 | }; 1043 | 1044 | validate.color = function(key, val) { 1045 | var type = typeof_(val); 1046 | if (type !== 'string') { 1047 | error(key, val, 'color expected, %s found', type); 1048 | } else if (parseCSSColor(val) === null) { 1049 | error(key, val, 'color expected, "%s" found', val); 1050 | } 1051 | }; 1052 | 1053 | function typeValidator(expected) { 1054 | return function(key, val, spec) { 1055 | var actual = typeof_(val); 1056 | if (actual !== expected) { 1057 | error(key, val, '%s expected, %s found', expected, actual); 1058 | } 1059 | 1060 | if ('minimum' in spec && val < spec.minimum) { 1061 | error(key, val, '%s is less than the minimum value %s', val, spec.minimum); 1062 | } 1063 | 1064 | if ('maximum' in spec && val > spec.maximum) { 1065 | error(key, val, '%s is greater than the maximum value %s', val, spec.maximum); 1066 | } 1067 | }; 1068 | } 1069 | 1070 | validate.number = typeValidator('number'); 1071 | validate.string = typeValidator('string'); 1072 | validate.boolean = typeValidator('boolean'); 1073 | 1074 | validate['*'] = function() {}; 1075 | 1076 | validate('', style, reference.$root); 1077 | 1078 | return errors; 1079 | }; 1080 | 1081 | function typeof_(val) { 1082 | if (val instanceof Number) 1083 | return 'number'; 1084 | if (val instanceof String) 1085 | return 'string'; 1086 | if (val instanceof Boolean) 1087 | return 'boolean'; 1088 | if (Array.isArray(val)) 1089 | return 'array'; 1090 | if (val === null) 1091 | return 'null'; 1092 | return typeof val; 1093 | } 1094 | 1095 | function unbundle(_) { 1096 | if (_ instanceof Number || 1097 | _ instanceof String || 1098 | _ instanceof Boolean) { 1099 | return _.valueOf(); 1100 | } else { 1101 | return _; 1102 | } 1103 | } 1104 | 1105 | },{"csscolorparser":6,"util":4}],6:[function(require,module,exports){ 1106 | // (c) Dean McNamee , 2012. 1107 | // 1108 | // https://github.com/deanm/css-color-parser-js 1109 | // 1110 | // Permission is hereby granted, free of charge, to any person obtaining a copy 1111 | // of this software and associated documentation files (the "Software"), to 1112 | // deal in the Software without restriction, including without limitation the 1113 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 1114 | // sell copies of the Software, and to permit persons to whom the Software is 1115 | // furnished to do so, subject to the following conditions: 1116 | // 1117 | // The above copyright notice and this permission notice shall be included in 1118 | // all copies or substantial portions of the Software. 1119 | // 1120 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1121 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1122 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1123 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1124 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 1125 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 1126 | // IN THE SOFTWARE. 1127 | 1128 | // http://www.w3.org/TR/css3-color/ 1129 | var kCSSColorTable = { 1130 | "transparent": [0,0,0,0], "aliceblue": [240,248,255,1], 1131 | "antiquewhite": [250,235,215,1], "aqua": [0,255,255,1], 1132 | "aquamarine": [127,255,212,1], "azure": [240,255,255,1], 1133 | "beige": [245,245,220,1], "bisque": [255,228,196,1], 1134 | "black": [0,0,0,1], "blanchedalmond": [255,235,205,1], 1135 | "blue": [0,0,255,1], "blueviolet": [138,43,226,1], 1136 | "brown": [165,42,42,1], "burlywood": [222,184,135,1], 1137 | "cadetblue": [95,158,160,1], "chartreuse": [127,255,0,1], 1138 | "chocolate": [210,105,30,1], "coral": [255,127,80,1], 1139 | "cornflowerblue": [100,149,237,1], "cornsilk": [255,248,220,1], 1140 | "crimson": [220,20,60,1], "cyan": [0,255,255,1], 1141 | "darkblue": [0,0,139,1], "darkcyan": [0,139,139,1], 1142 | "darkgoldenrod": [184,134,11,1], "darkgray": [169,169,169,1], 1143 | "darkgreen": [0,100,0,1], "darkgrey": [169,169,169,1], 1144 | "darkkhaki": [189,183,107,1], "darkmagenta": [139,0,139,1], 1145 | "darkolivegreen": [85,107,47,1], "darkorange": [255,140,0,1], 1146 | "darkorchid": [153,50,204,1], "darkred": [139,0,0,1], 1147 | "darksalmon": [233,150,122,1], "darkseagreen": [143,188,143,1], 1148 | "darkslateblue": [72,61,139,1], "darkslategray": [47,79,79,1], 1149 | "darkslategrey": [47,79,79,1], "darkturquoise": [0,206,209,1], 1150 | "darkviolet": [148,0,211,1], "deeppink": [255,20,147,1], 1151 | "deepskyblue": [0,191,255,1], "dimgray": [105,105,105,1], 1152 | "dimgrey": [105,105,105,1], "dodgerblue": [30,144,255,1], 1153 | "firebrick": [178,34,34,1], "floralwhite": [255,250,240,1], 1154 | "forestgreen": [34,139,34,1], "fuchsia": [255,0,255,1], 1155 | "gainsboro": [220,220,220,1], "ghostwhite": [248,248,255,1], 1156 | "gold": [255,215,0,1], "goldenrod": [218,165,32,1], 1157 | "gray": [128,128,128,1], "green": [0,128,0,1], 1158 | "greenyellow": [173,255,47,1], "grey": [128,128,128,1], 1159 | "honeydew": [240,255,240,1], "hotpink": [255,105,180,1], 1160 | "indianred": [205,92,92,1], "indigo": [75,0,130,1], 1161 | "ivory": [255,255,240,1], "khaki": [240,230,140,1], 1162 | "lavender": [230,230,250,1], "lavenderblush": [255,240,245,1], 1163 | "lawngreen": [124,252,0,1], "lemonchiffon": [255,250,205,1], 1164 | "lightblue": [173,216,230,1], "lightcoral": [240,128,128,1], 1165 | "lightcyan": [224,255,255,1], "lightgoldenrodyellow": [250,250,210,1], 1166 | "lightgray": [211,211,211,1], "lightgreen": [144,238,144,1], 1167 | "lightgrey": [211,211,211,1], "lightpink": [255,182,193,1], 1168 | "lightsalmon": [255,160,122,1], "lightseagreen": [32,178,170,1], 1169 | "lightskyblue": [135,206,250,1], "lightslategray": [119,136,153,1], 1170 | "lightslategrey": [119,136,153,1], "lightsteelblue": [176,196,222,1], 1171 | "lightyellow": [255,255,224,1], "lime": [0,255,0,1], 1172 | "limegreen": [50,205,50,1], "linen": [250,240,230,1], 1173 | "magenta": [255,0,255,1], "maroon": [128,0,0,1], 1174 | "mediumaquamarine": [102,205,170,1], "mediumblue": [0,0,205,1], 1175 | "mediumorchid": [186,85,211,1], "mediumpurple": [147,112,219,1], 1176 | "mediumseagreen": [60,179,113,1], "mediumslateblue": [123,104,238,1], 1177 | "mediumspringgreen": [0,250,154,1], "mediumturquoise": [72,209,204,1], 1178 | "mediumvioletred": [199,21,133,1], "midnightblue": [25,25,112,1], 1179 | "mintcream": [245,255,250,1], "mistyrose": [255,228,225,1], 1180 | "moccasin": [255,228,181,1], "navajowhite": [255,222,173,1], 1181 | "navy": [0,0,128,1], "oldlace": [253,245,230,1], 1182 | "olive": [128,128,0,1], "olivedrab": [107,142,35,1], 1183 | "orange": [255,165,0,1], "orangered": [255,69,0,1], 1184 | "orchid": [218,112,214,1], "palegoldenrod": [238,232,170,1], 1185 | "palegreen": [152,251,152,1], "paleturquoise": [175,238,238,1], 1186 | "palevioletred": [219,112,147,1], "papayawhip": [255,239,213,1], 1187 | "peachpuff": [255,218,185,1], "peru": [205,133,63,1], 1188 | "pink": [255,192,203,1], "plum": [221,160,221,1], 1189 | "powderblue": [176,224,230,1], "purple": [128,0,128,1], 1190 | "red": [255,0,0,1], "rosybrown": [188,143,143,1], 1191 | "royalblue": [65,105,225,1], "saddlebrown": [139,69,19,1], 1192 | "salmon": [250,128,114,1], "sandybrown": [244,164,96,1], 1193 | "seagreen": [46,139,87,1], "seashell": [255,245,238,1], 1194 | "sienna": [160,82,45,1], "silver": [192,192,192,1], 1195 | "skyblue": [135,206,235,1], "slateblue": [106,90,205,1], 1196 | "slategray": [112,128,144,1], "slategrey": [112,128,144,1], 1197 | "snow": [255,250,250,1], "springgreen": [0,255,127,1], 1198 | "steelblue": [70,130,180,1], "tan": [210,180,140,1], 1199 | "teal": [0,128,128,1], "thistle": [216,191,216,1], 1200 | "tomato": [255,99,71,1], "turquoise": [64,224,208,1], 1201 | "violet": [238,130,238,1], "wheat": [245,222,179,1], 1202 | "white": [255,255,255,1], "whitesmoke": [245,245,245,1], 1203 | "yellow": [255,255,0,1], "yellowgreen": [154,205,50,1]} 1204 | 1205 | function clamp_css_byte(i) { // Clamp to integer 0 .. 255. 1206 | i = Math.round(i); // Seems to be what Chrome does (vs truncation). 1207 | return i < 0 ? 0 : i > 255 ? 255 : i; 1208 | } 1209 | 1210 | function clamp_css_float(f) { // Clamp to float 0.0 .. 1.0. 1211 | return f < 0 ? 0 : f > 1 ? 1 : f; 1212 | } 1213 | 1214 | function parse_css_int(str) { // int or percentage. 1215 | if (str[str.length - 1] === '%') 1216 | return clamp_css_byte(parseFloat(str) / 100 * 255); 1217 | return clamp_css_byte(parseInt(str)); 1218 | } 1219 | 1220 | function parse_css_float(str) { // float or percentage. 1221 | if (str[str.length - 1] === '%') 1222 | return clamp_css_float(parseFloat(str) / 100); 1223 | return clamp_css_float(parseFloat(str)); 1224 | } 1225 | 1226 | function css_hue_to_rgb(m1, m2, h) { 1227 | if (h < 0) h += 1; 1228 | else if (h > 1) h -= 1; 1229 | 1230 | if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; 1231 | if (h * 2 < 1) return m2; 1232 | if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; 1233 | return m1; 1234 | } 1235 | 1236 | function parseCSSColor(css_str) { 1237 | // Remove all whitespace, not compliant, but should just be more accepting. 1238 | var str = css_str.replace(/ /g, '').toLowerCase(); 1239 | 1240 | // Color keywords (and transparent) lookup. 1241 | if (str in kCSSColorTable) return kCSSColorTable[str].slice(); // dup. 1242 | 1243 | // #abc and #abc123 syntax. 1244 | if (str[0] === '#') { 1245 | if (str.length === 4) { 1246 | var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. 1247 | if (!(iv >= 0 && iv <= 0xfff)) return null; // Covers NaN. 1248 | return [((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), 1249 | (iv & 0xf0) | ((iv & 0xf0) >> 4), 1250 | (iv & 0xf) | ((iv & 0xf) << 4), 1251 | 1]; 1252 | } else if (str.length === 7) { 1253 | var iv = parseInt(str.substr(1), 16); // TODO(deanm): Stricter parsing. 1254 | if (!(iv >= 0 && iv <= 0xffffff)) return null; // Covers NaN. 1255 | return [(iv & 0xff0000) >> 16, 1256 | (iv & 0xff00) >> 8, 1257 | iv & 0xff, 1258 | 1]; 1259 | } 1260 | 1261 | return null; 1262 | } 1263 | 1264 | var op = str.indexOf('('), ep = str.indexOf(')'); 1265 | if (op !== -1 && ep + 1 === str.length) { 1266 | var fname = str.substr(0, op); 1267 | var params = str.substr(op+1, ep-(op+1)).split(','); 1268 | var alpha = 1; // To allow case fallthrough. 1269 | switch (fname) { 1270 | case 'rgba': 1271 | if (params.length !== 4) return null; 1272 | alpha = parse_css_float(params.pop()); 1273 | // Fall through. 1274 | case 'rgb': 1275 | if (params.length !== 3) return null; 1276 | return [parse_css_int(params[0]), 1277 | parse_css_int(params[1]), 1278 | parse_css_int(params[2]), 1279 | alpha]; 1280 | case 'hsla': 1281 | if (params.length !== 4) return null; 1282 | alpha = parse_css_float(params.pop()); 1283 | // Fall through. 1284 | case 'hsl': 1285 | if (params.length !== 3) return null; 1286 | var h = (((parseFloat(params[0]) % 360) + 360) % 360) / 360; // 0 .. 1 1287 | // NOTE(deanm): According to the CSS spec s/l should only be 1288 | // percentages, but we don't bother and let float or percentage. 1289 | var s = parse_css_float(params[1]); 1290 | var l = parse_css_float(params[2]); 1291 | var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; 1292 | var m1 = l * 2 - m2; 1293 | return [clamp_css_byte(css_hue_to_rgb(m1, m2, h+1/3) * 255), 1294 | clamp_css_byte(css_hue_to_rgb(m1, m2, h) * 255), 1295 | clamp_css_byte(css_hue_to_rgb(m1, m2, h-1/3) * 255), 1296 | alpha]; 1297 | default: 1298 | return null; 1299 | } 1300 | } 1301 | 1302 | return null; 1303 | } 1304 | 1305 | try { exports.parseCSSColor = parseCSSColor } catch(e) { } 1306 | 1307 | },{}],7:[function(require,module,exports){ 1308 | module.exports = require('./v7.json'); 1309 | 1310 | },{"./v7.json":8}],8:[function(require,module,exports){ 1311 | module.exports={ 1312 | "$version": 7, 1313 | "$root": { 1314 | "version": { 1315 | "required": true, 1316 | "type": "enum", 1317 | "values": [ 1318 | 7 1319 | ], 1320 | "doc": "Stylesheet version number. Must be 7." 1321 | }, 1322 | "name": { 1323 | "type": "string", 1324 | "doc": "A human-readable name for the style." 1325 | }, 1326 | "constants": { 1327 | "type": "constants", 1328 | "doc": "An object of constants to be referenced in layers." 1329 | }, 1330 | "sources": { 1331 | "required": true, 1332 | "type": "sources", 1333 | "doc": "Data source specifications." 1334 | }, 1335 | "sprite": { 1336 | "type": "string", 1337 | "doc": "A base URL for retrieving the sprite image and metadata. The extensions `.png`, `.json` and scale factor `@2x.png` will be automatically appended." 1338 | }, 1339 | "glyphs": { 1340 | "type": "string", 1341 | "doc": "A URL template for loading signed-distance-field glyph sets in PBF format. Valid tokens are {fontstack} and {range}." 1342 | }, 1343 | "transition": { 1344 | "type": "transition", 1345 | "doc": "A global transition definition to use as a default across properties." 1346 | }, 1347 | "layers": { 1348 | "required": true, 1349 | "type": "array", 1350 | "value": "layer", 1351 | "doc": "Layers will be drawn in the order of this array." 1352 | } 1353 | }, 1354 | "constants": { 1355 | "*": { 1356 | "type": "*", 1357 | "doc": "A constant that will be replaced verbatim in the referencing place. This can be anything, including objects and arrays. All variable names must be prefixed with an `@` symbol." 1358 | } 1359 | }, 1360 | "sources": { 1361 | "*": { 1362 | "type": "source", 1363 | "doc": "Specification of a data source. For vector and raster sources, either TileJSON or a URL to a TileJSON must be provided. For GeoJSON and video sources, a URL must be provided." 1364 | } 1365 | }, 1366 | "source": [ 1367 | "source_tile", 1368 | "source_geojson", 1369 | "source_video" 1370 | ], 1371 | "source_tile": { 1372 | "type": { 1373 | "required": true, 1374 | "type": "enum", 1375 | "values": [ 1376 | "vector", 1377 | "raster" 1378 | ], 1379 | "doc": "The data type of the source." 1380 | }, 1381 | "url": { 1382 | "type": "string", 1383 | "doc": "A URL to a TileJSON resource. Supported protocols are `http:`, `https:`, and `mapbox://`." 1384 | }, 1385 | "tiles": { 1386 | "type": "array", 1387 | "value": "string", 1388 | "doc": "An array of one or more tile source URLs, as in the TileJSON spec." 1389 | }, 1390 | "minzoom": { 1391 | "type": "number", 1392 | "default": 0, 1393 | "doc": "Minimum zoom level for which tiles are available, as in the TileJSON spec." 1394 | }, 1395 | "maxzoom": { 1396 | "type": "number", 1397 | "default": 22, 1398 | "doc": "Maximum zoom level for which tiles are available, as in the TileJSON spec. Data from tiles at the maxzoom are used when displaying the map at higher zoom levels." 1399 | }, 1400 | "tileSize": { 1401 | "type": "number", 1402 | "default": 512, 1403 | "units": "pixels", 1404 | "doc": "The minimum visual size to display tiles for this layer. Only configurable for raster layers." 1405 | }, 1406 | "*": { 1407 | "type": "*", 1408 | "doc": "Other keys to configure the data source." 1409 | } 1410 | }, 1411 | "source_geojson": { 1412 | "type": { 1413 | "required": true, 1414 | "type": "enum", 1415 | "values": [ 1416 | "geojson" 1417 | ] 1418 | }, 1419 | "data": { 1420 | "type": "*" 1421 | } 1422 | }, 1423 | "source_video": { 1424 | "type": { 1425 | "required": true, 1426 | "type": "enum", 1427 | "values": [ 1428 | "video" 1429 | ] 1430 | }, 1431 | "url": { 1432 | "required": true, 1433 | "type": "array", 1434 | "value": "string", 1435 | "doc": "URLs to video content in order of preferred format." 1436 | }, 1437 | "coordinates": { 1438 | "required": true, 1439 | "type": "array", 1440 | "length": 4, 1441 | "value": { 1442 | "type": "array", 1443 | "length": 2, 1444 | "value": "number" 1445 | } 1446 | } 1447 | }, 1448 | "layer": { 1449 | "id": { 1450 | "type": "string", 1451 | "doc": "Unique layer name." 1452 | }, 1453 | "type": { 1454 | "type": "enum", 1455 | "values": [ 1456 | "fill", 1457 | "line", 1458 | "symbol", 1459 | "raster", 1460 | "background" 1461 | ], 1462 | "doc": "Rendering type of this layer." 1463 | }, 1464 | "ref": { 1465 | "type": "string", 1466 | "doc": "References another layer to copy `type`, `source`, `source-layer`, `minzoom`, `maxzoom`, `filter`, and `layout` properties from. This allows the layers to share processing and be more efficient." 1467 | }, 1468 | "source": { 1469 | "type": "string", 1470 | "doc": "Name of a source description to be used for this layer." 1471 | }, 1472 | "source-layer": { 1473 | "type": "string", 1474 | "doc": "Layer to use from a vector tile source. Required if the source supports multiple layers." 1475 | }, 1476 | "minzoom": { 1477 | "type": "number", 1478 | "minimum": 0, 1479 | "maximum": 22, 1480 | "doc": "The minimum zoom level on which the layer gets parsed and appears on." 1481 | }, 1482 | "maxzoom": { 1483 | "type": "number", 1484 | "minimum": 0, 1485 | "maximum": 22, 1486 | "doc": "The maximum zoom level on which the layer gets parsed and appears on." 1487 | }, 1488 | "interactive": { 1489 | "type": "boolean", 1490 | "doc": "Enable querying of feature data from this layer for interactivity.", 1491 | "default": false 1492 | }, 1493 | "filter": { 1494 | "type": "filter", 1495 | "doc": "A expression specifying conditions on source features. Only features that match the filter are displayed." 1496 | }, 1497 | "layout": { 1498 | "type": "layout", 1499 | "doc": "Layout properties for the layer." 1500 | }, 1501 | "paint": { 1502 | "type": "paint", 1503 | "doc": "Default paint properties for this layer." 1504 | }, 1505 | "paint.*": { 1506 | "type": "paint", 1507 | "doc": "Class-specific paint properties for this layer. The class name is the part after the first dot." 1508 | } 1509 | }, 1510 | "layout": [ 1511 | "layout_fill", 1512 | "layout_line", 1513 | "layout_symbol", 1514 | "layout_raster", 1515 | "layout_background" 1516 | ], 1517 | "layout_background": { 1518 | "visibility": { 1519 | "type": "enum", 1520 | "function": "piecewise-constant", 1521 | "values": [ 1522 | "visible", 1523 | "none" 1524 | ], 1525 | "default": "visible", 1526 | "doc": "The display of this layer. `none` hides this layer." 1527 | } 1528 | }, 1529 | "layout_fill": { 1530 | "visibility": { 1531 | "type": "enum", 1532 | "function": "piecewise-constant", 1533 | "values": [ 1534 | "visible", 1535 | "none" 1536 | ], 1537 | "default": "visible", 1538 | "doc": "The display of this layer. `none` hides this layer." 1539 | } 1540 | }, 1541 | "layout_line": { 1542 | "line-cap": { 1543 | "type": "enum", 1544 | "function": "piecewise-constant", 1545 | "values": [ 1546 | "butt", 1547 | "round", 1548 | "square" 1549 | ], 1550 | "default": "butt", 1551 | "doc": "The display of line endings." 1552 | }, 1553 | "line-join": { 1554 | "type": "enum", 1555 | "function": "piecewise-constant", 1556 | "values": [ 1557 | "bevel", 1558 | "round", 1559 | "miter" 1560 | ], 1561 | "default": "miter", 1562 | "doc": "The display of lines when joining." 1563 | }, 1564 | "line-miter-limit": { 1565 | "type": "number", 1566 | "default": 2, 1567 | "function": "interpolated", 1568 | "doc": "Used to automatically convert miter joins to bevel joins for sharp angles.", 1569 | "requires": [ 1570 | { 1571 | "line-join": "miter" 1572 | } 1573 | ] 1574 | }, 1575 | "line-round-limit": { 1576 | "type": "number", 1577 | "default": 1, 1578 | "function": "interpolated", 1579 | "doc": "Used to automatically convert round joins to miter joins for shallow angles.", 1580 | "requires": [ 1581 | { 1582 | "line-join": "round" 1583 | } 1584 | ] 1585 | }, 1586 | "visibility": { 1587 | "type": "enum", 1588 | "function": "piecewise-constant", 1589 | "values": [ 1590 | "visible", 1591 | "none" 1592 | ], 1593 | "default": "visible", 1594 | "doc": "The display of this layer. `none` hides this layer." 1595 | } 1596 | }, 1597 | "layout_symbol": { 1598 | "symbol-placement": { 1599 | "type": "enum", 1600 | "function": "piecewise-constant", 1601 | "values": [ 1602 | "point", 1603 | "line" 1604 | ], 1605 | "default": "point", 1606 | "doc": "Label placement relative to its geometry. `line` can only be used on LineStrings and Polygons." 1607 | }, 1608 | "symbol-min-distance": { 1609 | "type": "number", 1610 | "default": 250, 1611 | "minimum": 1, 1612 | "function": "interpolated", 1613 | "units": "pixels", 1614 | "doc": "Minimum distance between two symbol anchors.", 1615 | "requires": [ 1616 | { 1617 | "symbol-placement": "line" 1618 | } 1619 | ] 1620 | }, 1621 | "symbol-avoid-edges": { 1622 | "type": "boolean", 1623 | "function": "piecewise-constant", 1624 | "default": false, 1625 | "doc": "If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer." 1626 | }, 1627 | "icon-allow-overlap": { 1628 | "type": "boolean", 1629 | "function": "piecewise-constant", 1630 | "default": false, 1631 | "doc": "If true, the icon will be visible even if it collides with other icons and text.", 1632 | "requires": [ 1633 | "icon-image" 1634 | ] 1635 | }, 1636 | "icon-ignore-placement": { 1637 | "type": "boolean", 1638 | "function": "piecewise-constant", 1639 | "default": false, 1640 | "doc": "If true, the icon won't affect placement of other icons and text.", 1641 | "requires": [ 1642 | "icon-image" 1643 | ] 1644 | }, 1645 | "icon-optional": { 1646 | "type": "boolean", 1647 | "function": "piecewise-constant", 1648 | "default": false, 1649 | "doc": "If true, the symbol will appear without its icon, in spaces where the icon would make it too large to fit.", 1650 | "requires": [ 1651 | "icon-image", 1652 | "text-field" 1653 | ] 1654 | }, 1655 | "icon-rotation-alignment": { 1656 | "type": "enum", 1657 | "function": "piecewise-constant", 1658 | "values": [ 1659 | "map", 1660 | "viewport" 1661 | ], 1662 | "default": "viewport", 1663 | "doc": "Orientation of icon when map is rotated.", 1664 | "requires": [ 1665 | "icon-image" 1666 | ] 1667 | }, 1668 | "icon-max-size": { 1669 | "type": "number", 1670 | "default": 1, 1671 | "minimum": 0, 1672 | "function": "interpolated", 1673 | "doc": "The maximum factor to scale the icon.", 1674 | "requires": [ 1675 | "icon-image" 1676 | ] 1677 | }, 1678 | "icon-image": { 1679 | "type": "string", 1680 | "function": "piecewise-constant", 1681 | "doc": "A string with {tokens} replaced, referencing the data property to pull from.", 1682 | "tokens": true 1683 | }, 1684 | "icon-rotate": { 1685 | "type": "number", 1686 | "default": 0, 1687 | "period": 360, 1688 | "function": "interpolated", 1689 | "units": "degrees", 1690 | "doc": "Rotates the icon clockwise.", 1691 | "requires": [ 1692 | "icon-image" 1693 | ] 1694 | }, 1695 | "icon-padding": { 1696 | "type": "number", 1697 | "default": 2, 1698 | "minimum": 0, 1699 | "function": "interpolated", 1700 | "units": "pixels", 1701 | "doc": "Padding value around icon bounding box to avoid icon collisions.", 1702 | "requires": [ 1703 | "icon-image" 1704 | ] 1705 | }, 1706 | "icon-keep-upright": { 1707 | "type": "boolean", 1708 | "function": "piecewise-constant", 1709 | "default": false, 1710 | "doc": "If true, the icon may be flipped to prevent it from being rendered upside-down", 1711 | "requires": [ 1712 | "icon-image", 1713 | { 1714 | "icon-rotation-alignment": "map" 1715 | } 1716 | ] 1717 | }, 1718 | "icon-offset": { 1719 | "type": "array", 1720 | "value": "number", 1721 | "length": 2, 1722 | "default": [ 1723 | 0, 1724 | 0 1725 | ], 1726 | "function": "interpolated", 1727 | "doc": "Icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", 1728 | "requires": [ 1729 | "icon-image" 1730 | ] 1731 | }, 1732 | "text-rotation-alignment": { 1733 | "type": "enum", 1734 | "function": "piecewise-constant", 1735 | "values": [ 1736 | "map", 1737 | "viewport" 1738 | ], 1739 | "default": "viewport", 1740 | "doc": "Orientation of icon or text when map is rotated.", 1741 | "requires": [ 1742 | "text-field" 1743 | ] 1744 | }, 1745 | "text-field": { 1746 | "type": "string", 1747 | "function": "piecewise-constant", 1748 | "default": "", 1749 | "tokens": true, 1750 | "doc": "Value to use for a text label. Feature properties are specified using tokens like {field_name}." 1751 | }, 1752 | "text-font": { 1753 | "type": "string", 1754 | "function": "piecewise-constant", 1755 | "default": "Open Sans Regular, Arial Unicode MS Regular", 1756 | "doc": "Font stack to use for displaying text.", 1757 | "requires": [ 1758 | "text-field" 1759 | ] 1760 | }, 1761 | "text-max-size": { 1762 | "type": "number", 1763 | "default": 16, 1764 | "minimum": 0, 1765 | "units": "pixels", 1766 | "function": "interpolated", 1767 | "doc": "The maximum size text will be laid out, to calculate collisions with.", 1768 | "requires": [ 1769 | "text-field" 1770 | ] 1771 | }, 1772 | "text-max-width": { 1773 | "type": "number", 1774 | "default": 15, 1775 | "minimum": 0, 1776 | "units": "em", 1777 | "function": "interpolated", 1778 | "doc": "The maximum line width for text wrapping.", 1779 | "requires": [ 1780 | "text-field" 1781 | ] 1782 | }, 1783 | "text-line-height": { 1784 | "type": "number", 1785 | "default": 1.2, 1786 | "units": "em", 1787 | "function": "interpolated", 1788 | "doc": "Text leading value for multi-line text.", 1789 | "requires": [ 1790 | "text-field" 1791 | ] 1792 | }, 1793 | "text-letter-spacing": { 1794 | "type": "number", 1795 | "default": 0, 1796 | "units": "em", 1797 | "function": "interpolated", 1798 | "doc": "Text kerning value.", 1799 | "requires": [ 1800 | "text-field" 1801 | ] 1802 | }, 1803 | "text-justify": { 1804 | "type": "enum", 1805 | "function": "piecewise-constant", 1806 | "values": [ 1807 | "left", 1808 | "center", 1809 | "right" 1810 | ], 1811 | "default": "center", 1812 | "doc": "Text justification options.", 1813 | "requires": [ 1814 | "text-field" 1815 | ] 1816 | }, 1817 | "text-anchor": { 1818 | "type": "enum", 1819 | "function": "piecewise-constant", 1820 | "values": [ 1821 | "center", 1822 | "left", 1823 | "right", 1824 | "top", 1825 | "bottom", 1826 | "top-left", 1827 | "top-right", 1828 | "bottom-left", 1829 | "bottom-right" 1830 | ], 1831 | "default": "center", 1832 | "doc": "Which part of the text to place closest to the anchor.", 1833 | "requires": [ 1834 | "text-field" 1835 | ] 1836 | }, 1837 | "text-max-angle": { 1838 | "type": "number", 1839 | "default": 45, 1840 | "units": "degrees", 1841 | "function": "interpolated", 1842 | "doc": "Maximum angle change between adjacent characters.", 1843 | "requires": [ 1844 | "text-field", 1845 | { 1846 | "symbol-placement": "line" 1847 | } 1848 | ] 1849 | }, 1850 | "text-rotate": { 1851 | "type": "number", 1852 | "default": 0, 1853 | "period": 360, 1854 | "units": "degrees", 1855 | "function": "interpolated", 1856 | "doc": "Rotates the text clockwise.", 1857 | "requires": [ 1858 | "text-field" 1859 | ] 1860 | }, 1861 | "text-padding": { 1862 | "type": "number", 1863 | "default": 2, 1864 | "minimum": 0, 1865 | "units": "pixels", 1866 | "function": "interpolated", 1867 | "doc": "Padding value around text bounding box to avoid label collisions.", 1868 | "requires": [ 1869 | "text-field" 1870 | ] 1871 | }, 1872 | "text-keep-upright": { 1873 | "type": "boolean", 1874 | "function": "piecewise-constant", 1875 | "default": true, 1876 | "doc": "If true, the text may be flipped vertically to prevent it from being rendered upside-down.", 1877 | "requires": [ 1878 | "text-field", 1879 | { 1880 | "text-rotation-alignment": "map" 1881 | } 1882 | ] 1883 | }, 1884 | "text-transform": { 1885 | "type": "enum", 1886 | "function": "piecewise-constant", 1887 | "values": [ 1888 | "none", 1889 | "uppercase", 1890 | "lowercase" 1891 | ], 1892 | "default": "none", 1893 | "doc": "Specifies how to capitalize text, similar to the CSS `text-transform` property.", 1894 | "requires": [ 1895 | "text-field" 1896 | ] 1897 | }, 1898 | "text-offset": { 1899 | "type": "array", 1900 | "doc": "Specifies the distance that text is offset from its anchor horizontally and vertically.", 1901 | "value": "number", 1902 | "units": "ems", 1903 | "function": "interpolated", 1904 | "length": 2, 1905 | "default": [ 1906 | 0, 1907 | 0 1908 | ], 1909 | "requires": [ 1910 | "text-field" 1911 | ] 1912 | }, 1913 | "text-allow-overlap": { 1914 | "type": "boolean", 1915 | "function": "piecewise-constant", 1916 | "default": false, 1917 | "doc": "If true, the text will be visible even if it collides with other icons and labels.", 1918 | "requires": [ 1919 | "text-field" 1920 | ] 1921 | }, 1922 | "text-ignore-placement": { 1923 | "type": "boolean", 1924 | "function": "piecewise-constant", 1925 | "default": false, 1926 | "doc": "If true, the text won't affect placement of other icons and labels.", 1927 | "requires": [ 1928 | "text-field" 1929 | ] 1930 | }, 1931 | "text-optional": { 1932 | "type": "boolean", 1933 | "function": "piecewise-constant", 1934 | "default": false, 1935 | "doc": "If true, the symbol will appear without its text, in spaces where the text would make it too large to fit.", 1936 | "requires": [ 1937 | "text-field", 1938 | "icon-image" 1939 | ] 1940 | }, 1941 | "visibility": { 1942 | "type": "enum", 1943 | "function": "piecewise-constant", 1944 | "values": [ 1945 | "visible", 1946 | "none" 1947 | ], 1948 | "default": "visible", 1949 | "doc": "The display of this layer. `none` hides this layer." 1950 | } 1951 | }, 1952 | "layout_raster": { 1953 | "visibility": { 1954 | "type": "enum", 1955 | "function": "piecewise-constant", 1956 | "values": [ 1957 | "visible", 1958 | "none" 1959 | ], 1960 | "default": "visible", 1961 | "doc": "The display of this layer. `none` hides this layer." 1962 | } 1963 | }, 1964 | "filter": { 1965 | "type": "array", 1966 | "value": "*" 1967 | }, 1968 | "filter_operator": { 1969 | "type": "enum", 1970 | "values": [ 1971 | "==", 1972 | "!=", 1973 | ">", 1974 | ">=", 1975 | "<", 1976 | "<=", 1977 | "in", 1978 | "!in", 1979 | "all", 1980 | "any", 1981 | "none" 1982 | ] 1983 | }, 1984 | "geometry_type": { 1985 | "type": "enum", 1986 | "values": [ 1987 | "Point", 1988 | "LineString", 1989 | "Polygon" 1990 | ] 1991 | }, 1992 | "function": { 1993 | "stops": { 1994 | "type": "array", 1995 | "required": true, 1996 | "doc": "An array of stops.", 1997 | "value": "function_stop" 1998 | }, 1999 | "base": { 2000 | "type": "number", 2001 | "default": 1, 2002 | "minimum": 0, 2003 | "doc": "The exponential base of the interpolation curve. It controls the rate at which the result increases. Higher values make the result increase more towards the high end of the range. With `1` the stops are interpolated linearly." 2004 | } 2005 | }, 2006 | "function_stop": { 2007 | "type": "array", 2008 | "minimum": 0, 2009 | "maximum": 22, 2010 | "value": [ 2011 | "number", 2012 | "color" 2013 | ], 2014 | "length": 2, 2015 | "doc": "Zoom level and value pair." 2016 | }, 2017 | "paint": [ 2018 | "paint_fill", 2019 | "paint_line", 2020 | "paint_symbol", 2021 | "paint_raster", 2022 | "paint_background" 2023 | ], 2024 | "paint_fill": { 2025 | "fill-antialias": { 2026 | "type": "boolean", 2027 | "function": "piecewise-constant", 2028 | "default": true, 2029 | "doc": "Whether or not the fill should be antialiased." 2030 | }, 2031 | "fill-opacity": { 2032 | "type": "number", 2033 | "function": "interpolated", 2034 | "default": 1, 2035 | "minimum": 0, 2036 | "maximum": 1, 2037 | "doc": "The opacity given to the fill color.", 2038 | "transition": true 2039 | }, 2040 | "fill-color": { 2041 | "type": "color", 2042 | "default": "#000000", 2043 | "doc": "The color of the fill.", 2044 | "function": "interpolated", 2045 | "transition": true, 2046 | "requires": [ 2047 | { 2048 | "!": "fill-image" 2049 | } 2050 | ] 2051 | }, 2052 | "fill-outline-color": { 2053 | "type": "color", 2054 | "doc": "The outline color of the fill. Matches the value of `fill-color` if unspecified.", 2055 | "function": "interpolated", 2056 | "transition": true, 2057 | "requires": [ 2058 | { 2059 | "!": "fill-image" 2060 | }, 2061 | { 2062 | "fill-antialias": true 2063 | } 2064 | ] 2065 | }, 2066 | "fill-translate": { 2067 | "type": "array", 2068 | "value": "number", 2069 | "length": 2, 2070 | "default": [ 2071 | 0, 2072 | 0 2073 | ], 2074 | "function": "interpolated", 2075 | "transition": true, 2076 | "units": "pixels", 2077 | "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." 2078 | }, 2079 | "fill-translate-anchor": { 2080 | "type": "enum", 2081 | "function": "piecewise-constant", 2082 | "values": [ 2083 | "map", 2084 | "viewport" 2085 | ], 2086 | "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", 2087 | "default": "map", 2088 | "requires": [ 2089 | "fill-translate" 2090 | ] 2091 | }, 2092 | "fill-image": { 2093 | "type": "string", 2094 | "function": "piecewise-constant", 2095 | "transition": true, 2096 | "doc": "Name of image in sprite to use for drawing image fills." 2097 | } 2098 | }, 2099 | "paint_line": { 2100 | "line-opacity": { 2101 | "type": "number", 2102 | "doc": "The opacity at which the line will be drawn.", 2103 | "function": "interpolated", 2104 | "default": 1, 2105 | "minimum": 0, 2106 | "maximum": 1, 2107 | "transition": true 2108 | }, 2109 | "line-color": { 2110 | "type": "color", 2111 | "doc": "The color with which the line will be drawn.", 2112 | "default": "#000000", 2113 | "function": "interpolated", 2114 | "transition": true, 2115 | "requires": [ 2116 | { 2117 | "!": "line-image" 2118 | } 2119 | ] 2120 | }, 2121 | "line-translate": { 2122 | "type": "array", 2123 | "value": "number", 2124 | "length": 2, 2125 | "default": [ 2126 | 0, 2127 | 0 2128 | ], 2129 | "function": "interpolated", 2130 | "transition": true, 2131 | "units": "pixels", 2132 | "doc": "The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively." 2133 | }, 2134 | "line-translate-anchor": { 2135 | "type": "enum", 2136 | "function": "piecewise-constant", 2137 | "values": [ 2138 | "map", 2139 | "viewport" 2140 | ], 2141 | "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", 2142 | "default": "map", 2143 | "requires": [ 2144 | "line-translate" 2145 | ] 2146 | }, 2147 | "line-width": { 2148 | "type": "number", 2149 | "default": 1, 2150 | "minimum": 0, 2151 | "function": "interpolated", 2152 | "transition": true, 2153 | "units": "pixels", 2154 | "doc": "Stroke thickness." 2155 | }, 2156 | "line-gap-width": { 2157 | "type": "number", 2158 | "default": 0, 2159 | "minimum": 0, 2160 | "doc": "Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.", 2161 | "function": "interpolated", 2162 | "transition": true, 2163 | "units": "pixels" 2164 | }, 2165 | "line-blur": { 2166 | "type": "number", 2167 | "default": 0, 2168 | "minimum": 0, 2169 | "function": "interpolated", 2170 | "transition": true, 2171 | "units": "pixels", 2172 | "doc": "Blur applied to the line, in pixels." 2173 | }, 2174 | "line-dasharray": { 2175 | "type": "array", 2176 | "function": "piecewise-constant", 2177 | "value": "number", 2178 | "doc": "Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to pixels, multiply the length by the current line width.", 2179 | "minimum": 0, 2180 | "transition": true, 2181 | "units": "line widths", 2182 | "requires": [ 2183 | { 2184 | "!": "line-image" 2185 | } 2186 | ] 2187 | }, 2188 | "line-image": { 2189 | "type": "string", 2190 | "function": "piecewise-constant", 2191 | "transition": true, 2192 | "doc": "Name of image in sprite to use for drawing image lines." 2193 | } 2194 | }, 2195 | "paint_symbol": { 2196 | "icon-opacity": { 2197 | "doc": "The opacity at which the icon will be drawn.", 2198 | "type": "number", 2199 | "default": 1, 2200 | "minimum": 0, 2201 | "maximum": 1, 2202 | "function": "interpolated", 2203 | "transition": true, 2204 | "requires": [ 2205 | "icon-image" 2206 | ] 2207 | }, 2208 | "icon-size": { 2209 | "type": "number", 2210 | "default": 1, 2211 | "function": "interpolated", 2212 | "transition": true, 2213 | "doc": "Scale factor for icon. 1 is original size, 3 triples the size.", 2214 | "requires": [ 2215 | "icon-image" 2216 | ] 2217 | }, 2218 | "icon-color": { 2219 | "type": "color", 2220 | "default": "#000000", 2221 | "function": "interpolated", 2222 | "transition": true, 2223 | "doc": "The color of the icon. This can only be used with sdf icons.", 2224 | "requires": [ 2225 | "icon-image" 2226 | ] 2227 | }, 2228 | "icon-halo-color": { 2229 | "type": "color", 2230 | "default": "rgba(0, 0, 0, 0)", 2231 | "function": "interpolated", 2232 | "transition": true, 2233 | "doc": "The color of the icon's halo. Icon halos can only be used with sdf icons.", 2234 | "requires": [ 2235 | "icon-image" 2236 | ] 2237 | }, 2238 | "icon-halo-width": { 2239 | "type": "number", 2240 | "default": 0, 2241 | "minimum": 0, 2242 | "function": "interpolated", 2243 | "transition": true, 2244 | "units": "pixels", 2245 | "doc": "Distance of halo to the icon outline.", 2246 | "requires": [ 2247 | "icon-image" 2248 | ] 2249 | }, 2250 | "icon-halo-blur": { 2251 | "type": "number", 2252 | "default": 0, 2253 | "minimum": 0, 2254 | "function": "interpolated", 2255 | "transition": true, 2256 | "units": "pixels", 2257 | "doc": "Fade out the halo towards the outside.", 2258 | "requires": [ 2259 | "icon-image" 2260 | ] 2261 | }, 2262 | "icon-translate": { 2263 | "type": "array", 2264 | "value": "number", 2265 | "length": 2, 2266 | "default": [ 2267 | 0, 2268 | 0 2269 | ], 2270 | "function": "interpolated", 2271 | "transition": true, 2272 | "units": "pixels", 2273 | "doc": "An icon's offset distance. Values are [x, y] where negatives indicate left and up, respectively.", 2274 | "requires": [ 2275 | "icon-image" 2276 | ] 2277 | }, 2278 | "icon-translate-anchor": { 2279 | "type": "enum", 2280 | "function": "piecewise-constant", 2281 | "values": [ 2282 | "map", 2283 | "viewport" 2284 | ], 2285 | "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", 2286 | "default": "map", 2287 | "requires": [ 2288 | "icon-image", 2289 | "icon-translate" 2290 | ] 2291 | }, 2292 | "text-opacity": { 2293 | "type": "number", 2294 | "doc": "The opacity at which the text will be drawn.", 2295 | "default": 1, 2296 | "minimum": 0, 2297 | "maximum": 1, 2298 | "function": "interpolated", 2299 | "transition": true, 2300 | "requires": [ 2301 | "text-field" 2302 | ] 2303 | }, 2304 | "text-size": { 2305 | "type": "number", 2306 | "default": 16, 2307 | "minimum": 0, 2308 | "function": "interpolated", 2309 | "transition": true, 2310 | "units": "pixels", 2311 | "doc": "Font size. If unspecified, the text will be as big as allowed by the layer definition.", 2312 | "requires": [ 2313 | "text-field" 2314 | ] 2315 | }, 2316 | "text-color": { 2317 | "type": "color", 2318 | "doc": "The color with which the text will be drawn.", 2319 | "default": "#000000", 2320 | "function": "interpolated", 2321 | "transition": true, 2322 | "requires": [ 2323 | "text-field" 2324 | ] 2325 | }, 2326 | "text-halo-color": { 2327 | "type": "color", 2328 | "default": "rgba(0, 0, 0, 0)", 2329 | "function": "interpolated", 2330 | "transition": true, 2331 | "doc": "The color of the text's halo, which helps it stand out from backgrounds.", 2332 | "requires": [ 2333 | "text-field" 2334 | ] 2335 | }, 2336 | "text-halo-width": { 2337 | "type": "number", 2338 | "default": 0, 2339 | "minimum": 0, 2340 | "function": "interpolated", 2341 | "transition": true, 2342 | "units": "pixels", 2343 | "doc": "Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.", 2344 | "requires": [ 2345 | "text-field" 2346 | ] 2347 | }, 2348 | "text-halo-blur": { 2349 | "type": "number", 2350 | "default": 0, 2351 | "minimum": 0, 2352 | "function": "interpolated", 2353 | "transition": true, 2354 | "units": "pixels", 2355 | "doc": "The halo's fadeout distance towards the outside.", 2356 | "requires": [ 2357 | "text-field" 2358 | ] 2359 | }, 2360 | "text-translate": { 2361 | "type": "array", 2362 | "value": "number", 2363 | "length": 2, 2364 | "default": [ 2365 | 0, 2366 | 0 2367 | ], 2368 | "function": "interpolated", 2369 | "transition": true, 2370 | "units": "pixels", 2371 | "doc": "Label offset. Values are [x, y] where negatives indicate left and up, respectively.", 2372 | "requires": [ 2373 | "text-field" 2374 | ] 2375 | }, 2376 | "text-translate-anchor": { 2377 | "type": "enum", 2378 | "function": "piecewise-constant", 2379 | "values": [ 2380 | "map", 2381 | "viewport" 2382 | ], 2383 | "doc": "Control whether the translation is relative to the map (north) or viewport (screen)", 2384 | "default": "map", 2385 | "requires": [ 2386 | "text-field", 2387 | "text-translate" 2388 | ] 2389 | } 2390 | }, 2391 | "paint_raster": { 2392 | "raster-opacity": { 2393 | "type": "number", 2394 | "doc": "The opacity at which the image will be drawn.", 2395 | "default": 1, 2396 | "minimum": 0, 2397 | "maximum": 1, 2398 | "function": "interpolated", 2399 | "transition": true 2400 | }, 2401 | "raster-hue-rotate": { 2402 | "type": "number", 2403 | "default": 0, 2404 | "period": 360, 2405 | "function": "interpolated", 2406 | "transition": true, 2407 | "units": "degrees", 2408 | "doc": "Rotates hues around the color wheel." 2409 | }, 2410 | "raster-brightness-min": { 2411 | "type": "number", 2412 | "function": "interpolated", 2413 | "doc": "Increase or reduce the brightness of the image. The value is the minimum brightness.", 2414 | "default": 0, 2415 | "minimum": 0, 2416 | "maximum": 1, 2417 | "transition": true 2418 | }, 2419 | "raster-brightness-max": { 2420 | "type": "number", 2421 | "function": "interpolated", 2422 | "doc": "Increase or reduce the brightness of the image. The value is the maximum brightness.", 2423 | "default": 1, 2424 | "minimum": 0, 2425 | "maximum": 1, 2426 | "transition": true 2427 | }, 2428 | "raster-saturation": { 2429 | "type": "number", 2430 | "doc": "Increase or reduce the saturation of the image.", 2431 | "default": 0, 2432 | "minimum": -1, 2433 | "maximum": 1, 2434 | "function": "interpolated", 2435 | "transition": true 2436 | }, 2437 | "raster-contrast": { 2438 | "type": "number", 2439 | "doc": "Increase or reduce the contrast of the image.", 2440 | "default": 0, 2441 | "minimum": -1, 2442 | "maximum": 1, 2443 | "function": "interpolated", 2444 | "transition": true 2445 | }, 2446 | "raster-fade-duration": { 2447 | "type": "number", 2448 | "default": 300, 2449 | "minimum": 0, 2450 | "function": "interpolated", 2451 | "transition": true, 2452 | "units": "milliseconds", 2453 | "doc": "Fade duration when a new tile is added." 2454 | } 2455 | }, 2456 | "paint_background": { 2457 | "background-color": { 2458 | "type": "color", 2459 | "default": "#000000", 2460 | "doc": "The color with which the background will be drawn.", 2461 | "function": "interpolated", 2462 | "transition": true, 2463 | "requires": [ 2464 | { 2465 | "!": "background-image" 2466 | } 2467 | ] 2468 | }, 2469 | "background-image": { 2470 | "type": "string", 2471 | "function": "piecewise-constant", 2472 | "transition": true, 2473 | "doc": "Optionally an image which is drawn as the background." 2474 | }, 2475 | "background-opacity": { 2476 | "type": "number", 2477 | "default": 1, 2478 | "minimum": 0, 2479 | "maximum": 1, 2480 | "doc": "The opacity at which the background will be drawn.", 2481 | "function": "interpolated", 2482 | "transition": true 2483 | } 2484 | }, 2485 | "transition": { 2486 | "duration": { 2487 | "type": "number", 2488 | "default": 300, 2489 | "minimum": 0, 2490 | "units": "milliseconds", 2491 | "doc": "Time allotted for transitions to complete." 2492 | }, 2493 | "delay": { 2494 | "type": "number", 2495 | "default": 0, 2496 | "minimum": 0, 2497 | "units": "milliseconds", 2498 | "doc": "Length of time before a transition begins." 2499 | } 2500 | } 2501 | } 2502 | 2503 | },{}],"mapbox-gl-style-spec/lib/validate/latest":[function(require,module,exports){ 2504 | 'use strict'; 2505 | 2506 | var reference = require('../../reference/latest.js'); 2507 | var validate = require('./parsed'); 2508 | 2509 | module.exports = function(style) { 2510 | return validate(style, reference); 2511 | }; 2512 | 2513 | },{"../../reference/latest.js":7,"./parsed":5}]},{},[])("mapbox-gl-style-spec/lib/validate/latest") 2514 | }); -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | // extra input formats we want to support, to let 3 | // people add comments and drop extra gunk from stylesheets. 4 | json5 = require('gulp-json5'), 5 | yaml = require('gulp-yaml'), 6 | toml = require('gulp-toml'), 7 | through2 = require('through2'), 8 | exec = require('gulp-exec'), 9 | rename = require('gulp-rename'), 10 | connect = require('gulp-connect'); 11 | 12 | var path = require('path'), 13 | minimist = require('minimist'); 14 | 15 | var options = minimist(process.argv.slice(2), { 16 | string: 'style', 17 | default: { style: 'style.json' } 18 | }); 19 | 20 | gulp.task('connect', function() { 21 | connect.server({ 22 | root: 'app', 23 | livereload: true 24 | }); 25 | }); 26 | 27 | gulp.task('html', function() { 28 | gulp.src(['./app/*.html', options.style]) 29 | .pipe(connect.reload()); 30 | }); 31 | 32 | gulp.task('watch', function() { 33 | gulp.watch(['./app/*.html', options.style], 34 | ['compile', 'html']); 35 | }); 36 | 37 | gulp.task('compile', function() { 38 | switch (path.extname(options.style)) { 39 | case '.json5': 40 | return gulp.src(options.style) 41 | .pipe(json5()) 42 | .pipe(gulp.dest('app')); 43 | case '.yaml': 44 | case '.yml': 45 | return gulp.src(options.style) 46 | .pipe(yaml({ space: 4 })) 47 | .pipe(gulp.dest('app')); 48 | case '.js': 49 | return gulp.src(options.style) 50 | .pipe(exec('<%= file.path %>', { pipeStdout: true, continueOnError: true })) 51 | .pipe(through2.obj(function(file, enc, cb) { 52 | if (!file.exec.stdout && file.exec.stderr) { 53 | file.contents = new Buffer(JSON.stringify({ error: file.exec.stderr })); 54 | } 55 | cb(null, file); 56 | })) 57 | .pipe(rename({ basename: 'style', extname: '.json' })) 58 | .pipe(gulp.dest('app')); 59 | case '.toml': 60 | return gulp.src(options.style) 61 | .pipe(toml()) 62 | .pipe(gulp.dest('app')); 63 | case '.json': 64 | default: 65 | return gulp.src(options.style) 66 | .pipe(gulp.dest('app')); 67 | } 68 | }); 69 | 70 | gulp.task('default', ['connect', 'watch', 'compile']); 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mapbox-gl-codeflow-example", 3 | "version": "1.0.0", 4 | "description": "an example of using mapbox gl to style vector tiles by hand", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "mapbox", 11 | "gl", 12 | "codeflow", 13 | "example", 14 | "cli", 15 | "maps" 16 | ], 17 | "author": "Tom MacWright", 18 | "license": "ISC", 19 | "devDependencies": { 20 | "chroma-js": "^1.1.1", 21 | "gulp": "^3.9.0", 22 | "gulp-connect": "^2.2.0", 23 | "gulp-exec": "^2.1.1", 24 | "gulp-json5": "0.0.2", 25 | "gulp-rename": "^1.2.2", 26 | "gulp-yaml": "^0.2.4", 27 | "mapbox-gl-style-spec": "^7.4.1", 28 | "minimist": "^1.1.3", 29 | "through2": "^2.0.0" 30 | }, 31 | "dependencies": { 32 | "gulp-toml": "^0.1.1", 33 | "minimist": "^1.1.3" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /style.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // An example of generating a style from a node.js script. 4 | // Since this is a fully-functional imperative language, we can use 5 | // modules, constants, and the like. 6 | var chroma = require('chroma-js'); 7 | 8 | var WATER_COLOR = '#ace'; 9 | var BACKGROUND = chroma(WATER_COLOR).darken().hex(); 10 | 11 | var style = { 12 | 'version': 7, 13 | 'name': 'Basic', 14 | 'constants': {}, 15 | 'sources': { 16 | 'mapbox': { 17 | 'type': 'vector', 18 | 'url': 'mapbox://mapbox.mapbox-streets-v6' 19 | } 20 | }, 21 | 'sprite': '', 22 | 'glyphs': '', 23 | 'layers': [{ 24 | 'id': 'background', 25 | 'type': 'background', 26 | 'paint': { 27 | 'background-color': BACKGROUND 28 | } 29 | }, { 30 | 'id': 'water', 31 | 'type': 'fill', 32 | 'source': 'mapbox', 33 | 'source-layer': 'water', 34 | 'paint': { 35 | 'fill-color': WATER_COLOR 36 | } 37 | }] 38 | }; 39 | 40 | process.stdout.write(JSON.stringify(style, null, 4)); 41 | -------------------------------------------------------------------------------- /style.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 7, 3 | "name": "Basic", 4 | "constants": {}, 5 | "sources": { 6 | "mapbox": { 7 | "type": "vector", 8 | "url": "mapbox://mapbox.mapbox-streets-v6" 9 | } 10 | }, 11 | "sprite": "", 12 | "glyphs": "", 13 | "layers": [{ 14 | "id": "background", 15 | "type": "background", 16 | "paint": { 17 | "background-color": "#000" 18 | } 19 | }, { 20 | "id": "water", 21 | "type": "fill", 22 | "source": "mapbox", 23 | "source-layer": "water", 24 | "paint": { 25 | "fill-color": "#f0f" 26 | } 27 | }] 28 | } 29 | -------------------------------------------------------------------------------- /style.json5: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a JSON5 version of a style: unlike a normal JSON 3 | * style, it can have comments, single quotes, no quotes (where appropriate) 4 | * and trailing commas. See json5.org for the whole documentation. 5 | */ 6 | { 7 | version: 7, 8 | // This is the basic style 9 | name: 'Basic', 10 | // Here are our constants 11 | constants: {}, 12 | // Here are the sources 13 | sources: { 14 | mapbox: { 15 | type: 'vector', 16 | url: 'mapbox://mapbox.mapbox-streets-v6' 17 | } 18 | }, 19 | sprite: '', 20 | glyphs: '', 21 | layers: [{ 22 | id: 'background', 23 | type: 'background', 24 | paint: { 25 | 'background-color': '#ff0' 26 | } 27 | }, { 28 | id: 'water', 29 | type: 'fill', 30 | source: 'mapbox', 31 | 'source-layer': 'water', 32 | paint: { 33 | 'fill-color': '#f0f', 34 | 'fill-opacity': 0.8 35 | } 36 | }] 37 | } 38 | -------------------------------------------------------------------------------- /style.toml: -------------------------------------------------------------------------------- 1 | # This is a TOML version of a style. 2 | # See https://github.com/toml-lang/toml for full details 3 | version = 7 4 | # This is the basic style 5 | name = 'Basic' 6 | # Here are our constants 7 | constants = {} 8 | sprite = '' 9 | glyphs = '' 10 | # Here are the sources 11 | [sources.mapbox] 12 | type = 'vector' 13 | url = 'mapbox://mapbox.mapbox-streets-v6' 14 | [[layers]] 15 | id = 'background' 16 | type = 'background' 17 | [layers.paint] 18 | background-color = '#f0f' 19 | [[layers]] 20 | id = 'water' 21 | type = 'fill' 22 | source = 'mapbox' 23 | source-layer = 'water' 24 | [layers.paint] 25 | fill-color = '#fff' 26 | fill-opacity = 1 27 | -------------------------------------------------------------------------------- /style.yml: -------------------------------------------------------------------------------- 1 | # This is a YML version of a style. 2 | version: 7 3 | # This is the basic style 4 | name: 'Basic' 5 | # Here are our constants 6 | constants: {} 7 | # Here are the sources 8 | sources: 9 | mapbox: 10 | type: 'vector' 11 | url: 'mapbox://mapbox.mapbox-streets-v6' 12 | sprite: '' 13 | glyphs: '' 14 | layers: 15 | - id: 'background' 16 | type: 'background' 17 | paint: 18 | 'background-color': '#ff0' 19 | - id: 'water' 20 | type: 'fill' 21 | source: 'mapbox' 22 | 'source-layer': 'water' 23 | paint: 24 | 'fill-color': '#f0f' 25 | 'fill-opacity': 0.8 26 | --------------------------------------------------------------------------------