@mapbox/mapbox-gl-style-spec 14.8.0-beta.1 → 14.9.0-beta.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.
- package/diff.ts +16 -0
- package/dist/index.cjs +861 -153
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +171 -9
- package/dist/index.es.js +861 -153
- package/dist/index.es.js.map +1 -1
- package/expression/definitions/coercion.ts +1 -1
- package/expression/definitions/config.ts +1 -1
- package/expression/definitions/image.ts +184 -14
- package/expression/definitions/index.ts +7 -0
- package/expression/definitions/interpolate.ts +54 -13
- package/expression/expression.ts +1 -0
- package/expression/index.ts +23 -9
- package/expression/types/formatted.ts +1 -1
- package/expression/types/image_id_with_options.ts +54 -0
- package/expression/types/resolved_image.ts +49 -7
- package/expression/values.ts +9 -7
- package/feature_filter/index.ts +13 -7
- package/function/index.ts +1 -1
- package/group_by_layout.ts +35 -3
- package/package.json +1 -1
- package/reference/v8.json +407 -88
- package/types.ts +128 -9
- package/util/color.ts +62 -1
- package/util/properties.ts +4 -0
- package/validate/validate_fog.ts +10 -1
- package/validate/validate_function.ts +1 -1
- package/validate/validate_light.ts +10 -1
- package/validate/validate_lights.ts +11 -1
- package/validate/validate_property.ts +11 -0
- package/validate/validate_rain.ts +47 -0
- package/validate/validate_snow.ts +47 -0
- package/validate/validate_terrain.ts +11 -2
- package/validate_style.min.ts +4 -0
|
@@ -138,7 +138,7 @@ class Coercion implements Expression {
|
|
|
138
138
|
// created by properties that expect the 'formatted' type.
|
|
139
139
|
return Formatted.fromString(valueToString(this.args[0].evaluate(ctx)));
|
|
140
140
|
} else if (this.type.kind === 'resolvedImage') {
|
|
141
|
-
return ResolvedImage.
|
|
141
|
+
return ResolvedImage.build(valueToString(this.args[0].evaluate(ctx)));
|
|
142
142
|
} else if (this.type.kind === 'array') {
|
|
143
143
|
return this.args.map(arg => { return arg.evaluate(ctx); });
|
|
144
144
|
} else {
|
|
@@ -19,7 +19,7 @@ function coerceValue(type: string, value: any): any {
|
|
|
19
19
|
return Formatted.fromString(valueToString(value));
|
|
20
20
|
}
|
|
21
21
|
case 'resolvedImage': {
|
|
22
|
-
return ResolvedImage.
|
|
22
|
+
return ResolvedImage.build(valueToString(value));
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
return value;
|
|
@@ -1,20 +1,47 @@
|
|
|
1
|
-
import {ResolvedImageType, StringType} from '../types';
|
|
1
|
+
import {ColorType, ResolvedImageType, StringType} from '../types';
|
|
2
2
|
import ResolvedImage from '../types/resolved_image';
|
|
3
|
+
import {isExpression} from '..';
|
|
3
4
|
|
|
5
|
+
import type Color from '../../util/color';
|
|
4
6
|
import type {Expression, SerializedExpression} from '../expression';
|
|
5
7
|
import type EvaluationContext from '../evaluation_context';
|
|
6
8
|
import type ParsingContext from '../parsing_context';
|
|
7
9
|
import type {Type} from '../types';
|
|
8
10
|
|
|
11
|
+
export type ImageParams = Record<string, Expression>;
|
|
12
|
+
|
|
13
|
+
export type ImageOptions = {
|
|
14
|
+
params: ImageParams;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isImageOptions(value: unknown) {
|
|
18
|
+
if (typeof value !== 'string' && !isExpression(value)) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
9
25
|
export default class ImageExpression implements Expression {
|
|
10
26
|
type: Type;
|
|
11
27
|
inputPrimary: Expression;
|
|
28
|
+
inputPrimaryParams: Record<string, Expression> | undefined;
|
|
12
29
|
inputSecondary: Expression | null | undefined;
|
|
30
|
+
inputSecondaryParams: Record<string, Expression> | undefined;
|
|
13
31
|
|
|
14
|
-
|
|
32
|
+
_imageWarnHistory: Record<string, boolean> = {};
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
inputPrimary: Expression,
|
|
36
|
+
inputSecondary?: Expression | null,
|
|
37
|
+
inputPrimaryParams?: Record<string, Expression>,
|
|
38
|
+
inputSecondaryParams?: Record<string, Expression>
|
|
39
|
+
) {
|
|
15
40
|
this.type = ResolvedImageType;
|
|
16
41
|
this.inputPrimary = inputPrimary;
|
|
17
42
|
this.inputSecondary = inputSecondary;
|
|
43
|
+
this.inputPrimaryParams = inputPrimaryParams;
|
|
44
|
+
this.inputSecondaryParams = inputSecondaryParams;
|
|
18
45
|
}
|
|
19
46
|
|
|
20
47
|
static parse(args: ReadonlyArray<unknown>, context: ParsingContext): Expression | null | undefined {
|
|
@@ -23,23 +50,126 @@ export default class ImageExpression implements Expression {
|
|
|
23
50
|
return context.error(`Expected two or more arguments.`);
|
|
24
51
|
}
|
|
25
52
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
53
|
+
let nextArgId = 1;
|
|
54
|
+
const imageExpression: Array<{image: Expression, options: Record<string, Expression>}> = [];
|
|
55
|
+
|
|
56
|
+
function tryParseImage() {
|
|
57
|
+
if (nextArgId < args.length) {
|
|
58
|
+
const imageName = context.parse(args[nextArgId], nextArgId++, StringType);
|
|
59
|
+
if (!imageName) {
|
|
60
|
+
context.error(imageExpression.length ? `Secondary image variant is not a string.` : `No image name provided.`);
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
imageExpression.push({image: imageName, options: undefined});
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function tryParseOptions() {
|
|
72
|
+
if (nextArgId < args.length) {
|
|
73
|
+
if (!isImageOptions(args[nextArgId])) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const params = (args[nextArgId] as ImageOptions).params;
|
|
78
|
+
|
|
79
|
+
const optionsContext = context.concat(nextArgId);
|
|
80
|
+
|
|
81
|
+
if (!params) {
|
|
82
|
+
nextArgId++;
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (typeof params !== 'object' || params.constructor !== Object) {
|
|
87
|
+
optionsContext.error(`Image options \"params\" should be an object`);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const parsed = {};
|
|
92
|
+
|
|
93
|
+
const childContext = optionsContext.concat(undefined, 'params');
|
|
94
|
+
|
|
95
|
+
for (const key in params) {
|
|
96
|
+
if (!key) {
|
|
97
|
+
childContext.error(`Image parameter name should be non-empty`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const value = childContext.concat(undefined, key).parse(params[key], undefined, ColorType, undefined, {typeAnnotation: 'coerce'});
|
|
102
|
+
if (!value) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
parsed[key] = value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
imageExpression[imageExpression.length - 1].options = parsed;
|
|
110
|
+
nextArgId++;
|
|
111
|
+
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Parse the primary and secondary image expressions
|
|
119
|
+
for (let i = 0; i < 2; i++) {
|
|
120
|
+
if (!tryParseImage() || !tryParseOptions()) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
29
124
|
|
|
30
|
-
|
|
31
|
-
|
|
125
|
+
return new ImageExpression(
|
|
126
|
+
imageExpression[0].image,
|
|
127
|
+
imageExpression[1] ? imageExpression[1].image : undefined,
|
|
128
|
+
imageExpression[0].options,
|
|
129
|
+
imageExpression[1] ? imageExpression[1].options : undefined
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
evaluateParams(ctx: EvaluationContext, params: Record<string, Expression> | undefined): {params: Record<string, Color>} {
|
|
134
|
+
const result: Record<string, Color> = {};
|
|
135
|
+
if (params) {
|
|
136
|
+
for (const key in params) {
|
|
137
|
+
if (params[key]) {
|
|
138
|
+
try {
|
|
139
|
+
const color = params[key].evaluate(ctx);
|
|
140
|
+
const msg = `Ignoring image parameter "${key}" with semi-transparent color ${color.toString()}`;
|
|
141
|
+
|
|
142
|
+
if (color.a !== 1) {
|
|
143
|
+
if (!this._imageWarnHistory[msg]) {
|
|
144
|
+
console.warn(msg);
|
|
145
|
+
this._imageWarnHistory[msg] = true;
|
|
146
|
+
}
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
result[key] = color;
|
|
150
|
+
} catch (err) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
return undefined;
|
|
32
157
|
}
|
|
33
158
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
159
|
+
if (Object.keys(result).length === 0) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
37
162
|
|
|
38
|
-
return
|
|
163
|
+
return {params: result};
|
|
39
164
|
}
|
|
40
165
|
|
|
41
166
|
evaluate(ctx: EvaluationContext): null | ResolvedImage {
|
|
42
|
-
const value = ResolvedImage.
|
|
167
|
+
const value = ResolvedImage.build(
|
|
168
|
+
this.inputPrimary.evaluate(ctx),
|
|
169
|
+
this.inputSecondary ? this.inputSecondary.evaluate(ctx) : undefined,
|
|
170
|
+
this.inputPrimaryParams ? this.evaluateParams(ctx, this.inputPrimaryParams) : undefined,
|
|
171
|
+
this.inputSecondaryParams ? this.evaluateParams(ctx, this.inputSecondaryParams) : undefined
|
|
172
|
+
);
|
|
43
173
|
if (value && ctx.availableImages) {
|
|
44
174
|
value.available = ctx.availableImages.indexOf(value.namePrimary) > -1;
|
|
45
175
|
// If there's a secondary variant, only mark it available if both are present
|
|
@@ -53,8 +183,22 @@ export default class ImageExpression implements Expression {
|
|
|
53
183
|
|
|
54
184
|
eachChild(fn: (_: Expression) => void) {
|
|
55
185
|
fn(this.inputPrimary);
|
|
186
|
+
if (this.inputPrimaryParams) {
|
|
187
|
+
for (const key in this.inputPrimaryParams) {
|
|
188
|
+
if (this.inputPrimaryParams[key]) {
|
|
189
|
+
fn(this.inputPrimaryParams[key]);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
56
193
|
if (this.inputSecondary) {
|
|
57
194
|
fn(this.inputSecondary);
|
|
195
|
+
if (this.inputSecondaryParams) {
|
|
196
|
+
for (const key in this.inputSecondaryParams) {
|
|
197
|
+
if (this.inputSecondaryParams[key]) {
|
|
198
|
+
fn(this.inputSecondaryParams[key]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
58
202
|
}
|
|
59
203
|
}
|
|
60
204
|
|
|
@@ -63,10 +207,36 @@ export default class ImageExpression implements Expression {
|
|
|
63
207
|
return false;
|
|
64
208
|
}
|
|
65
209
|
|
|
210
|
+
serializeParams(params: Record<string, Expression> | undefined): {params: Record<string, SerializedExpression>} {
|
|
211
|
+
const result: Record<string, SerializedExpression> = {};
|
|
212
|
+
if (params) {
|
|
213
|
+
for (const key in params) {
|
|
214
|
+
if (params[key]) {
|
|
215
|
+
result[key] = params[key].serialize();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return {params: result};
|
|
223
|
+
}
|
|
224
|
+
|
|
66
225
|
serialize(): SerializedExpression {
|
|
226
|
+
const serialized: SerializedExpression = ["image", this.inputPrimary.serialize()];
|
|
227
|
+
|
|
228
|
+
if (this.inputPrimaryParams) {
|
|
229
|
+
serialized.push(this.serializeParams(this.inputPrimaryParams));
|
|
230
|
+
}
|
|
231
|
+
|
|
67
232
|
if (this.inputSecondary) {
|
|
68
|
-
|
|
233
|
+
serialized.push(this.inputSecondary.serialize());
|
|
234
|
+
|
|
235
|
+
if (this.inputSecondaryParams) {
|
|
236
|
+
serialized.push(this.serializeParams(this.inputSecondaryParams));
|
|
237
|
+
}
|
|
69
238
|
}
|
|
70
|
-
|
|
239
|
+
|
|
240
|
+
return serialized;
|
|
71
241
|
}
|
|
72
242
|
}
|
|
@@ -182,6 +182,13 @@ CompoundExpression.register(expressions, {
|
|
|
182
182
|
return v.evaluate(ctx).toRenderColor(null).toArray();
|
|
183
183
|
}
|
|
184
184
|
],
|
|
185
|
+
'to-hsla': [
|
|
186
|
+
array(NumberType, 4),
|
|
187
|
+
[ColorType],
|
|
188
|
+
(ctx, [v]) => {
|
|
189
|
+
return v.evaluate(ctx).toRenderColor(null).toHslaArray();
|
|
190
|
+
}
|
|
191
|
+
],
|
|
185
192
|
'rgb': [
|
|
186
193
|
ColorType,
|
|
187
194
|
[NumberType, NumberType, NumberType],
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import UnitBezier from '@mapbox/unitbezier';
|
|
2
2
|
import * as interpolate from '../../util/interpolate';
|
|
3
|
-
import {toString, NumberType, ColorType} from '../types';
|
|
3
|
+
import {toString, NumberType, ColorType, ValueType} from '../types';
|
|
4
4
|
import {findStopLessThanOrEqualTo} from '../stops';
|
|
5
5
|
import {hcl, lab} from '../../util/color_spaces';
|
|
6
|
+
import Literal from './literal';
|
|
7
|
+
import RuntimeError from '../runtime_error';
|
|
6
8
|
|
|
7
9
|
import type Color from '../../util/color';
|
|
8
10
|
import type {Stops} from '../stops';
|
|
@@ -27,14 +29,16 @@ class Interpolate implements Expression {
|
|
|
27
29
|
operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab';
|
|
28
30
|
interpolation: InterpolationType;
|
|
29
31
|
input: Expression;
|
|
32
|
+
dynamicStops: Expression | null;
|
|
30
33
|
labels: Array<number>;
|
|
31
34
|
outputs: Array<Expression>;
|
|
32
35
|
|
|
33
|
-
constructor(type: Type, operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab', interpolation: InterpolationType, input: Expression, stops: Stops) {
|
|
36
|
+
constructor(type: Type, operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab', interpolation: InterpolationType, input: Expression, dynamicStops: Expression | null, stops: Stops) {
|
|
34
37
|
this.type = type;
|
|
35
38
|
this.operator = operator;
|
|
36
39
|
this.interpolation = interpolation;
|
|
37
40
|
this.input = input;
|
|
41
|
+
this.dynamicStops = dynamicStops;
|
|
38
42
|
|
|
39
43
|
this.labels = [];
|
|
40
44
|
this.outputs = [];
|
|
@@ -101,12 +105,12 @@ class Interpolate implements Expression {
|
|
|
101
105
|
return context.error(`Unknown interpolation type ${String(interpolation[0])}`, 1, 0);
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
if (args.length - 1 <
|
|
108
|
+
if (args.length - 1 < 3) {
|
|
105
109
|
// @ts-expect-error - TS2322 - Type 'void' is not assignable to type 'Interpolate'.
|
|
106
|
-
return context.error(`Expected at least
|
|
110
|
+
return context.error(`Expected at least 3 arguments, but found only ${args.length - 1}.`);
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
if ((args.length - 1) % 2 !== 0) {
|
|
113
|
+
if (args.length - 1 > 3 && (args.length - 1) % 2 !== 0) {
|
|
110
114
|
// @ts-expect-error - TS2322 - Type 'void' is not assignable to type 'Interpolate'.
|
|
111
115
|
return context.error(`Expected an even number of arguments.`);
|
|
112
116
|
}
|
|
@@ -123,6 +127,15 @@ class Interpolate implements Expression {
|
|
|
123
127
|
outputType = context.expectedType;
|
|
124
128
|
}
|
|
125
129
|
|
|
130
|
+
// Exactly 3 arguments means that the steps are created by an expression
|
|
131
|
+
if (args.length - 1 === 3) {
|
|
132
|
+
const dynamicStops = context.parse(rest[0], 3, ValueType);
|
|
133
|
+
if (!dynamicStops) return null;
|
|
134
|
+
|
|
135
|
+
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'InterpolationType'.
|
|
136
|
+
return new Interpolate(outputType, (operator as any), interpolation, input, dynamicStops, stops);
|
|
137
|
+
}
|
|
138
|
+
|
|
126
139
|
for (let i = 0; i < rest.length; i += 2) {
|
|
127
140
|
const label = rest[i];
|
|
128
141
|
const value = rest[i + 1];
|
|
@@ -159,12 +172,36 @@ class Interpolate implements Expression {
|
|
|
159
172
|
}
|
|
160
173
|
|
|
161
174
|
// @ts-expect-error - TS2345 - Argument of type 'unknown' is not assignable to parameter of type 'InterpolationType'.
|
|
162
|
-
return new Interpolate(outputType, (operator as any), interpolation, input, stops);
|
|
175
|
+
return new Interpolate(outputType, (operator as any), interpolation, input, null, stops);
|
|
163
176
|
}
|
|
164
177
|
|
|
165
178
|
evaluate(ctx: EvaluationContext): Color {
|
|
166
|
-
|
|
167
|
-
|
|
179
|
+
let labels = this.labels;
|
|
180
|
+
let outputs = this.outputs;
|
|
181
|
+
|
|
182
|
+
if (this.dynamicStops) {
|
|
183
|
+
const dynamicStopsValue = (this.dynamicStops.evaluate(ctx) as [number]);
|
|
184
|
+
if (dynamicStopsValue.length % 2 !== 0) {
|
|
185
|
+
throw new RuntimeError('Expected an even number of arguments.');
|
|
186
|
+
}
|
|
187
|
+
labels = [];
|
|
188
|
+
outputs = [];
|
|
189
|
+
for (let i = 0; i < dynamicStopsValue.length; i += 2) {
|
|
190
|
+
const label = dynamicStopsValue[i];
|
|
191
|
+
const output = new Literal(NumberType, dynamicStopsValue[i + 1]);
|
|
192
|
+
if (typeof label !== 'number') {
|
|
193
|
+
throw new RuntimeError('Input/output pairs for "interpolate" expressions must be defined using literal numeric values (not computed expressions) for the input values.');
|
|
194
|
+
}
|
|
195
|
+
if (labels.length && labels[labels.length - 1] >= label) {
|
|
196
|
+
throw new RuntimeError('Input/output pairs for "interpolate" expressions must be arranged with input values in strictly ascending order.');
|
|
197
|
+
}
|
|
198
|
+
labels.push(label);
|
|
199
|
+
outputs.push(output);
|
|
200
|
+
}
|
|
201
|
+
if (labels.length === 0) {
|
|
202
|
+
throw new RuntimeError('Expected at least one input/output pair.');
|
|
203
|
+
}
|
|
204
|
+
}
|
|
168
205
|
|
|
169
206
|
if (labels.length === 1) {
|
|
170
207
|
return outputs[0].evaluate(ctx);
|
|
@@ -225,11 +262,15 @@ class Interpolate implements Expression {
|
|
|
225
262
|
|
|
226
263
|
const serialized = [this.operator, interpolation, this.input.serialize()];
|
|
227
264
|
|
|
228
|
-
|
|
229
|
-
serialized.push(
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
265
|
+
if (this.dynamicStops) {
|
|
266
|
+
serialized.push(this.dynamicStops.serialize());
|
|
267
|
+
} else {
|
|
268
|
+
for (let i = 0; i < this.labels.length; i++) {
|
|
269
|
+
serialized.push(
|
|
270
|
+
this.labels[i],
|
|
271
|
+
this.outputs[i].serialize()
|
|
272
|
+
);
|
|
273
|
+
}
|
|
233
274
|
}
|
|
234
275
|
return serialized;
|
|
235
276
|
}
|
package/expression/expression.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type ExpressionParser = (args: ReadonlyArray<unknown>, context: ParsingCo
|
|
|
22
22
|
export type ExpressionRegistration = {
|
|
23
23
|
new(...args: any[]): Expression;
|
|
24
24
|
readonly parse: ExpressionParser;
|
|
25
|
+
_classRegistryKey?: string;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
export type ExpressionRegistry = {
|
package/expression/index.ts
CHANGED
|
@@ -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(
|
|
@@ -183,11 +186,13 @@ export class ZoomConstantExpression<Kind extends EvaluationKind> {
|
|
|
183
186
|
configDependencies: Set<string>;
|
|
184
187
|
_styleExpression: StyleExpression;
|
|
185
188
|
isLightConstant: boolean | null | undefined;
|
|
189
|
+
isLineProgressConstant: boolean | null | undefined;
|
|
186
190
|
|
|
187
|
-
constructor(kind: Kind, expression: StyleExpression, isLightConstant?: boolean | null) {
|
|
191
|
+
constructor(kind: Kind, expression: StyleExpression, isLightConstant?: boolean | null, isLineProgressConstant?: boolean | null) {
|
|
188
192
|
this.kind = kind;
|
|
189
193
|
this._styleExpression = expression;
|
|
190
194
|
this.isLightConstant = isLightConstant;
|
|
195
|
+
this.isLineProgressConstant = isLineProgressConstant;
|
|
191
196
|
this.isStateDependent = kind !== ('constant' as EvaluationKind) && !isConstant.isStateConstant(expression.expression);
|
|
192
197
|
this.configDependencies = isConstant.getConfigDependencies(expression.expression);
|
|
193
198
|
}
|
|
@@ -220,17 +225,19 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
|
|
|
220
225
|
zoomStops: Array<number>;
|
|
221
226
|
isStateDependent: boolean;
|
|
222
227
|
isLightConstant: boolean | null | undefined;
|
|
228
|
+
isLineProgressConstant: boolean | null | undefined;
|
|
223
229
|
configDependencies: Set<string>;
|
|
224
230
|
|
|
225
231
|
_styleExpression: StyleExpression;
|
|
226
232
|
interpolationType: InterpolationType | null | undefined;
|
|
227
233
|
|
|
228
|
-
constructor(kind: Kind, expression: StyleExpression, zoomStops: Array<number>, interpolationType?: InterpolationType, isLightConstant?: boolean | null) {
|
|
234
|
+
constructor(kind: Kind, expression: StyleExpression, zoomStops: Array<number>, interpolationType?: InterpolationType, isLightConstant?: boolean | null, isLineProgressConstant?: boolean | null) {
|
|
229
235
|
this.kind = kind;
|
|
230
236
|
this.zoomStops = zoomStops;
|
|
231
237
|
this._styleExpression = expression;
|
|
232
238
|
this.isStateDependent = kind !== ('camera' as EvaluationKind) && !isConstant.isStateConstant(expression.expression);
|
|
233
239
|
this.isLightConstant = isLightConstant;
|
|
240
|
+
this.isLineProgressConstant = isLineProgressConstant;
|
|
234
241
|
this.configDependencies = isConstant.getConfigDependencies(expression.expression);
|
|
235
242
|
this.interpolationType = interpolationType;
|
|
236
243
|
}
|
|
@@ -282,6 +289,7 @@ export type SourceExpression = {
|
|
|
282
289
|
kind: 'source';
|
|
283
290
|
isStateDependent: boolean;
|
|
284
291
|
isLightConstant: boolean | null | undefined;
|
|
292
|
+
isLineProgressConstant: boolean | null | undefined;
|
|
285
293
|
configDependencies: Set<string>;
|
|
286
294
|
readonly evaluate: (
|
|
287
295
|
globals: GlobalProperties,
|
|
@@ -313,6 +321,7 @@ export interface CompositeExpression {
|
|
|
313
321
|
kind: 'composite';
|
|
314
322
|
isStateDependent: boolean;
|
|
315
323
|
isLightConstant: boolean | null | undefined;
|
|
324
|
+
isLineProgressConstant: boolean | null | undefined;
|
|
316
325
|
configDependencies: Set<string>;
|
|
317
326
|
readonly evaluate: (
|
|
318
327
|
globals: GlobalProperties,
|
|
@@ -360,6 +369,11 @@ export function createPropertyExpression(
|
|
|
360
369
|
return error([new ParsingError('', 'measure-light expression not supported')]);
|
|
361
370
|
}
|
|
362
371
|
|
|
372
|
+
const isLineProgressConstant = isConstant.isGlobalPropertyConstant(parsed, ['line-progress']);
|
|
373
|
+
if (!isLineProgressConstant && !supportsLineProgressExpression(propertySpec)) {
|
|
374
|
+
return error([new ParsingError('', 'line-progress expression not supported')]);
|
|
375
|
+
}
|
|
376
|
+
|
|
363
377
|
const canRelaxZoomRestriction = propertySpec.expression && propertySpec.expression.relaxZoomRestriction;
|
|
364
378
|
const zoomCurve = findZoomCurve(parsed);
|
|
365
379
|
if (!zoomCurve && !isZoomConstant && !canRelaxZoomRestriction) {
|
|
@@ -371,20 +385,20 @@ export function createPropertyExpression(
|
|
|
371
385
|
}
|
|
372
386
|
|
|
373
387
|
if (!zoomCurve) {
|
|
374
|
-
return success(isFeatureConstant ?
|
|
388
|
+
return success((isFeatureConstant && isLineProgressConstant) ?
|
|
375
389
|
// @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
|
|
376
|
-
(new ZoomConstantExpression('constant', expression.value, isLightConstant) as ConstantExpression) :
|
|
390
|
+
(new ZoomConstantExpression('constant', expression.value, isLightConstant, isLineProgressConstant) as ConstantExpression) :
|
|
377
391
|
// @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
|
|
378
|
-
(new ZoomConstantExpression('source', expression.value, isLightConstant) as SourceExpression));
|
|
392
|
+
(new ZoomConstantExpression('source', expression.value, isLightConstant, isLineProgressConstant) as SourceExpression));
|
|
379
393
|
}
|
|
380
394
|
|
|
381
395
|
const interpolationType = zoomCurve instanceof Interpolate ? zoomCurve.interpolation : undefined;
|
|
382
396
|
|
|
383
|
-
return success(isFeatureConstant ?
|
|
397
|
+
return success((isFeatureConstant && isLineProgressConstant) ?
|
|
384
398
|
// @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
|
|
385
|
-
(new ZoomDependentExpression('camera', expression.value, zoomCurve.labels, interpolationType, isLightConstant) as CameraExpression) :
|
|
399
|
+
(new ZoomDependentExpression('camera', expression.value, zoomCurve.labels, interpolationType, isLightConstant, isLineProgressConstant) as CameraExpression) :
|
|
386
400
|
// @ts-expect-error - TS2339 - Property 'value' does not exist on type 'unknown'.
|
|
387
|
-
(new ZoomDependentExpression('composite', expression.value, zoomCurve.labels, interpolationType, isLightConstant) as CompositeExpression));
|
|
401
|
+
(new ZoomDependentExpression('composite', expression.value, zoomCurve.labels, interpolationType, isLightConstant, isLineProgressConstant) as CompositeExpression));
|
|
388
402
|
}
|
|
389
403
|
|
|
390
404
|
// serialization wrapper for old-style stop functions normalized to the
|
|
@@ -32,7 +32,7 @@ export default class Formatted {
|
|
|
32
32
|
isEmpty(): boolean {
|
|
33
33
|
if (this.sections.length === 0) return true;
|
|
34
34
|
return !this.sections.some(section => section.text.length !== 0 ||
|
|
35
|
-
(section.image && section.image.namePrimary
|
|
35
|
+
(section.image && section.image.namePrimary));
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
static factory(text: Formatted | string): Formatted {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type {RasterizationOptions} from "./resolved_image";
|
|
2
|
+
|
|
3
|
+
export class ImageIdWithOptions {
|
|
4
|
+
id: string;
|
|
5
|
+
options: RasterizationOptions;
|
|
6
|
+
|
|
7
|
+
constructor(id: string, options?: RasterizationOptions) {
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.options = options || {params: {}};
|
|
10
|
+
|
|
11
|
+
if (!this.options.transform) {
|
|
12
|
+
this.options.transform = new DOMMatrix([1, 0, 0, 1, 0, 0]);
|
|
13
|
+
} else {
|
|
14
|
+
const {a, b, c, d, e, f} = this.options.transform;
|
|
15
|
+
this.options.transform = new DOMMatrix([a, b, c, d, e, f]);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static deserializeFromString(serialized: string): ImageIdWithOptions {
|
|
20
|
+
const deserializedObject = JSON.parse(serialized);
|
|
21
|
+
const options: RasterizationOptions = {params: deserializedObject.options.params};
|
|
22
|
+
|
|
23
|
+
const {a, b, c, d, e, f} = deserializedObject.options.transform;
|
|
24
|
+
|
|
25
|
+
options.transform = new DOMMatrix([a, b, c, d, e, f]);
|
|
26
|
+
|
|
27
|
+
return new ImageIdWithOptions(deserializedObject.id, deserializedObject.options);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
scaleSelf(factor: number): this {
|
|
31
|
+
this.options.transform = this.options.transform.scale(factor);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
serialize(): string {
|
|
36
|
+
const serialisedObject: Record<string, any> = {
|
|
37
|
+
id: this.id,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (this.options) {
|
|
41
|
+
serialisedObject.options = this.options;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
a, b, c, d, e, f,
|
|
46
|
+
} = this.options.transform;
|
|
47
|
+
|
|
48
|
+
serialisedObject.options.transform = {
|
|
49
|
+
a, b, c, d, e, f,
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return JSON.stringify(serialisedObject);
|
|
53
|
+
}
|
|
54
|
+
}
|