@mapbox/mapbox-gl-style-spec 14.23.0 → 14.24.0-rc.1

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 (50) hide show
  1. package/composite.ts +5 -3
  2. package/diff.ts +37 -80
  3. package/dist/index.cjs +159 -113
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +4 -0
  6. package/dist/index.es.js +159 -113
  7. package/dist/index.es.js.map +1 -1
  8. package/error/parsing_error.ts +3 -1
  9. package/expression/compound_expression.ts +11 -4
  10. package/expression/definitions/assertion.ts +2 -3
  11. package/expression/definitions/case.ts +1 -1
  12. package/expression/definitions/coercion.ts +4 -4
  13. package/expression/definitions/format.ts +1 -1
  14. package/expression/definitions/image.ts +2 -2
  15. package/expression/definitions/in.ts +1 -1
  16. package/expression/definitions/index.ts +7 -8
  17. package/expression/definitions/interpolate.ts +1 -1
  18. package/expression/definitions/let.ts +4 -2
  19. package/expression/definitions/match.ts +1 -1
  20. package/expression/definitions/step.ts +1 -1
  21. package/expression/is_constant.ts +2 -2
  22. package/expression/parsing_context.ts +18 -4
  23. package/expression/stops.ts +2 -1
  24. package/expression/types/image_variant.ts +5 -3
  25. package/feature_filter/index.ts +7 -30
  26. package/function/index.ts +7 -6
  27. package/migrate/v9.ts +1 -1
  28. package/package.json +1 -1
  29. package/reference/v8.json +20 -0
  30. package/types.ts +5 -1
  31. package/util/color.ts +2 -7
  32. package/util/geometry_util.ts +3 -8
  33. package/util/interpolate.ts +2 -3
  34. package/util/lerp.ts +3 -0
  35. package/util/properties.ts +4 -1
  36. package/validate/validate_enum.ts +2 -2
  37. package/validate/validate_fog.ts +3 -2
  38. package/validate/validate_function.ts +2 -2
  39. package/validate/validate_glyphs_url.ts +2 -2
  40. package/validate/validate_layer.ts +6 -5
  41. package/validate/validate_light.ts +3 -2
  42. package/validate/validate_lights.ts +3 -2
  43. package/validate/validate_model.ts +1 -1
  44. package/validate/validate_object.ts +1 -3
  45. package/validate/validate_property.ts +7 -5
  46. package/validate/validate_rain.ts +2 -1
  47. package/validate/validate_snow.ts +2 -1
  48. package/validate/validate_style.ts +1 -0
  49. package/validate/validate_terrain.ts +3 -2
  50. package/validate_mapbox_api_supported.ts +9 -8
@@ -1,5 +1,7 @@
1
1
  // Note: Do not inherit from Error. It breaks when transpiling to ES5.
2
2
 
3
+ const LINE_NUMBER_RE = /line (\d+)/;
4
+
3
5
  export default class ParsingError {
4
6
  message: string;
5
7
  error: Error;
@@ -8,7 +10,7 @@ export default class ParsingError {
8
10
  constructor(error: Error) {
9
11
  this.error = error;
10
12
  this.message = error.message;
11
- const match = error.message.match(/line (\d+)/);
13
+ const match = error.message.match(LINE_NUMBER_RE);
12
14
  this.line = match ? parseInt(match[1], 10) : 0;
13
15
  }
14
16
  }
@@ -83,9 +83,16 @@ class CompoundExpression implements Expression {
83
83
  overloadParams.push(params);
84
84
  overloadIndex++;
85
85
 
86
- // Use a fresh context for each attempted signature so that, if
87
- // we eventually succeed, we haven't polluted `context.errors`.
88
- signatureContext = new ParsingContext(context.registry, context.path, null, context.scope, undefined, context._scope, context.options, context.iconImageUseTheme);
86
+ // Use a fresh-looking context for each attempted signature so
87
+ // that, if we eventually succeed, we haven't polluted
88
+ // `context.errors`. We allocate the context once and reset its
89
+ // errors between overload attempts; the other fields are
90
+ // identical across attempts.
91
+ if (signatureContext === null) {
92
+ signatureContext = new ParsingContext(context.registry, context.path, null, context.scope, [], context._scope, context.options, context.iconImageUseTheme);
93
+ } else {
94
+ signatureContext.errors.length = 0;
95
+ }
89
96
 
90
97
  // First parse all the args, potentially coercing to the
91
98
  // types expected by this overload.
@@ -120,7 +127,7 @@ class CompoundExpression implements Expression {
120
127
  for (let i = 0; i < parsedArgs.length; i++) {
121
128
  const expected = Array.isArray(params) ? params[i] : params.type;
122
129
  const arg = parsedArgs[i];
123
- signatureContext.concat(i + 1).checkSubtype(expected, arg.type);
130
+ signatureContext.checkSubtype(expected, arg.type, i + 1);
124
131
  }
125
132
 
126
133
  if (signatureContext.errors.length === 0) {
@@ -38,11 +38,11 @@ class Assertion implements Expression {
38
38
  return context.error(`Expected at least one argument.`);
39
39
 
40
40
  let i = 1;
41
- let type;
41
+ let type: Type;
42
42
 
43
43
  const name = args[0] as string;
44
44
  if (name === 'array') {
45
- let itemType;
45
+ let itemType: Type;
46
46
  if (args.length > 2) {
47
47
  const type = args[1];
48
48
  if (typeof type !== 'string' || !(type in types) || type === 'object')
@@ -67,7 +67,6 @@ class Assertion implements Expression {
67
67
  i++;
68
68
  }
69
69
 
70
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
71
70
  type = array(itemType, N);
72
71
  } else {
73
72
  assert(types[name], name);
@@ -48,7 +48,7 @@ class Case implements Expression {
48
48
  outputType = outputType || result.type;
49
49
  }
50
50
 
51
- const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
51
+ const otherwise = context.parse(args.at(-1), args.length - 1, outputType);
52
52
  if (!otherwise) return null;
53
53
 
54
54
  assert(outputType);
@@ -65,7 +65,7 @@ class Coercion implements Expression {
65
65
  for (let i = 0; i < arrayLength; i++) {
66
66
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
67
67
  const member = args[1][i];
68
- let parsedMember;
68
+ let parsedMember: Expression | null | void;
69
69
  if (Array.isArray(member)) {
70
70
  parsedMember = context.parse(member, undefined, type.itemType);
71
71
  } else {
@@ -103,8 +103,9 @@ class Coercion implements Expression {
103
103
  if (this.type.kind === 'boolean') {
104
104
  return Boolean(this.args[0].evaluate(ctx));
105
105
  } else if (this.type.kind === 'color') {
106
- let input;
107
- let error;
106
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
107
+ let input: any;
108
+ let error: string | null;
108
109
  for (const arg of this.args) {
109
110
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
110
111
  input = arg.evaluate(ctx);
@@ -126,7 +127,6 @@ class Coercion implements Expression {
126
127
  }
127
128
  }
128
129
  }
129
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
130
130
  throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : String(JSON.stringify(input))}'`);
131
131
  } else if (this.type.kind === 'number') {
132
132
  let value = null;
@@ -70,7 +70,7 @@ export default class FormatExpression implements Expression {
70
70
  if (!textColor) return null;
71
71
  }
72
72
 
73
- const lastExpression = sections[sections.length - 1];
73
+ const lastExpression = sections.at(-1);
74
74
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
75
75
  lastExpression.scale = scale;
76
76
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -121,7 +121,7 @@ export default class ImageExpression implements Expression {
121
121
  parsedParams[key] = value;
122
122
  }
123
123
 
124
- imageExpression[imageExpression.length - 1].options.params = parsedParams;
124
+ imageExpression.at(-1).options.params = parsedParams;
125
125
  }
126
126
 
127
127
  // Validate the iconset image options
@@ -136,7 +136,7 @@ export default class ImageExpression implements Expression {
136
136
  return false;
137
137
  }
138
138
 
139
- imageExpression[imageExpression.length - 1].options.iconset = iconset;
139
+ imageExpression.at(-1).options.iconset = iconset;
140
140
  }
141
141
 
142
142
  nextArgId++;
@@ -66,7 +66,7 @@ class In implements Expression {
66
66
  }
67
67
 
68
68
  // Type assertions safe due to isValidNativeType checks above
69
- return (haystack as string | unknown[]).indexOf(needle as string) >= 0;
69
+ return (haystack as string | unknown[]).includes(needle as string);
70
70
  }
71
71
 
72
72
  eachChild(fn: (_: Expression) => void) {
@@ -617,21 +617,21 @@ CompoundExpression.register(expressions, {
617
617
  'filter-type-in': [
618
618
  BooleanType,
619
619
  [array(StringType)],
620
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
621
- (ctx, [v]) => (v).value.indexOf(ctx.geometryType()) >= 0
620
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
621
+ (ctx, [v]) => (v).value.includes(ctx.geometryType())
622
622
  ],
623
623
  'filter-id-in': [
624
624
  BooleanType,
625
625
  [array(ValueType)],
626
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
627
- (ctx, [v]) => (v).value.indexOf(ctx.id()) >= 0
626
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
627
+ (ctx, [v]) => (v).value.includes(ctx.id())
628
628
  ],
629
629
  'filter-in-small': [
630
630
  BooleanType,
631
631
  [StringType, array(ValueType)],
632
632
  // assumes v is an array literal
633
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
634
- (ctx, [k, v]) => (v).value.indexOf(ctx.properties()[(k).value]) >= 0
633
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
634
+ (ctx, [k, v]) => (v).value.includes(ctx.properties()[(k).value])
635
635
  ],
636
636
  'filter-in-large': [
637
637
  BooleanType,
@@ -736,7 +736,7 @@ CompoundExpression.register(expressions, {
736
736
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
737
737
  return min;
738
738
  }
739
- let seedVal;
739
+ let seedVal: number;
740
740
  if (typeof seed === 'string') {
741
741
  seedVal = hashString(seed);
742
742
  } else if (typeof seed === 'number') {
@@ -744,7 +744,6 @@ CompoundExpression.register(expressions, {
744
744
  } else {
745
745
  throw new RuntimeError(`Invalid seed input: ${seed}`);
746
746
  }
747
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
748
747
  const random = mulberry32(seedVal)();
749
748
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
750
749
  return min + random * (max - min);
@@ -129,7 +129,7 @@ class Interpolate implements Expression {
129
129
  return context.error('Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
130
130
  }
131
131
 
132
- if (stops.length && stops[stops.length - 1][0] >= label) {
132
+ if (stops.length && stops.at(-1)[0] >= label) {
133
133
  return context.error('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.', labelKey);
134
134
  }
135
135
 
@@ -3,6 +3,8 @@ import type {Expression, SerializedExpression} from '../expression';
3
3
  import type ParsingContext from '../parsing_context';
4
4
  import type EvaluationContext from '../evaluation_context';
5
5
 
6
+ const INVALID_VAR_CHAR_RE = /[^a-zA-Z0-9_]/;
7
+
6
8
  class Let implements Expression {
7
9
  type: Type;
8
10
  bindings: Array<[string, Expression]>;
@@ -39,7 +41,7 @@ class Let implements Expression {
39
41
  return context.error(`Expected string, but found ${typeof name} instead.`, i);
40
42
  }
41
43
 
42
- if (/[^a-zA-Z0-9_]/.test(name)) {
44
+ if (INVALID_VAR_CHAR_RE.test(name)) {
43
45
  return context.error(`Variable names must contain only alphanumeric characters or '_'.`, i);
44
46
  }
45
47
 
@@ -49,7 +51,7 @@ class Let implements Expression {
49
51
  bindings.push([name, value]);
50
52
  }
51
53
 
52
- const result = context.parse(args[args.length - 1], args.length - 1, context.expectedType, bindings);
54
+ const result = context.parse(args.at(-1), args.length - 1, context.expectedType, bindings);
53
55
  if (!result) return null;
54
56
 
55
57
  return new Let(bindings, result);
@@ -86,7 +86,7 @@ class Match implements Expression {
86
86
  const input = context.parse(args[1], 1, ValueType);
87
87
  if (!input) return null;
88
88
 
89
- const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
89
+ const otherwise = context.parse(args.at(-1), args.length - 1, outputType);
90
90
  if (!otherwise) return null;
91
91
 
92
92
  assert(inputType && outputType);
@@ -56,7 +56,7 @@ class Step implements Expression {
56
56
  return context.error('Input/output pairs for "step" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
57
57
  }
58
58
 
59
- if (stops.length && stops[stops.length - 1][0] >= label) {
59
+ if (stops.length && stops.at(-1)[0] >= label) {
60
60
  return context.error('Input/output pairs for "step" expressions must be arranged with input values in strictly ascending order.', labelKey);
61
61
  }
62
62
 
@@ -19,7 +19,7 @@ function isFeatureConstant(e: Expression): boolean {
19
19
  e.name === 'id'
20
20
  ) {
21
21
  return false;
22
- } else if (/^filter-/.test(e.name)) {
22
+ } else if (e.name.startsWith('filter-')) {
23
23
  return false;
24
24
  }
25
25
  }
@@ -57,7 +57,7 @@ function isStateConstant(e: Expression): boolean {
57
57
  }
58
58
 
59
59
  function isGlobalPropertyConstant(e: Expression, properties: Array<string>): boolean {
60
- if (e instanceof CompoundExpression && properties.indexOf(e.name) >= 0) { return false; }
60
+ if (e instanceof CompoundExpression && properties.includes(e.name)) { return false; }
61
61
  let result = true;
62
62
  e.eachChild((arg) => {
63
63
  if (result && !isGlobalPropertyConstant(arg, properties)) { result = false; }
@@ -24,7 +24,6 @@ import type {ConfigOptions} from '../types/config_options';
24
24
  class ParsingContext {
25
25
  registry: ExpressionRegistry;
26
26
  path: Array<number | string>;
27
- key: string;
28
27
  scope: Scope;
29
28
  errors: Array<ParsingError>;
30
29
  _scope: string | null | undefined;
@@ -37,6 +36,9 @@ class ParsingContext {
37
36
  // `expectedType`.
38
37
  expectedType: Type | null | undefined;
39
38
 
39
+ // `key` is only consulted on the error path, so compute it lazily.
40
+ private _key: string | undefined;
41
+
40
42
  constructor(
41
43
  registry: ExpressionRegistry,
42
44
  path: Array<number | string> = [],
@@ -49,7 +51,6 @@ class ParsingContext {
49
51
  ) {
50
52
  this.registry = registry;
51
53
  this.path = path;
52
- this.key = path.map(part => { if (typeof part === 'string') { return `['${part}']`; } return `[${part}]`; }).join('');
53
54
  this.scope = scope;
54
55
  this.errors = errors;
55
56
  this.expectedType = expectedType;
@@ -58,6 +59,19 @@ class ParsingContext {
58
59
  this.iconImageUseTheme = iconImageUseTheme;
59
60
  }
60
61
 
62
+ get key(): string {
63
+ if (this._key === undefined) {
64
+ const path = this.path;
65
+ let key = '';
66
+ for (let i = 0; i < path.length; i++) {
67
+ const part = path[i];
68
+ key += typeof part === 'string' ? `['${part}']` : `[${part}]`;
69
+ }
70
+ this._key = key;
71
+ }
72
+ return this._key;
73
+ }
74
+
61
75
  /**
62
76
  * @param expr the JSON expression to parse
63
77
  * @param index the optional argument index if this expression is an argument of a parent expression that's being parsed
@@ -226,9 +240,9 @@ class ParsingContext {
226
240
  * Returns null if `t` is a subtype of `expected`; otherwise returns an
227
241
  * error message and also pushes it to `this.errors`.
228
242
  */
229
- checkSubtype(expected: Type, t: Type): string | null | undefined {
243
+ checkSubtype(expected: Type, t: Type, index?: number): string | null | undefined {
230
244
  const error = checkSubtype(expected, t);
231
- if (error) this.error(error);
245
+ if (error) this.error(error, ...(typeof index === 'number' ? [index] : []));
232
246
  return error;
233
247
  }
234
248
  }
@@ -13,7 +13,8 @@ export function findStopLessThanOrEqualTo(stops: Array<number>, input: number):
13
13
  let lowerIndex = 0;
14
14
  let upperIndex = lastIndex;
15
15
  let currentIndex = 0;
16
- let currentValue, nextValue;
16
+ let currentValue: number;
17
+ let nextValue: number;
17
18
 
18
19
  while (lowerIndex <= upperIndex) {
19
20
  currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
@@ -47,7 +47,10 @@ export class ImageVariant implements RasterizationOptions {
47
47
  }
48
48
 
49
49
  static parse(str: StringifiedImageVariant): ImageVariant | null {
50
- let id, params, sx, sy;
50
+ let id: ImageIdSpec | undefined;
51
+ let params: Record<string, Color> | undefined;
52
+ let sx: number | undefined;
53
+ let sy: number | undefined;
51
54
 
52
55
  try {
53
56
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
@@ -58,8 +61,7 @@ export class ImageVariant implements RasterizationOptions {
58
61
 
59
62
  if (!id) return null;
60
63
 
61
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
62
- return new ImageVariant(id as ImageIdSpec, {params, sx, sy});
64
+ return new ImageVariant(id, {params, sx, sy});
63
65
  }
64
66
 
65
67
  scaleSelf(factor: number, yFactor: number = factor): this {
@@ -160,7 +160,7 @@ ${JSON.stringify(filterExp, null, 2)}
160
160
  }
161
161
 
162
162
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
- function extractStaticFilter(filter: any): any {
163
+ function extractStaticFilter(filter: unknown | unknown[]): any {
164
164
  if (!isDynamicFilter(filter)) {
165
165
  return filter;
166
166
  }
@@ -169,7 +169,7 @@ function extractStaticFilter(filter: any): any {
169
169
  let result = deepUnbundle(filter);
170
170
 
171
171
  // 1. Union branches
172
- unionDynamicBranches(result);
172
+ unionDynamicBranches(result as unknown[]);
173
173
 
174
174
  // 2. Collapse dynamic conditions to `true`
175
175
  result = collapseDynamicBooleanExpressions(result);
@@ -202,59 +202,36 @@ function collapseDynamicBooleanExpressions(expression: any): any {
202
202
  *
203
203
  * @param {Array<any>} filter the filter expression mutated in-place.
204
204
  */
205
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
206
- function unionDynamicBranches(filter: any) {
205
+ function unionDynamicBranches(filter: unknown[]) {
207
206
  let isBranchingDynamically = false;
208
- const branches = [];
209
-
210
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
207
+ const branches: unknown[] = [];
211
208
  if (filter[0] === 'case') {
212
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
213
209
  for (let i = 1; i < filter.length - 1; i += 2) {
214
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
215
210
  isBranchingDynamically = isBranchingDynamically || isDynamicFilter(filter[i]);
216
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
217
211
  branches.push(filter[i + 1]);
218
212
  }
219
-
220
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
221
- branches.push(filter[filter.length - 1]);
222
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
213
+ branches.push(filter.at(-1));
223
214
  } else if (filter[0] === 'match') {
224
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
225
215
  isBranchingDynamically = isBranchingDynamically || isDynamicFilter(filter[1]);
226
-
227
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
228
216
  for (let i = 2; i < filter.length - 1; i += 2) {
229
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
230
217
  branches.push(filter[i + 1]);
231
218
  }
232
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
233
- branches.push(filter[filter.length - 1]);
234
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
219
+ branches.push(filter.at(-1));
235
220
  } else if (filter[0] === 'step') {
236
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
237
221
  isBranchingDynamically = isBranchingDynamically || isDynamicFilter(filter[1]);
238
-
239
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
240
222
  for (let i = 1; i < filter.length - 1; i += 2) {
241
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
242
223
  branches.push(filter[i + 1]);
243
224
  }
244
225
  }
245
226
 
246
227
  if (isBranchingDynamically) {
247
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
248
228
  filter.length = 0;
249
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
250
229
  filter.push('any', ...branches);
251
230
  }
252
231
 
253
232
  // traverse and recurse into children
254
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
255
233
  for (let i = 1; i < filter.length; i++) {
256
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
257
- unionDynamicBranches(filter[i]);
234
+ unionDynamicBranches(filter[i] as unknown[]);
258
235
  }
259
236
  }
260
237
 
package/function/index.ts CHANGED
@@ -60,9 +60,10 @@ export function createFunction(parameters, propertySpec) {
60
60
  throw new Error(`Unknown color space: ${parameters.colorSpace}`);
61
61
  }
62
62
 
63
- let innerFun;
64
- let hashedStops;
65
- let categoricalKeyType;
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ let innerFun: ((parameters: any, propertySpec: any, input: any, hashedStops?: any, categoricalKeyType?: any) => any) | undefined;
65
+ let hashedStops: Record<string | number, unknown> | undefined;
66
+ let categoricalKeyType: string | undefined;
66
67
  if (type === 'exponential') {
67
68
  innerFun = evaluateExponentialFunction;
68
69
  } else if (type === 'interval') {
@@ -75,7 +76,7 @@ export function createFunction(parameters, propertySpec) {
75
76
  hashedStops = Object.create(null);
76
77
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
77
78
  for (const stop of parameters.stops) {
78
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
79
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
79
80
  hashedStops[stop[0]] = stop[1];
80
81
  }
81
82
 
@@ -154,7 +155,7 @@ export function createFunction(parameters, propertySpec) {
154
155
  interpolationFactor: Interpolate.interpolationFactor.bind(undefined, interpolationType),
155
156
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
156
157
  zoomStops: parameters.stops.map(s => s[0]),
157
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
158
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
158
159
  evaluate: ({zoom}) => innerFun(parameters, propertySpec, zoom, hashedStops, categoricalKeyType)
159
160
  };
160
161
  } else {
@@ -167,7 +168,7 @@ export function createFunction(parameters, propertySpec) {
167
168
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
168
169
  return coalesce(parameters.default, propertySpec.default);
169
170
  }
170
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
171
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
171
172
  return innerFun(parameters, propertySpec, value, hashedStops, categoricalKeyType);
172
173
  }
173
174
  };
package/migrate/v9.ts CHANGED
@@ -21,7 +21,7 @@ export default function (style) {
21
21
  // remove class-specific paint properties
22
22
  eachLayer(style, (layer) => {
23
23
  for (const k in layer) {
24
- if (/paint\..*/.test(k)) {
24
+ if (k.includes('paint.')) {
25
25
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
26
26
  delete layer[k];
27
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapbox/mapbox-gl-style-spec",
3
- "version": "14.23.0",
3
+ "version": "14.24.0-rc.1",
4
4
  "description": "a specification for mapbox gl styles",
5
5
  "author": "Mapbox",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
package/reference/v8.json CHANGED
@@ -8982,6 +8982,26 @@
8982
8982
  ]
8983
8983
  },
8984
8984
  "property-type": "data-constant"
8985
+ },
8986
+ "line-blend-additive-clamp": {
8987
+ "type": "number",
8988
+ "default": 0,
8989
+ "minimum": 0,
8990
+ "doc": "Controls the brightness of lines in additive blend mode. When set to 0 (the default), brightness is adjusted automatically based on the density of lines visible on screen. Increase this value if the lines appear too bright, or decrease it if they appear too faint.",
8991
+ "experimental": true,
8992
+ "private": true,
8993
+ "sdk-support": {
8994
+ "basic functionality": {
8995
+ "js": "3.21.0"
8996
+ }
8997
+ },
8998
+ "expression": {
8999
+ "interpolated": true,
9000
+ "parameters": [
9001
+ "zoom"
9002
+ ]
9003
+ },
9004
+ "property-type": "data-constant"
8985
9005
  }
8986
9006
  },
8987
9007
  "paint_circle": {
package/types.ts CHANGED
@@ -759,7 +759,11 @@ export type LineLayerSpecification = {
759
759
  /**
760
760
  * @experimental This property is experimental and subject to change in future versions.
761
761
  */
762
- "line-blend-mode"?: PropertyValueSpecification<"default" | "multiply" | "additive">
762
+ "line-blend-mode"?: PropertyValueSpecification<"default" | "multiply" | "additive">,
763
+ /**
764
+ * @experimental This property is experimental and subject to change in future versions.
765
+ */
766
+ "line-blend-additive-clamp"?: PropertyValueSpecification<number>
763
767
  },
764
768
  /**
765
769
  * @experimental This property is experimental and subject to change in future versions.
package/util/color.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import {parseCSSColor} from 'csscolorparser';
2
- import {number as lerp} from './interpolate';
2
+ import {number as lerp} from './lerp';
3
3
 
4
4
  import type {LUT} from '../types/lut';
5
5
 
@@ -74,12 +74,7 @@ class Color {
74
74
  * translucentGreen.toString(); // = "rgba(26,207,26,0.73)"
75
75
  */
76
76
  toString(): string {
77
- const [r, g, b, a] = [
78
- this.r,
79
- this.g,
80
- this.b,
81
- this.a
82
- ];
77
+ const {r, g, b, a} = this;
83
78
  return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;
84
79
  }
85
80
 
@@ -13,10 +13,9 @@ export type BBox = [number, number, number, number];
13
13
  */
14
14
  function calculateSignedArea(ring: Ring): number {
15
15
  let sum = 0;
16
- for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
16
+ for (let i = 0, len = ring.length, j = len - 1, p1: Point, p2: Point; 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
20
19
  sum += (p2.x - p1.x) * (p1.y + p2.y);
21
20
  }
22
21
  return sum;
@@ -33,8 +32,8 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
33
32
  if (len <= 1) return [rings];
34
33
 
35
34
  const polygons: Array<Array<Ring>> = [];
36
- let polygon,
37
- ccw;
35
+ let polygon: Array<Ring>,
36
+ ccw: boolean;
38
37
 
39
38
  for (let i = 0; i < len; i++) {
40
39
  const area = calculateSignedArea(rings[i]);
@@ -45,16 +44,12 @@ export function classifyRings(rings: Array<Ring>, maxRings: number): Array<Array
45
44
  if (ccw === undefined) ccw = area < 0;
46
45
 
47
46
  if (ccw === area < 0) {
48
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
49
47
  if (polygon) polygons.push(polygon);
50
48
  polygon = [rings[i]];
51
-
52
49
  } else {
53
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
54
50
  (polygon).push(rings[i]);
55
51
  }
56
52
  }
57
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
58
53
  if (polygon) polygons.push(polygon);
59
54
 
60
55
  // Earcut performance degrades with the # of rings in a polygon. For this
@@ -1,8 +1,7 @@
1
1
  import Color from './color';
2
+ import {number} from './lerp';
2
3
 
3
- export function number(a: number, b: number, t: number): number {
4
- return (a * (1 - t)) + (b * t);
5
- }
4
+ export {number};
6
5
 
7
6
  export function color(from: Color, to: Color, t: number): Color {
8
7
  return new Color(
package/util/lerp.ts ADDED
@@ -0,0 +1,3 @@
1
+ export function number(a: number, b: number, t: number): number {
2
+ return (a * (1 - t)) + (b * t);
3
+ }
@@ -1,12 +1,15 @@
1
1
  import type {PropertyExpressionSpecification, StylePropertySpecification} from '../style-spec';
2
2
 
3
+ export const TRANSITION_KEY_RE = /^(.*)-transition$/;
4
+ export const USE_THEME_KEY_RE = /^(.*)-use-theme$/;
5
+
3
6
  type ExpressionParameter = PropertyExpressionSpecification['parameters'][number];
4
7
 
5
8
  function expressionHasParameter(
6
9
  expression: PropertyExpressionSpecification | null | undefined,
7
10
  parameter: ExpressionParameter,
8
11
  ): boolean {
9
- return !!expression && !!expression.parameters && expression.parameters.indexOf(parameter) > -1;
12
+ return !!expression && !!expression.parameters && expression.parameters.includes(parameter);
10
13
  }
11
14
 
12
15
  export function supportsPropertyExpression(spec: StylePropertySpecification): boolean {