@mapbox/mapbox-gl-style-spec 14.7.1 → 14.8.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.
@@ -40,15 +40,28 @@ class At implements Expression {
40
40
  throw new RuntimeError(`Array index out of bounds: ${index} < 0.`);
41
41
  }
42
42
 
43
- if (index >= array.length) {
43
+ if (index > array.length - 1) {
44
44
  throw new RuntimeError(`Array index out of bounds: ${index} > ${array.length - 1}.`);
45
45
  }
46
46
 
47
- if (index !== Math.floor(index)) {
48
- throw new RuntimeError(`Array index must be an integer, but found ${index} instead.`);
47
+ if (index === Math.floor(index)) {
48
+ return array[index];
49
49
  }
50
50
 
51
- return array[index];
51
+ // Interpolation logic for non-integer indices
52
+ const lowerIndex = Math.floor(index);
53
+ const upperIndex = Math.ceil(index);
54
+
55
+ const lowerValue = array[lowerIndex];
56
+ const upperValue = array[upperIndex];
57
+
58
+ if (typeof lowerValue !== 'number' || typeof upperValue !== 'number') {
59
+ throw new RuntimeError(`Cannot interpolate between non-number values at index ${index}.`);
60
+ }
61
+
62
+ // Linear interpolation
63
+ const fraction = index - lowerIndex;
64
+ return lowerValue * (1 - fraction) + upperValue * fraction;
52
65
  }
53
66
 
54
67
  eachChild(fn: (_: Expression) => void) {
@@ -80,20 +80,18 @@ function splitRange(range: IndexRange, isLine: boolean) {
80
80
  }
81
81
 
82
82
  function getBBox(pointSets: Array<GeoJSON.Position>, range: IndexRange) {
83
- const bbox = [Infinity, Infinity, -Infinity, -Infinity];
83
+ const bbox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
84
84
  if (!isRangeSafe(range, pointSets.length)) return bbox;
85
85
  for (let i = range[0]; i <= range[1]; ++i) {
86
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
87
86
  updateBBox(bbox, pointSets[i]);
88
87
  }
89
88
  return bbox;
90
89
  }
91
90
 
92
91
  function getPolygonBBox(polygon: Array<Array<GeoJSON.Position>>) {
93
- const bbox = [Infinity, Infinity, -Infinity, -Infinity];
92
+ const bbox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
94
93
  for (let i = 0; i < polygon.length; ++i) {
95
94
  for (let j = 0; j < polygon[i].length; ++j) {
96
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
97
95
  updateBBox(bbox, polygon[i][j]);
98
96
  }
99
97
  }
@@ -263,11 +261,9 @@ function polygonIntersect(polygon1: Array<Array<GeoJSON.Position>>, polygon2: Ar
263
261
  function polygonToPolygonDistance(polygon1: Array<Array<GeoJSON.Position>>, polygon2: Array<Array<GeoJSON.Position>>, ruler: CheapRuler, currentMiniDist: number = Infinity) {
264
262
  const bbox1 = getPolygonBBox(polygon1);
265
263
  const bbox2 = getPolygonBBox(polygon2);
266
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
267
264
  if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2, ruler) >= currentMiniDist) {
268
265
  return currentMiniDist;
269
266
  }
270
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
271
267
  if (boxWithinBox(bbox1, bbox2)) {
272
268
  if (polygonIntersect(polygon1, polygon2)) return 0.0;
273
269
  } else if (polygonIntersect(polygon2, polygon1)) {
@@ -289,7 +285,6 @@ function polygonToPolygonDistance(polygon1: Array<Array<GeoJSON.Position>>, poly
289
285
 
290
286
  function updateQueue(distQueue: any, miniDist: number, ruler: CheapRuler, pointSet1: Array<GeoJSON.Position>, pointSet2: Array<GeoJSON.Position>, r1: IndexRange | null, r2: IndexRange | null) {
291
287
  if (r1 === null || r2 === null) return;
292
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
293
288
  const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2), ruler);
294
289
  // Insert new pair to the queue if the bbox distance is less than miniDist, the pair with biggest distance will be at the top
295
290
  if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: r1, range2: r2});
@@ -330,12 +325,10 @@ function pointSetToPolygonDistance(pointSets: Array<GeoJSON.Position>, isLine: b
330
325
  } else {
331
326
  const newRanges = splitRange(range, isLine);
332
327
  if (newRanges[0] !== null) {
333
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
334
328
  const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox, ruler);
335
329
  if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[0], range2: [0, 0]});
336
330
  }
337
331
  if (newRanges[1] !== null) {
338
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
339
332
  const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox, ruler);
340
333
  if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[1], range2: [0, 0]});
341
334
  }
@@ -394,7 +387,6 @@ function pointSetToLinesDistance(pointSet: Array<GeoJSON.Position>, isLine: bool
394
387
  let dist = currentMiniDist;
395
388
  const bbox1 = getBBox(pointSet, [0, pointSet.length - 1]);
396
389
  for (const line of lines) {
397
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
398
390
  if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]), ruler) >= dist) continue;
399
391
  dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true /*isLine*/, ruler, dist));
400
392
  if (dist === 0.0) return dist;
@@ -406,7 +398,6 @@ function pointSetToPolygonsDistance(points: Array<GeoJSON.Position>, isLine: boo
406
398
  let dist = currentMiniDist;
407
399
  const bbox1 = getBBox(points, [0, points.length - 1]);
408
400
  for (const polygon of polygons) {
409
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
410
401
  if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon), ruler) >= dist) continue;
411
402
  const tempDist = pointSetToPolygonDistance(points, isLine, polygon, ruler, dist);
412
403
  if (isNaN(tempDist)) return tempDist;
@@ -155,8 +155,8 @@ function getTileLines(geometry: Array<Array<Point>> | null | undefined, lineBBox
155
155
  }
156
156
 
157
157
  function pointsWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPolygons) {
158
- const pointBBox = [Infinity, Infinity, -Infinity, -Infinity];
159
- const polyBBox = [Infinity, Infinity, -Infinity, -Infinity];
158
+ const pointBBox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
159
+ const polyBBox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
160
160
 
161
161
  const canonical = ctx.canonicalID();
162
162
  if (!canonical) {
@@ -164,11 +164,8 @@ function pointsWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPo
164
164
  }
165
165
 
166
166
  if (polygonGeometry.type === 'Polygon') {
167
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
168
167
  const tilePolygon = getTilePolygon(polygonGeometry.coordinates, polyBBox, canonical);
169
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
170
168
  const tilePoints = getTilePoints(ctx.geometry(), pointBBox, polyBBox, canonical);
171
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
172
169
  if (!boxWithinBox(pointBBox, polyBBox)) return false;
173
170
 
174
171
  for (const point of tilePoints) {
@@ -176,11 +173,8 @@ function pointsWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPo
176
173
  }
177
174
  }
178
175
  if (polygonGeometry.type === 'MultiPolygon') {
179
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
180
176
  const tilePolygons = getTilePolygons(polygonGeometry.coordinates, polyBBox, canonical);
181
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
182
177
  const tilePoints = getTilePoints(ctx.geometry(), pointBBox, polyBBox, canonical);
183
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
184
178
  if (!boxWithinBox(pointBBox, polyBBox)) return false;
185
179
 
186
180
  for (const point of tilePoints) {
@@ -192,8 +186,8 @@ function pointsWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPo
192
186
  }
193
187
 
194
188
  function linesWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPolygons) {
195
- const lineBBox = [Infinity, Infinity, -Infinity, -Infinity];
196
- const polyBBox = [Infinity, Infinity, -Infinity, -Infinity];
189
+ const lineBBox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
190
+ const polyBBox: BBox = [Infinity, Infinity, -Infinity, -Infinity];
197
191
 
198
192
  const canonical = ctx.canonicalID();
199
193
  if (!canonical) {
@@ -201,11 +195,8 @@ function linesWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPol
201
195
  }
202
196
 
203
197
  if (polygonGeometry.type === 'Polygon') {
204
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
205
198
  const tilePolygon = getTilePolygon(polygonGeometry.coordinates, polyBBox, canonical);
206
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
207
199
  const tileLines = getTileLines(ctx.geometry(), lineBBox, polyBBox, canonical);
208
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
209
200
  if (!boxWithinBox(lineBBox, polyBBox)) return false;
210
201
 
211
202
  for (const line of tileLines) {
@@ -213,11 +204,8 @@ function linesWithinPolygons(ctx: EvaluationContext, polygonGeometry: GeoJSONPol
213
204
  }
214
205
  }
215
206
  if (polygonGeometry.type === 'MultiPolygon') {
216
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
217
207
  const tilePolygons = getTilePolygons(polygonGeometry.coordinates, polyBBox, canonical);
218
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
219
208
  const tileLines = getTileLines(ctx.geometry(), lineBBox, polyBBox, canonical);
220
- // @ts-expect-error - TS2345 - Argument of type 'number[]' is not assignable to parameter of type 'BBox'.
221
209
  if (!boxWithinBox(lineBBox, polyBBox)) return false;
222
210
 
223
211
  for (const line of tileLines) {
@@ -238,9 +226,8 @@ class Within implements Expression {
238
226
  this.geometries = geometries;
239
227
  }
240
228
 
241
- static parse(args: ReadonlyArray<unknown>, context: ParsingContext): Within | null | undefined {
229
+ static parse(args: ReadonlyArray<unknown>, context: ParsingContext): Within | void {
242
230
  if (args.length !== 2)
243
- // @ts-expect-error - TS2322 - Type 'void' is not assignable to type 'Within'.
244
231
  return context.error(`'within' expression requires exactly one argument, but found ${args.length - 1} instead.`);
245
232
  if (isValue(args[1])) {
246
233
  const geojson = (args[1] as any);
@@ -256,11 +243,10 @@ class Within implements Expression {
256
243
  if (type === 'Polygon' || type === 'MultiPolygon') {
257
244
  return new Within(geojson, geojson.geometry);
258
245
  }
259
- } else if (geojson.type === 'Polygon' || geojson.type === 'MultiPolygon') {
246
+ } else if (geojson.type === 'Polygon' || geojson.type === 'MultiPolygon') {
260
247
  return new Within(geojson, geojson);
261
248
  }
262
249
  }
263
- // @ts-expect-error - TS2322 - Type 'void' is not assignable to type 'Within'.
264
250
  return context.error(`'within' expression requires valid geojson object that contains polygon geometry type.`);
265
251
  }
266
252
 
@@ -16,7 +16,8 @@ import {
16
16
  supportsPropertyExpression,
17
17
  supportsZoomExpression,
18
18
  supportsLightExpression,
19
- supportsInterpolation
19
+ supportsInterpolation,
20
+ supportsLineProgressExpression
20
21
  } from '../util/properties';
21
22
  import {isFunction, createFunction} from '../function/index';
22
23
  import {Color} from './values';
@@ -71,6 +72,7 @@ export class StyleExpression {
71
72
  _defaultValue: Value;
72
73
  _warningHistory: {[key: string]: boolean};
73
74
  _enumValues?: {[_: string]: unknown};
75
+ configDependencies: Set<string>;
74
76
 
75
77
  constructor(expression: Expression, propertySpec?: StylePropertySpecification, scope?: string, options?: ConfigOptions) {
76
78
  this.expression = expression;
@@ -78,6 +80,7 @@ export class StyleExpression {
78
80
  this._evaluator = new EvaluationContext(scope, options);
79
81
  this._defaultValue = propertySpec ? getDefaultValue(propertySpec) : null;
80
82
  this._enumValues = propertySpec && propertySpec.type === 'enum' ? propertySpec.values : null;
83
+ this.configDependencies = isConstant.getConfigDependencies(expression);
81
84
  }
82
85
 
83
86
  evaluateWithoutErrorHandling(
@@ -360,6 +363,11 @@ export function createPropertyExpression(
360
363
  return error([new ParsingError('', 'measure-light expression not supported')]);
361
364
  }
362
365
 
366
+ const isLineProgressConstant = isConstant.isGlobalPropertyConstant(parsed, ['line-progress']);
367
+ if (!isLineProgressConstant && !supportsLineProgressExpression(propertySpec)) {
368
+ return error([new ParsingError('', 'line-progress expression not supported')]);
369
+ }
370
+
363
371
  const canRelaxZoomRestriction = propertySpec.expression && propertySpec.expression.relaxZoomRestriction;
364
372
  const zoomCurve = findZoomCurve(parsed);
365
373
  if (!zoomCurve && !isZoomConstant && !canRelaxZoomRestriction) {
@@ -371,7 +379,7 @@ export function createPropertyExpression(
371
379
  }
372
380
 
373
381
  if (!zoomCurve) {
374
- return success(isFeatureConstant ?
382
+ return success((isFeatureConstant && isLineProgressConstant) ?
375
383
  // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
376
384
  (new ZoomConstantExpression('constant', expression.value, isLightConstant) as ConstantExpression) :
377
385
  // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
@@ -380,7 +388,7 @@ export function createPropertyExpression(
380
388
 
381
389
  const interpolationType = zoomCurve instanceof Interpolate ? zoomCurve.interpolation : undefined;
382
390
 
383
- return success(isFeatureConstant ?
391
+ return success((isFeatureConstant && isLineProgressConstant) ?
384
392
  // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
385
393
  (new ZoomDependentExpression('camera', expression.value, zoomCurve.labels, interpolationType, isLightConstant) as CameraExpression) :
386
394
  // @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
@@ -1,6 +1,6 @@
1
1
  class ParsingError extends Error {
2
2
  key: string;
3
- message: string;
3
+ override message: string;
4
4
  constructor(key: string, message: string) {
5
5
  super(message);
6
6
  this.message = message;
@@ -2,6 +2,7 @@ import latest from '../reference/latest';
2
2
  import {deepUnbundle} from '../util/unbundle_jsonlint';
3
3
  import {createExpression} from '../expression/index';
4
4
  import {isFeatureConstant} from '../expression/is_constant';
5
+ import assert from 'assert';
5
6
 
6
7
  import type Point from '@mapbox/point-geometry';
7
8
  import type {CanonicalTileID} from '../types/tile_id';
@@ -109,14 +110,18 @@ ${JSON.stringify(filterExp, null, 2)}
109
110
  }
110
111
 
111
112
  // Compile the static component of the filter
112
- const filterSpec = latest[`filter_${layerType}`];
113
- const compiledStaticFilter = createExpression(staticFilter, filterSpec, scope, options);
114
-
115
113
  let filterFunc = null;
116
- if (compiledStaticFilter.result === 'error') {
117
- throw new Error(compiledStaticFilter.value.map(err => `${err.key}: ${err.message}`).join(', '));
118
- } else {
119
- filterFunc = (globalProperties: GlobalProperties, feature: Feature, canonical?: CanonicalTileID) => compiledStaticFilter.value.evaluate(globalProperties, feature, {}, canonical);
114
+ let filterSpec = null;
115
+ if (layerType !== 'background' && layerType !== 'sky' && layerType !== 'slot') {
116
+ filterSpec = latest[`filter_${layerType}`];
117
+ assert(filterSpec);
118
+ const compiledStaticFilter = createExpression(staticFilter, filterSpec, scope, options);
119
+
120
+ if (compiledStaticFilter.result === 'error') {
121
+ throw new Error(compiledStaticFilter.value.map(err => `${err.key}: ${err.message}`).join(', '));
122
+ } else {
123
+ filterFunc = (globalProperties: GlobalProperties, feature: Feature, canonical?: CanonicalTileID) => compiledStaticFilter.value.evaluate(globalProperties, feature, {}, canonical);
124
+ }
120
125
  }
121
126
 
122
127
  // If the static component is not equal to the entire filter then we have a dynamic component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapbox/mapbox-gl-style-spec",
3
- "version": "14.7.1",
3
+ "version": "14.8.0",
4
4
  "description": "a specification for mapbox gl styles",
5
5
  "author": "Mapbox",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",