@mapbox/mapbox-gl-style-spec 14.6.0 → 14.7.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 (45) hide show
  1. package/dist/index.cjs +2423 -2497
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.ts +57 -29
  4. package/dist/index.es.js +2423 -2497
  5. package/dist/index.es.js.map +1 -1
  6. package/expression/compound_expression.ts +1 -2
  7. package/expression/definitions/assertion.ts +1 -2
  8. package/expression/definitions/at.ts +0 -1
  9. package/expression/definitions/case.ts +0 -1
  10. package/expression/definitions/coalesce.ts +1 -2
  11. package/expression/definitions/coercion.ts +1 -2
  12. package/expression/definitions/collator.ts +7 -5
  13. package/expression/definitions/distance.ts +1 -1
  14. package/expression/definitions/format.ts +4 -4
  15. package/expression/definitions/index.ts +0 -1
  16. package/expression/definitions/interpolate.ts +1 -2
  17. package/expression/definitions/length.ts +1 -2
  18. package/expression/definitions/match.ts +0 -1
  19. package/expression/definitions/number_format.ts +5 -5
  20. package/expression/definitions/step.ts +0 -1
  21. package/expression/definitions/within.ts +3 -3
  22. package/expression/expression.ts +4 -4
  23. package/expression/index.ts +4 -7
  24. package/expression/is_constant.ts +1 -0
  25. package/expression/parsing_context.ts +28 -5
  26. package/expression/values.ts +1 -2
  27. package/feature_filter/index.ts +6 -5
  28. package/group_by_layout.ts +2 -2
  29. package/package.json +1 -1
  30. package/reference/v8.json +196 -37
  31. package/rollup.config.js +1 -2
  32. package/style-spec.ts +2 -3
  33. package/types.ts +59 -36
  34. package/union-to-intersection.ts +4 -0
  35. package/util/color.ts +1 -0
  36. package/util/color_spaces.ts +0 -1
  37. package/util/deep_equal.ts +1 -1
  38. package/util/geometry_util.ts +1 -2
  39. package/validate/validate.ts +2 -3
  40. package/validate/validate_expression.ts +0 -1
  41. package/validate/validate_function.ts +1 -1
  42. package/validate/validate_property.ts +2 -3
  43. package/validate/validate_style.ts +1 -2
  44. package/validate_style.min.ts +0 -1
  45. package/visit.ts +2 -2
@@ -1,9 +1,8 @@
1
1
  import {toString} from './types';
2
-
3
2
  import ParsingContext from './parsing_context';
4
- import EvaluationContext from './evaluation_context';
5
3
  import assert from 'assert';
6
4
 
5
+ import type EvaluationContext from './evaluation_context';
7
6
  import type {Expression, ExpressionRegistry} from './expression';
8
7
  import type {Type} from './types';
9
8
  import type {Value} from './values';
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import {
4
3
  ObjectType,
5
4
  ValueType,
@@ -83,7 +82,7 @@ class Assertion implements Expression {
83
82
  return new Assertion(type, parsed);
84
83
  }
85
84
 
86
- evaluate(ctx: EvaluationContext): any | null {
85
+ evaluate(ctx: EvaluationContext): any {
87
86
  for (let i = 0; i < this.args.length; i++) {
88
87
  const value = this.args[i].evaluate(ctx);
89
88
  const error = checkSubtype(this.type, typeOf(value));
@@ -1,5 +1,4 @@
1
1
  import {array, ValueType, NumberType} from '../types';
2
-
3
2
  import RuntimeError from '../runtime_error';
4
3
 
5
4
  import type {Expression, SerializedExpression} from '../expression';
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import {BooleanType} from '../types';
4
3
 
5
4
  import type {Expression, SerializedExpression} from '../expression';
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import {checkSubtype, ValueType} from '../types';
4
3
  import ResolvedImage from '../types/resolved_image';
5
4
 
@@ -50,7 +49,7 @@ class Coalesce implements Expression {
50
49
  new Coalesce((outputType as any), parsedArgs);
51
50
  }
52
51
 
53
- evaluate(ctx: EvaluationContext): any | null {
52
+ evaluate(ctx: EvaluationContext): any {
54
53
  let result = null;
55
54
  let argCount = 0;
56
55
  let firstImage;
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import {BooleanType, ColorType, NumberType, StringType, ValueType, array, NullType} from '../types';
4
3
  import {Color, isValue, toString as valueToString, typeOf, validateRGBA} from '../values';
5
4
  import RuntimeError from '../runtime_error';
@@ -7,12 +6,12 @@ import Formatted from '../types/formatted';
7
6
  import FormatExpression from '../definitions/format';
8
7
  import ImageExpression from '../definitions/image';
9
8
  import ResolvedImage from '../types/resolved_image';
9
+ import getType from '../../util/get_type';
10
10
 
11
11
  import type {Expression, SerializedExpression} from '../expression';
12
12
  import type ParsingContext from '../parsing_context';
13
13
  import type EvaluationContext from '../evaluation_context';
14
14
  import type {Type, ArrayType} from '../types';
15
- import getType from '../../util/get_type';
16
15
 
17
16
  const types = {
18
17
  'to-boolean': BooleanType,
@@ -29,17 +29,19 @@ export default class CollatorExpression implements Expression {
29
29
  // @ts-expect-error - TS2322 - Type 'void' is not assignable to type 'Expression'.
30
30
  return context.error(`Collator options argument must be an object.`);
31
31
 
32
- const caseSensitive = context.parse(
33
- options['case-sensitive'] === undefined ? false : options['case-sensitive'], 1, BooleanType);
32
+ const caseSensitive = options['case-sensitive'] === undefined ?
33
+ context.parse(false, 1, BooleanType) :
34
+ context.parseObjectValue(options['case-sensitive'], 1, 'case-sensitive', BooleanType);
34
35
  if (!caseSensitive) return null;
35
36
 
36
- const diacriticSensitive = context.parse(
37
- options['diacritic-sensitive'] === undefined ? false : options['diacritic-sensitive'], 1, BooleanType);
37
+ const diacriticSensitive = options['diacritic-sensitive'] === undefined ?
38
+ context.parse(false, 1, BooleanType) :
39
+ context.parseObjectValue(options['diacritic-sensitive'], 1, 'diacritic-sensitive', BooleanType);
38
40
  if (!diacriticSensitive) return null;
39
41
 
40
42
  let locale = null;
41
43
  if (options['locale']) {
42
- locale = context.parse(options['locale'], 1, StringType);
44
+ locale = context.parseObjectValue(options['locale'], 1, 'locale', StringType);
43
45
  if (!locale) return null;
44
46
  }
45
47
 
@@ -2,10 +2,10 @@ import {isValue} from '../values';
2
2
  import {NumberType} from '../types';
3
3
  import {classifyRings, updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util';
4
4
  import CheapRuler from "cheap-ruler";
5
- import Point from "@mapbox/point-geometry";
6
5
  import TinyQueue from "tinyqueue";
7
6
  import EXTENT from '../../data/extent';
8
7
 
8
+ import type Point from "@mapbox/point-geometry";
9
9
  import type ParsingContext from '../parsing_context';
10
10
  import type {BBox} from '../../util/geometry_util';
11
11
  import type {Type} from '../types';
@@ -55,19 +55,19 @@ export default class FormatExpression implements Expression {
55
55
 
56
56
  let scale = null;
57
57
  if (arg['font-scale']) {
58
- scale = context.parse(arg['font-scale'], 1, NumberType);
58
+ scale = context.parseObjectValue(arg['font-scale'], i, 'font-scale', NumberType);
59
59
  if (!scale) return null;
60
60
  }
61
61
 
62
62
  let font = null;
63
63
  if (arg['text-font']) {
64
- font = context.parse(arg['text-font'], 1, array(StringType));
64
+ font = context.parseObjectValue(arg['text-font'], i, 'text-font', array(StringType));
65
65
  if (!font) return null;
66
66
  }
67
67
 
68
68
  let textColor = null;
69
69
  if (arg['text-color']) {
70
- textColor = context.parse(arg['text-color'], 1, ColorType);
70
+ textColor = context.parseObjectValue(arg['text-color'], i, 'text-color', ColorType);
71
71
  if (!textColor) return null;
72
72
  }
73
73
 
@@ -76,7 +76,7 @@ export default class FormatExpression implements Expression {
76
76
  lastExpression.font = font;
77
77
  lastExpression.textColor = textColor;
78
78
  } else {
79
- const content = context.parse(args[i], 1, ValueType);
79
+ const content = context.parse(args[i], i, ValueType);
80
80
  if (!content) return null;
81
81
 
82
82
  const kind = content.type.kind;
@@ -10,7 +10,6 @@ import {
10
10
  array,
11
11
  toString as typeToString,
12
12
  } from '../types';
13
-
14
13
  import {typeOf, Color, validateRGBA, validateHSLA, toString as valueToString} from '../values';
15
14
  import CompoundExpression from '../compound_expression';
16
15
  import RuntimeError from '../runtime_error';
@@ -1,11 +1,10 @@
1
1
  import UnitBezier from '@mapbox/unitbezier';
2
-
3
2
  import * as interpolate from '../../util/interpolate';
4
3
  import {toString, NumberType, ColorType} from '../types';
5
4
  import {findStopLessThanOrEqualTo} from '../stops';
6
5
  import {hcl, lab} from '../../util/color_spaces';
7
- import Color from '../../util/color';
8
6
 
7
+ import type Color from '../../util/color';
9
8
  import type {Stops} from '../stops';
10
9
  import type {Expression, SerializedExpression} from '../expression';
11
10
  import type ParsingContext from '../parsing_context';
@@ -1,5 +1,4 @@
1
1
  import {NumberType, toString} from '../types';
2
-
3
2
  import {typeOf} from '../values';
4
3
  import RuntimeError from '../runtime_error';
5
4
 
@@ -32,7 +31,7 @@ class Length implements Expression {
32
31
  return new Length(input);
33
32
  }
34
33
 
35
- evaluate(ctx: EvaluationContext): any | number {
34
+ evaluate(ctx: EvaluationContext): number {
36
35
  const input = this.input.evaluate(ctx);
37
36
  if (typeof input === 'string') {
38
37
  return input.length;
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import {typeOf} from '../values';
4
3
  import {ValueType} from '../types';
5
4
 
@@ -44,31 +44,31 @@ export default class NumberFormat implements Expression {
44
44
 
45
45
  let locale = null;
46
46
  if (options['locale']) {
47
- locale = context.parse(options['locale'], 1, StringType);
47
+ locale = context.parseObjectValue(options['locale'], 2, 'locale', StringType);
48
48
  if (!locale) return null;
49
49
  }
50
50
 
51
51
  let currency = null;
52
52
  if (options['currency']) {
53
- currency = context.parse(options['currency'], 1, StringType);
53
+ currency = context.parseObjectValue(options['currency'], 2, 'currency', StringType);
54
54
  if (!currency) return null;
55
55
  }
56
56
 
57
57
  let unit = null;
58
58
  if (options['unit']) {
59
- unit = context.parse(options['unit'], 1, StringType);
59
+ unit = context.parseObjectValue(options['unit'], 2, 'unit', StringType);
60
60
  if (!unit) return null;
61
61
  }
62
62
 
63
63
  let minFractionDigits = null;
64
64
  if (options['min-fraction-digits']) {
65
- minFractionDigits = context.parse(options['min-fraction-digits'], 1, NumberType);
65
+ minFractionDigits = context.parseObjectValue(options['min-fraction-digits'], 2, 'min-fraction-digits', NumberType);
66
66
  if (!minFractionDigits) return null;
67
67
  }
68
68
 
69
69
  let maxFractionDigits = null;
70
70
  if (options['max-fraction-digits']) {
71
- maxFractionDigits = context.parse(options['max-fraction-digits'], 1, NumberType);
71
+ maxFractionDigits = context.parseObjectValue(options['max-fraction-digits'], 2, 'max-fraction-digits', NumberType);
72
72
  if (!maxFractionDigits) return null;
73
73
  }
74
74
 
@@ -1,5 +1,4 @@
1
1
  import {NumberType} from '../types';
2
-
3
2
  import {findStopLessThanOrEqualTo} from '../stops';
4
3
 
5
4
  import type {Stops} from '../stops';
@@ -1,13 +1,13 @@
1
1
  import {isValue} from '../values';
2
- import type {Type} from '../types';
3
2
  import {BooleanType} from '../types';
3
+ import {updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util';
4
+
5
+ import type {Type} from '../types';
4
6
  import type {Expression, SerializedExpression} from '../expression';
5
7
  import type ParsingContext from '../parsing_context';
6
8
  import type EvaluationContext from '../evaluation_context';
7
9
  import type Point from '@mapbox/point-geometry';
8
10
  import type {CanonicalTileID} from '../../types/tile_id';
9
-
10
- import {updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util';
11
11
  import type {BBox} from '../../util/geometry_util';
12
12
 
13
13
  type GeoJSONPolygons = GeoJSON.Polygon | GeoJSON.MultiPolygon;
@@ -7,14 +7,14 @@ export type SerializedExpression = Array<unknown> | Array<string> | string | num
7
7
  export interface Expression {
8
8
  readonly type: Type;
9
9
  value?: any;
10
- evaluate(ctx: EvaluationContext): any;
11
- eachChild(fn: (arg1: Expression) => void): void;
10
+ evaluate: (ctx: EvaluationContext) => any;
11
+ eachChild: (fn: (arg1: Expression) => void) => void;
12
12
  /**
13
13
  * Statically analyze the expression, attempting to enumerate possible outputs. Returns
14
14
  * false if the complete set of outputs is statically undecidable, otherwise true.
15
15
  */
16
- outputDefined(): boolean;
17
- serialize(): SerializedExpression;
16
+ outputDefined: () => boolean;
17
+ serialize: () => SerializedExpression;
18
18
  }
19
19
 
20
20
  export type ExpressionParser = (args: ReadonlyArray<unknown>, context: ParsingContext) => Expression | void;
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import extend from '../util/extend';
4
3
  import ParsingError from './parsing_error';
5
4
  import ParsingContext from './parsing_context';
@@ -19,6 +18,9 @@ import {
19
18
  supportsLightExpression,
20
19
  supportsInterpolation
21
20
  } from '../util/properties';
21
+ import {isFunction, createFunction} from '../function/index';
22
+ import {Color} from './values';
23
+ import {ColorType, StringType, NumberType, BooleanType, ValueType, FormattedType, ResolvedImageType, array} from './types';
22
24
 
23
25
  import type {Type, EvaluationKind} from './types';
24
26
  import type {Value} from './values';
@@ -34,7 +36,7 @@ import type {FeatureDistanceData} from '../feature_filter/index';
34
36
  import type {ConfigOptions} from '../types/config_options';
35
37
 
36
38
  export interface Feature {
37
- readonly type: 1 | 2 | 3 | 'Unknown' | 'Point' | 'LineString' | 'Polygon';
39
+ readonly type: 0 | 1 | 2 | 3 | 'Unknown' | 'Point' | 'LineString' | 'Polygon';
38
40
  readonly id?: number | null;
39
41
  readonly properties: {
40
42
  [_: string]: any;
@@ -385,9 +387,6 @@ export function createPropertyExpression(
385
387
  (new ZoomDependentExpression('composite', expression.value, zoomCurve.labels, interpolationType, isLightConstant) as CompositeExpression));
386
388
  }
387
389
 
388
- import {isFunction, createFunction} from '../function/index';
389
- import {Color} from './values';
390
-
391
390
  // serialization wrapper for old-style stop functions normalized to the
392
391
  // expression interface
393
392
  export class StylePropertyFunction<T> {
@@ -494,8 +493,6 @@ function findZoomCurve(expression: Expression): Step | Interpolate | ParsingErro
494
493
  return result;
495
494
  }
496
495
 
497
- import {ColorType, StringType, NumberType, BooleanType, ValueType, FormattedType, ResolvedImageType, array} from './types';
498
-
499
496
  function getExpectedType(spec: StylePropertySpecification): Type {
500
497
  const types = {
501
498
  color: ColorType,
@@ -2,6 +2,7 @@ import CompoundExpression from './compound_expression';
2
2
  import Within from './definitions/within';
3
3
  import Distance from './definitions/distance';
4
4
  import Config from './definitions/config';
5
+
5
6
  import type {Expression} from './expression';
6
7
 
7
8
  function isFeatureConstant(e: Expression): boolean {
@@ -23,7 +23,7 @@ import type {ConfigOptions} from '../types/config_options';
23
23
  */
24
24
  class ParsingContext {
25
25
  registry: ExpressionRegistry;
26
- path: Array<number>;
26
+ path: Array<number | string>;
27
27
  key: string;
28
28
  scope: Scope;
29
29
  errors: Array<ParsingError>;
@@ -38,7 +38,7 @@ class ParsingContext {
38
38
 
39
39
  constructor(
40
40
  registry: ExpressionRegistry,
41
- path: Array<number> = [],
41
+ path: Array<number | string> = [],
42
42
  expectedType?: Type | null,
43
43
  scope: Scope = new Scope(),
44
44
  errors: Array<ParsingError> = [],
@@ -47,7 +47,7 @@ class ParsingContext {
47
47
  ) {
48
48
  this.registry = registry;
49
49
  this.path = path;
50
- this.key = path.map(part => `[${part}]`).join('');
50
+ this.key = path.map(part => { if (typeof part === 'string') { return `['${part}']`; } return `[${part}]`; }).join('');
51
51
  this.scope = scope;
52
52
  this.errors = errors;
53
53
  this.expectedType = expectedType;
@@ -72,11 +72,32 @@ class ParsingContext {
72
72
  } = {},
73
73
  ): Expression | null | undefined {
74
74
  if (index || expectedType) {
75
- return this.concat(index, expectedType, bindings)._parse(expr, options);
75
+ return this.concat(index, null, expectedType, bindings)._parse(expr, options);
76
76
  }
77
77
  return this._parse(expr, options);
78
78
  }
79
79
 
80
+ /**
81
+ * @param expr the JSON expression to parse
82
+ * @param index the optional argument index if parent object being is an argument of another expression
83
+ * @param key key of parent object being parsed
84
+ * @param options
85
+ * @param options.omitTypeAnnotations set true to omit inferred type annotations. Caller beware: with this option set, the parsed expression's type will NOT satisfy `expectedType` if it would normally be wrapped in an inferred annotation.
86
+ * @private
87
+ */
88
+ parseObjectValue(
89
+ expr: unknown,
90
+ index: number,
91
+ key: string,
92
+ expectedType?: Type | null,
93
+ bindings?: Array<[string, Expression]>,
94
+ options: {
95
+ typeAnnotation?: 'assert' | 'coerce' | 'omit';
96
+ } = {},
97
+ ): Expression | null | undefined {
98
+ return this.concat(index, key, expectedType, bindings)._parse(expr, options);
99
+ }
100
+
80
101
  _parse(
81
102
  expr: unknown,
82
103
  options: {
@@ -170,10 +191,12 @@ class ParsingContext {
170
191
  */
171
192
  concat(
172
193
  index?: number | null,
194
+ key?: string | null,
173
195
  expectedType?: Type | null,
174
196
  bindings?: Array<[string, Expression]>,
175
197
  ): ParsingContext {
176
- const path = typeof index === 'number' ? this.path.concat(index) : this.path;
198
+ let path = typeof index === 'number' ? this.path.concat(index) : this.path;
199
+ path = typeof key === 'string' ? path.concat(key) : path;
177
200
  const scope = bindings ? this.scope.concat(bindings) : this.scope;
178
201
  return new ParsingContext(
179
202
  this.registry,
@@ -1,5 +1,4 @@
1
1
  import assert from 'assert';
2
-
3
2
  import Color from '../util/color';
4
3
  import Collator from './types/collator';
5
4
  import Formatted from './types/formatted';
@@ -111,7 +110,7 @@ export function typeOf(value: Value): Type {
111
110
  return ResolvedImageType;
112
111
  } else if (Array.isArray(value)) {
113
112
  const length = value.length;
114
- let itemType: Type | typeof undefined;
113
+ let itemType: Type;
115
114
 
116
115
  for (const item of value) {
117
116
  const t = typeOf(item);
@@ -1,12 +1,13 @@
1
- import type Point from '@mapbox/point-geometry';
2
1
  import latest from '../reference/latest';
3
-
4
2
  import {deepUnbundle} from '../util/unbundle_jsonlint';
5
3
  import {createExpression} from '../expression/index';
6
4
  import {isFeatureConstant} from '../expression/is_constant';
5
+
6
+ import type Point from '@mapbox/point-geometry';
7
7
  import type {CanonicalTileID} from '../types/tile_id';
8
8
  import type {GlobalProperties, Feature} from '../expression/index';
9
9
  import type {FilterSpecification, ExpressionSpecification} from '../types';
10
+ import type {ConfigOptions} from '../types/config_options';
10
11
 
11
12
  export type FeatureDistanceData = {
12
13
  bearing: [number, number];
@@ -82,7 +83,7 @@ function isExpressionFilter(filter: unknown): boolean {
82
83
  * @param {string} layerType the type of the layer this filter will be applied to.
83
84
  * @returns {Function} filter-evaluating function
84
85
  */
85
- function createFilter(filter?: FilterSpecification, layerType: string = 'fill'): FeatureFilter {
86
+ function createFilter(filter?: FilterSpecification, scope: string = "", options: ConfigOptions | null = null, layerType: string = 'fill'): FeatureFilter {
86
87
  if (filter === null || filter === undefined) {
87
88
  return {filter: () => true, needGeometry: false, needFeature: false};
88
89
  }
@@ -109,7 +110,7 @@ ${JSON.stringify(filterExp, null, 2)}
109
110
 
110
111
  // Compile the static component of the filter
111
112
  const filterSpec = latest[`filter_${layerType}`];
112
- const compiledStaticFilter = createExpression(staticFilter, filterSpec);
113
+ const compiledStaticFilter = createExpression(staticFilter, filterSpec, scope, options);
113
114
 
114
115
  let filterFunc = null;
115
116
  if (compiledStaticFilter.result === 'error') {
@@ -123,7 +124,7 @@ ${JSON.stringify(filterExp, null, 2)}
123
124
  let dynamicFilterFunc = null;
124
125
  let needFeature = null;
125
126
  if (staticFilter !== filterExp) {
126
- const compiledDynamicFilter = createExpression(filterExp, filterSpec);
127
+ const compiledDynamicFilter = createExpression(filterExp, filterSpec, scope, options);
127
128
 
128
129
  if (compiledDynamicFilter.result === 'error') {
129
130
  throw new Error(compiledDynamicFilter.value.map(err => `${err.key}: ${err.message}`).join(', '));
@@ -1,7 +1,7 @@
1
- import type {LayerSpecification} from './types';
2
-
3
1
  import refProperties from './util/ref_properties';
4
2
 
3
+ import type {LayerSpecification} from './types';
4
+
5
5
  function stringify(obj: any) {
6
6
  if (typeof obj === 'number' || typeof obj === 'boolean' || typeof obj === 'string' || obj === undefined || obj === null)
7
7
  return JSON.stringify(obj);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapbox/mapbox-gl-style-spec",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "description": "a specification for mapbox gl styles",
5
5
  "author": "Mapbox",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",