@mapbox/mapbox-gl-style-spec 14.11.0 → 14.12.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/composite.ts +2 -0
- package/deref.ts +5 -5
- package/diff.ts +65 -31
- package/dist/index.cjs +816 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +224 -16
- package/dist/index.es.js +816 -16
- package/dist/index.es.js.map +1 -1
- package/error/validation_error.ts +1 -3
- package/expression/compound_expression.ts +1 -1
- package/expression/definitions/assertion.ts +2 -1
- package/expression/definitions/at.ts +1 -1
- package/expression/definitions/at_interpolated.ts +1 -1
- package/expression/definitions/case.ts +3 -1
- package/expression/definitions/coalesce.ts +3 -2
- package/expression/definitions/coercion.ts +3 -1
- package/expression/definitions/collator.ts +2 -1
- package/expression/definitions/comparison.ts +15 -1
- package/expression/definitions/config.ts +4 -1
- package/expression/definitions/distance.ts +6 -4
- package/expression/definitions/format.ts +1 -1
- package/expression/definitions/index.ts +24 -2
- package/expression/definitions/index_of.ts +1 -0
- package/expression/definitions/interpolate.ts +7 -3
- package/expression/definitions/let.ts +1 -0
- package/expression/definitions/literal.ts +2 -2
- package/expression/definitions/match.ts +4 -2
- package/expression/definitions/number_format.ts +3 -4
- package/expression/definitions/slice.ts +1 -0
- package/expression/definitions/step.ts +2 -1
- package/expression/definitions/var.ts +1 -0
- package/expression/definitions/within.ts +6 -2
- package/expression/evaluation_context.ts +3 -5
- package/expression/expression.ts +3 -0
- package/expression/index.ts +20 -10
- package/expression/parsing_context.ts +1 -1
- package/expression/types/image_variant.ts +2 -2
- package/expression/types.ts +1 -0
- package/expression/values.ts +1 -3
- package/feature_filter/convert.ts +13 -6
- package/feature_filter/index.ts +17 -1
- package/format.ts +1 -0
- package/function/convert.ts +5 -1
- package/function/index.ts +28 -0
- package/group_by_layout.ts +17 -8
- package/migrate/expressions.ts +3 -3
- package/migrate/v8.ts +10 -1
- package/migrate/v9.ts +2 -1
- package/migrate.ts +2 -1
- package/package.json +1 -1
- package/read_style.ts +1 -0
- package/reference/latest.ts +1 -0
- package/reference/v8.json +425 -8
- package/test.js +2 -4
- package/types.ts +207 -1
- package/union-to-intersection.ts +1 -0
- package/util/extend.ts +2 -1
- package/util/geometry_util.ts +25 -9
- package/util/interpolate.ts +1 -1
- package/validate/validate.ts +6 -0
- package/validate/validate_array.ts +2 -0
- package/validate/validate_enum.ts +1 -0
- package/validate/validate_expression.ts +4 -0
- package/validate/validate_filter.ts +4 -2
- package/validate/validate_fog.ts +4 -1
- package/validate/validate_function.ts +7 -2
- package/validate/validate_glyphs_url.ts +1 -1
- package/validate/validate_iconset.ts +1 -0
- package/validate/validate_layer.ts +3 -2
- package/validate/validate_light.ts +4 -1
- package/validate/validate_lights.ts +7 -1
- package/validate/validate_model.ts +4 -0
- package/validate/validate_object.ts +2 -2
- package/validate/validate_projection.ts +1 -0
- package/validate/validate_property.ts +5 -1
- package/validate/validate_rain.ts +3 -0
- package/validate/validate_snow.ts +3 -0
- package/validate/validate_source.ts +9 -9
- package/validate/validate_terrain.ts +5 -1
- package/validate_mapbox_api_supported.ts +31 -20
- package/validate_style.ts +1 -0
- package/visit.ts +4 -2
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
|
|
15
15
|
import type {ValidationOptions} from './validate';
|
|
16
16
|
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
18
|
export default function validateFunction(options: ValidationOptions): any {
|
|
18
19
|
const functionValueSpec = options.valueSpec;
|
|
19
20
|
const functionType = unbundle(options.value.type);
|
|
@@ -88,6 +89,7 @@ export default function validateFunction(options: ValidationOptions): any {
|
|
|
88
89
|
errors.push(new ValidationError(options.key, value, 'array must have at least one stop'));
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
91
93
|
return errors;
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -147,9 +149,11 @@ export default function validateFunction(options: ValidationOptions): any {
|
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
if (isExpression(deepUnbundle(value[1]))) {
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
150
153
|
return errors.concat([new ValidationError(`${key}[1]`, value[1], 'expressions are not allowed in function stops.')]);
|
|
151
154
|
}
|
|
152
155
|
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
153
157
|
return errors.concat(validate({
|
|
154
158
|
key: `${key}[1]`,
|
|
155
159
|
value: value[1],
|
|
@@ -159,6 +163,7 @@ export default function validateFunction(options: ValidationOptions): any {
|
|
|
159
163
|
}));
|
|
160
164
|
}
|
|
161
165
|
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
162
167
|
function validateStopDomainValue(options: ValidationOptions, stop: any) {
|
|
163
168
|
const type = getType(options.value);
|
|
164
169
|
const value = unbundle(options.value);
|
|
@@ -193,10 +198,10 @@ export default function validateFunction(options: ValidationOptions): any {
|
|
|
193
198
|
previousStopDomainValue = value;
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
if (functionType === 'categorical' && (value as
|
|
201
|
+
if (functionType === 'categorical' && (value as string) in stopDomainValues) {
|
|
197
202
|
return [new ValidationError(options.key, reportValue, 'stop domain values must be unique')];
|
|
198
203
|
} else {
|
|
199
|
-
stopDomainValues[(value as
|
|
204
|
+
stopDomainValues[(value as string)] = true;
|
|
200
205
|
}
|
|
201
206
|
|
|
202
207
|
return [];
|
|
@@ -3,7 +3,7 @@ import validateString from './validate_string';
|
|
|
3
3
|
|
|
4
4
|
import type {ValidationOptions} from './validate';
|
|
5
5
|
|
|
6
|
-
export default function(options: ValidationOptions): Array<ValidationError> {
|
|
6
|
+
export default function (options: ValidationOptions): Array<ValidationError> {
|
|
7
7
|
const value = options.value;
|
|
8
8
|
const key = options.key;
|
|
9
9
|
|
|
@@ -79,8 +79,8 @@ export default function validateLayer(options: Options): Array<ValidationError>
|
|
|
79
79
|
} else if (sourceType === 'raster-array' && !['raster', 'raster-particle'].includes(type)) {
|
|
80
80
|
errors.push(new ValidationError(key, layer.source, `raster-array source can only be used with layer type \'raster\'.`));
|
|
81
81
|
} else if (type === 'line' && layer.paint && (layer.paint['line-gradient'] || layer.paint['line-trim-offset']) &&
|
|
82
|
-
(sourceType
|
|
83
|
-
errors.push(new ValidationError(key, layer, `layer "${layer.id}" specifies a line-gradient, which requires
|
|
82
|
+
(sourceType === 'geojson' && !(source as GeoJSONSourceSpecification).lineMetrics)) {
|
|
83
|
+
errors.push(new ValidationError(key, layer, `layer "${layer.id}" specifies a line-gradient, which requires the GeoJSON source to have \`lineMetrics\` enabled.`));
|
|
84
84
|
} else if (type === 'raster-particle' && sourceType !== 'raster-array') {
|
|
85
85
|
errors.push(new ValidationError(key, layer.source, `layer "${layer.id}" requires a \'raster-array\' source.`));
|
|
86
86
|
}
|
|
@@ -146,5 +146,6 @@ export default function validateLayer(options: Options): Array<ValidationError>
|
|
|
146
146
|
}
|
|
147
147
|
}));
|
|
148
148
|
|
|
149
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
149
150
|
return errors;
|
|
150
151
|
}
|
|
@@ -14,9 +14,11 @@ export default function validateLight(options: ValidationOptions): Array<Validat
|
|
|
14
14
|
|
|
15
15
|
const rootType = getType(light);
|
|
16
16
|
if (light === undefined) {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
17
18
|
return errors;
|
|
18
19
|
} else if (rootType !== 'object') {
|
|
19
20
|
errors = errors.concat([new ValidationError('light', light, `object expected, ${rootType} found`)]);
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
20
22
|
return errors;
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -28,7 +30,7 @@ export default function validateLight(options: ValidationOptions): Array<Validat
|
|
|
28
30
|
errors = errors.concat(validate({
|
|
29
31
|
key,
|
|
30
32
|
value: light[key],
|
|
31
|
-
valueSpec: {type:'string'},
|
|
33
|
+
valueSpec: {type: 'string'},
|
|
32
34
|
style,
|
|
33
35
|
styleSpec
|
|
34
36
|
}));
|
|
@@ -53,5 +55,6 @@ export default function validateLight(options: ValidationOptions): Array<Validat
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
56
59
|
return errors;
|
|
57
60
|
}
|
|
@@ -15,12 +15,14 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
15
15
|
let errors = [];
|
|
16
16
|
|
|
17
17
|
if (!light) {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
18
19
|
return errors;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
const type = getType(light);
|
|
22
23
|
if (type !== 'object') {
|
|
23
24
|
errors = errors.concat([new ValidationError('light-3d', light, `object expected, ${type} found`)]);
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
24
26
|
return errors;
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -33,6 +35,7 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
33
35
|
for (const key of ['type', 'id']) {
|
|
34
36
|
if (!(key in light)) {
|
|
35
37
|
errors = errors.concat([new ValidationError('light-3d', light, `missing property ${key} on light`)]);
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
36
39
|
return errors;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
@@ -51,6 +54,7 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
51
54
|
const lightType = `properties_light_${light['type']}`;
|
|
52
55
|
if (!(lightType in styleSpec)) {
|
|
53
56
|
errors = errors.concat([new ValidationError('light-3d', light, `Invalid light type ${light['type']}`)]);
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
54
58
|
return errors;
|
|
55
59
|
}
|
|
56
60
|
|
|
@@ -62,6 +66,7 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
62
66
|
const propertiesType = getType(properties);
|
|
63
67
|
if (propertiesType !== 'object') {
|
|
64
68
|
errors = errors.concat([new ValidationError('properties', properties, `object expected, ${propertiesType} found`)]);
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
65
70
|
return errors;
|
|
66
71
|
}
|
|
67
72
|
for (const propertyKey in properties) {
|
|
@@ -85,7 +90,7 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
85
90
|
errors = errors.concat(validate({
|
|
86
91
|
key,
|
|
87
92
|
value: light[key],
|
|
88
|
-
valueSpec: {type:'string'},
|
|
93
|
+
valueSpec: {type: 'string'},
|
|
89
94
|
style,
|
|
90
95
|
styleSpec
|
|
91
96
|
}));
|
|
@@ -111,5 +116,6 @@ export default function validateLights(options: Options): Array<ValidationError>
|
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
118
|
|
|
119
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
114
120
|
return errors;
|
|
115
121
|
}
|
|
@@ -9,6 +9,7 @@ export function isValidUrl(str: string, allowRelativeUrls: boolean): boolean {
|
|
|
9
9
|
try {
|
|
10
10
|
new URL(str, isRelative && allowRelativeUrls ? 'http://example.com' : undefined);
|
|
11
11
|
return true;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
13
|
} catch (_: any) {
|
|
13
14
|
return false;
|
|
14
15
|
}
|
|
@@ -19,12 +20,14 @@ export default function validateModel(options: ValidationOptions): Array<Validat
|
|
|
19
20
|
let errors = [];
|
|
20
21
|
|
|
21
22
|
if (!url) {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
22
24
|
return errors;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
const type = getType(url);
|
|
26
28
|
if (type !== 'string') {
|
|
27
29
|
errors = errors.concat([new ValidationError(options.key, url, `string expected, "${type}" found`)]);
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
28
31
|
return errors;
|
|
29
32
|
}
|
|
30
33
|
|
|
@@ -32,5 +35,6 @@ export default function validateModel(options: ValidationOptions): Array<Validat
|
|
|
32
35
|
errors = errors.concat([new ValidationError(options.key, url, `invalid url "${url}"`)]);
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
35
39
|
return errors;
|
|
36
40
|
}
|
|
@@ -7,7 +7,7 @@ import type {LayerSpecification} from '../types';
|
|
|
7
7
|
|
|
8
8
|
type Options = ValidationOptions & {
|
|
9
9
|
layer?: LayerSpecification;
|
|
10
|
-
objectElementValidators?:
|
|
10
|
+
objectElementValidators?: object;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export default function validateObject(options: Options): Array<ValidationError> {
|
|
@@ -17,7 +17,7 @@ export default function validateObject(options: Options): Array<ValidationError>
|
|
|
17
17
|
const elementValidators = options.objectElementValidators || {};
|
|
18
18
|
const style = options.style;
|
|
19
19
|
const styleSpec = options.styleSpec;
|
|
20
|
-
let errors = [];
|
|
20
|
+
let errors: ValidationError[] = [];
|
|
21
21
|
|
|
22
22
|
const type = getType(object);
|
|
23
23
|
if (type !== 'object') {
|
|
@@ -28,5 +28,6 @@ export default function validateProjection(options: ValidationOptions): Array<Va
|
|
|
28
28
|
errors = errors.concat([new ValidationError('projection', projection, `object or string expected, ${rootType} found`)]);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
31
32
|
return errors;
|
|
32
33
|
}
|
|
@@ -12,6 +12,7 @@ import type {ValidationOptions} from './validate';
|
|
|
12
12
|
export type PropertyValidationOptions = ValidationOptions & {
|
|
13
13
|
objectKey: string;
|
|
14
14
|
layerType: string;
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
16
|
layer: any;
|
|
16
17
|
};
|
|
17
18
|
|
|
@@ -30,6 +31,7 @@ export default function validateProperty(options: PropertyValidationOptions, pro
|
|
|
30
31
|
if (propertyType === 'paint' && useThemeMatch && layerSpec[useThemeMatch[1]]) {
|
|
31
32
|
if (isExpression(value)) {
|
|
32
33
|
const errors = [];
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
33
35
|
return errors.concat(validate({
|
|
34
36
|
key: options.key,
|
|
35
37
|
value,
|
|
@@ -55,7 +57,7 @@ export default function validateProperty(options: PropertyValidationOptions, pro
|
|
|
55
57
|
return validate({
|
|
56
58
|
key,
|
|
57
59
|
value,
|
|
58
|
-
valueSpec: {type:'string'},
|
|
60
|
+
valueSpec: {type: 'string'},
|
|
59
61
|
style,
|
|
60
62
|
styleSpec
|
|
61
63
|
});
|
|
@@ -99,6 +101,7 @@ export default function validateProperty(options: PropertyValidationOptions, pro
|
|
|
99
101
|
if (supportsPropertyExpression(valueSpec) && (supportsLightExpression(valueSpec) || supportsZoomExpression(valueSpec))) {
|
|
100
102
|
// Performance related style spec limitation: zoom and light expressions are not allowed for e.g. trees.
|
|
101
103
|
const expression = createPropertyExpression(deepUnbundle(value), valueSpec);
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
105
|
const expressionObj = (expression.value as any).expression || (expression.value as any)._styleExpression.expression;
|
|
103
106
|
|
|
104
107
|
if (expressionObj && !isGlobalPropertyConstant(expressionObj, ['measure-light'])) {
|
|
@@ -109,6 +112,7 @@ export default function validateProperty(options: PropertyValidationOptions, pro
|
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
112
116
|
return errors.concat(validate({
|
|
113
117
|
key: options.key,
|
|
114
118
|
value,
|
|
@@ -13,9 +13,11 @@ export default function validateRain(options: ValidationOptions): Array<Validati
|
|
|
13
13
|
|
|
14
14
|
const rootType = getType(rain);
|
|
15
15
|
if (rain === undefined) {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
16
17
|
return errors;
|
|
17
18
|
} else if (rootType !== 'object') {
|
|
18
19
|
errors = errors.concat([new ValidationError('rain', rain, `object expected, ${rootType} found`)]);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
19
21
|
return errors;
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -43,5 +45,6 @@ export default function validateRain(options: ValidationOptions): Array<Validati
|
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
46
49
|
return errors;
|
|
47
50
|
}
|
|
@@ -13,9 +13,11 @@ export default function validateSnow(options: ValidationOptions): Array<Validati
|
|
|
13
13
|
|
|
14
14
|
const rootType = getType(snow);
|
|
15
15
|
if (snow === undefined) {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
16
17
|
return errors;
|
|
17
18
|
} else if (rootType !== 'object') {
|
|
18
19
|
errors = errors.concat([new ValidationError('snow', snow, `object expected, ${rootType} found`)]);
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
19
21
|
return errors;
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -43,5 +45,6 @@ export default function validateSnow(options: ValidationOptions): Array<Validati
|
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
46
49
|
return errors;
|
|
47
50
|
}
|
|
@@ -25,10 +25,9 @@ export default function validateSource(options: ValidationOptions): Array<Valida
|
|
|
25
25
|
return [new ValidationError(key, value, '"type" is required')];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const type = unbundle(value.type);
|
|
29
|
-
let errors = [];
|
|
28
|
+
const type = unbundle(value.type) as string;
|
|
29
|
+
let errors: ValidationError[] = [];
|
|
30
30
|
|
|
31
|
-
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'string'.
|
|
32
31
|
if (['vector', 'raster', 'raster-dem', 'raster-array'].includes(type)) {
|
|
33
32
|
if (!value.url && !value.tiles) {
|
|
34
33
|
errors.push(new ValidationWarning(key, value, 'Either "url" or "tiles" is required.'));
|
|
@@ -49,7 +48,6 @@ export default function validateSource(options: ValidationOptions): Array<Valida
|
|
|
49
48
|
objectElementValidators
|
|
50
49
|
}));
|
|
51
50
|
return errors;
|
|
52
|
-
|
|
53
51
|
case 'geojson':
|
|
54
52
|
errors = validateObject({
|
|
55
53
|
key,
|
|
@@ -59,6 +57,7 @@ export default function validateSource(options: ValidationOptions): Array<Valida
|
|
|
59
57
|
styleSpec,
|
|
60
58
|
objectElementValidators
|
|
61
59
|
});
|
|
60
|
+
|
|
62
61
|
if (value.cluster) {
|
|
63
62
|
for (const prop in value.clusterProperties) {
|
|
64
63
|
const [operator, mapExpr] = value.clusterProperties[prop];
|
|
@@ -76,8 +75,8 @@ export default function validateSource(options: ValidationOptions): Array<Valida
|
|
|
76
75
|
}));
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
|
-
return errors;
|
|
80
78
|
|
|
79
|
+
return errors;
|
|
81
80
|
case 'video':
|
|
82
81
|
return validateObject({
|
|
83
82
|
key,
|
|
@@ -111,8 +110,8 @@ export default function validateSource(options: ValidationOptions): Array<Valida
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
function getSourceTypeValues(styleSpec: StyleReference) {
|
|
114
|
-
//
|
|
115
|
-
return styleSpec.source.reduce
|
|
113
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
114
|
+
return styleSpec.source.reduce((memo: string[], source: string) => {
|
|
116
115
|
const sourceType = styleSpec[source];
|
|
117
116
|
if (sourceType.type.type === 'enum') {
|
|
118
117
|
memo = memo.concat(Object.keys(sourceType.type.values));
|
|
@@ -128,7 +127,7 @@ function validatePromoteId({
|
|
|
128
127
|
if (getType(value) === 'string') {
|
|
129
128
|
return validateString({key, value});
|
|
130
129
|
} else if (Array.isArray(value)) {
|
|
131
|
-
const errors = [];
|
|
130
|
+
const errors: ValidationError[] = [];
|
|
132
131
|
const unbundledValue = deepUnbundle(value);
|
|
133
132
|
const expression = createExpression(unbundledValue);
|
|
134
133
|
if (expression.result === 'error') {
|
|
@@ -146,10 +145,11 @@ function validatePromoteId({
|
|
|
146
145
|
|
|
147
146
|
return errors;
|
|
148
147
|
} else {
|
|
149
|
-
const errors = [];
|
|
148
|
+
const errors: ValidationError[] = [];
|
|
150
149
|
for (const prop in value) {
|
|
151
150
|
errors.push(...validatePromoteId({key: `${key}.${prop}`, value: value[prop]}));
|
|
152
151
|
}
|
|
152
|
+
|
|
153
153
|
return errors;
|
|
154
154
|
}
|
|
155
155
|
}
|
|
@@ -15,11 +15,14 @@ export default function validateTerrain(options: ValidationOptions): Array<Valid
|
|
|
15
15
|
|
|
16
16
|
const rootType = getType(terrain);
|
|
17
17
|
if (terrain === undefined) {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
18
19
|
return errors;
|
|
19
20
|
} else if (rootType === 'null') {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
20
22
|
return errors;
|
|
21
23
|
} else if (rootType !== 'object') {
|
|
22
24
|
errors = errors.concat([new ValidationError('terrain', terrain, `object expected, ${rootType} found`)]);
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
23
26
|
return errors;
|
|
24
27
|
}
|
|
25
28
|
|
|
@@ -31,7 +34,7 @@ export default function validateTerrain(options: ValidationOptions): Array<Valid
|
|
|
31
34
|
errors = errors.concat(validate({
|
|
32
35
|
key,
|
|
33
36
|
value: terrain[key],
|
|
34
|
-
valueSpec: {type:'string'},
|
|
37
|
+
valueSpec: {type: 'string'},
|
|
35
38
|
style,
|
|
36
39
|
styleSpec
|
|
37
40
|
}));
|
|
@@ -68,5 +71,6 @@ export default function validateTerrain(options: ValidationOptions): Array<Valid
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
71
75
|
return errors;
|
|
72
76
|
}
|
|
@@ -4,7 +4,19 @@ import readStyle from './read_style';
|
|
|
4
4
|
import ValidationError from './error/validation_error';
|
|
5
5
|
import getType from './util/get_type';
|
|
6
6
|
|
|
7
|
+
import type {StyleReference} from './reference/latest';
|
|
7
8
|
import type {ValidationErrors} from './validate_style.min';
|
|
9
|
+
import type {
|
|
10
|
+
StyleSpecification,
|
|
11
|
+
SourceSpecification,
|
|
12
|
+
SourcesSpecification,
|
|
13
|
+
ImportSpecification
|
|
14
|
+
} from './types';
|
|
15
|
+
|
|
16
|
+
type MapboxStyleSpecification = StyleSpecification & {
|
|
17
|
+
visibility?: 'public' | 'private';
|
|
18
|
+
protected?: boolean;
|
|
19
|
+
};
|
|
8
20
|
|
|
9
21
|
const SUPPORTED_SPEC_VERSION = 8;
|
|
10
22
|
const MAX_SOURCES_IN_STYLE = 15;
|
|
@@ -14,17 +26,17 @@ function isValid(value: string | null | undefined, regex: RegExp): boolean {
|
|
|
14
26
|
return !!value.match(regex);
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
function getSourceCount(source:
|
|
18
|
-
if (source
|
|
29
|
+
function getSourceCount(source: SourceSpecification): number {
|
|
30
|
+
if ('url' in source) {
|
|
19
31
|
return source.url.split(',').length;
|
|
20
32
|
} else {
|
|
21
33
|
return 0;
|
|
22
34
|
}
|
|
23
35
|
}
|
|
24
36
|
|
|
25
|
-
function getAllowedKeyErrors(obj:
|
|
37
|
+
function getAllowedKeyErrors(obj: object, keys: string[], path?: string | null): Array<ValidationError> {
|
|
26
38
|
const allowed = new Set(keys);
|
|
27
|
-
const errors = [];
|
|
39
|
+
const errors: ValidationError[] = [];
|
|
28
40
|
Object.keys(obj).forEach(k => {
|
|
29
41
|
if (!allowed.has(k)) {
|
|
30
42
|
const prop = path ? `${path}.${k}` : null;
|
|
@@ -34,9 +46,9 @@ function getAllowedKeyErrors(obj: any, keys: Array<any>, path?: string | null):
|
|
|
34
46
|
return errors;
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
const acceptedSourceTypes = new Set([
|
|
38
|
-
function getSourceErrors(source:
|
|
39
|
-
const errors = [];
|
|
49
|
+
const acceptedSourceTypes = new Set<SourceSpecification['type']>(['vector', 'raster', 'raster-dem', 'raster-array', 'model', 'batched-model']);
|
|
50
|
+
function getSourceErrors(source: SourceSpecification, i: number): Array<ValidationError> {
|
|
51
|
+
const errors: ValidationError[] = [];
|
|
40
52
|
|
|
41
53
|
/*
|
|
42
54
|
* Inlined sources are not supported by the Mapbox Styles API, so only
|
|
@@ -48,7 +60,7 @@ function getSourceErrors(source: any, i: number): Array<ValidationError> {
|
|
|
48
60
|
/*
|
|
49
61
|
* "type" is required and must be one of "vector", "raster", "raster-dem", "raster-array"
|
|
50
62
|
*/
|
|
51
|
-
if (!acceptedSourceTypes.has(String(source.type))) {
|
|
63
|
+
if (!acceptedSourceTypes.has(String(source.type) as SourceSpecification['type'])) {
|
|
52
64
|
errors.push(new ValidationError(`sources[${i}].type`, source.type, `Expected one of [${Array.from(acceptedSourceTypes).join(", ")}]`));
|
|
53
65
|
}
|
|
54
66
|
|
|
@@ -59,22 +71,22 @@ function getSourceErrors(source: any, i: number): Array<ValidationError> {
|
|
|
59
71
|
* mapbox://mapbox.abcd1234,penny.abcd1234
|
|
60
72
|
*/
|
|
61
73
|
const sourceUrlPattern = /^mapbox:\/\/([^/]*)$/;
|
|
62
|
-
if (!
|
|
63
|
-
errors.push(new ValidationError(`sources[${i}].url`, source.url, 'Expected a valid Mapbox tileset url'));
|
|
74
|
+
if (!('url' in source) || !isValid(source.url, sourceUrlPattern)) {
|
|
75
|
+
errors.push(new ValidationError(`sources[${i}].url`, (source as {url?: string}).url, 'Expected a valid Mapbox tileset url'));
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
return errors;
|
|
67
79
|
}
|
|
68
80
|
|
|
69
81
|
function getMaxSourcesErrors(sourcesCount: number): Array<ValidationError> {
|
|
70
|
-
const errors = [];
|
|
82
|
+
const errors: ValidationError[] = [];
|
|
71
83
|
if (sourcesCount > MAX_SOURCES_IN_STYLE) {
|
|
72
84
|
errors.push(new ValidationError('sources', null, `Styles must contain ${MAX_SOURCES_IN_STYLE} or fewer sources`));
|
|
73
85
|
}
|
|
74
86
|
return errors;
|
|
75
87
|
}
|
|
76
88
|
|
|
77
|
-
function getSourcesErrors(sources:
|
|
89
|
+
function getSourcesErrors(sources: SourcesSpecification): {
|
|
78
90
|
errors: Array<ValidationError>;
|
|
79
91
|
sourcesCount: number;
|
|
80
92
|
} {
|
|
@@ -95,14 +107,11 @@ function getSourcesErrors(sources: any): {
|
|
|
95
107
|
return {errors, sourcesCount};
|
|
96
108
|
}
|
|
97
109
|
|
|
98
|
-
function getImportErrors(imports:
|
|
99
|
-
errors: Array<ValidationError>;
|
|
100
|
-
sourcesCount: number;
|
|
101
|
-
} {
|
|
110
|
+
function getImportErrors(imports: ImportSpecification[] = []): {errors: Array<ValidationError>; sourcesCount: number} {
|
|
102
111
|
let errors: Array<ValidationError> = [];
|
|
103
112
|
|
|
104
113
|
let sourcesCount = 0;
|
|
105
|
-
const validateImports = (imports:
|
|
114
|
+
const validateImports = (imports: ImportSpecification[] = []) => {
|
|
106
115
|
for (const importSpec of imports) {
|
|
107
116
|
const style = importSpec.data;
|
|
108
117
|
if (!style) continue;
|
|
@@ -129,7 +138,7 @@ function getImportErrors(imports: Array<any> = []): {
|
|
|
129
138
|
return {errors, sourcesCount};
|
|
130
139
|
}
|
|
131
140
|
|
|
132
|
-
function getRootErrors(style:
|
|
141
|
+
function getRootErrors(style: MapboxStyleSpecification, specKeys: string[]): Array<ValidationError> {
|
|
133
142
|
const errors = [];
|
|
134
143
|
|
|
135
144
|
/*
|
|
@@ -195,6 +204,7 @@ function getRootErrors(style: any, specKeys: Array<any>): Array<ValidationError>
|
|
|
195
204
|
errors.push(new ValidationError('protected', style.protected, 'Style protection must be true or false'));
|
|
196
205
|
}
|
|
197
206
|
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
198
208
|
return errors;
|
|
199
209
|
}
|
|
200
210
|
|
|
@@ -208,11 +218,12 @@ function getRootErrors(style: any, specKeys: Array<any>): Array<ValidationError>
|
|
|
208
218
|
* var validateMapboxApiSupported = require('mapbox-gl-style-spec/lib/validate_style_mapbox_api_supported.js');
|
|
209
219
|
* var errors = validateMapboxApiSupported(style);
|
|
210
220
|
*/
|
|
211
|
-
export default function validateMapboxApiSupported(style:
|
|
221
|
+
export default function validateMapboxApiSupported(style: MapboxStyleSpecification, styleSpec: StyleReference = v8): ValidationErrors {
|
|
212
222
|
let s = style;
|
|
213
223
|
try {
|
|
214
224
|
s = readStyle(s);
|
|
215
|
-
} catch (e
|
|
225
|
+
} catch (e) {
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
216
227
|
return [e];
|
|
217
228
|
}
|
|
218
229
|
|
package/validate_style.ts
CHANGED
package/visit.ts
CHANGED
|
@@ -11,16 +11,18 @@ import type {
|
|
|
11
11
|
function getPropertyReference(propertyName: string): StylePropertySpecification {
|
|
12
12
|
for (let i = 0; i < Reference.layout.length; i++) {
|
|
13
13
|
for (const key in Reference[Reference.layout[i]]) {
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
14
15
|
if (key === propertyName) return Reference[Reference.layout[i]][key];
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
for (let i = 0; i < Reference.paint.length; i++) {
|
|
18
19
|
for (const key in Reference[Reference.paint[i]]) {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
19
21
|
if (key === propertyName) return Reference[Reference.paint[i]][key];
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
return null
|
|
25
|
+
return null;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export function eachSource(style: StyleSpecification, callback: (_: SourceSpecification) => void) {
|
|
@@ -57,7 +59,7 @@ export function eachProperty(
|
|
|
57
59
|
) {
|
|
58
60
|
function inner(layer: LayerSpecification, propertyType: 'paint' | 'layout') {
|
|
59
61
|
if (layer.type === 'slot' || layer.type === 'clip') return;
|
|
60
|
-
const properties =
|
|
62
|
+
const properties = layer[propertyType];
|
|
61
63
|
if (!properties) return;
|
|
62
64
|
Object.keys(properties).forEach((key) => {
|
|
63
65
|
callback({
|