@mapbox/mapbox-gl-style-spec 14.15.0-beta.1 → 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.
Files changed (75) hide show
  1. package/deref.ts +3 -0
  2. package/diff.ts +63 -0
  3. package/dist/index.cjs +743 -65
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +85 -6
  6. package/dist/index.es.js +743 -65
  7. package/dist/index.es.js.map +1 -1
  8. package/expression/compound_expression.ts +4 -0
  9. package/expression/definitions/assertion.ts +7 -0
  10. package/expression/definitions/case.ts +2 -1
  11. package/expression/definitions/coalesce.ts +4 -0
  12. package/expression/definitions/coercion.ts +12 -0
  13. package/expression/definitions/collator.ts +8 -5
  14. package/expression/definitions/comparison.ts +12 -5
  15. package/expression/definitions/config.ts +12 -0
  16. package/expression/definitions/distance.ts +13 -2
  17. package/expression/definitions/format.ts +10 -0
  18. package/expression/definitions/image.ts +3 -0
  19. package/expression/definitions/in.ts +5 -0
  20. package/expression/definitions/index.ts +62 -10
  21. package/expression/definitions/index_of.ts +6 -0
  22. package/expression/definitions/interpolate.ts +5 -1
  23. package/expression/definitions/length.ts +2 -0
  24. package/expression/definitions/let.ts +1 -0
  25. package/expression/definitions/match.ts +5 -0
  26. package/expression/definitions/number_format.ts +7 -0
  27. package/expression/definitions/slice.ts +4 -0
  28. package/expression/definitions/within.ts +1 -0
  29. package/expression/index.ts +28 -19
  30. package/expression/parsing_context.ts +2 -0
  31. package/expression/types/image_variant.ts +3 -0
  32. package/expression/types.ts +1 -2
  33. package/expression/values.ts +1 -0
  34. package/feature_filter/convert.ts +9 -1
  35. package/feature_filter/index.ts +41 -1
  36. package/format.ts +5 -0
  37. package/function/convert.ts +5 -0
  38. package/function/index.ts +79 -25
  39. package/group_by_layout.ts +4 -5
  40. package/migrate/v8.ts +42 -3
  41. package/migrate/v9.ts +5 -0
  42. package/migrate.ts +1 -0
  43. package/package.json +1 -1
  44. package/read_style.ts +2 -0
  45. package/reference/v8.json +457 -12
  46. package/rollup.config.js +1 -0
  47. package/test.js +4 -0
  48. package/types.ts +74 -5
  49. package/util/color.ts +21 -26
  50. package/util/geometry_util.ts +4 -0
  51. package/validate/validate.ts +1 -0
  52. package/validate/validate_appearance.ts +101 -0
  53. package/validate/validate_array.ts +1 -0
  54. package/validate/validate_expression.ts +48 -3
  55. package/validate/validate_filter.ts +5 -3
  56. package/validate/validate_fog.ts +6 -0
  57. package/validate/validate_function.ts +2 -0
  58. package/validate/validate_iconset.ts +1 -0
  59. package/validate/validate_import.ts +2 -2
  60. package/validate/validate_layer.ts +37 -4
  61. package/validate/validate_light.ts +6 -0
  62. package/validate/validate_lights.ts +9 -0
  63. package/validate/validate_model.ts +1 -2
  64. package/validate/validate_number.ts +2 -0
  65. package/validate/validate_object.ts +7 -0
  66. package/validate/validate_projection.ts +2 -0
  67. package/validate/validate_property.ts +15 -4
  68. package/validate/validate_rain.ts +5 -0
  69. package/validate/validate_snow.ts +5 -0
  70. package/validate/validate_source.ts +12 -0
  71. package/validate/validate_style.ts +1 -0
  72. package/validate/validate_terrain.ts +6 -0
  73. package/validate_mapbox_api_supported.ts +1 -0
  74. package/visit.ts +2 -0
  75. 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"?: ExpressionSpecification,
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/color.ts CHANGED
@@ -206,46 +206,41 @@ export abstract class RenderColor {
206
206
 
207
207
  if (this.premultiplied) {
208
208
  if (a === 0) return [0, 0, 0, 0];
209
-
210
- r /= a;
211
- g /= a;
212
- b /= a;
209
+ const invA = 1 / a; // Single division, then multiply
210
+ r *= invA;
211
+ g *= invA;
212
+ b *= invA;
213
213
  }
214
214
 
215
- const red = Math.min(Math.max(r, 0.0), 1.0);
216
- const green = Math.min(Math.max(g, 0.0), 1.0);
217
- const blue = Math.min(Math.max(b, 0.0), 1.0);
215
+ const red = Math.min(Math.max(r, 0), 1);
216
+ const green = Math.min(Math.max(g, 0), 1);
217
+ const blue = Math.min(Math.max(b, 0), 1);
218
218
 
219
219
  const min = Math.min(red, green, blue);
220
220
  const max = Math.max(red, green, blue);
221
+ const delta = max - min;
221
222
 
222
- const l = (min + max) / 2;
223
+ const l = (min + max) * 0.5;
223
224
 
224
- if (min === max) {
225
+ if (delta === 0) {
225
226
  return [0, 0, l * 100, a];
226
227
  }
227
228
 
228
- const delta = max - min;
229
-
230
229
  const s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);
231
230
 
232
- let h = 0;
233
- if (max === red) {
234
- h = (green - blue) / delta + (green < blue ? 6 : 0);
235
- } else if (max === green) {
236
- h = (blue - red) / delta + 2;
237
- } else if (max === blue) {
238
- h = (red - green) / delta + 4;
231
+ let h: number;
232
+ switch (max) {
233
+ case red:
234
+ h = ((green - blue) / delta + (green < blue ? 6 : 0)) * 60;
235
+ break;
236
+ case green:
237
+ h = ((blue - red) / delta + 2) * 60;
238
+ break;
239
+ default: // blue
240
+ h = ((red - green) / delta + 4) * 60;
239
241
  }
240
242
 
241
- h *= 60;
242
-
243
- return [
244
- Math.min(Math.max(h, 0), 360),
245
- Math.min(Math.max(s * 100, 0), 100),
246
- Math.min(Math.max(l * 100, 0), 100),
247
- a
248
- ];
243
+ return [h, s * 100, l * 100, a];
249
244
  }
250
245
 
251
246
  /**
@@ -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
@@ -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(extend({}, options, {
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])) {
@@ -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(extend({}, options, {
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