@mapbox/mapbox-gl-style-spec 13.19.2 → 13.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mapbox/mapbox-gl-style-spec",
3
3
  "description": "a specification for mapbox gl styles",
4
- "version": "13.19.2",
4
+ "version": "13.21.0",
5
5
  "author": "Mapbox",
6
6
  "keywords": [
7
7
  "mapbox",
@@ -9,14 +9,23 @@
9
9
  "mapbox-gl-js"
10
10
  ],
11
11
  "license": "ISC",
12
- "main": "./dist/index.js",
12
+ "main": "./dist/index.cjs",
13
13
  "module": "./dist/index.es.js",
14
14
  "type": "module",
15
+ "exports": {
16
+ ".": {
17
+ "require": "./dist/index.cjs",
18
+ "import": "./dist/index.es.js"
19
+ },
20
+ "./": {
21
+ "import": "./"
22
+ }
23
+ },
15
24
  "scripts": {
16
25
  "copy-flow-typed": "cp -R ../../flow-typed .",
17
26
  "build": "../../node_modules/.bin/rollup -c && ../../node_modules/.bin/rollup -c --environment esm",
18
27
  "prepublishOnly": "git clean -fdx && yarn copy-flow-typed && yarn build",
19
- "postpublish": "rm -r flow-typed dist/index.js"
28
+ "postpublish": "rm -r flow-typed dist/index.cjs"
20
29
  },
21
30
  "repository": {
22
31
  "type": "git",
package/reference/v8.json CHANGED
@@ -61,6 +61,10 @@
61
61
  "type": "terrain",
62
62
  "doc": "A global modifier that elevates layers and markers based on a DEM data source."
63
63
  },
64
+ "fog": {
65
+ "type": "fog",
66
+ "doc": "A global effect that fades layers and markers based on their distance to the camera. The fog can be used to approximate the effect of atmosphere on distant objects and enhance the depth perception of the map when used with terrain or 3D features."
67
+ },
64
68
  "sources": {
65
69
  "required": true,
66
70
  "type": "sources",
@@ -612,7 +616,9 @@
612
616
  "doc": "A spherical dome around the map that is always rendered behind all other layers.",
613
617
  "sdk-support": {
614
618
  "basic functionality": {
615
- "js": "2.0.0"
619
+ "js": "2.0.0",
620
+ "ios": "10.0.0",
621
+ "android": "10.0.0"
616
622
  }
617
623
  }
618
624
  }
@@ -708,7 +714,9 @@
708
714
  "doc": "Whether this layer is displayed.",
709
715
  "sdk-support": {
710
716
  "basic functionality": {
711
- "js": "2.0.0"
717
+ "js": "2.0.0",
718
+ "ios": "10.0.0",
719
+ "android": "10.0.0"
712
720
  }
713
721
  },
714
722
  "property-type": "constant"
@@ -884,15 +892,19 @@
884
892
  "android": "2.0.1",
885
893
  "ios": "2.0.0",
886
894
  "macos": "0.1.0"
895
+ },
896
+ "data-driven styling": {
897
+ "js": "2.3.0"
887
898
  }
888
899
  },
889
900
  "expression": {
890
901
  "interpolated": false,
891
902
  "parameters": [
892
- "zoom"
903
+ "zoom",
904
+ "feature"
893
905
  ]
894
906
  },
895
- "property-type": "data-constant"
907
+ "property-type": "data-driven"
896
908
  },
897
909
  "line-join": {
898
910
  "type": "enum",
@@ -1823,7 +1835,12 @@
1823
1835
  "units": "ems",
1824
1836
  "doc": "The maximum line width for text wrapping.",
1825
1837
  "requires": [
1826
- "text-field"
1838
+ "text-field",
1839
+ {
1840
+ "symbol-placement": [
1841
+ "point"
1842
+ ]
1843
+ }
1827
1844
  ],
1828
1845
  "sdk-support": {
1829
1846
  "basic functionality": {
@@ -1862,15 +1879,19 @@
1862
1879
  "android": "2.0.1",
1863
1880
  "ios": "2.0.0",
1864
1881
  "macos": "0.1.0"
1882
+ },
1883
+ "data-driven styling": {
1884
+ "js": "2.3.0"
1865
1885
  }
1866
1886
  },
1867
1887
  "expression": {
1868
1888
  "interpolated": true,
1869
1889
  "parameters": [
1870
- "zoom"
1890
+ "zoom",
1891
+ "feature"
1871
1892
  ]
1872
1893
  },
1873
- "property-type": "data-constant"
1894
+ "property-type": "data-driven"
1874
1895
  },
1875
1896
  "text-letter-spacing": {
1876
1897
  "type": "number",
@@ -2138,20 +2159,15 @@
2138
2159
  "value": "enum",
2139
2160
  "values": {
2140
2161
  "horizontal": {
2141
- "doc": "If a text's language supports horizontal writing mode, symbols with point placement would be laid out horizontally."
2162
+ "doc": "If a text's language supports horizontal writing mode, symbols would be laid out horizontally."
2142
2163
  },
2143
2164
  "vertical": {
2144
- "doc": "If a text's language supports vertical writing mode, symbols with point placement would be laid out vertically."
2165
+ "doc": "If a text's language supports vertical writing mode, symbols would be laid out vertically."
2145
2166
  }
2146
2167
  },
2147
- "doc": "The property allows control over a symbol's orientation. Note that the property values act as a hint, so that a symbol whose language doesn’t support the provided orientation will be laid out in its natural orientation. Example: English point symbol will be rendered horizontally even if array value contains single 'vertical' enum value. The order of elements in an array define priority order for the placement of an orientation variant.",
2168
+ "doc": "The property allows control over a symbol's orientation. Note that the property values act as a hint, so that a symbol whose language doesn’t support the provided orientation will be laid out in its natural orientation. Example: English point symbol will be rendered horizontally even if array value contains single 'vertical' enum value. For symbol with point placement, the order of elements in an array define priority order for the placement of an orientation variant. For symbol with line placement, the default text writing mode is either ['horizontal', 'vertical'] or ['vertical', 'horizontal'], the order doesn't affect the placement.",
2148
2169
  "requires": [
2149
- "text-field",
2150
- {
2151
- "symbol-placement": [
2152
- "point"
2153
- ]
2154
- }
2170
+ "text-field"
2155
2171
  ],
2156
2172
  "sdk-support": {
2157
2173
  "basic functionality": {
@@ -2691,7 +2707,7 @@
2691
2707
  }
2692
2708
  },
2693
2709
  "in": {
2694
- "doc": "Determines whether an item exists in an array or a substring exists in a string.",
2710
+ "doc": "Determines whether an item exists in an array or a substring exists in a string. In the specific case when the second and third arguments are string literals, you must wrap at least one of them in a [`literal`](#types-literal) expression to hint correct interpretation to the [type system](#type-system).",
2695
2711
  "group": "Lookup",
2696
2712
  "sdk-support": {
2697
2713
  "basic functionality": {
@@ -2733,7 +2749,7 @@
2733
2749
  }
2734
2750
  },
2735
2751
  "match": {
2736
- "doc": "Selects the output whose label value matches the input value, or the fallback value if no match is found. The input can be any expression (e.g. `[\"get\", \"building_type\"]`). Each label must be either:\n - a single literal value; or\n - an array of literal values, whose values must be all strings or all numbers (e.g. `[100, 101]` or `[\"c\", \"b\"]`). The input matches if any of the values in the array matches, similar to the `\"in\"` operator.\nEach label must be unique. If the input type does not match the type of the labels, the result will be the fallback value.",
2752
+ "doc": "Selects the output for which the label value matches the input value, or the fallback value if no match is found. The input can be any expression (for example, `[\"get\", \"building_type\"]`). Each label must be unique, and must be either:\n - a single literal value; or\n - an array of literal values, the values of which must be all strings or all numbers (for example `[100, 101]` or `[\"c\", \"b\"]`).\n\nThe input matches if any of the values in the array matches using strict equality, similar to the `\"in\"` operator.\nIf the input type does not match the type of the labels, the result will be the fallback value.",
2737
2753
  "group": "Decision",
2738
2754
  "sdk-support": {
2739
2755
  "basic functionality": {
@@ -2959,7 +2975,10 @@
2959
2975
  "group": "Types",
2960
2976
  "sdk-support": {
2961
2977
  "basic functionality": {
2962
- "js": "0.54.0"
2978
+ "js": "0.54.0",
2979
+ "android" : "8.4.0",
2980
+ "ios": "5.4.0",
2981
+ "macos": "0.15.0"
2963
2982
  }
2964
2983
  }
2965
2984
  },
@@ -3105,7 +3124,7 @@
3105
3124
  }
3106
3125
  },
3107
3126
  "geometry-type": {
3108
- "doc": "Gets the feature's geometry type: `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`.",
3127
+ "doc": "Gets the feature's geometry type: `Point`, `MultiPoint`, `LineString`, `MultiLineString`, `Polygon`, `MultiPolygon`. `Multi*` feature types are only returned in GeoJSON sources. When working with vector tile sources, use the singular forms.",
3109
3128
  "group": "Feature data",
3110
3129
  "sdk-support": {
3111
3130
  "basic functionality": {
@@ -3169,7 +3188,9 @@
3169
3188
  "group": "sky",
3170
3189
  "sdk-support": {
3171
3190
  "basic functionality": {
3172
- "js": "2.0.0"
3191
+ "js": "2.0.0",
3192
+ "ios": "10.0.0",
3193
+ "android": "10.0.0"
3173
3194
  }
3174
3195
  }
3175
3196
  },
@@ -3178,7 +3199,10 @@
3178
3199
  "group": "Feature data",
3179
3200
  "sdk-support": {
3180
3201
  "basic functionality": {
3181
- "js": "0.53.0"
3202
+ "js": "0.53.0",
3203
+ "android": "8.4.0",
3204
+ "ios": "5.5.0",
3205
+ "macos": "0.15.0"
3182
3206
  }
3183
3207
  }
3184
3208
  },
@@ -3673,6 +3697,75 @@
3673
3697
  }
3674
3698
  }
3675
3699
  },
3700
+ "fog": {
3701
+ "range": {
3702
+ "type": "array",
3703
+ "default": [
3704
+ 0.5,
3705
+ 10
3706
+ ],
3707
+ "minimum": -20,
3708
+ "maximum": 20,
3709
+ "length": 2,
3710
+ "value": "number",
3711
+ "property-type": "data-constant",
3712
+ "transition": true,
3713
+ "expression": {
3714
+ "interpolated": true,
3715
+ "parameters": [
3716
+ "zoom"
3717
+ ]
3718
+ },
3719
+ "doc": "The start and end distance range in which fog fades from fully transparent to fully opaque. The distance to the point at the center of the map is defined as zero, so that negative range values are closer to the camera, and positive values are farther away.",
3720
+ "example": [
3721
+ 0.5,
3722
+ 10
3723
+ ],
3724
+ "sdk-support": {
3725
+ "basic functionality": {
3726
+ "js": "2.3.0"
3727
+ }
3728
+ }
3729
+ },
3730
+ "color": {
3731
+ "type": "color",
3732
+ "property-type": "data-constant",
3733
+ "default": "#ffffff",
3734
+ "expression": {
3735
+ "interpolated": true,
3736
+ "parameters": [
3737
+ "zoom"
3738
+ ]
3739
+ },
3740
+ "transition": true,
3741
+ "doc": "The color of the fog. Using opacity is recommended only for smoothly transitioning fog on/off as anything less than 100% opacity results in more tiles loaded and drawn.",
3742
+ "sdk-support": {
3743
+ "basic functionality": {
3744
+ "js": "2.3.0"
3745
+ }
3746
+ }
3747
+ },
3748
+ "horizon-blend": {
3749
+ "type": "number",
3750
+ "property-type": "data-constant",
3751
+ "default": 0.1,
3752
+ "minimum": 0,
3753
+ "maximum": 1,
3754
+ "expression": {
3755
+ "interpolated": true,
3756
+ "parameters": [
3757
+ "zoom"
3758
+ ]
3759
+ },
3760
+ "transition": true,
3761
+ "doc": "Horizon blend applies a smooth fade from the color of the fog to the color of the sky. A value of zero leaves a sharp transition from fog to sky. Increasing the value blends the color of fog into increasingly high angles of the sky.",
3762
+ "sdk-support": {
3763
+ "basic functionality": {
3764
+ "js": "2.3.0"
3765
+ }
3766
+ }
3767
+ }
3768
+ },
3676
3769
  "light": {
3677
3770
  "anchor": {
3678
3771
  "type": "enum",
@@ -3788,7 +3881,9 @@
3788
3881
  "required": true,
3789
3882
  "sdk-support": {
3790
3883
  "basic functionality": {
3791
- "js": "2.0.0"
3884
+ "js": "2.0.0",
3885
+ "ios": "10.0.0",
3886
+ "android": "10.0.0"
3792
3887
  }
3793
3888
  }
3794
3889
  },
@@ -3808,7 +3903,9 @@
3808
3903
  "doc": "Exaggerates the elevation of the terrain by multiplying the data from the DEM with this value.",
3809
3904
  "sdk-support": {
3810
3905
  "basic functionality": {
3811
- "js": "2.0.0"
3906
+ "js": "2.0.0",
3907
+ "ios": "10.0.0",
3908
+ "android": "10.0.0"
3812
3909
  }
3813
3910
  }
3814
3911
  }
@@ -4249,6 +4346,7 @@
4249
4346
  "sdk-support": {
4250
4347
  "basic functionality": {
4251
4348
  "js": "0.50.0",
4349
+ "android": "7.0.0",
4252
4350
  "ios": "4.7.0",
4253
4351
  "macos": "0.13.0"
4254
4352
  }
@@ -4528,15 +4626,18 @@
4528
4626
  "ios": "2.0.0",
4529
4627
  "macos": "0.1.0"
4530
4628
  },
4531
- "data-driven styling": {}
4629
+ "data-driven styling": {
4630
+ "js": "2.3.0"
4631
+ }
4532
4632
  },
4533
4633
  "expression": {
4534
4634
  "interpolated": false,
4535
4635
  "parameters": [
4536
- "zoom"
4636
+ "zoom",
4637
+ "feature"
4537
4638
  ]
4538
4639
  },
4539
- "property-type": "cross-faded"
4640
+ "property-type": "cross-faded-data-driven"
4540
4641
  },
4541
4642
  "line-pattern": {
4542
4643
  "type": "resolvedImage",
@@ -5954,7 +6055,9 @@
5954
6055
  "doc": "The type of the sky",
5955
6056
  "sdk-support": {
5956
6057
  "basic functionality": {
5957
- "js": "2.0.0"
6058
+ "js": "2.0.0",
6059
+ "ios": "10.0.0",
6060
+ "android": "10.0.0"
5958
6061
  }
5959
6062
  },
5960
6063
  "expression": {
@@ -5976,7 +6079,9 @@
5976
6079
  "doc": "Position of the sun center [a azimuthal angle, p polar angle]. The azimuthal angle indicates the position of the sun relative to 0° north, where degrees proceed clockwise. The polar angle indicates the height of the sun, where 0° is directly above, at zenith, and 90° at the horizon. When this property is ommitted, the sun center is directly inherited from the light position.",
5977
6080
  "sdk-support": {
5978
6081
  "basic functionality": {
5979
- "js": "2.0.0"
6082
+ "js": "2.0.0",
6083
+ "ios": "10.0.0",
6084
+ "android": "10.0.0"
5980
6085
  }
5981
6086
  },
5982
6087
  "requires": [
@@ -6006,7 +6111,9 @@
6006
6111
  "doc": "Intensity of the sun as a light source in the atmosphere (on a scale from 0 to a 100). Setting higher values will brighten up the sky.",
6007
6112
  "sdk-support": {
6008
6113
  "basic functionality": {
6009
- "js": "2.0.0"
6114
+ "js": "2.0.0",
6115
+ "ios": "10.0.0",
6116
+ "android": "10.0.0"
6010
6117
  }
6011
6118
  },
6012
6119
  "property-type": "data-constant"
@@ -6031,7 +6138,9 @@
6031
6138
  "doc": "Position of the gradient center [a azimuthal angle, p polar angle]. The azimuthal angle indicates the position of the gradient center relative to 0° north, where degrees proceed clockwise. The polar angle indicates the height of the gradient center, where 0° is directly above, at zenith, and 90° at the horizon.",
6032
6139
  "sdk-support": {
6033
6140
  "basic functionality": {
6034
- "js": "2.0.0"
6141
+ "js": "2.0.0",
6142
+ "ios": "10.0.0",
6143
+ "android": "10.0.0"
6035
6144
  }
6036
6145
  },
6037
6146
  "expression": {
@@ -6056,7 +6165,9 @@
6056
6165
  "doc": "The angular distance (measured in degrees) from `sky-gradient-center` up to which the gradient extends. A value of 180 causes the gradient to wrap around to the opposite direction from `sky-gradient-center`.",
6057
6166
  "sdk-support": {
6058
6167
  "basic functionality": {
6059
- "js": "2.0.0"
6168
+ "js": "2.0.0",
6169
+ "ios": "10.0.0",
6170
+ "android": "10.0.0"
6060
6171
  }
6061
6172
  },
6062
6173
  "expression": {
@@ -6091,7 +6202,9 @@
6091
6202
  ],
6092
6203
  "sdk-support": {
6093
6204
  "basic functionality": {
6094
- "js": "2.0.0"
6205
+ "js": "2.0.0",
6206
+ "ios": "10.0.0",
6207
+ "android": "10.0.0"
6095
6208
  },
6096
6209
  "data-driven styling": {}
6097
6210
  },
@@ -6115,7 +6228,9 @@
6115
6228
  ],
6116
6229
  "sdk-support": {
6117
6230
  "basic functionality": {
6118
- "js": "2.0.0"
6231
+ "js": "2.0.0",
6232
+ "ios": "10.0.0",
6233
+ "android": "10.0.0"
6119
6234
  }
6120
6235
  },
6121
6236
  "property-type": "data-constant"
@@ -6132,7 +6247,9 @@
6132
6247
  ],
6133
6248
  "sdk-support": {
6134
6249
  "basic functionality": {
6135
- "js": "2.0.0"
6250
+ "js": "2.0.0",
6251
+ "ios": "10.0.0",
6252
+ "android": "10.0.0"
6136
6253
  }
6137
6254
  },
6138
6255
  "property-type": "data-constant"
@@ -6146,7 +6263,9 @@
6146
6263
  "transition": true,
6147
6264
  "sdk-support": {
6148
6265
  "basic functionality": {
6149
- "js": "2.0.0"
6266
+ "js": "2.0.0",
6267
+ "ios": "10.0.0",
6268
+ "android": "10.0.0"
6150
6269
  }
6151
6270
  },
6152
6271
  "expression": {
package/rollup.config.js CHANGED
@@ -16,7 +16,7 @@ const config = [{
16
16
  input: `${__dirname}/style-spec.js`,
17
17
  output: {
18
18
  name: 'mapboxGlStyleSpecification',
19
- file: `${__dirname}/dist/${esm ? 'index.es.js' : 'index.js'}`,
19
+ file: `${__dirname}/dist/${esm ? 'index.es.js' : 'index.cjs'}`,
20
20
  format: esm ? 'esm' : 'umd',
21
21
  sourcemap: true
22
22
  },
package/types.js CHANGED
@@ -67,6 +67,7 @@ export type StyleSpecification = {|
67
67
  "pitch"?: number,
68
68
  "light"?: LightSpecification,
69
69
  "terrain"?: TerrainSpecification,
70
+ "fog"?: FogSpecification,
70
71
  "sources": {[_: string]: SourceSpecification},
71
72
  "sprite"?: string,
72
73
  "glyphs"?: string,
@@ -86,6 +87,12 @@ export type TerrainSpecification = {|
86
87
  "exaggeration"?: PropertyValueSpecification<number>
87
88
  |}
88
89
 
90
+ export type FogSpecification = {|
91
+ "range"?: PropertyValueSpecification<[number, number]>,
92
+ "color"?: PropertyValueSpecification<ColorSpecification>,
93
+ "horizon-blend"?: PropertyValueSpecification<number>
94
+ |}
95
+
89
96
  export type VectorSourceSpecification = {
90
97
  "type": "vector",
91
98
  "url"?: string,
@@ -197,7 +204,7 @@ export type LineLayerSpecification = {|
197
204
  "maxzoom"?: number,
198
205
  "filter"?: FilterSpecification,
199
206
  "layout"?: {|
200
- "line-cap"?: PropertyValueSpecification<"butt" | "round" | "square">,
207
+ "line-cap"?: DataDrivenPropertyValueSpecification<"butt" | "round" | "square">,
201
208
  "line-join"?: DataDrivenPropertyValueSpecification<"bevel" | "round" | "miter">,
202
209
  "line-miter-limit"?: PropertyValueSpecification<number>,
203
210
  "line-round-limit"?: PropertyValueSpecification<number>,
@@ -213,7 +220,7 @@ export type LineLayerSpecification = {|
213
220
  "line-gap-width"?: DataDrivenPropertyValueSpecification<number>,
214
221
  "line-offset"?: DataDrivenPropertyValueSpecification<number>,
215
222
  "line-blur"?: DataDrivenPropertyValueSpecification<number>,
216
- "line-dasharray"?: PropertyValueSpecification<Array<number>>,
223
+ "line-dasharray"?: DataDrivenPropertyValueSpecification<Array<number>>,
217
224
  "line-pattern"?: DataDrivenPropertyValueSpecification<ResolvedImageSpecification>,
218
225
  "line-gradient"?: ExpressionSpecification
219
226
  |}
@@ -254,7 +261,7 @@ export type SymbolLayerSpecification = {|
254
261
  "text-font"?: DataDrivenPropertyValueSpecification<Array<string>>,
255
262
  "text-size"?: DataDrivenPropertyValueSpecification<number>,
256
263
  "text-max-width"?: DataDrivenPropertyValueSpecification<number>,
257
- "text-line-height"?: PropertyValueSpecification<number>,
264
+ "text-line-height"?: DataDrivenPropertyValueSpecification<number>,
258
265
  "text-letter-spacing"?: DataDrivenPropertyValueSpecification<number>,
259
266
  "text-justify"?: DataDrivenPropertyValueSpecification<"auto" | "left" | "center" | "right">,
260
267
  "text-radial-offset"?: DataDrivenPropertyValueSpecification<number>,
@@ -18,6 +18,7 @@ import validateLayer from './validate_layer.js';
18
18
  import validateSource from './validate_source.js';
19
19
  import validateLight from './validate_light.js';
20
20
  import validateTerrain from './validate_terrain.js';
21
+ import validateFog from './validate_fog.js';
21
22
  import validateString from './validate_string.js';
22
23
  import validateFormatted from './validate_formatted.js';
23
24
  import validateImage from './validate_image.js';
@@ -39,6 +40,7 @@ const VALIDATORS = {
39
40
  'source': validateSource,
40
41
  'light': validateLight,
41
42
  'terrain': validateTerrain,
43
+ 'fog': validateFog,
42
44
  'string': validateString,
43
45
  'formatted': validateFormatted,
44
46
  'resolvedImage': validateImage
@@ -0,0 +1,46 @@
1
+
2
+ import ValidationError from '../error/validation_error.js';
3
+ import validate from './validate.js';
4
+ import getType from '../util/get_type.js';
5
+
6
+ export default function validateFog(options) {
7
+ const fog = options.value;
8
+ const style = options.style;
9
+ const styleSpec = options.styleSpec;
10
+ const fogSpec = styleSpec.fog;
11
+ let errors = [];
12
+
13
+ const rootType = getType(fog);
14
+ if (fog === undefined) {
15
+ return errors;
16
+ } else if (rootType !== 'object') {
17
+ errors = errors.concat([new ValidationError('fog', fog, `object expected, ${rootType} found`)]);
18
+ return errors;
19
+ }
20
+
21
+ for (const key in fog) {
22
+ const transitionMatch = key.match(/^(.*)-transition$/);
23
+
24
+ if (transitionMatch && fogSpec[transitionMatch[1]] && fogSpec[transitionMatch[1]].transition) {
25
+ errors = errors.concat(validate({
26
+ key,
27
+ value: fog[key],
28
+ valueSpec: styleSpec.transition,
29
+ style,
30
+ styleSpec
31
+ }));
32
+ } else if (fogSpec[key]) {
33
+ errors = errors.concat(validate({
34
+ key,
35
+ value: fog[key],
36
+ valueSpec: fogSpec[key],
37
+ style,
38
+ styleSpec
39
+ }));
40
+ } else {
41
+ errors = errors.concat([new ValidationError(key, fog[key], `unknown property "${key}"`)]);
42
+ }
43
+ }
44
+
45
+ return errors;
46
+ }
@@ -34,6 +34,7 @@ function getAllowedKeyErrors(obj: Object, keys: Array<*>, path: ?string): Array<
34
34
  return errors;
35
35
  }
36
36
 
37
+ const acceptedSourceTypes = new Set(["vector", "raster", "raster-dem"]);
37
38
  function getSourceErrors(source: Object, i: number): Array<?ValidationError> {
38
39
  const errors = [];
39
40
 
@@ -44,6 +45,13 @@ function getSourceErrors(source: Object, i: number): Array<?ValidationError> {
44
45
  const sourceKeys = ['type', 'url', 'tileSize'];
45
46
  errors.push(...getAllowedKeyErrors(source, sourceKeys, 'source'));
46
47
 
48
+ /*
49
+ * "type" is required and must be one of "vector", "raster", "raster-dem"
50
+ */
51
+ if (!acceptedSourceTypes.has(String(source.type))) {
52
+ errors.push(new ValidationError(`sources[${i}].type`, source.type, `Expected one of [${Array.from(acceptedSourceTypes).join(", ")}]`));
53
+ }
54
+
47
55
  /*
48
56
  * "source" is required. Valid examples:
49
57
  * mapbox://mapbox.abcd1234
@@ -51,8 +59,8 @@ function getSourceErrors(source: Object, i: number): Array<?ValidationError> {
51
59
  * mapbox://mapbox.abcd1234,penny.abcd1234
52
60
  */
53
61
  const sourceUrlPattern = /^mapbox:\/\/([^/]*)$/;
54
- if (!isValid(source.url, sourceUrlPattern)) {
55
- errors.push(new ValidationError(`sources[${i}]`, source.url, 'Source url must be a valid Mapbox tileset url'));
62
+ if (!source.url || !isValid(source.url, sourceUrlPattern)) {
63
+ errors.push(new ValidationError(`sources[${i}].url`, source.url, 'Expected a valid Mapbox tileset url'));
56
64
  }
57
65
 
58
66
  return errors;
@@ -7,6 +7,7 @@ import validateGlyphsURL from './validate/validate_glyphs_url.js';
7
7
  import validateSource from './validate/validate_source.js';
8
8
  import validateLight from './validate/validate_light.js';
9
9
  import validateTerrain from './validate/validate_terrain.js';
10
+ import validateFog from './validate/validate_fog.js';
10
11
  import validateLayer from './validate/validate_layer.js';
11
12
  import validateFilter from './validate/validate_filter.js';
12
13
  import validatePaintProperty from './validate/validate_paint_property.js';
@@ -60,6 +61,7 @@ function validateStyleMin(style, styleSpec = latestStyleSpec) {
60
61
  validateStyleMin.source = wrapCleanErrors(validateSource);
61
62
  validateStyleMin.light = wrapCleanErrors(validateLight);
62
63
  validateStyleMin.terrain = wrapCleanErrors(validateTerrain);
64
+ validateStyleMin.fog = wrapCleanErrors(validateFog);
63
65
  validateStyleMin.layer = wrapCleanErrors(validateLayer);
64
66
  validateStyleMin.filter = wrapCleanErrors(validateFilter);
65
67
  validateStyleMin.paintProperty = wrapCleanErrors(validatePaintProperty);