@mapbox/mapbox-gl-style-spec 14.15.0-beta.2 → 14.15.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/deref.ts +3 -0
- package/diff.ts +63 -0
- package/dist/index.cjs +722 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +85 -6
- package/dist/index.es.js +722 -47
- package/dist/index.es.js.map +1 -1
- package/expression/compound_expression.ts +4 -0
- package/expression/definitions/assertion.ts +7 -0
- package/expression/definitions/case.ts +2 -1
- package/expression/definitions/coalesce.ts +4 -0
- package/expression/definitions/coercion.ts +12 -0
- package/expression/definitions/collator.ts +8 -5
- package/expression/definitions/comparison.ts +12 -5
- package/expression/definitions/config.ts +12 -0
- package/expression/definitions/distance.ts +13 -2
- package/expression/definitions/format.ts +10 -0
- package/expression/definitions/image.ts +3 -0
- package/expression/definitions/in.ts +5 -0
- package/expression/definitions/index.ts +62 -10
- package/expression/definitions/index_of.ts +6 -0
- package/expression/definitions/interpolate.ts +5 -1
- package/expression/definitions/length.ts +2 -0
- package/expression/definitions/let.ts +1 -0
- package/expression/definitions/match.ts +5 -0
- package/expression/definitions/number_format.ts +7 -0
- package/expression/definitions/slice.ts +4 -0
- package/expression/definitions/within.ts +1 -0
- package/expression/index.ts +28 -19
- package/expression/parsing_context.ts +2 -0
- package/expression/types/image_variant.ts +3 -0
- package/expression/types.ts +1 -2
- package/expression/values.ts +1 -0
- package/feature_filter/convert.ts +9 -1
- package/feature_filter/index.ts +41 -1
- package/format.ts +5 -0
- package/function/convert.ts +5 -0
- package/function/index.ts +79 -25
- package/group_by_layout.ts +4 -5
- package/migrate/v8.ts +42 -3
- package/migrate/v9.ts +5 -0
- package/migrate.ts +1 -0
- package/package.json +1 -1
- package/read_style.ts +2 -0
- package/reference/v8.json +457 -12
- package/rollup.config.js +1 -0
- package/test.js +4 -0
- package/types.ts +74 -5
- package/util/geometry_util.ts +4 -0
- package/validate/validate.ts +1 -0
- package/validate/validate_appearance.ts +101 -0
- package/validate/validate_array.ts +1 -0
- package/validate/validate_expression.ts +48 -3
- package/validate/validate_filter.ts +5 -3
- package/validate/validate_fog.ts +6 -0
- package/validate/validate_function.ts +2 -0
- package/validate/validate_iconset.ts +1 -0
- package/validate/validate_import.ts +2 -2
- package/validate/validate_layer.ts +37 -4
- package/validate/validate_light.ts +6 -0
- package/validate/validate_lights.ts +9 -0
- package/validate/validate_model.ts +1 -2
- package/validate/validate_number.ts +2 -0
- package/validate/validate_object.ts +7 -0
- package/validate/validate_projection.ts +2 -0
- package/validate/validate_property.ts +15 -4
- package/validate/validate_rain.ts +5 -0
- package/validate/validate_snow.ts +5 -0
- package/validate/validate_source.ts +12 -0
- package/validate/validate_style.ts +1 -0
- package/validate/validate_terrain.ts +6 -0
- package/validate_mapbox_api_supported.ts +1 -0
- package/visit.ts +2 -0
- package/util/extend.ts +0 -9
package/types.ts
CHANGED
|
@@ -130,6 +130,35 @@ export type ModelsSpecification = {
|
|
|
130
130
|
[_: string]: ModelSpecification
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
export type ModelNodeOverrideSpecification = {
|
|
134
|
+
"orientation"?: [number, number, number]
|
|
135
|
+
};
|
|
136
|
+
export type ModelNodeOverridesSpecification = {
|
|
137
|
+
[_: string]: ModelNodeOverrideSpecification
|
|
138
|
+
};
|
|
139
|
+
export type ModelMaterialOverrideSpecification = {
|
|
140
|
+
"model-color"?: ColorSpecification,
|
|
141
|
+
"model-color-mix-intensity"?: number,
|
|
142
|
+
"model-opacity"?: number,
|
|
143
|
+
"model-emissive-strength"?: number
|
|
144
|
+
};
|
|
145
|
+
export type ModelMaterialOverridesSpecification = {
|
|
146
|
+
[_: string]: ModelMaterialOverrideSpecification
|
|
147
|
+
};
|
|
148
|
+
export type ModelSourceModelsSpecification = {
|
|
149
|
+
[_: string]: ModelSourceModelSpecification
|
|
150
|
+
};
|
|
151
|
+
export type ModelSourceModelSpecification = {
|
|
152
|
+
"uri": string,
|
|
153
|
+
"position"?: [number, number],
|
|
154
|
+
"orientation"?: [number, number, number],
|
|
155
|
+
"nodeOverrides"?: ModelNodeOverridesSpecification,
|
|
156
|
+
"materialOverrides"?: ModelMaterialOverridesSpecification,
|
|
157
|
+
"nodeOverrideNames"?: Array<string>,
|
|
158
|
+
"materialOverrideNames"?: Array<string>,
|
|
159
|
+
"featureProperties"?: unknown
|
|
160
|
+
};
|
|
161
|
+
|
|
133
162
|
export type IconsetsSpecification = {
|
|
134
163
|
[_: string]: IconsetSpecification
|
|
135
164
|
};
|
|
@@ -383,7 +412,7 @@ export type SelectorPropertySpecification = {
|
|
|
383
412
|
};
|
|
384
413
|
|
|
385
414
|
export type AppearanceSpecification = {
|
|
386
|
-
"condition"?:
|
|
415
|
+
"condition"?: DataDrivenPropertyValueSpecification<boolean>,
|
|
387
416
|
"name"?: string,
|
|
388
417
|
"properties"?: unknown
|
|
389
418
|
};
|
|
@@ -499,7 +528,8 @@ export type ModelSourceSpecification = {
|
|
|
499
528
|
"type": "model" | "batched-model",
|
|
500
529
|
"maxzoom"?: number,
|
|
501
530
|
"minzoom"?: number,
|
|
502
|
-
"tiles"?: Array<string
|
|
531
|
+
"tiles"?: Array<string>,
|
|
532
|
+
"models"?: ModelSourceModelsSpecification
|
|
503
533
|
};
|
|
504
534
|
|
|
505
535
|
export type SourceSpecification =
|
|
@@ -1099,6 +1129,10 @@ export type BuildingLayerSpecification = {
|
|
|
1099
1129
|
* @experimental This property is experimental and subject to change in future versions.
|
|
1100
1130
|
*/
|
|
1101
1131
|
"building-facade-floors"?: DataDrivenPropertyValueSpecification<number>,
|
|
1132
|
+
/**
|
|
1133
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1134
|
+
*/
|
|
1135
|
+
"building-facade-unit-width"?: DataDrivenPropertyValueSpecification<number>,
|
|
1102
1136
|
/**
|
|
1103
1137
|
* @experimental This property is experimental and subject to change in future versions.
|
|
1104
1138
|
*/
|
|
@@ -1116,7 +1150,22 @@ export type BuildingLayerSpecification = {
|
|
|
1116
1150
|
* @experimental This property is experimental and subject to change in future versions.
|
|
1117
1151
|
*/
|
|
1118
1152
|
"building-base"?: DataDrivenPropertyValueSpecification<number>,
|
|
1119
|
-
"building-base-transition"?: TransitionSpecification
|
|
1153
|
+
"building-base-transition"?: TransitionSpecification,
|
|
1154
|
+
/**
|
|
1155
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1156
|
+
*/
|
|
1157
|
+
"building-flood-light-wall-radius"?: DataDrivenPropertyValueSpecification<number>,
|
|
1158
|
+
"building-flood-light-wall-radius-transition"?: TransitionSpecification,
|
|
1159
|
+
/**
|
|
1160
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1161
|
+
*/
|
|
1162
|
+
"building-flood-light-ground-radius"?: DataDrivenPropertyValueSpecification<number>,
|
|
1163
|
+
"building-flood-light-ground-radius-transition"?: TransitionSpecification,
|
|
1164
|
+
/**
|
|
1165
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1166
|
+
*/
|
|
1167
|
+
"building-flip-roof-orientation"?: DataDrivenPropertyValueSpecification<boolean>,
|
|
1168
|
+
"building-flip-roof-orientation-transition"?: TransitionSpecification
|
|
1120
1169
|
},
|
|
1121
1170
|
"paint"?: {
|
|
1122
1171
|
/**
|
|
@@ -1166,7 +1215,23 @@ export type BuildingLayerSpecification = {
|
|
|
1166
1215
|
* @experimental This property is experimental and subject to change in future versions.
|
|
1167
1216
|
*/
|
|
1168
1217
|
"building-facade-emissive-chance"?: PropertyValueSpecification<number>,
|
|
1169
|
-
"building-cutoff-fade-range"?: ExpressionSpecification
|
|
1218
|
+
"building-cutoff-fade-range"?: ExpressionSpecification,
|
|
1219
|
+
/**
|
|
1220
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1221
|
+
*/
|
|
1222
|
+
"building-flood-light-color"?: PropertyValueSpecification<ColorSpecification>,
|
|
1223
|
+
"building-flood-light-color-transition"?: TransitionSpecification,
|
|
1224
|
+
"building-flood-light-color-use-theme"?: PropertyValueSpecification<string>,
|
|
1225
|
+
/**
|
|
1226
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1227
|
+
*/
|
|
1228
|
+
"building-flood-light-intensity"?: PropertyValueSpecification<number>,
|
|
1229
|
+
"building-flood-light-intensity-transition"?: TransitionSpecification,
|
|
1230
|
+
/**
|
|
1231
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1232
|
+
*/
|
|
1233
|
+
"building-flood-light-ground-attenuation"?: PropertyValueSpecification<number>,
|
|
1234
|
+
"building-flood-light-ground-attenuation-transition"?: TransitionSpecification
|
|
1170
1235
|
},
|
|
1171
1236
|
"appearances"?: Array<AppearanceSpecification>
|
|
1172
1237
|
};
|
|
@@ -1363,7 +1428,11 @@ export type ModelLayerSpecification = {
|
|
|
1363
1428
|
"model-height-based-emissive-strength-multiplier"?: DataDrivenPropertyValueSpecification<[number, number, number, number, number]>,
|
|
1364
1429
|
"model-height-based-emissive-strength-multiplier-transition"?: TransitionSpecification,
|
|
1365
1430
|
"model-cutoff-fade-range"?: ExpressionSpecification,
|
|
1366
|
-
"model-front-cutoff"?: PropertyValueSpecification<[number, number, number]
|
|
1431
|
+
"model-front-cutoff"?: PropertyValueSpecification<[number, number, number]>,
|
|
1432
|
+
/**
|
|
1433
|
+
* @experimental This property is experimental and subject to change in future versions.
|
|
1434
|
+
*/
|
|
1435
|
+
"model-elevation-reference"?: "sea" | "ground" | "hd-road-markup" | ExpressionSpecification
|
|
1367
1436
|
},
|
|
1368
1437
|
"appearances"?: Array<AppearanceSpecification>
|
|
1369
1438
|
};
|
package/util/geometry_util.ts
CHANGED
|
@@ -16,6 +16,7 @@ function calculateSignedArea(ring: Ring): number {
|
|
|
16
16
|
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
|
|
17
17
|
p1 = ring[i];
|
|
18
18
|
p2 = ring[j];
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
19
20
|
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
|
20
21
|
}
|
|
21
22
|
return sum;
|
|
@@ -44,13 +45,16 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
|
|
|
44
45
|
if (ccw === undefined) ccw = area < 0;
|
|
45
46
|
|
|
46
47
|
if (ccw === area < 0) {
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
47
49
|
if (polygon) polygons.push(polygon);
|
|
48
50
|
polygon = [rings[i]];
|
|
49
51
|
|
|
50
52
|
} else {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
51
54
|
(polygon).push(rings[i]);
|
|
52
55
|
}
|
|
53
56
|
}
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
54
58
|
if (polygon) polygons.push(polygon);
|
|
55
59
|
|
|
56
60
|
// Earcut performance degrades with the # of rings in a polygon. For this
|
package/validate/validate.ts
CHANGED
|
@@ -122,6 +122,7 @@ export default function validate(options: ValidatorOptions, arrayAsExpression: b
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
const errors = validateObject(Object.assign({}, options, {
|
|
125
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
125
126
|
valueSpec: valueSpec.type ? styleSpec[valueSpec.type] : valueSpec
|
|
126
127
|
}));
|
|
127
128
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import validateObject from './validate_object';
|
|
2
|
+
import ValidationError from '../error/validation_error';
|
|
3
|
+
import validateProperty from './validate_property';
|
|
4
|
+
import {unbundle} from '../util/unbundle_jsonlint';
|
|
5
|
+
import validateExpression from './validate_expression';
|
|
6
|
+
import latest from '../reference/latest';
|
|
7
|
+
|
|
8
|
+
import type {StyleSpecification, LayerSpecification, AppearanceSpecification} from '../types';
|
|
9
|
+
import type {StyleReference} from '../reference/latest';
|
|
10
|
+
|
|
11
|
+
export type AppearanceValidatorOptions = {
|
|
12
|
+
key: string;
|
|
13
|
+
value: unknown;
|
|
14
|
+
style: Partial<StyleSpecification>;
|
|
15
|
+
styleSpec: StyleReference;
|
|
16
|
+
object?: object;
|
|
17
|
+
objectKey?: string;
|
|
18
|
+
layer: LayerSpecification;
|
|
19
|
+
layerType: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default function validateAppearance(options: AppearanceValidatorOptions): Array<ValidationError> {
|
|
23
|
+
const {key, layer, layerType} = options;
|
|
24
|
+
const value = unbundle(options.value) as AppearanceSpecification;
|
|
25
|
+
const name = unbundle(value.name);
|
|
26
|
+
const condition = unbundle(value.condition);
|
|
27
|
+
|
|
28
|
+
const errors = validateObject({
|
|
29
|
+
key,
|
|
30
|
+
value,
|
|
31
|
+
valueSpec: options.styleSpec.appearance as object,
|
|
32
|
+
style: options.style,
|
|
33
|
+
styleSpec: options.styleSpec,
|
|
34
|
+
objectElementValidators: {
|
|
35
|
+
condition: (options) => validateCondition(Object.assign({layer, layerType}, options)),
|
|
36
|
+
properties: (options) => validateProperties(Object.assign({layer, layerType}, options)),
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (name !== 'hidden' && !condition) {
|
|
41
|
+
errors.push(new ValidationError(options.key, 'name', `Appearance with name different than "hidden" must have a condition`));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return errors;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function validateProperties(options: AppearanceValidatorOptions): Array<ValidationError> {
|
|
48
|
+
const errors: Array<ValidationError> = [];
|
|
49
|
+
|
|
50
|
+
const {styleSpec, layer, layerType} = options;
|
|
51
|
+
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
53
|
+
const paintProperties = styleSpec[`paint_${layerType}`];
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
55
|
+
const layoutProperties = styleSpec[`layout_${layerType}`];
|
|
56
|
+
const properties = options.object[options.objectKey] as object;
|
|
57
|
+
|
|
58
|
+
for (const propertyKey in properties) {
|
|
59
|
+
const propertyType =
|
|
60
|
+
propertyKey in paintProperties ? 'paint' :
|
|
61
|
+
propertyKey in layoutProperties ? 'layout' :
|
|
62
|
+
undefined;
|
|
63
|
+
|
|
64
|
+
if (!propertyType) {
|
|
65
|
+
errors.push(new ValidationError(options.key, propertyKey, `unknown property "${propertyKey}" for layer type "${layerType}"`));
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const propertyValidationOptions = Object.assign({}, options, {
|
|
70
|
+
key: `${options.key}.${propertyKey}`,
|
|
71
|
+
object: properties,
|
|
72
|
+
objectKey: propertyKey,
|
|
73
|
+
layer,
|
|
74
|
+
layerType,
|
|
75
|
+
value: properties[propertyKey] as unknown,
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
77
|
+
valueSpec: (propertyType === 'paint' ? paintProperties[propertyKey] : layoutProperties[propertyKey]) as object,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
errors.push(...validateProperty(propertyValidationOptions, propertyType));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return errors;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function validateCondition(options: AppearanceValidatorOptions): Array<ValidationError> {
|
|
87
|
+
const errors: Array<ValidationError> = [];
|
|
88
|
+
|
|
89
|
+
const appearance = options.object as AppearanceSpecification;
|
|
90
|
+
const condition = appearance.condition;
|
|
91
|
+
|
|
92
|
+
errors.push(...validateExpression({
|
|
93
|
+
key: options.key,
|
|
94
|
+
value: condition,
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
96
|
+
valueSpec: latest['appearance']['condition'],
|
|
97
|
+
expressionContext: 'appearance'
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
return errors;
|
|
101
|
+
}
|
|
@@ -72,6 +72,7 @@ export default function validateArray(options: ArrayValidatorOptions): Validatio
|
|
|
72
72
|
errors = errors.concat(validateArrayElement({
|
|
73
73
|
array,
|
|
74
74
|
arrayIndex: i,
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
75
76
|
value: array[i],
|
|
76
77
|
valueSpec: arrayElementSpec,
|
|
77
78
|
style,
|
|
@@ -4,10 +4,10 @@ import {deepUnbundle} from '../util/unbundle_jsonlint';
|
|
|
4
4
|
import {isStateConstant, isGlobalPropertyConstant, isFeatureConstant} from '../expression/is_constant';
|
|
5
5
|
import CompoundExpression from '../expression/compound_expression';
|
|
6
6
|
|
|
7
|
+
import type {StylePropertySpecification} from '../../style-spec/style-spec';
|
|
7
8
|
import type {Expression} from '../expression/expression';
|
|
8
9
|
import type {StyleReference} from '../reference/latest';
|
|
9
10
|
import type {StyleSpecification} from '../types';
|
|
10
|
-
import type {StylePropertySpecification} from '../style-spec';
|
|
11
11
|
|
|
12
12
|
export type ExpressionValidatorOptions = {
|
|
13
13
|
key: string;
|
|
@@ -17,7 +17,7 @@ export type ExpressionValidatorOptions = {
|
|
|
17
17
|
propertyType?: 'layout' | 'paint' | 'filter';
|
|
18
18
|
style?: Partial<StyleSpecification>;
|
|
19
19
|
styleSpec?: StyleReference;
|
|
20
|
-
expressionContext?: 'property' | 'filter' | 'cluster-initial' | 'cluster-reduce' | 'cluster-map';
|
|
20
|
+
expressionContext?: 'property' | 'filter' | 'cluster-initial' | 'cluster-reduce' | 'cluster-map' | 'appearance';
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export default function validateExpression(options: ExpressionValidatorOptions): ValidationError[] {
|
|
@@ -28,27 +28,37 @@ export default function validateExpression(options: ExpressionValidatorOptions):
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
32
32
|
const expressionObj = (expression.value as any).expression || (expression.value as any)._styleExpression.expression;
|
|
33
33
|
|
|
34
34
|
if (options.expressionContext === 'property' && (options.propertyKey === 'text-font') &&
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
|
35
36
|
!expressionObj.outputDefined()) {
|
|
36
37
|
return [new ValidationError(options.key, options.value, `Invalid data expression for "${options.propertyKey}". Output values must be contained as literals within the expression.`)];
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
if (options.expressionContext === 'property' && options.propertyType === 'layout' &&
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
40
42
|
(!isStateConstant(expressionObj))) {
|
|
41
43
|
return [new ValidationError(options.key, options.value, '"feature-state" data expressions are not supported with layout properties.')];
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
if (options.expressionContext === 'filter') {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
45
48
|
return disallowedFilterParameters(expressionObj, options);
|
|
46
49
|
}
|
|
47
50
|
|
|
51
|
+
if (options.expressionContext === 'appearance') {
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
53
|
+
return checkDisallowedParameters(expressionObj, options);
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
if (options.expressionContext && options.expressionContext.indexOf('cluster') === 0) {
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
49
58
|
if (!isGlobalPropertyConstant(expressionObj, ['zoom', 'feature-state'])) {
|
|
50
59
|
return [new ValidationError(options.key, options.value, '"zoom" and "feature-state" expressions are not supported with cluster properties.')];
|
|
51
60
|
}
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
52
62
|
if (options.expressionContext === 'cluster-initial' && !isFeatureConstant(expressionObj)) {
|
|
53
63
|
return [new ValidationError(options.key, options.value, 'Feature data expressions are not supported with initial expression part of cluster properties.')];
|
|
54
64
|
}
|
|
@@ -66,8 +76,11 @@ export function disallowedFilterParameters(e: Expression, options: any): Validat
|
|
|
66
76
|
'distance-from-center'
|
|
67
77
|
]);
|
|
68
78
|
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
69
80
|
if (options.valueSpec && options.valueSpec.expression) {
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
70
82
|
for (const param of options.valueSpec.expression.parameters) {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
71
84
|
disallowedParameters.delete(param);
|
|
72
85
|
}
|
|
73
86
|
}
|
|
@@ -79,6 +92,7 @@ export function disallowedFilterParameters(e: Expression, options: any): Validat
|
|
|
79
92
|
|
|
80
93
|
if (e instanceof CompoundExpression) {
|
|
81
94
|
if (disallowedParameters.has(e.name)) {
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
|
|
82
96
|
return [new ValidationError(options.key, options.value, `["${e.name}"] expression is not supported in a filter for a ${options.object.type} layer with id: ${options.object.id}`)];
|
|
83
97
|
}
|
|
84
98
|
}
|
|
@@ -88,3 +102,34 @@ export function disallowedFilterParameters(e: Expression, options: any): Validat
|
|
|
88
102
|
|
|
89
103
|
return errors;
|
|
90
104
|
}
|
|
105
|
+
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
107
|
+
function checkDisallowedParameters(e: Expression, options: any): ValidationError[] {
|
|
108
|
+
const allowedParameters = new Set<string>();
|
|
109
|
+
|
|
110
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
111
|
+
if (options.valueSpec && options.valueSpec.expression) {
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
113
|
+
for (const param of options.valueSpec.expression.parameters) {
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
115
|
+
allowedParameters.add(param);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (allowedParameters.size === 0) {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
const errors: ValidationError[] = [];
|
|
123
|
+
|
|
124
|
+
if (e instanceof CompoundExpression) {
|
|
125
|
+
if (!allowedParameters.has(e.name)) {
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
|
|
127
|
+
return [new ValidationError(options.key, options.value, `["${e.name}"] is not an allowed parameter`)];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
e.eachChild((arg) => {
|
|
131
|
+
errors.push(...checkDisallowedParameters(arg, options));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
return errors;
|
|
135
|
+
}
|
|
@@ -3,7 +3,6 @@ import validateExpression from './validate_expression';
|
|
|
3
3
|
import validateEnum from './validate_enum';
|
|
4
4
|
import {getType, isString, isNumber, isBoolean} from '../util/get_type';
|
|
5
5
|
import {unbundle, deepUnbundle} from '../util/unbundle_jsonlint';
|
|
6
|
-
import extend from '../util/extend';
|
|
7
6
|
import {isExpressionFilter} from '../feature_filter/index';
|
|
8
7
|
|
|
9
8
|
import type {StyleReference} from '../reference/latest';
|
|
@@ -26,8 +25,9 @@ export default function validateFilter(options: FilterValidatorOptions): Validat
|
|
|
26
25
|
// We default to a layerType of `fill` because that points to a non-dynamic filter definition within the style-spec.
|
|
27
26
|
const layerType = options.layerType || 'fill';
|
|
28
27
|
|
|
29
|
-
return validateExpression(
|
|
30
|
-
expressionContext: 'filter',
|
|
28
|
+
return validateExpression(Object.assign({}, options, {
|
|
29
|
+
expressionContext: 'filter' as const,
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
31
31
|
valueSpec: options.styleSpec[`filter_${layerType}`]
|
|
32
32
|
}));
|
|
33
33
|
} else {
|
|
@@ -51,6 +51,7 @@ function validateNonExpressionFilter(options: FilterValidatorOptions): Validatio
|
|
|
51
51
|
let errors: ValidationError[] = validateEnum({
|
|
52
52
|
key: `${key}[0]`,
|
|
53
53
|
value: value[0],
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
54
55
|
valueSpec: styleSpec.filter_operator
|
|
55
56
|
});
|
|
56
57
|
|
|
@@ -83,6 +84,7 @@ function validateNonExpressionFilter(options: FilterValidatorOptions): Validatio
|
|
|
83
84
|
errors = errors.concat(validateEnum({
|
|
84
85
|
key: `${key}[${i}]`,
|
|
85
86
|
value: value[i],
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
86
88
|
valueSpec: styleSpec.geometry_type
|
|
87
89
|
}));
|
|
88
90
|
} else if (!isString(value[i]) && !isNumber(value[i]) && !isBoolean(value[i])) {
|
package/validate/validate_fog.ts
CHANGED
|
@@ -16,6 +16,7 @@ export default function validateFog(options: FogValidatorOptions): ValidationErr
|
|
|
16
16
|
const fog = options.value;
|
|
17
17
|
const style = options.style;
|
|
18
18
|
const styleSpec = options.styleSpec;
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
19
20
|
const fogSpec = styleSpec.fog;
|
|
20
21
|
|
|
21
22
|
if (fog === undefined) {
|
|
@@ -31,6 +32,7 @@ export default function validateFog(options: FogValidatorOptions): ValidationErr
|
|
|
31
32
|
const transitionMatch = key.match(/^(.*)-transition$/);
|
|
32
33
|
const useThemeMatch = key.match(/^(.*)-use-theme$/);
|
|
33
34
|
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
34
36
|
if (useThemeMatch && fogSpec[useThemeMatch[1]]) {
|
|
35
37
|
errors = errors.concat(validate({
|
|
36
38
|
key,
|
|
@@ -39,18 +41,22 @@ export default function validateFog(options: FogValidatorOptions): ValidationErr
|
|
|
39
41
|
style,
|
|
40
42
|
styleSpec
|
|
41
43
|
}));
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
42
45
|
} else if (transitionMatch && fogSpec[transitionMatch[1]] && fogSpec[transitionMatch[1]].transition) {
|
|
43
46
|
errors = errors.concat(validate({
|
|
44
47
|
key,
|
|
45
48
|
value: fog[key],
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
50
|
valueSpec: styleSpec.transition,
|
|
47
51
|
style,
|
|
48
52
|
styleSpec
|
|
49
53
|
}));
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
50
55
|
} else if (fogSpec[key]) {
|
|
51
56
|
errors = errors.concat(validate({
|
|
52
57
|
key,
|
|
53
58
|
value: fog[key],
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
54
60
|
valueSpec: fogSpec[key],
|
|
55
61
|
style,
|
|
56
62
|
styleSpec
|
|
@@ -17,6 +17,7 @@ import type {StyleSpecification} from '../types';
|
|
|
17
17
|
import type {StylePropertySpecification} from '../style-spec';
|
|
18
18
|
|
|
19
19
|
function hasObjectStops(value: object): value is {stops: Array<Record<PropertyKey, unknown>>} {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
20
21
|
const stops = value['stops'];
|
|
21
22
|
return Array.isArray(stops) && Array.isArray(stops[0]) && isObject(stops[0][0]);
|
|
22
23
|
}
|
|
@@ -51,6 +52,7 @@ export default function validateFunction(options: FunctionValidatorOptions): Val
|
|
|
51
52
|
const errors = validateObject({
|
|
52
53
|
key: options.key,
|
|
53
54
|
value: options.value,
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
54
56
|
valueSpec: options.styleSpec.function,
|
|
55
57
|
style: options.style,
|
|
56
58
|
styleSpec: options.styleSpec,
|
|
@@ -38,6 +38,7 @@ export default function validateIconset(options: IconsetValidatorOptions): Valid
|
|
|
38
38
|
errors = errors.concat(validateObject({
|
|
39
39
|
key,
|
|
40
40
|
value: iconset,
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
41
42
|
valueSpec: styleSpec[`iconset_${type}`],
|
|
42
43
|
style,
|
|
43
44
|
styleSpec
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import extend from '../util/extend';
|
|
2
1
|
import validateStyle from './validate_style';
|
|
3
2
|
import validateObject from './validate_object';
|
|
4
3
|
import ValidationError from '../error/validation_error';
|
|
@@ -31,8 +30,9 @@ export default function validateImport(options: ImportValidatorOptions): Validat
|
|
|
31
30
|
enumerable: false
|
|
32
31
|
});
|
|
33
32
|
|
|
34
|
-
let errors = validateObject(
|
|
33
|
+
let errors = validateObject(Object.assign({}, options, {
|
|
35
34
|
value: importSpec,
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
36
36
|
valueSpec: styleSpec.import
|
|
37
37
|
}));
|
|
38
38
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import ValidationError from '../error/validation_error';
|
|
2
2
|
import {unbundle} from '../util/unbundle_jsonlint';
|
|
3
|
+
import validateArray from './validate_array';
|
|
3
4
|
import validateObject from './validate_object';
|
|
4
5
|
import validateFilter from './validate_filter';
|
|
6
|
+
import validateAppearance, {type AppearanceValidatorOptions} from './validate_appearance';
|
|
5
7
|
import validatePaintProperty from './validate_paint_property';
|
|
6
8
|
import validateLayoutProperty from './validate_layout_property';
|
|
7
9
|
import validateSpec from './validate';
|
|
8
|
-
import extend from '../util/extend';
|
|
9
10
|
import {isObject, isString} from '../util/get_type';
|
|
10
11
|
|
|
11
12
|
import type {StyleReference} from '../reference/latest';
|
|
@@ -64,9 +65,11 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
64
65
|
if (!parent) {
|
|
65
66
|
if (typeof ref === 'string')
|
|
66
67
|
errors.push(new ValidationError(key, layer.ref, `ref layer "${ref}" not found`));
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
67
69
|
} else if (parent.ref) {
|
|
68
70
|
errors.push(new ValidationError(key, layer.ref, 'ref cannot reference another ref layer'));
|
|
69
71
|
} else {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
70
73
|
type = unbundle(parent.type) as string;
|
|
71
74
|
}
|
|
72
75
|
} else if (!(type === 'background' || type === 'sky' || type === 'slot')) {
|
|
@@ -101,6 +104,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
101
104
|
errors = errors.concat(validateObject({
|
|
102
105
|
key,
|
|
103
106
|
value: layer,
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
104
108
|
valueSpec: styleSpec.layer,
|
|
105
109
|
style: options.style,
|
|
106
110
|
styleSpec: options.styleSpec,
|
|
@@ -114,6 +118,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
114
118
|
return validateSpec({
|
|
115
119
|
key: `${key}.type`,
|
|
116
120
|
value: layer.type,
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
117
122
|
valueSpec: styleSpec.layer.type,
|
|
118
123
|
style: options.style,
|
|
119
124
|
styleSpec: options.styleSpec,
|
|
@@ -122,7 +127,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
122
127
|
});
|
|
123
128
|
},
|
|
124
129
|
filter(options) {
|
|
125
|
-
return validateFilter(
|
|
130
|
+
return validateFilter(Object.assign({layerType: type}, options));
|
|
126
131
|
},
|
|
127
132
|
layout(options) {
|
|
128
133
|
return validateObject({
|
|
@@ -134,7 +139,7 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
134
139
|
styleSpec: options.styleSpec,
|
|
135
140
|
objectElementValidators: {
|
|
136
141
|
'*'(options) {
|
|
137
|
-
return validateLayoutProperty(
|
|
142
|
+
return validateLayoutProperty(Object.assign({layerType: type}, options));
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
145
|
});
|
|
@@ -149,10 +154,38 @@ export default function validateLayer(options: LayerValidatorOptions): Validatio
|
|
|
149
154
|
styleSpec: options.styleSpec,
|
|
150
155
|
objectElementValidators: {
|
|
151
156
|
'*'(options) {
|
|
152
|
-
return validatePaintProperty(
|
|
157
|
+
return validatePaintProperty(Object.assign({layerType: type, layer}, options));
|
|
153
158
|
}
|
|
154
159
|
}
|
|
155
160
|
});
|
|
161
|
+
},
|
|
162
|
+
appearances(options) {
|
|
163
|
+
const validationErrors = validateArray({
|
|
164
|
+
key: options.key,
|
|
165
|
+
value: options.value,
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
167
|
+
valueSpec: options.valueSpec,
|
|
168
|
+
style: options.style,
|
|
169
|
+
styleSpec: options.styleSpec,
|
|
170
|
+
arrayElementValidator: (options) => validateAppearance(Object.assign({layerType: type, layer}, options) as AppearanceValidatorOptions)
|
|
171
|
+
});
|
|
172
|
+
// Check non-repeated names on a given layer
|
|
173
|
+
const appearances = Array.isArray(options.value) ? options.value : [];
|
|
174
|
+
const dedupedNames = new Set<string>();
|
|
175
|
+
appearances.forEach((a, index) => {
|
|
176
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
177
|
+
const name: string | undefined = unbundle(a.name) as string | undefined;
|
|
178
|
+
if (name) {
|
|
179
|
+
if (dedupedNames.has(name)) {
|
|
180
|
+
const layerId = unbundle((layer as LayerSpecification).id) as string;
|
|
181
|
+
validationErrors.push(new ValidationError(options.key, name, `Duplicated appearance name "${name}" for layer "${layerId}"`));
|
|
182
|
+
} else {
|
|
183
|
+
dedupedNames.add(name);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
return validationErrors;
|
|
156
189
|
}
|
|
157
190
|
}
|
|
158
191
|
}));
|
|
@@ -15,6 +15,7 @@ type LightValidatorOptions = {
|
|
|
15
15
|
export default function validateLight(options: LightValidatorOptions): ValidationError[] {
|
|
16
16
|
const light = options.value;
|
|
17
17
|
const styleSpec = options.styleSpec;
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
18
19
|
const lightSpec = styleSpec.light;
|
|
19
20
|
const style = options.style;
|
|
20
21
|
|
|
@@ -31,6 +32,7 @@ export default function validateLight(options: LightValidatorOptions): Validatio
|
|
|
31
32
|
const transitionMatch = key.match(/^(.*)-transition$/);
|
|
32
33
|
const useThemeMatch = key.match(/^(.*)-use-theme$/);
|
|
33
34
|
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
34
36
|
if (useThemeMatch && lightSpec[useThemeMatch[1]]) {
|
|
35
37
|
errors = errors.concat(validate({
|
|
36
38
|
key,
|
|
@@ -39,18 +41,22 @@ export default function validateLight(options: LightValidatorOptions): Validatio
|
|
|
39
41
|
style,
|
|
40
42
|
styleSpec
|
|
41
43
|
}));
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
42
45
|
} else if (transitionMatch && lightSpec[transitionMatch[1]] && lightSpec[transitionMatch[1]].transition) {
|
|
43
46
|
errors = errors.concat(validate({
|
|
44
47
|
key,
|
|
45
48
|
value: light[key],
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
50
|
valueSpec: styleSpec.transition,
|
|
47
51
|
style,
|
|
48
52
|
styleSpec
|
|
49
53
|
}));
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
50
55
|
} else if (lightSpec[key]) {
|
|
51
56
|
errors = errors.concat(validate({
|
|
52
57
|
key,
|
|
53
58
|
value: light[key],
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
|
|
54
60
|
valueSpec: lightSpec[key],
|
|
55
61
|
style,
|
|
56
62
|
styleSpec
|