@versatiles/png-renderer 2.4.2 → 2.6.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.
- package/README.md +1 -1
- package/dist/index.d.ts +185 -62
- package/dist/index.js +1086 -834
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7470,7 +7470,7 @@ function pixelAlignedBox(project) {
|
|
|
7470
7470
|
return [minX, minY, maxX, maxY];
|
|
7471
7471
|
}
|
|
7472
7472
|
|
|
7473
|
-
|
|
7473
|
+
// src/reference/v8.json
|
|
7474
7474
|
var v8_default = {
|
|
7475
7475
|
$version: 8,
|
|
7476
7476
|
$root: {
|
|
@@ -7565,6 +7565,14 @@ var v8_default = {
|
|
|
7565
7565
|
},
|
|
7566
7566
|
"default": "xyz"
|
|
7567
7567
|
},
|
|
7568
|
+
"emptyResponse": {
|
|
7569
|
+
"type": "enum",
|
|
7570
|
+
"values": {
|
|
7571
|
+
"blank": {},
|
|
7572
|
+
"missing": {}
|
|
7573
|
+
},
|
|
7574
|
+
"default": "blank"
|
|
7575
|
+
},
|
|
7568
7576
|
"minzoom": {
|
|
7569
7577
|
"type": "number",
|
|
7570
7578
|
"default": 0
|
|
@@ -7632,6 +7640,14 @@ var v8_default = {
|
|
|
7632
7640
|
},
|
|
7633
7641
|
"default": "xyz"
|
|
7634
7642
|
},
|
|
7643
|
+
"emptyResponse": {
|
|
7644
|
+
"type": "enum",
|
|
7645
|
+
"values": {
|
|
7646
|
+
"blank": {},
|
|
7647
|
+
"missing": {}
|
|
7648
|
+
},
|
|
7649
|
+
"default": "blank"
|
|
7650
|
+
},
|
|
7635
7651
|
"attribution": { "type": "string" },
|
|
7636
7652
|
"volatile": {
|
|
7637
7653
|
"type": "boolean",
|
|
@@ -7674,6 +7690,14 @@ var v8_default = {
|
|
|
7674
7690
|
"default": 512,
|
|
7675
7691
|
"units": "pixels"
|
|
7676
7692
|
},
|
|
7693
|
+
"emptyResponse": {
|
|
7694
|
+
"type": "enum",
|
|
7695
|
+
"values": {
|
|
7696
|
+
"blank": {},
|
|
7697
|
+
"missing": {}
|
|
7698
|
+
},
|
|
7699
|
+
"default": "blank"
|
|
7700
|
+
},
|
|
7677
7701
|
"attribution": { "type": "string" },
|
|
7678
7702
|
"encoding": {
|
|
7679
7703
|
"type": "enum",
|
|
@@ -8953,6 +8977,21 @@ var v8_default = {
|
|
|
8953
8977
|
},
|
|
8954
8978
|
"property-type": "data-constant"
|
|
8955
8979
|
},
|
|
8980
|
+
"fill-layer-blend": {
|
|
8981
|
+
"type": "enum",
|
|
8982
|
+
"values": {
|
|
8983
|
+
"normal": {},
|
|
8984
|
+
"multiply": {},
|
|
8985
|
+
"color": {},
|
|
8986
|
+
"luminosity": {},
|
|
8987
|
+
"plus-lighter": {},
|
|
8988
|
+
"screen": {},
|
|
8989
|
+
"overlay": {}
|
|
8990
|
+
},
|
|
8991
|
+
"default": "normal",
|
|
8992
|
+
"property-type": "constant",
|
|
8993
|
+
"transition": false
|
|
8994
|
+
},
|
|
8956
8995
|
"fill-color": {
|
|
8957
8996
|
"type": "color",
|
|
8958
8997
|
"default": "#000000",
|
|
@@ -9041,7 +9080,8 @@ var v8_default = {
|
|
|
9041
9080
|
"parameters": [
|
|
9042
9081
|
"zoom",
|
|
9043
9082
|
"feature",
|
|
9044
|
-
"feature-state"
|
|
9083
|
+
"feature-state",
|
|
9084
|
+
"elevation"
|
|
9045
9085
|
]
|
|
9046
9086
|
},
|
|
9047
9087
|
"property-type": "data-driven"
|
|
@@ -9153,6 +9193,21 @@ var v8_default = {
|
|
|
9153
9193
|
},
|
|
9154
9194
|
"property-type": "data-constant"
|
|
9155
9195
|
},
|
|
9196
|
+
"line-layer-blend": {
|
|
9197
|
+
"type": "enum",
|
|
9198
|
+
"values": {
|
|
9199
|
+
"normal": {},
|
|
9200
|
+
"multiply": {},
|
|
9201
|
+
"color": {},
|
|
9202
|
+
"luminosity": {},
|
|
9203
|
+
"plus-lighter": {},
|
|
9204
|
+
"screen": {},
|
|
9205
|
+
"overlay": {}
|
|
9206
|
+
},
|
|
9207
|
+
"default": "normal",
|
|
9208
|
+
"property-type": "constant",
|
|
9209
|
+
"transition": false
|
|
9210
|
+
},
|
|
9156
9211
|
"line-color": {
|
|
9157
9212
|
"type": "color",
|
|
9158
9213
|
"default": "#000000",
|
|
@@ -9775,6 +9830,21 @@ var v8_default = {
|
|
|
9775
9830
|
},
|
|
9776
9831
|
"property-type": "data-constant"
|
|
9777
9832
|
},
|
|
9833
|
+
"raster-layer-blend": {
|
|
9834
|
+
"type": "enum",
|
|
9835
|
+
"values": {
|
|
9836
|
+
"normal": {},
|
|
9837
|
+
"multiply": {},
|
|
9838
|
+
"color": {},
|
|
9839
|
+
"luminosity": {},
|
|
9840
|
+
"plus-lighter": {},
|
|
9841
|
+
"screen": {},
|
|
9842
|
+
"overlay": {}
|
|
9843
|
+
},
|
|
9844
|
+
"default": "normal",
|
|
9845
|
+
"property-type": "constant",
|
|
9846
|
+
"transition": false
|
|
9847
|
+
},
|
|
9778
9848
|
"raster-hue-rotate": {
|
|
9779
9849
|
"type": "number",
|
|
9780
9850
|
"default": 0,
|
|
@@ -10135,10 +10205,44 @@ var v8_default = {
|
|
|
10135
10205
|
}
|
|
10136
10206
|
};
|
|
10137
10207
|
|
|
10138
|
-
|
|
10208
|
+
// src/reference/latest.ts
|
|
10139
10209
|
const latest = v8_default;
|
|
10140
10210
|
|
|
10141
|
-
|
|
10211
|
+
// src/expression/parsing_error.ts
|
|
10212
|
+
var ExpressionParsingError = class extends Error {
|
|
10213
|
+
constructor(key, message) {
|
|
10214
|
+
super(message);
|
|
10215
|
+
this.message = message;
|
|
10216
|
+
this.key = key;
|
|
10217
|
+
}
|
|
10218
|
+
};
|
|
10219
|
+
|
|
10220
|
+
// src/expression/scope.ts
|
|
10221
|
+
/**
|
|
10222
|
+
* Tracks `let` bindings during expression parsing.
|
|
10223
|
+
* @private
|
|
10224
|
+
*/
|
|
10225
|
+
var Scope = class Scope {
|
|
10226
|
+
constructor(parent, bindings = []) {
|
|
10227
|
+
this.parent = parent;
|
|
10228
|
+
this.bindings = {};
|
|
10229
|
+
for (const [name, expression] of bindings) this.bindings[name] = expression;
|
|
10230
|
+
}
|
|
10231
|
+
concat(bindings) {
|
|
10232
|
+
return new Scope(this, bindings);
|
|
10233
|
+
}
|
|
10234
|
+
get(name) {
|
|
10235
|
+
if (this.bindings[name]) return this.bindings[name];
|
|
10236
|
+
if (this.parent) return this.parent.get(name);
|
|
10237
|
+
throw new Error(`${name} not found in scope.`);
|
|
10238
|
+
}
|
|
10239
|
+
has(name) {
|
|
10240
|
+
if (this.bindings[name]) return true;
|
|
10241
|
+
return this.parent ? this.parent.has(name) : false;
|
|
10242
|
+
}
|
|
10243
|
+
};
|
|
10244
|
+
|
|
10245
|
+
// src/expression/types.ts
|
|
10142
10246
|
const NullType = { kind: "null" };
|
|
10143
10247
|
const NumberType = { kind: "number" };
|
|
10144
10248
|
const StringType = { kind: "string" };
|
|
@@ -10234,7 +10338,7 @@ function verifyType(provided, sample) {
|
|
|
10234
10338
|
return provided.kind === sample.kind;
|
|
10235
10339
|
}
|
|
10236
10340
|
|
|
10237
|
-
|
|
10341
|
+
// src/expression/types/color_spaces.ts
|
|
10238
10342
|
const Xn = .96422;
|
|
10239
10343
|
const Yn = 1;
|
|
10240
10344
|
const Zn = .82521;
|
|
@@ -10329,7 +10433,7 @@ function hslToRgb([h, s, l, alpha]) {
|
|
|
10329
10433
|
];
|
|
10330
10434
|
}
|
|
10331
10435
|
|
|
10332
|
-
|
|
10436
|
+
// src/util/get_own.ts
|
|
10333
10437
|
const hasOwnProperty = Object.hasOwn || function hasOwnProperty(object, key) {
|
|
10334
10438
|
return Object.prototype.hasOwnProperty.call(object, key);
|
|
10335
10439
|
};
|
|
@@ -10337,7 +10441,7 @@ function getOwn(object, key) {
|
|
|
10337
10441
|
return hasOwnProperty(object, key) ? object[key] : void 0;
|
|
10338
10442
|
}
|
|
10339
10443
|
|
|
10340
|
-
|
|
10444
|
+
// src/expression/types/parse_css_color.ts
|
|
10341
10445
|
/**
|
|
10342
10446
|
* CSS color parser compliant with CSS Color 4 Specification.
|
|
10343
10447
|
* Supports: named colors, `transparent` keyword, all rgb hex notations,
|
|
@@ -11215,7 +11319,7 @@ const namedColors = {
|
|
|
11215
11319
|
]
|
|
11216
11320
|
};
|
|
11217
11321
|
|
|
11218
|
-
|
|
11322
|
+
// src/util/interpolate-primitives.ts
|
|
11219
11323
|
function interpolateNumber(from, to, t) {
|
|
11220
11324
|
return from + t * (to - from);
|
|
11221
11325
|
}
|
|
@@ -11225,7 +11329,7 @@ function interpolateArray(from, to, t) {
|
|
|
11225
11329
|
});
|
|
11226
11330
|
}
|
|
11227
11331
|
|
|
11228
|
-
|
|
11332
|
+
// src/expression/types/color.ts
|
|
11229
11333
|
/**
|
|
11230
11334
|
* Checks whether the specified color space is one of the supported interpolation color spaces.
|
|
11231
11335
|
*
|
|
@@ -11409,7 +11513,26 @@ var Color$1 = class Color {
|
|
|
11409
11513
|
}
|
|
11410
11514
|
};
|
|
11411
11515
|
|
|
11412
|
-
|
|
11516
|
+
// src/expression/types/collator.ts
|
|
11517
|
+
var Collator = class {
|
|
11518
|
+
constructor(caseSensitive, diacriticSensitive, locale) {
|
|
11519
|
+
if (caseSensitive) this.sensitivity = diacriticSensitive ? "variant" : "case";
|
|
11520
|
+
else this.sensitivity = diacriticSensitive ? "accent" : "base";
|
|
11521
|
+
this.locale = locale;
|
|
11522
|
+
this.collator = new Intl.Collator(this.locale ? this.locale : [], {
|
|
11523
|
+
sensitivity: this.sensitivity,
|
|
11524
|
+
usage: "search"
|
|
11525
|
+
});
|
|
11526
|
+
}
|
|
11527
|
+
compare(lhs, rhs) {
|
|
11528
|
+
return this.collator.compare(lhs, rhs);
|
|
11529
|
+
}
|
|
11530
|
+
resolvedLocale() {
|
|
11531
|
+
return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
|
|
11532
|
+
}
|
|
11533
|
+
};
|
|
11534
|
+
|
|
11535
|
+
// src/expression/types/formatted.ts
|
|
11413
11536
|
const VERTICAL_ALIGN_OPTIONS = [
|
|
11414
11537
|
"bottom",
|
|
11415
11538
|
"center",
|
|
@@ -11446,7 +11569,7 @@ var Formatted = class Formatted {
|
|
|
11446
11569
|
}
|
|
11447
11570
|
};
|
|
11448
11571
|
|
|
11449
|
-
|
|
11572
|
+
// src/expression/types/padding.ts
|
|
11450
11573
|
/**
|
|
11451
11574
|
* A set of four numbers representing padding around a box. Create instances from
|
|
11452
11575
|
* bare arrays or numeric values using the static method `Padding.parse`.
|
|
@@ -11506,7 +11629,7 @@ var Padding = class Padding {
|
|
|
11506
11629
|
}
|
|
11507
11630
|
};
|
|
11508
11631
|
|
|
11509
|
-
|
|
11632
|
+
// src/expression/types/number_array.ts
|
|
11510
11633
|
/**
|
|
11511
11634
|
* An array of numbers. Create instances from
|
|
11512
11635
|
* bare arrays or numeric values using the static method `NumberArray.parse`.
|
|
@@ -11536,7 +11659,7 @@ var NumberArray = class NumberArray {
|
|
|
11536
11659
|
}
|
|
11537
11660
|
};
|
|
11538
11661
|
|
|
11539
|
-
|
|
11662
|
+
// src/expression/types/color_array.ts
|
|
11540
11663
|
/**
|
|
11541
11664
|
* An array of colors. Create instances from
|
|
11542
11665
|
* bare arrays or strings using the static method `ColorArray.parse`.
|
|
@@ -11579,7 +11702,7 @@ var ColorArray = class ColorArray {
|
|
|
11579
11702
|
}
|
|
11580
11703
|
};
|
|
11581
11704
|
|
|
11582
|
-
|
|
11705
|
+
// src/expression/runtime_error.ts
|
|
11583
11706
|
var RuntimeError = class extends Error {
|
|
11584
11707
|
constructor(message, path) {
|
|
11585
11708
|
super(message);
|
|
@@ -11591,7 +11714,7 @@ var RuntimeError = class extends Error {
|
|
|
11591
11714
|
}
|
|
11592
11715
|
};
|
|
11593
11716
|
|
|
11594
|
-
|
|
11717
|
+
// src/expression/types/variable_anchor_offset_collection.ts
|
|
11595
11718
|
/** Set of valid anchor positions, as a set for validation */
|
|
11596
11719
|
const anchors = /* @__PURE__ */ new Set([
|
|
11597
11720
|
"center",
|
|
@@ -11643,7 +11766,7 @@ var VariableAnchorOffsetCollection = class VariableAnchorOffsetCollection {
|
|
|
11643
11766
|
}
|
|
11644
11767
|
};
|
|
11645
11768
|
|
|
11646
|
-
|
|
11769
|
+
// src/expression/types/resolved_image.ts
|
|
11647
11770
|
var ResolvedImage = class ResolvedImage {
|
|
11648
11771
|
constructor(options) {
|
|
11649
11772
|
this.name = options.name;
|
|
@@ -11661,7 +11784,7 @@ var ResolvedImage = class ResolvedImage {
|
|
|
11661
11784
|
}
|
|
11662
11785
|
};
|
|
11663
11786
|
|
|
11664
|
-
|
|
11787
|
+
// src/expression/types/projection_definition.ts
|
|
11665
11788
|
var ProjectionDefinition = class ProjectionDefinition {
|
|
11666
11789
|
constructor(from, to, transition) {
|
|
11667
11790
|
this.from = from;
|
|
@@ -11687,26 +11810,7 @@ var ProjectionDefinition = class ProjectionDefinition {
|
|
|
11687
11810
|
}
|
|
11688
11811
|
};
|
|
11689
11812
|
|
|
11690
|
-
|
|
11691
|
-
var Collator = class {
|
|
11692
|
-
constructor(caseSensitive, diacriticSensitive, locale) {
|
|
11693
|
-
if (caseSensitive) this.sensitivity = diacriticSensitive ? "variant" : "case";
|
|
11694
|
-
else this.sensitivity = diacriticSensitive ? "accent" : "base";
|
|
11695
|
-
this.locale = locale;
|
|
11696
|
-
this.collator = new Intl.Collator(this.locale ? this.locale : [], {
|
|
11697
|
-
sensitivity: this.sensitivity,
|
|
11698
|
-
usage: "search"
|
|
11699
|
-
});
|
|
11700
|
-
}
|
|
11701
|
-
compare(lhs, rhs) {
|
|
11702
|
-
return this.collator.compare(lhs, rhs);
|
|
11703
|
-
}
|
|
11704
|
-
resolvedLocale() {
|
|
11705
|
-
return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
|
|
11706
|
-
}
|
|
11707
|
-
};
|
|
11708
|
-
|
|
11709
|
-
//#region src/expression/values.ts
|
|
11813
|
+
// src/expression/values.ts
|
|
11710
11814
|
function validateRGBA(r, g, b, a) {
|
|
11711
11815
|
if (!(typeof r === "number" && r >= 0 && r <= 255 && typeof g === "number" && g >= 0 && g <= 255 && typeof b === "number" && b >= 0 && b <= 255)) return `Invalid rgba value [${(typeof a === "number" ? [
|
|
11712
11816
|
r,
|
|
@@ -11773,7 +11877,7 @@ function valueToString(value) {
|
|
|
11773
11877
|
else return JSON.stringify(value);
|
|
11774
11878
|
}
|
|
11775
11879
|
|
|
11776
|
-
|
|
11880
|
+
// src/expression/definitions/literal.ts
|
|
11777
11881
|
var Literal = class Literal {
|
|
11778
11882
|
constructor(type, value) {
|
|
11779
11883
|
this.type = type;
|
|
@@ -11797,539 +11901,100 @@ var Literal = class Literal {
|
|
|
11797
11901
|
}
|
|
11798
11902
|
};
|
|
11799
11903
|
|
|
11800
|
-
|
|
11801
|
-
const
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
var
|
|
11808
|
-
constructor() {
|
|
11809
|
-
this.
|
|
11810
|
-
this.
|
|
11811
|
-
this.
|
|
11812
|
-
this.formattedSection = null;
|
|
11813
|
-
this._parseColorCache = /* @__PURE__ */ new Map();
|
|
11814
|
-
this.availableImages = null;
|
|
11815
|
-
this.canonical = null;
|
|
11816
|
-
}
|
|
11817
|
-
id() {
|
|
11818
|
-
return this.feature && "id" in this.feature ? this.feature.id : null;
|
|
11819
|
-
}
|
|
11820
|
-
geometryType() {
|
|
11821
|
-
return this.feature ? typeof this.feature.type === "number" ? geometryTypes[this.feature.type] : this.feature.type : null;
|
|
11904
|
+
// src/expression/definitions/assertion.ts
|
|
11905
|
+
const types$1 = {
|
|
11906
|
+
string: StringType,
|
|
11907
|
+
number: NumberType,
|
|
11908
|
+
boolean: BooleanType,
|
|
11909
|
+
object: ObjectType
|
|
11910
|
+
};
|
|
11911
|
+
var Assertion = class Assertion {
|
|
11912
|
+
constructor(type, args, key) {
|
|
11913
|
+
this.type = type;
|
|
11914
|
+
this.args = args;
|
|
11915
|
+
this.key = key;
|
|
11822
11916
|
}
|
|
11823
|
-
|
|
11824
|
-
|
|
11917
|
+
static parse(args, context) {
|
|
11918
|
+
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
11919
|
+
let i = 1;
|
|
11920
|
+
let type;
|
|
11921
|
+
const name = args[0];
|
|
11922
|
+
if (name === "array") {
|
|
11923
|
+
let itemType;
|
|
11924
|
+
if (args.length > 2) {
|
|
11925
|
+
const type = args[1];
|
|
11926
|
+
if (typeof type !== "string" || !(type in types$1) || type === "object") return context.error("The item type argument of \"array\" must be one of string, number, boolean", 1);
|
|
11927
|
+
itemType = types$1[type];
|
|
11928
|
+
i++;
|
|
11929
|
+
} else itemType = ValueType;
|
|
11930
|
+
let N;
|
|
11931
|
+
if (args.length > 3) {
|
|
11932
|
+
if (args[2] !== null && (typeof args[2] !== "number" || args[2] < 0 || args[2] !== Math.floor(args[2]))) return context.error("The length argument to \"array\" must be a positive integer literal", 2);
|
|
11933
|
+
N = args[2];
|
|
11934
|
+
i++;
|
|
11935
|
+
}
|
|
11936
|
+
type = array(itemType, N);
|
|
11937
|
+
} else {
|
|
11938
|
+
if (!types$1[name]) throw new Error(`Types doesn't contain name = ${name}`);
|
|
11939
|
+
type = types$1[name];
|
|
11940
|
+
}
|
|
11941
|
+
const parsed = [];
|
|
11942
|
+
for (; i < args.length; i++) {
|
|
11943
|
+
const input = context.parse(args[i], i, ValueType);
|
|
11944
|
+
if (!input) return null;
|
|
11945
|
+
parsed.push(input);
|
|
11946
|
+
}
|
|
11947
|
+
return new Assertion(type, parsed, context.key);
|
|
11825
11948
|
}
|
|
11826
|
-
|
|
11827
|
-
|
|
11949
|
+
evaluate(ctx) {
|
|
11950
|
+
for (let i = 0; i < this.args.length; i++) {
|
|
11951
|
+
const value = this.args[i].evaluate(ctx);
|
|
11952
|
+
if (!checkSubtype(this.type, typeOf(value))) return value;
|
|
11953
|
+
else if (i === this.args.length - 1) throw new RuntimeError(`Expected value to be of type ${typeToString(this.type)}, but found ${typeToString(typeOf(value))} instead.`, this.key);
|
|
11954
|
+
}
|
|
11955
|
+
throw new Error();
|
|
11828
11956
|
}
|
|
11829
|
-
|
|
11830
|
-
|
|
11957
|
+
eachChild(fn) {
|
|
11958
|
+
this.args.forEach(fn);
|
|
11831
11959
|
}
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
if (!cached) {
|
|
11835
|
-
cached = Color$1.parse(input);
|
|
11836
|
-
this._parseColorCache.set(input, cached);
|
|
11837
|
-
}
|
|
11838
|
-
return cached;
|
|
11960
|
+
outputDefined() {
|
|
11961
|
+
return this.args.every((arg) => arg.outputDefined());
|
|
11839
11962
|
}
|
|
11840
11963
|
};
|
|
11841
11964
|
|
|
11842
|
-
|
|
11965
|
+
// src/expression/definitions/coercion.ts
|
|
11966
|
+
const types = {
|
|
11967
|
+
"to-boolean": BooleanType,
|
|
11968
|
+
"to-color": ColorType,
|
|
11969
|
+
"to-number": NumberType,
|
|
11970
|
+
"to-string": StringType
|
|
11971
|
+
};
|
|
11843
11972
|
/**
|
|
11844
|
-
*
|
|
11973
|
+
* Special form for error-coalescing coercion expressions "to-number",
|
|
11974
|
+
* "to-color". Since these coercions can fail at runtime, they accept multiple
|
|
11975
|
+
* arguments, only evaluating one at a time until one succeeds.
|
|
11976
|
+
*
|
|
11845
11977
|
* @private
|
|
11846
11978
|
*/
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
let lowerIndex = 0;
|
|
11850
|
-
let upperIndex = lastIndex;
|
|
11851
|
-
let currentIndex = 0;
|
|
11852
|
-
let currentValue, nextValue;
|
|
11853
|
-
while (lowerIndex <= upperIndex) {
|
|
11854
|
-
currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
|
|
11855
|
-
currentValue = stops[currentIndex];
|
|
11856
|
-
nextValue = stops[currentIndex + 1];
|
|
11857
|
-
if (currentValue <= input) {
|
|
11858
|
-
if (currentIndex === lastIndex || input < nextValue) return currentIndex;
|
|
11859
|
-
lowerIndex = currentIndex + 1;
|
|
11860
|
-
} else if (currentValue > input) upperIndex = currentIndex - 1;
|
|
11861
|
-
else throw new RuntimeError("Input is not a number.", key);
|
|
11862
|
-
}
|
|
11863
|
-
return 0;
|
|
11864
|
-
}
|
|
11865
|
-
|
|
11866
|
-
//#region src/expression/definitions/step.ts
|
|
11867
|
-
var Step = class Step {
|
|
11868
|
-
constructor(type, input, stops, key) {
|
|
11979
|
+
var Coercion = class Coercion {
|
|
11980
|
+
constructor(type, args, key) {
|
|
11869
11981
|
this.type = type;
|
|
11870
|
-
this.
|
|
11982
|
+
this.args = args;
|
|
11871
11983
|
this.key = key;
|
|
11872
|
-
this.labels = [];
|
|
11873
|
-
this.outputs = [];
|
|
11874
|
-
for (const [label, expression] of stops) {
|
|
11875
|
-
this.labels.push(label);
|
|
11876
|
-
this.outputs.push(expression);
|
|
11877
|
-
}
|
|
11878
11984
|
}
|
|
11879
11985
|
static parse(args, context) {
|
|
11880
|
-
if (args.length
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
if (
|
|
11884
|
-
const
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
const labelKey = i;
|
|
11891
|
-
const valueKey = i + 1;
|
|
11892
|
-
if (typeof label !== "number") return context.error("Input/output pairs for \"step\" expressions must be defined using literal numeric values (not computed expressions) for the input values.", labelKey);
|
|
11893
|
-
if (stops.length && stops[stops.length - 1][0] >= label) return context.error("Input/output pairs for \"step\" expressions must be arranged with input values in strictly ascending order.", labelKey);
|
|
11894
|
-
const parsed = context.parse(value, valueKey, outputType);
|
|
11895
|
-
if (!parsed) return null;
|
|
11896
|
-
outputType = outputType || parsed.type;
|
|
11897
|
-
stops.push([label, parsed]);
|
|
11986
|
+
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
11987
|
+
const name = args[0];
|
|
11988
|
+
if (!types[name]) throw new Error(`Can't parse ${name} as it is not part of the known types`);
|
|
11989
|
+
if ((name === "to-boolean" || name === "to-string") && args.length !== 2) return context.error("Expected one argument.");
|
|
11990
|
+
const type = types[name];
|
|
11991
|
+
const parsed = [];
|
|
11992
|
+
for (let i = 1; i < args.length; i++) {
|
|
11993
|
+
const input = context.parse(args[i], i, ValueType);
|
|
11994
|
+
if (!input) return null;
|
|
11995
|
+
parsed.push(input);
|
|
11898
11996
|
}
|
|
11899
|
-
return new
|
|
11900
|
-
}
|
|
11901
|
-
evaluate(ctx) {
|
|
11902
|
-
const labels = this.labels;
|
|
11903
|
-
const outputs = this.outputs;
|
|
11904
|
-
if (labels.length === 1) return outputs[0].evaluate(ctx);
|
|
11905
|
-
const value = this.input.evaluate(ctx);
|
|
11906
|
-
if (value <= labels[0]) return outputs[0].evaluate(ctx);
|
|
11907
|
-
const stopCount = labels.length;
|
|
11908
|
-
if (value >= labels[stopCount - 1]) return outputs[stopCount - 1].evaluate(ctx);
|
|
11909
|
-
return outputs[findStopLessThanOrEqualTo(labels, value, this.key)].evaluate(ctx);
|
|
11910
|
-
}
|
|
11911
|
-
eachChild(fn) {
|
|
11912
|
-
fn(this.input);
|
|
11913
|
-
for (const expression of this.outputs) fn(expression);
|
|
11914
|
-
}
|
|
11915
|
-
outputDefined() {
|
|
11916
|
-
return this.outputs.every((out) => out.outputDefined());
|
|
11917
|
-
}
|
|
11918
|
-
};
|
|
11919
|
-
|
|
11920
|
-
//#region node_modules/@mapbox/unitbezier/index.js
|
|
11921
|
-
function unitBezier(p1x, p1y, p2x, p2y) {
|
|
11922
|
-
const cx = 3 * p1x;
|
|
11923
|
-
const bx = 3 * (p2x - p1x) - cx;
|
|
11924
|
-
const ax = 1 - cx - bx;
|
|
11925
|
-
const cy = 3 * p1y;
|
|
11926
|
-
const by = 3 * (p2y - p1y) - cy;
|
|
11927
|
-
const ay = 1 - cy - by;
|
|
11928
|
-
return function solve(x, epsilon = 1e-6) {
|
|
11929
|
-
if (x <= 0) return 0;
|
|
11930
|
-
if (x >= 1) return 1;
|
|
11931
|
-
let t = x;
|
|
11932
|
-
for (let i = 0; i < 8; i++) {
|
|
11933
|
-
const x2 = ((ax * t + bx) * t + cx) * t - x;
|
|
11934
|
-
if (Math.abs(x2) < epsilon) return ((ay * t + by) * t + cy) * t;
|
|
11935
|
-
const d2 = (3 * ax * t + 2 * bx) * t + cx;
|
|
11936
|
-
if (Math.abs(d2) < 1e-6) break;
|
|
11937
|
-
t -= x2 / d2;
|
|
11938
|
-
}
|
|
11939
|
-
let t0 = 0;
|
|
11940
|
-
let t1 = 1;
|
|
11941
|
-
t = x;
|
|
11942
|
-
for (let i = 0; i < 20; i++) {
|
|
11943
|
-
const x2 = ((ax * t + bx) * t + cx) * t;
|
|
11944
|
-
if (Math.abs(x2 - x) < epsilon) break;
|
|
11945
|
-
if (x > x2) t0 = t;
|
|
11946
|
-
else t1 = t;
|
|
11947
|
-
t = (t0 + t1) * .5;
|
|
11948
|
-
}
|
|
11949
|
-
return ((ay * t + by) * t + cy) * t;
|
|
11950
|
-
};
|
|
11951
|
-
}
|
|
11952
|
-
|
|
11953
|
-
//#region src/expression/definitions/interpolate.ts
|
|
11954
|
-
var Interpolate = class Interpolate {
|
|
11955
|
-
constructor(type, operator, interpolation, input, stops, key) {
|
|
11956
|
-
this.type = type;
|
|
11957
|
-
this.operator = operator;
|
|
11958
|
-
this.interpolation = interpolation;
|
|
11959
|
-
this.input = input;
|
|
11960
|
-
this.key = key;
|
|
11961
|
-
this.labels = [];
|
|
11962
|
-
this.outputs = [];
|
|
11963
|
-
for (const [label, expression] of stops) {
|
|
11964
|
-
this.labels.push(label);
|
|
11965
|
-
this.outputs.push(expression);
|
|
11966
|
-
}
|
|
11967
|
-
}
|
|
11968
|
-
static interpolationFactor(interpolation, input, lower, upper) {
|
|
11969
|
-
let t = 0;
|
|
11970
|
-
if (interpolation.name === "exponential") t = exponentialInterpolation(input, interpolation.base, lower, upper);
|
|
11971
|
-
else if (interpolation.name === "linear") t = exponentialInterpolation(input, 1, lower, upper);
|
|
11972
|
-
else if (interpolation.name === "cubic-bezier") {
|
|
11973
|
-
const c = interpolation.controlPoints;
|
|
11974
|
-
t = unitBezier(c[0], c[1], c[2], c[3])(exponentialInterpolation(input, 1, lower, upper));
|
|
11975
|
-
}
|
|
11976
|
-
return t;
|
|
11977
|
-
}
|
|
11978
|
-
static parse(args, context) {
|
|
11979
|
-
let [operator, interpolation, input, ...rest] = args;
|
|
11980
|
-
if (!Array.isArray(interpolation) || interpolation.length === 0) return context.error("Expected an interpolation type expression.", 1);
|
|
11981
|
-
if (interpolation[0] === "linear") interpolation = { name: "linear" };
|
|
11982
|
-
else if (interpolation[0] === "exponential") {
|
|
11983
|
-
const base = interpolation[1];
|
|
11984
|
-
if (typeof base !== "number") return context.error("Exponential interpolation requires a numeric base.", 1, 1);
|
|
11985
|
-
interpolation = {
|
|
11986
|
-
name: "exponential",
|
|
11987
|
-
base
|
|
11988
|
-
};
|
|
11989
|
-
} else if (interpolation[0] === "cubic-bezier") {
|
|
11990
|
-
const controlPoints = interpolation.slice(1);
|
|
11991
|
-
if (controlPoints.length !== 4 || controlPoints.some((t) => typeof t !== "number" || t < 0 || t > 1)) return context.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.", 1);
|
|
11992
|
-
interpolation = {
|
|
11993
|
-
name: "cubic-bezier",
|
|
11994
|
-
controlPoints
|
|
11995
|
-
};
|
|
11996
|
-
} else return context.error(`Unknown interpolation type ${String(interpolation[0])}`, 1, 0);
|
|
11997
|
-
if (args.length - 1 < 4) return context.error(`Expected at least 4 arguments, but found only ${args.length - 1}.`);
|
|
11998
|
-
if ((args.length - 1) % 2 !== 0) return context.error("Expected an even number of arguments.");
|
|
11999
|
-
input = context.parse(input, 2, NumberType);
|
|
12000
|
-
if (!input) return null;
|
|
12001
|
-
const stops = [];
|
|
12002
|
-
let outputType = null;
|
|
12003
|
-
if ((operator === "interpolate-hcl" || operator === "interpolate-lab") && context.expectedType != ColorArrayType) outputType = ColorType;
|
|
12004
|
-
else if (context.expectedType && context.expectedType.kind !== "value") outputType = context.expectedType;
|
|
12005
|
-
for (let i = 0; i < rest.length; i += 2) {
|
|
12006
|
-
const label = rest[i];
|
|
12007
|
-
const value = rest[i + 1];
|
|
12008
|
-
const labelKey = i + 3;
|
|
12009
|
-
const valueKey = i + 4;
|
|
12010
|
-
if (typeof label !== "number") return context.error("Input/output pairs for \"interpolate\" expressions must be defined using literal numeric values (not computed expressions) for the input values.", labelKey);
|
|
12011
|
-
if (stops.length && stops[stops.length - 1][0] >= label) return context.error("Input/output pairs for \"interpolate\" expressions must be arranged with input values in strictly ascending order.", labelKey);
|
|
12012
|
-
const parsed = context.parse(value, valueKey, outputType);
|
|
12013
|
-
if (!parsed) return null;
|
|
12014
|
-
outputType = outputType || parsed.type;
|
|
12015
|
-
stops.push([label, parsed]);
|
|
12016
|
-
}
|
|
12017
|
-
if (!verifyType(outputType, NumberType) && !verifyType(outputType, ProjectionDefinitionType) && !verifyType(outputType, ColorType) && !verifyType(outputType, PaddingType) && !verifyType(outputType, NumberArrayType) && !verifyType(outputType, ColorArrayType) && !verifyType(outputType, VariableAnchorOffsetCollectionType) && !verifyType(outputType, array(NumberType))) return context.error(`Type ${typeToString(outputType)} is not interpolatable.`);
|
|
12018
|
-
return new Interpolate(outputType, operator, interpolation, input, stops, context.key);
|
|
12019
|
-
}
|
|
12020
|
-
evaluate(ctx) {
|
|
12021
|
-
const labels = this.labels;
|
|
12022
|
-
const outputs = this.outputs;
|
|
12023
|
-
if (labels.length === 1) return outputs[0].evaluate(ctx);
|
|
12024
|
-
const value = this.input.evaluate(ctx);
|
|
12025
|
-
if (value <= labels[0]) return outputs[0].evaluate(ctx);
|
|
12026
|
-
const stopCount = labels.length;
|
|
12027
|
-
if (value >= labels[stopCount - 1]) return outputs[stopCount - 1].evaluate(ctx);
|
|
12028
|
-
const index = findStopLessThanOrEqualTo(labels, value, this.key);
|
|
12029
|
-
const lower = labels[index];
|
|
12030
|
-
const upper = labels[index + 1];
|
|
12031
|
-
const t = Interpolate.interpolationFactor(this.interpolation, value, lower, upper);
|
|
12032
|
-
const outputLower = outputs[index].evaluate(ctx);
|
|
12033
|
-
const outputUpper = outputs[index + 1].evaluate(ctx);
|
|
12034
|
-
switch (this.operator) {
|
|
12035
|
-
case "interpolate": switch (this.type.kind) {
|
|
12036
|
-
case "number": return interpolateNumber(outputLower, outputUpper, t);
|
|
12037
|
-
case "color": return Color$1.interpolate(outputLower, outputUpper, t);
|
|
12038
|
-
case "padding": return Padding.interpolate(outputLower, outputUpper, t);
|
|
12039
|
-
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t);
|
|
12040
|
-
case "numberArray": return NumberArray.interpolate(outputLower, outputUpper, t);
|
|
12041
|
-
case "variableAnchorOffsetCollection": return VariableAnchorOffsetCollection.interpolate(outputLower, outputUpper, t, this.key);
|
|
12042
|
-
case "array": return interpolateArray(outputLower, outputUpper, t);
|
|
12043
|
-
case "projectionDefinition": return ProjectionDefinition.interpolate(outputLower, outputUpper, t);
|
|
12044
|
-
}
|
|
12045
|
-
case "interpolate-hcl": switch (this.type.kind) {
|
|
12046
|
-
case "color": return Color$1.interpolate(outputLower, outputUpper, t, "hcl");
|
|
12047
|
-
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t, "hcl");
|
|
12048
|
-
}
|
|
12049
|
-
case "interpolate-lab": switch (this.type.kind) {
|
|
12050
|
-
case "color": return Color$1.interpolate(outputLower, outputUpper, t, "lab");
|
|
12051
|
-
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t, "lab");
|
|
12052
|
-
}
|
|
12053
|
-
}
|
|
12054
|
-
}
|
|
12055
|
-
eachChild(fn) {
|
|
12056
|
-
fn(this.input);
|
|
12057
|
-
for (const expression of this.outputs) fn(expression);
|
|
12058
|
-
}
|
|
12059
|
-
outputDefined() {
|
|
12060
|
-
return this.outputs.every((out) => out.outputDefined());
|
|
12061
|
-
}
|
|
12062
|
-
};
|
|
12063
|
-
/**
|
|
12064
|
-
* Returns a ratio that can be used to interpolate between exponential function
|
|
12065
|
-
* stops.
|
|
12066
|
-
* How it works: Two consecutive stop values define a (scaled and shifted) exponential function `f(x) = a * base^x + b`, where `base` is the user-specified base,
|
|
12067
|
-
* and `a` and `b` are constants affording sufficient degrees of freedom to fit
|
|
12068
|
-
* the function to the given stops.
|
|
12069
|
-
*
|
|
12070
|
-
* Here's a bit of algebra that lets us compute `f(x)` directly from the stop
|
|
12071
|
-
* values without explicitly solving for `a` and `b`:
|
|
12072
|
-
*
|
|
12073
|
-
* First stop value: `f(x0) = y0 = a * base^x0 + b`
|
|
12074
|
-
* Second stop value: `f(x1) = y1 = a * base^x1 + b`
|
|
12075
|
-
* => `y1 - y0 = a(base^x1 - base^x0)`
|
|
12076
|
-
* => `a = (y1 - y0)/(base^x1 - base^x0)`
|
|
12077
|
-
*
|
|
12078
|
-
* Desired value: `f(x) = y = a * base^x + b`
|
|
12079
|
-
* => `f(x) = y0 + a * (base^x - base^x0)`
|
|
12080
|
-
*
|
|
12081
|
-
* From the above, we can replace the `a` in `a * (base^x - base^x0)` and do a
|
|
12082
|
-
* little algebra:
|
|
12083
|
-
* ```
|
|
12084
|
-
* a * (base^x - base^x0) = (y1 - y0)/(base^x1 - base^x0) * (base^x - base^x0)
|
|
12085
|
-
* = (y1 - y0) * (base^x - base^x0) / (base^x1 - base^x0)
|
|
12086
|
-
* ```
|
|
12087
|
-
*
|
|
12088
|
-
* If we let `(base^x - base^x0) / (base^x1 base^x0)`, then we have
|
|
12089
|
-
* `f(x) = y0 + (y1 - y0) * ratio`. In other words, `ratio` may be treated as
|
|
12090
|
-
* an interpolation factor between the two stops' output values.
|
|
12091
|
-
*
|
|
12092
|
-
* (Note: a slightly different form for `ratio`,
|
|
12093
|
-
* `(base^(x-x0) - 1) / (base^(x1-x0) - 1) `, is equivalent, but requires fewer
|
|
12094
|
-
* expensive `Math.pow()` operations.)
|
|
12095
|
-
*
|
|
12096
|
-
* @private
|
|
12097
|
-
*/
|
|
12098
|
-
function exponentialInterpolation(input, base, lowerValue, upperValue) {
|
|
12099
|
-
const difference = upperValue - lowerValue;
|
|
12100
|
-
const progress = input - lowerValue;
|
|
12101
|
-
if (difference === 0) return 0;
|
|
12102
|
-
else if (base === 1) return progress / difference;
|
|
12103
|
-
else return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
|
|
12104
|
-
}
|
|
12105
|
-
const interpolateFactory = {
|
|
12106
|
-
color: Color$1.interpolate,
|
|
12107
|
-
number: interpolateNumber,
|
|
12108
|
-
padding: Padding.interpolate,
|
|
12109
|
-
numberArray: NumberArray.interpolate,
|
|
12110
|
-
colorArray: ColorArray.interpolate,
|
|
12111
|
-
variableAnchorOffsetCollection: VariableAnchorOffsetCollection.interpolate,
|
|
12112
|
-
array: interpolateArray
|
|
12113
|
-
};
|
|
12114
|
-
|
|
12115
|
-
//#region src/expression/definitions/format.ts
|
|
12116
|
-
var FormatExpression = class FormatExpression {
|
|
12117
|
-
constructor(sections) {
|
|
12118
|
-
this.type = FormattedType;
|
|
12119
|
-
this.sections = sections;
|
|
12120
|
-
}
|
|
12121
|
-
static parse(args, context) {
|
|
12122
|
-
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
12123
|
-
const firstArg = args[1];
|
|
12124
|
-
if (!Array.isArray(firstArg) && typeof firstArg === "object") return context.error("First argument must be an image or text section.");
|
|
12125
|
-
const sections = [];
|
|
12126
|
-
let nextTokenMayBeObject = false;
|
|
12127
|
-
for (let i = 1; i <= args.length - 1; ++i) {
|
|
12128
|
-
const arg = args[i];
|
|
12129
|
-
if (nextTokenMayBeObject && typeof arg === "object" && !Array.isArray(arg)) {
|
|
12130
|
-
nextTokenMayBeObject = false;
|
|
12131
|
-
let scale = null;
|
|
12132
|
-
if (arg["font-scale"]) {
|
|
12133
|
-
scale = context.parse(arg["font-scale"], 1, NumberType);
|
|
12134
|
-
if (!scale) return null;
|
|
12135
|
-
}
|
|
12136
|
-
let font = null;
|
|
12137
|
-
if (arg["text-font"]) {
|
|
12138
|
-
font = context.parse(arg["text-font"], 1, array(StringType));
|
|
12139
|
-
if (!font) return null;
|
|
12140
|
-
}
|
|
12141
|
-
let textColor = null;
|
|
12142
|
-
if (arg["text-color"]) {
|
|
12143
|
-
textColor = context.parse(arg["text-color"], 1, ColorType);
|
|
12144
|
-
if (!textColor) return null;
|
|
12145
|
-
}
|
|
12146
|
-
let verticalAlign = null;
|
|
12147
|
-
if (arg["vertical-align"]) {
|
|
12148
|
-
if (typeof arg["vertical-align"] === "string" && !VERTICAL_ALIGN_OPTIONS.includes(arg["vertical-align"])) return context.error(`'vertical-align' must be one of: 'bottom', 'center', 'top' but found '${arg["vertical-align"]}' instead.`);
|
|
12149
|
-
verticalAlign = context.parse(arg["vertical-align"], 1, StringType);
|
|
12150
|
-
if (!verticalAlign) return null;
|
|
12151
|
-
}
|
|
12152
|
-
const lastExpression = sections[sections.length - 1];
|
|
12153
|
-
lastExpression.scale = scale;
|
|
12154
|
-
lastExpression.font = font;
|
|
12155
|
-
lastExpression.textColor = textColor;
|
|
12156
|
-
lastExpression.verticalAlign = verticalAlign;
|
|
12157
|
-
} else {
|
|
12158
|
-
const content = context.parse(args[i], 1, ValueType);
|
|
12159
|
-
if (!content) return null;
|
|
12160
|
-
const kind = content.type.kind;
|
|
12161
|
-
if (kind !== "string" && kind !== "value" && kind !== "null" && kind !== "resolvedImage") return context.error("Formatted text type must be 'string', 'value', 'image' or 'null'.");
|
|
12162
|
-
nextTokenMayBeObject = true;
|
|
12163
|
-
sections.push({
|
|
12164
|
-
content,
|
|
12165
|
-
scale: null,
|
|
12166
|
-
font: null,
|
|
12167
|
-
textColor: null,
|
|
12168
|
-
verticalAlign: null
|
|
12169
|
-
});
|
|
12170
|
-
}
|
|
12171
|
-
}
|
|
12172
|
-
return new FormatExpression(sections);
|
|
12173
|
-
}
|
|
12174
|
-
evaluate(ctx) {
|
|
12175
|
-
const evaluateSection = (section) => {
|
|
12176
|
-
const evaluatedContent = section.content.evaluate(ctx);
|
|
12177
|
-
if (typeOf(evaluatedContent) === ResolvedImageType) return new FormattedSection("", evaluatedContent, null, null, null, section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null);
|
|
12178
|
-
return new FormattedSection(valueToString(evaluatedContent), null, section.scale ? section.scale.evaluate(ctx) : null, section.font ? section.font.evaluate(ctx).join(",") : null, section.textColor ? section.textColor.evaluate(ctx) : null, section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null);
|
|
12179
|
-
};
|
|
12180
|
-
return new Formatted(this.sections.map(evaluateSection));
|
|
12181
|
-
}
|
|
12182
|
-
eachChild(fn) {
|
|
12183
|
-
for (const section of this.sections) {
|
|
12184
|
-
fn(section.content);
|
|
12185
|
-
if (section.scale) fn(section.scale);
|
|
12186
|
-
if (section.font) fn(section.font);
|
|
12187
|
-
if (section.textColor) fn(section.textColor);
|
|
12188
|
-
if (section.verticalAlign) fn(section.verticalAlign);
|
|
12189
|
-
}
|
|
12190
|
-
}
|
|
12191
|
-
outputDefined() {
|
|
12192
|
-
return false;
|
|
12193
|
-
}
|
|
12194
|
-
};
|
|
12195
|
-
|
|
12196
|
-
//#region src/util/classify_rings.ts
|
|
12197
|
-
/**
|
|
12198
|
-
* Classifies an array of rings into polygons with outer rings and holes
|
|
12199
|
-
* @param rings - the rings to classify
|
|
12200
|
-
* @param maxRings - the maximum number of rings to include in a polygon, use 0 to include all rings
|
|
12201
|
-
* @returns an array of polygons with internal rings as holes
|
|
12202
|
-
*/
|
|
12203
|
-
function classifyRings$1(rings, maxRings) {
|
|
12204
|
-
if (rings.length <= 1) return [rings];
|
|
12205
|
-
const polygons = [];
|
|
12206
|
-
let polygon;
|
|
12207
|
-
let ccw;
|
|
12208
|
-
for (const ring of rings) {
|
|
12209
|
-
const area = calculateSignedArea(ring);
|
|
12210
|
-
if (area === 0) continue;
|
|
12211
|
-
ring.area = Math.abs(area);
|
|
12212
|
-
if (ccw === void 0) ccw = area < 0;
|
|
12213
|
-
if (ccw === area < 0) {
|
|
12214
|
-
if (polygon) polygons.push(polygon);
|
|
12215
|
-
polygon = [ring];
|
|
12216
|
-
} else polygon.push(ring);
|
|
12217
|
-
}
|
|
12218
|
-
if (polygon) polygons.push(polygon);
|
|
12219
|
-
return polygons;
|
|
12220
|
-
}
|
|
12221
|
-
/**
|
|
12222
|
-
* Returns the signed area for the polygon ring. Positive areas are exterior rings and
|
|
12223
|
-
* have a clockwise winding. Negative areas are interior rings and have a counter clockwise
|
|
12224
|
-
* ordering.
|
|
12225
|
-
*
|
|
12226
|
-
* @param ring - Exterior or interior ring
|
|
12227
|
-
* @returns Signed area
|
|
12228
|
-
*/
|
|
12229
|
-
function calculateSignedArea(ring) {
|
|
12230
|
-
let sum = 0;
|
|
12231
|
-
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
|
|
12232
|
-
p1 = ring[i];
|
|
12233
|
-
p2 = ring[j];
|
|
12234
|
-
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
|
12235
|
-
}
|
|
12236
|
-
return sum;
|
|
12237
|
-
}
|
|
12238
|
-
|
|
12239
|
-
//#region src/expression/definitions/assertion.ts
|
|
12240
|
-
const types$1 = {
|
|
12241
|
-
string: StringType,
|
|
12242
|
-
number: NumberType,
|
|
12243
|
-
boolean: BooleanType,
|
|
12244
|
-
object: ObjectType
|
|
12245
|
-
};
|
|
12246
|
-
var Assertion = class Assertion {
|
|
12247
|
-
constructor(type, args, key) {
|
|
12248
|
-
this.type = type;
|
|
12249
|
-
this.args = args;
|
|
12250
|
-
this.key = key;
|
|
12251
|
-
}
|
|
12252
|
-
static parse(args, context) {
|
|
12253
|
-
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
12254
|
-
let i = 1;
|
|
12255
|
-
let type;
|
|
12256
|
-
const name = args[0];
|
|
12257
|
-
if (name === "array") {
|
|
12258
|
-
let itemType;
|
|
12259
|
-
if (args.length > 2) {
|
|
12260
|
-
const type = args[1];
|
|
12261
|
-
if (typeof type !== "string" || !(type in types$1) || type === "object") return context.error("The item type argument of \"array\" must be one of string, number, boolean", 1);
|
|
12262
|
-
itemType = types$1[type];
|
|
12263
|
-
i++;
|
|
12264
|
-
} else itemType = ValueType;
|
|
12265
|
-
let N;
|
|
12266
|
-
if (args.length > 3) {
|
|
12267
|
-
if (args[2] !== null && (typeof args[2] !== "number" || args[2] < 0 || args[2] !== Math.floor(args[2]))) return context.error("The length argument to \"array\" must be a positive integer literal", 2);
|
|
12268
|
-
N = args[2];
|
|
12269
|
-
i++;
|
|
12270
|
-
}
|
|
12271
|
-
type = array(itemType, N);
|
|
12272
|
-
} else {
|
|
12273
|
-
if (!types$1[name]) throw new Error(`Types doesn't contain name = ${name}`);
|
|
12274
|
-
type = types$1[name];
|
|
12275
|
-
}
|
|
12276
|
-
const parsed = [];
|
|
12277
|
-
for (; i < args.length; i++) {
|
|
12278
|
-
const input = context.parse(args[i], i, ValueType);
|
|
12279
|
-
if (!input) return null;
|
|
12280
|
-
parsed.push(input);
|
|
12281
|
-
}
|
|
12282
|
-
return new Assertion(type, parsed, context.key);
|
|
12283
|
-
}
|
|
12284
|
-
evaluate(ctx) {
|
|
12285
|
-
for (let i = 0; i < this.args.length; i++) {
|
|
12286
|
-
const value = this.args[i].evaluate(ctx);
|
|
12287
|
-
if (!checkSubtype(this.type, typeOf(value))) return value;
|
|
12288
|
-
else if (i === this.args.length - 1) throw new RuntimeError(`Expected value to be of type ${typeToString(this.type)}, but found ${typeToString(typeOf(value))} instead.`, this.key);
|
|
12289
|
-
}
|
|
12290
|
-
throw new Error();
|
|
12291
|
-
}
|
|
12292
|
-
eachChild(fn) {
|
|
12293
|
-
this.args.forEach(fn);
|
|
12294
|
-
}
|
|
12295
|
-
outputDefined() {
|
|
12296
|
-
return this.args.every((arg) => arg.outputDefined());
|
|
12297
|
-
}
|
|
12298
|
-
};
|
|
12299
|
-
|
|
12300
|
-
//#region src/expression/definitions/coercion.ts
|
|
12301
|
-
const types = {
|
|
12302
|
-
"to-boolean": BooleanType,
|
|
12303
|
-
"to-color": ColorType,
|
|
12304
|
-
"to-number": NumberType,
|
|
12305
|
-
"to-string": StringType
|
|
12306
|
-
};
|
|
12307
|
-
/**
|
|
12308
|
-
* Special form for error-coalescing coercion expressions "to-number",
|
|
12309
|
-
* "to-color". Since these coercions can fail at runtime, they accept multiple
|
|
12310
|
-
* arguments, only evaluating one at a time until one succeeds.
|
|
12311
|
-
*
|
|
12312
|
-
* @private
|
|
12313
|
-
*/
|
|
12314
|
-
var Coercion = class Coercion {
|
|
12315
|
-
constructor(type, args, key) {
|
|
12316
|
-
this.type = type;
|
|
12317
|
-
this.args = args;
|
|
12318
|
-
this.key = key;
|
|
12319
|
-
}
|
|
12320
|
-
static parse(args, context) {
|
|
12321
|
-
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
12322
|
-
const name = args[0];
|
|
12323
|
-
if (!types[name]) throw new Error(`Can't parse ${name} as it is not part of the known types`);
|
|
12324
|
-
if ((name === "to-boolean" || name === "to-string") && args.length !== 2) return context.error("Expected one argument.");
|
|
12325
|
-
const type = types[name];
|
|
12326
|
-
const parsed = [];
|
|
12327
|
-
for (let i = 1; i < args.length; i++) {
|
|
12328
|
-
const input = context.parse(args[i], i, ValueType);
|
|
12329
|
-
if (!input) return null;
|
|
12330
|
-
parsed.push(input);
|
|
12331
|
-
}
|
|
12332
|
-
return new Coercion(type, parsed, context.key);
|
|
11997
|
+
return new Coercion(type, parsed, context.key);
|
|
12333
11998
|
}
|
|
12334
11999
|
evaluate(ctx) {
|
|
12335
12000
|
switch (this.type.kind) {
|
|
@@ -12409,15 +12074,179 @@ var Coercion = class Coercion {
|
|
|
12409
12074
|
default: return valueToString(this.args[0].evaluate(ctx));
|
|
12410
12075
|
}
|
|
12411
12076
|
}
|
|
12412
|
-
eachChild(fn) {
|
|
12413
|
-
this.args.forEach(fn);
|
|
12077
|
+
eachChild(fn) {
|
|
12078
|
+
this.args.forEach(fn);
|
|
12079
|
+
}
|
|
12080
|
+
outputDefined() {
|
|
12081
|
+
return this.args.every((arg) => arg.outputDefined());
|
|
12082
|
+
}
|
|
12083
|
+
};
|
|
12084
|
+
|
|
12085
|
+
// src/expression/evaluation_context.ts
|
|
12086
|
+
const geometryTypes = [
|
|
12087
|
+
"Unknown",
|
|
12088
|
+
"Point",
|
|
12089
|
+
"LineString",
|
|
12090
|
+
"Polygon"
|
|
12091
|
+
];
|
|
12092
|
+
var EvaluationContext = class {
|
|
12093
|
+
constructor() {
|
|
12094
|
+
this.globals = null;
|
|
12095
|
+
this.feature = null;
|
|
12096
|
+
this.featureState = null;
|
|
12097
|
+
this.formattedSection = null;
|
|
12098
|
+
this._parseColorCache = /* @__PURE__ */ new Map();
|
|
12099
|
+
this.availableImages = null;
|
|
12100
|
+
this.canonical = null;
|
|
12101
|
+
}
|
|
12102
|
+
id() {
|
|
12103
|
+
return this.feature && "id" in this.feature ? this.feature.id : null;
|
|
12104
|
+
}
|
|
12105
|
+
geometryType() {
|
|
12106
|
+
return this.feature ? typeof this.feature.type === "number" ? geometryTypes[this.feature.type] : this.feature.type : null;
|
|
12107
|
+
}
|
|
12108
|
+
geometry() {
|
|
12109
|
+
return this.feature && "geometry" in this.feature ? this.feature.geometry : null;
|
|
12110
|
+
}
|
|
12111
|
+
canonicalID() {
|
|
12112
|
+
return this.canonical;
|
|
12113
|
+
}
|
|
12114
|
+
properties() {
|
|
12115
|
+
return this.feature && this.feature.properties || {};
|
|
12116
|
+
}
|
|
12117
|
+
parseColor(input) {
|
|
12118
|
+
let cached = this._parseColorCache.get(input);
|
|
12119
|
+
if (!cached) {
|
|
12120
|
+
cached = Color$1.parse(input);
|
|
12121
|
+
this._parseColorCache.set(input, cached);
|
|
12122
|
+
}
|
|
12123
|
+
return cached;
|
|
12124
|
+
}
|
|
12125
|
+
};
|
|
12126
|
+
|
|
12127
|
+
// src/expression/parsing_context.ts
|
|
12128
|
+
/**
|
|
12129
|
+
* State associated parsing at a given point in an expression tree.
|
|
12130
|
+
* @private
|
|
12131
|
+
*/
|
|
12132
|
+
var ParsingContext = class ParsingContext {
|
|
12133
|
+
constructor(registry, isConstantFunc, path = [], expectedType, scope = new Scope(), errors = []) {
|
|
12134
|
+
this.registry = registry;
|
|
12135
|
+
this.path = path;
|
|
12136
|
+
this.key = path.map((part) => `[${part}]`).join("");
|
|
12137
|
+
this.scope = scope;
|
|
12138
|
+
this.errors = errors;
|
|
12139
|
+
this.expectedType = expectedType;
|
|
12140
|
+
this._isConstant = isConstantFunc;
|
|
12141
|
+
}
|
|
12142
|
+
/**
|
|
12143
|
+
* @param expr the JSON expression to parse
|
|
12144
|
+
* @param index the optional argument index if this expression is an argument of a parent expression that's being parsed
|
|
12145
|
+
* @param options
|
|
12146
|
+
* @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.
|
|
12147
|
+
* @private
|
|
12148
|
+
*/
|
|
12149
|
+
parse(expr, index, expectedType, bindings, options = {}) {
|
|
12150
|
+
if (index != null) return this.concat(index, expectedType, bindings)._parse(expr, options);
|
|
12151
|
+
return this._parse(expr, options);
|
|
12152
|
+
}
|
|
12153
|
+
_parse(expr, options) {
|
|
12154
|
+
if (expr === null || typeof expr === "string" || typeof expr === "boolean" || typeof expr === "number") expr = ["literal", expr];
|
|
12155
|
+
const key = this.key;
|
|
12156
|
+
function annotate(parsed, type, typeAnnotation) {
|
|
12157
|
+
if (typeAnnotation === "assert") return new Assertion(type, [parsed], key);
|
|
12158
|
+
else if (typeAnnotation === "coerce") return new Coercion(type, [parsed], key);
|
|
12159
|
+
else return parsed;
|
|
12160
|
+
}
|
|
12161
|
+
if (Array.isArray(expr)) {
|
|
12162
|
+
if (expr.length === 0) return this.error("Expected an array with at least one element. If you wanted a literal array, use [\"literal\", []].");
|
|
12163
|
+
const op = expr[0];
|
|
12164
|
+
if (typeof op !== "string") {
|
|
12165
|
+
this.error(`Expression name must be a string, but found ${typeof op} instead. If you wanted a literal array, use ["literal", [...]].`, 0);
|
|
12166
|
+
return null;
|
|
12167
|
+
}
|
|
12168
|
+
const Expr = this.registry[op];
|
|
12169
|
+
if (Expr) {
|
|
12170
|
+
let parsed = Expr.parse(expr, this);
|
|
12171
|
+
if (!parsed) return null;
|
|
12172
|
+
if (this.expectedType) {
|
|
12173
|
+
const expected = this.expectedType;
|
|
12174
|
+
const actual = parsed.type;
|
|
12175
|
+
if ((expected.kind === "string" || expected.kind === "number" || expected.kind === "boolean" || expected.kind === "object" || expected.kind === "array") && actual.kind === "value") parsed = annotate(parsed, expected, options.typeAnnotation || "assert");
|
|
12176
|
+
else if ("projectionDefinition" === expected.kind && [
|
|
12177
|
+
"string",
|
|
12178
|
+
"array",
|
|
12179
|
+
"value"
|
|
12180
|
+
].includes(actual.kind) || [
|
|
12181
|
+
"color",
|
|
12182
|
+
"formatted",
|
|
12183
|
+
"resolvedImage"
|
|
12184
|
+
].includes(expected.kind) && ["value", "string"].includes(actual.kind) || ["padding", "numberArray"].includes(expected.kind) && [
|
|
12185
|
+
"value",
|
|
12186
|
+
"number",
|
|
12187
|
+
"array"
|
|
12188
|
+
].includes(actual.kind) || "colorArray" === expected.kind && [
|
|
12189
|
+
"value",
|
|
12190
|
+
"string",
|
|
12191
|
+
"array"
|
|
12192
|
+
].includes(actual.kind) || "variableAnchorOffsetCollection" === expected.kind && ["value", "array"].includes(actual.kind)) parsed = annotate(parsed, expected, options.typeAnnotation || "coerce");
|
|
12193
|
+
else if (this.checkSubtype(expected, actual)) return null;
|
|
12194
|
+
}
|
|
12195
|
+
if (!(parsed instanceof Literal) && parsed.type.kind !== "resolvedImage" && this._isConstant(parsed)) {
|
|
12196
|
+
const ec = new EvaluationContext();
|
|
12197
|
+
try {
|
|
12198
|
+
parsed = new Literal(parsed.type, parsed.evaluate(ec));
|
|
12199
|
+
} catch (e) {
|
|
12200
|
+
this.error(e.message);
|
|
12201
|
+
return null;
|
|
12202
|
+
}
|
|
12203
|
+
}
|
|
12204
|
+
return parsed;
|
|
12205
|
+
}
|
|
12206
|
+
return this.error(`Unknown expression "${op}". If you wanted a literal array, use ["literal", [...]].`, 0);
|
|
12207
|
+
} else if (typeof expr === "undefined") return this.error("'undefined' value invalid. Use null instead.");
|
|
12208
|
+
else if (typeof expr === "object") return this.error("Bare objects invalid. Use [\"literal\", {...}] instead.");
|
|
12209
|
+
else return this.error(`Expected an array, but found ${typeof expr} instead.`);
|
|
12210
|
+
}
|
|
12211
|
+
/**
|
|
12212
|
+
* Returns a copy of this context suitable for parsing the subexpression at
|
|
12213
|
+
* index `index`, optionally appending to 'let' binding map.
|
|
12214
|
+
*
|
|
12215
|
+
* Note that `errors` property, intended for collecting errors while
|
|
12216
|
+
* parsing, is copied by reference rather than cloned.
|
|
12217
|
+
* @private
|
|
12218
|
+
*/
|
|
12219
|
+
concat(index, expectedType, bindings) {
|
|
12220
|
+
const path = typeof index === "number" ? this.path.concat(index) : this.path;
|
|
12221
|
+
const scope = bindings ? this.scope.concat(bindings) : this.scope;
|
|
12222
|
+
return new ParsingContext(this.registry, this._isConstant, path, expectedType || null, scope, this.errors);
|
|
12223
|
+
}
|
|
12224
|
+
/**
|
|
12225
|
+
* Push a parsing (or type checking) error into the `this.errors`
|
|
12226
|
+
* @param error The message
|
|
12227
|
+
* @param keys Optionally specify the source of the error at a child
|
|
12228
|
+
* of the current expression at `this.key`.
|
|
12229
|
+
* @private
|
|
12230
|
+
*/
|
|
12231
|
+
error(error, ...keys) {
|
|
12232
|
+
const key = `${this.key}${keys.map((k) => `[${k}]`).join("")}`;
|
|
12233
|
+
this.errors.push(new ExpressionParsingError(key, error));
|
|
12414
12234
|
}
|
|
12415
|
-
|
|
12416
|
-
|
|
12235
|
+
/**
|
|
12236
|
+
* Returns null if `t` is a subtype of `expected`; otherwise returns an
|
|
12237
|
+
* error message and also pushes it to `this.errors`.
|
|
12238
|
+
* @param expected The expected type
|
|
12239
|
+
* @param t The actual type
|
|
12240
|
+
* @returns null if `t` is a subtype of `expected`; otherwise returns an error message
|
|
12241
|
+
*/
|
|
12242
|
+
checkSubtype(expected, t) {
|
|
12243
|
+
const error = checkSubtype(expected, t);
|
|
12244
|
+
if (error) this.error(error);
|
|
12245
|
+
return error;
|
|
12417
12246
|
}
|
|
12418
12247
|
};
|
|
12419
12248
|
|
|
12420
|
-
|
|
12249
|
+
// src/expression/definitions/let.ts
|
|
12421
12250
|
var Let = class Let {
|
|
12422
12251
|
constructor(bindings, result) {
|
|
12423
12252
|
this.type = result.type;
|
|
@@ -12451,7 +12280,7 @@ var Let = class Let {
|
|
|
12451
12280
|
}
|
|
12452
12281
|
};
|
|
12453
12282
|
|
|
12454
|
-
|
|
12283
|
+
// src/expression/definitions/var.ts
|
|
12455
12284
|
var Var = class Var {
|
|
12456
12285
|
constructor(name, boundExpression) {
|
|
12457
12286
|
this.type = boundExpression.type;
|
|
@@ -12473,7 +12302,7 @@ var Var = class Var {
|
|
|
12473
12302
|
}
|
|
12474
12303
|
};
|
|
12475
12304
|
|
|
12476
|
-
|
|
12305
|
+
// src/expression/definitions/at.ts
|
|
12477
12306
|
var At = class At {
|
|
12478
12307
|
constructor(type, index, input, key) {
|
|
12479
12308
|
this.type = type;
|
|
@@ -12506,7 +12335,7 @@ var At = class At {
|
|
|
12506
12335
|
}
|
|
12507
12336
|
};
|
|
12508
12337
|
|
|
12509
|
-
|
|
12338
|
+
// src/expression/definitions/in.ts
|
|
12510
12339
|
var In = class In {
|
|
12511
12340
|
constructor(needle, haystack, key) {
|
|
12512
12341
|
this.needle = needle;
|
|
@@ -12550,7 +12379,7 @@ var In = class In {
|
|
|
12550
12379
|
}
|
|
12551
12380
|
};
|
|
12552
12381
|
|
|
12553
|
-
|
|
12382
|
+
// src/expression/definitions/index_of.ts
|
|
12554
12383
|
var IndexOf = class IndexOf {
|
|
12555
12384
|
constructor(needle, haystack, key, fromIndex) {
|
|
12556
12385
|
this.needle = needle;
|
|
@@ -12605,7 +12434,7 @@ var IndexOf = class IndexOf {
|
|
|
12605
12434
|
}
|
|
12606
12435
|
};
|
|
12607
12436
|
|
|
12608
|
-
|
|
12437
|
+
// src/expression/definitions/match.ts
|
|
12609
12438
|
var Match = class Match {
|
|
12610
12439
|
constructor(inputType, outputType, input, cases, outputs, otherwise) {
|
|
12611
12440
|
this.inputType = inputType;
|
|
@@ -12664,7 +12493,7 @@ var Match = class Match {
|
|
|
12664
12493
|
}
|
|
12665
12494
|
};
|
|
12666
12495
|
|
|
12667
|
-
|
|
12496
|
+
// src/expression/definitions/case.ts
|
|
12668
12497
|
var Case = class Case {
|
|
12669
12498
|
constructor(type, branches, otherwise) {
|
|
12670
12499
|
this.type = type;
|
|
@@ -12685,72 +12514,345 @@ var Case = class Case {
|
|
|
12685
12514
|
branches.push([test, result]);
|
|
12686
12515
|
outputType = outputType || result.type;
|
|
12687
12516
|
}
|
|
12688
|
-
const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
|
|
12689
|
-
if (!otherwise) return null;
|
|
12690
|
-
if (!outputType) throw new Error("Can't infer output type");
|
|
12691
|
-
return new Case(outputType, branches, otherwise);
|
|
12517
|
+
const otherwise = context.parse(args[args.length - 1], args.length - 1, outputType);
|
|
12518
|
+
if (!otherwise) return null;
|
|
12519
|
+
if (!outputType) throw new Error("Can't infer output type");
|
|
12520
|
+
return new Case(outputType, branches, otherwise);
|
|
12521
|
+
}
|
|
12522
|
+
evaluate(ctx) {
|
|
12523
|
+
for (const [test, expression] of this.branches) if (test.evaluate(ctx)) return expression.evaluate(ctx);
|
|
12524
|
+
return this.otherwise.evaluate(ctx);
|
|
12525
|
+
}
|
|
12526
|
+
eachChild(fn) {
|
|
12527
|
+
for (const [test, expression] of this.branches) {
|
|
12528
|
+
fn(test);
|
|
12529
|
+
fn(expression);
|
|
12530
|
+
}
|
|
12531
|
+
fn(this.otherwise);
|
|
12532
|
+
}
|
|
12533
|
+
outputDefined() {
|
|
12534
|
+
return this.branches.every(([_, out]) => out.outputDefined()) && this.otherwise.outputDefined();
|
|
12535
|
+
}
|
|
12536
|
+
};
|
|
12537
|
+
|
|
12538
|
+
// src/expression/definitions/slice.ts
|
|
12539
|
+
var Slice = class Slice {
|
|
12540
|
+
constructor(type, input, beginIndex, key, endIndex) {
|
|
12541
|
+
this.type = type;
|
|
12542
|
+
this.input = input;
|
|
12543
|
+
this.beginIndex = beginIndex;
|
|
12544
|
+
this.key = key;
|
|
12545
|
+
this.endIndex = endIndex;
|
|
12546
|
+
}
|
|
12547
|
+
static parse(args, context) {
|
|
12548
|
+
if (args.length <= 2 || args.length >= 5) return context.error(`Expected 2 or 3 arguments, but found ${args.length - 1} instead.`);
|
|
12549
|
+
const input = context.parse(args[1], 1, ValueType);
|
|
12550
|
+
const beginIndex = context.parse(args[2], 2, NumberType);
|
|
12551
|
+
if (!input || !beginIndex) return null;
|
|
12552
|
+
if (!isValidType(input.type, [
|
|
12553
|
+
array(ValueType),
|
|
12554
|
+
StringType,
|
|
12555
|
+
ValueType
|
|
12556
|
+
])) return context.error(`Expected first argument to be of type array or string, but found ${typeToString(input.type)} instead`);
|
|
12557
|
+
if (args.length === 4) {
|
|
12558
|
+
const endIndex = context.parse(args[3], 3, NumberType);
|
|
12559
|
+
if (!endIndex) return null;
|
|
12560
|
+
return new Slice(input.type, input, beginIndex, context.key, endIndex);
|
|
12561
|
+
} else return new Slice(input.type, input, beginIndex, context.key);
|
|
12562
|
+
}
|
|
12563
|
+
evaluate(ctx) {
|
|
12564
|
+
const input = this.input.evaluate(ctx);
|
|
12565
|
+
const beginIndex = this.beginIndex.evaluate(ctx);
|
|
12566
|
+
let endIndex;
|
|
12567
|
+
if (this.endIndex) endIndex = this.endIndex.evaluate(ctx);
|
|
12568
|
+
if (isValidNativeType(input, ["string"])) return [...input].slice(beginIndex, endIndex).join("");
|
|
12569
|
+
else if (isValidNativeType(input, ["array"])) return input.slice(beginIndex, endIndex);
|
|
12570
|
+
else throw new RuntimeError(`Expected first argument to be of type array or string, but found ${typeToString(typeOf(input))} instead.`, this.key);
|
|
12571
|
+
}
|
|
12572
|
+
eachChild(fn) {
|
|
12573
|
+
fn(this.input);
|
|
12574
|
+
fn(this.beginIndex);
|
|
12575
|
+
if (this.endIndex) fn(this.endIndex);
|
|
12576
|
+
}
|
|
12577
|
+
outputDefined() {
|
|
12578
|
+
return false;
|
|
12579
|
+
}
|
|
12580
|
+
};
|
|
12581
|
+
|
|
12582
|
+
// src/expression/stops.ts
|
|
12583
|
+
/**
|
|
12584
|
+
* Returns the index of the last stop <= input, or 0 if it doesn't exist.
|
|
12585
|
+
* @private
|
|
12586
|
+
*/
|
|
12587
|
+
function findStopLessThanOrEqualTo(stops, input, key) {
|
|
12588
|
+
const lastIndex = stops.length - 1;
|
|
12589
|
+
let lowerIndex = 0;
|
|
12590
|
+
let upperIndex = lastIndex;
|
|
12591
|
+
let currentIndex = 0;
|
|
12592
|
+
let currentValue, nextValue;
|
|
12593
|
+
while (lowerIndex <= upperIndex) {
|
|
12594
|
+
currentIndex = Math.floor((lowerIndex + upperIndex) / 2);
|
|
12595
|
+
currentValue = stops[currentIndex];
|
|
12596
|
+
nextValue = stops[currentIndex + 1];
|
|
12597
|
+
if (currentValue <= input) {
|
|
12598
|
+
if (currentIndex === lastIndex || input < nextValue) return currentIndex;
|
|
12599
|
+
lowerIndex = currentIndex + 1;
|
|
12600
|
+
} else if (currentValue > input) upperIndex = currentIndex - 1;
|
|
12601
|
+
else throw new RuntimeError("Input is not a number.", key);
|
|
12602
|
+
}
|
|
12603
|
+
return 0;
|
|
12604
|
+
}
|
|
12605
|
+
|
|
12606
|
+
// src/expression/definitions/step.ts
|
|
12607
|
+
var Step = class Step {
|
|
12608
|
+
constructor(type, input, stops, key) {
|
|
12609
|
+
this.type = type;
|
|
12610
|
+
this.input = input;
|
|
12611
|
+
this.key = key;
|
|
12612
|
+
this.labels = [];
|
|
12613
|
+
this.outputs = [];
|
|
12614
|
+
for (const [label, expression] of stops) {
|
|
12615
|
+
this.labels.push(label);
|
|
12616
|
+
this.outputs.push(expression);
|
|
12617
|
+
}
|
|
12618
|
+
}
|
|
12619
|
+
static parse(args, context) {
|
|
12620
|
+
if (args.length - 1 < 4) return context.error(`Expected at least 4 arguments, but found only ${args.length - 1}.`);
|
|
12621
|
+
if ((args.length - 1) % 2 !== 0) return context.error("Expected an even number of arguments.");
|
|
12622
|
+
const input = context.parse(args[1], 1, NumberType);
|
|
12623
|
+
if (!input) return null;
|
|
12624
|
+
const stops = [];
|
|
12625
|
+
let outputType = null;
|
|
12626
|
+
if (context.expectedType && context.expectedType.kind !== "value") outputType = context.expectedType;
|
|
12627
|
+
for (let i = 1; i < args.length; i += 2) {
|
|
12628
|
+
const label = i === 1 ? -Infinity : args[i];
|
|
12629
|
+
const value = args[i + 1];
|
|
12630
|
+
const labelKey = i;
|
|
12631
|
+
const valueKey = i + 1;
|
|
12632
|
+
if (typeof label !== "number") return context.error("Input/output pairs for \"step\" expressions must be defined using literal numeric values (not computed expressions) for the input values.", labelKey);
|
|
12633
|
+
if (stops.length && stops[stops.length - 1][0] >= label) return context.error("Input/output pairs for \"step\" expressions must be arranged with input values in strictly ascending order.", labelKey);
|
|
12634
|
+
const parsed = context.parse(value, valueKey, outputType);
|
|
12635
|
+
if (!parsed) return null;
|
|
12636
|
+
outputType = outputType || parsed.type;
|
|
12637
|
+
stops.push([label, parsed]);
|
|
12638
|
+
}
|
|
12639
|
+
return new Step(outputType, input, stops, context.key);
|
|
12640
|
+
}
|
|
12641
|
+
evaluate(ctx) {
|
|
12642
|
+
const labels = this.labels;
|
|
12643
|
+
const outputs = this.outputs;
|
|
12644
|
+
if (labels.length === 1) return outputs[0].evaluate(ctx);
|
|
12645
|
+
const value = this.input.evaluate(ctx);
|
|
12646
|
+
if (value <= labels[0]) return outputs[0].evaluate(ctx);
|
|
12647
|
+
const stopCount = labels.length;
|
|
12648
|
+
if (value >= labels[stopCount - 1]) return outputs[stopCount - 1].evaluate(ctx);
|
|
12649
|
+
return outputs[findStopLessThanOrEqualTo(labels, value, this.key)].evaluate(ctx);
|
|
12650
|
+
}
|
|
12651
|
+
eachChild(fn) {
|
|
12652
|
+
fn(this.input);
|
|
12653
|
+
for (const expression of this.outputs) fn(expression);
|
|
12654
|
+
}
|
|
12655
|
+
outputDefined() {
|
|
12656
|
+
return this.outputs.every((out) => out.outputDefined());
|
|
12657
|
+
}
|
|
12658
|
+
};
|
|
12659
|
+
|
|
12660
|
+
// node_modules/@mapbox/unitbezier/index.js
|
|
12661
|
+
function unitBezier(p1x, p1y, p2x, p2y) {
|
|
12662
|
+
const cx = 3 * p1x;
|
|
12663
|
+
const bx = 3 * (p2x - p1x) - cx;
|
|
12664
|
+
const ax = 1 - cx - bx;
|
|
12665
|
+
const cy = 3 * p1y;
|
|
12666
|
+
const by = 3 * (p2y - p1y) - cy;
|
|
12667
|
+
const ay = 1 - cy - by;
|
|
12668
|
+
return function solve(x, epsilon = 1e-6) {
|
|
12669
|
+
if (x <= 0) return 0;
|
|
12670
|
+
if (x >= 1) return 1;
|
|
12671
|
+
let t = x;
|
|
12672
|
+
for (let i = 0; i < 8; i++) {
|
|
12673
|
+
const x2 = ((ax * t + bx) * t + cx) * t - x;
|
|
12674
|
+
if (Math.abs(x2) < epsilon) return ((ay * t + by) * t + cy) * t;
|
|
12675
|
+
const d2 = (3 * ax * t + 2 * bx) * t + cx;
|
|
12676
|
+
if (Math.abs(d2) < 1e-6) break;
|
|
12677
|
+
t -= x2 / d2;
|
|
12678
|
+
}
|
|
12679
|
+
let t0 = 0;
|
|
12680
|
+
let t1 = 1;
|
|
12681
|
+
t = x;
|
|
12682
|
+
for (let i = 0; i < 20; i++) {
|
|
12683
|
+
const x2 = ((ax * t + bx) * t + cx) * t;
|
|
12684
|
+
if (Math.abs(x2 - x) < epsilon) break;
|
|
12685
|
+
if (x > x2) t0 = t;
|
|
12686
|
+
else t1 = t;
|
|
12687
|
+
t = (t0 + t1) * .5;
|
|
12688
|
+
}
|
|
12689
|
+
return ((ay * t + by) * t + cy) * t;
|
|
12690
|
+
};
|
|
12691
|
+
}
|
|
12692
|
+
|
|
12693
|
+
// src/expression/definitions/interpolate.ts
|
|
12694
|
+
var Interpolate = class Interpolate {
|
|
12695
|
+
constructor(type, operator, interpolation, input, stops, key) {
|
|
12696
|
+
this.type = type;
|
|
12697
|
+
this.operator = operator;
|
|
12698
|
+
this.interpolation = interpolation;
|
|
12699
|
+
this.input = input;
|
|
12700
|
+
this.key = key;
|
|
12701
|
+
this.labels = [];
|
|
12702
|
+
this.outputs = [];
|
|
12703
|
+
for (const [label, expression] of stops) {
|
|
12704
|
+
this.labels.push(label);
|
|
12705
|
+
this.outputs.push(expression);
|
|
12706
|
+
}
|
|
12707
|
+
}
|
|
12708
|
+
static interpolationFactor(interpolation, input, lower, upper) {
|
|
12709
|
+
let t = 0;
|
|
12710
|
+
if (interpolation.name === "exponential") t = exponentialInterpolation(input, interpolation.base, lower, upper);
|
|
12711
|
+
else if (interpolation.name === "linear") t = exponentialInterpolation(input, 1, lower, upper);
|
|
12712
|
+
else if (interpolation.name === "cubic-bezier") {
|
|
12713
|
+
const c = interpolation.controlPoints;
|
|
12714
|
+
t = unitBezier(c[0], c[1], c[2], c[3])(exponentialInterpolation(input, 1, lower, upper));
|
|
12715
|
+
}
|
|
12716
|
+
return t;
|
|
12717
|
+
}
|
|
12718
|
+
static parse(args, context) {
|
|
12719
|
+
let [operator, interpolation, input, ...rest] = args;
|
|
12720
|
+
if (!Array.isArray(interpolation) || interpolation.length === 0) return context.error("Expected an interpolation type expression.", 1);
|
|
12721
|
+
if (interpolation[0] === "linear") interpolation = { name: "linear" };
|
|
12722
|
+
else if (interpolation[0] === "exponential") {
|
|
12723
|
+
const base = interpolation[1];
|
|
12724
|
+
if (typeof base !== "number") return context.error("Exponential interpolation requires a numeric base.", 1, 1);
|
|
12725
|
+
interpolation = {
|
|
12726
|
+
name: "exponential",
|
|
12727
|
+
base
|
|
12728
|
+
};
|
|
12729
|
+
} else if (interpolation[0] === "cubic-bezier") {
|
|
12730
|
+
const controlPoints = interpolation.slice(1);
|
|
12731
|
+
if (controlPoints.length !== 4 || controlPoints.some((t) => typeof t !== "number" || t < 0 || t > 1)) return context.error("Cubic bezier interpolation requires four numeric arguments with values between 0 and 1.", 1);
|
|
12732
|
+
interpolation = {
|
|
12733
|
+
name: "cubic-bezier",
|
|
12734
|
+
controlPoints
|
|
12735
|
+
};
|
|
12736
|
+
} else return context.error(`Unknown interpolation type ${String(interpolation[0])}`, 1, 0);
|
|
12737
|
+
if (args.length - 1 < 4) return context.error(`Expected at least 4 arguments, but found only ${args.length - 1}.`);
|
|
12738
|
+
if ((args.length - 1) % 2 !== 0) return context.error("Expected an even number of arguments.");
|
|
12739
|
+
input = context.parse(input, 2, NumberType);
|
|
12740
|
+
if (!input) return null;
|
|
12741
|
+
const stops = [];
|
|
12742
|
+
let outputType = null;
|
|
12743
|
+
if ((operator === "interpolate-hcl" || operator === "interpolate-lab") && context.expectedType != ColorArrayType) outputType = ColorType;
|
|
12744
|
+
else if (context.expectedType && context.expectedType.kind !== "value") outputType = context.expectedType;
|
|
12745
|
+
for (let i = 0; i < rest.length; i += 2) {
|
|
12746
|
+
const label = rest[i];
|
|
12747
|
+
const value = rest[i + 1];
|
|
12748
|
+
const labelKey = i + 3;
|
|
12749
|
+
const valueKey = i + 4;
|
|
12750
|
+
if (typeof label !== "number") return context.error("Input/output pairs for \"interpolate\" expressions must be defined using literal numeric values (not computed expressions) for the input values.", labelKey);
|
|
12751
|
+
if (stops.length && stops[stops.length - 1][0] >= label) return context.error("Input/output pairs for \"interpolate\" expressions must be arranged with input values in strictly ascending order.", labelKey);
|
|
12752
|
+
const parsed = context.parse(value, valueKey, outputType);
|
|
12753
|
+
if (!parsed) return null;
|
|
12754
|
+
outputType = outputType || parsed.type;
|
|
12755
|
+
stops.push([label, parsed]);
|
|
12756
|
+
}
|
|
12757
|
+
if (!verifyType(outputType, NumberType) && !verifyType(outputType, ProjectionDefinitionType) && !verifyType(outputType, ColorType) && !verifyType(outputType, PaddingType) && !verifyType(outputType, NumberArrayType) && !verifyType(outputType, ColorArrayType) && !verifyType(outputType, VariableAnchorOffsetCollectionType) && !verifyType(outputType, array(NumberType))) return context.error(`Type ${typeToString(outputType)} is not interpolatable.`);
|
|
12758
|
+
return new Interpolate(outputType, operator, interpolation, input, stops, context.key);
|
|
12692
12759
|
}
|
|
12693
12760
|
evaluate(ctx) {
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
|
|
12699
|
-
|
|
12700
|
-
|
|
12761
|
+
const labels = this.labels;
|
|
12762
|
+
const outputs = this.outputs;
|
|
12763
|
+
if (labels.length === 1) return outputs[0].evaluate(ctx);
|
|
12764
|
+
const value = this.input.evaluate(ctx);
|
|
12765
|
+
if (value <= labels[0]) return outputs[0].evaluate(ctx);
|
|
12766
|
+
const stopCount = labels.length;
|
|
12767
|
+
if (value >= labels[stopCount - 1]) return outputs[stopCount - 1].evaluate(ctx);
|
|
12768
|
+
const index = findStopLessThanOrEqualTo(labels, value, this.key);
|
|
12769
|
+
const lower = labels[index];
|
|
12770
|
+
const upper = labels[index + 1];
|
|
12771
|
+
const t = Interpolate.interpolationFactor(this.interpolation, value, lower, upper);
|
|
12772
|
+
const outputLower = outputs[index].evaluate(ctx);
|
|
12773
|
+
const outputUpper = outputs[index + 1].evaluate(ctx);
|
|
12774
|
+
switch (this.operator) {
|
|
12775
|
+
case "interpolate": switch (this.type.kind) {
|
|
12776
|
+
case "number": return interpolateNumber(outputLower, outputUpper, t);
|
|
12777
|
+
case "color": return Color$1.interpolate(outputLower, outputUpper, t);
|
|
12778
|
+
case "padding": return Padding.interpolate(outputLower, outputUpper, t);
|
|
12779
|
+
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t);
|
|
12780
|
+
case "numberArray": return NumberArray.interpolate(outputLower, outputUpper, t);
|
|
12781
|
+
case "variableAnchorOffsetCollection": return VariableAnchorOffsetCollection.interpolate(outputLower, outputUpper, t, this.key);
|
|
12782
|
+
case "array": return interpolateArray(outputLower, outputUpper, t);
|
|
12783
|
+
case "projectionDefinition": return ProjectionDefinition.interpolate(outputLower, outputUpper, t);
|
|
12784
|
+
}
|
|
12785
|
+
case "interpolate-hcl": switch (this.type.kind) {
|
|
12786
|
+
case "color": return Color$1.interpolate(outputLower, outputUpper, t, "hcl");
|
|
12787
|
+
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t, "hcl");
|
|
12788
|
+
}
|
|
12789
|
+
case "interpolate-lab": switch (this.type.kind) {
|
|
12790
|
+
case "color": return Color$1.interpolate(outputLower, outputUpper, t, "lab");
|
|
12791
|
+
case "colorArray": return ColorArray.interpolate(outputLower, outputUpper, t, "lab");
|
|
12792
|
+
}
|
|
12701
12793
|
}
|
|
12702
|
-
fn(this.otherwise);
|
|
12703
|
-
}
|
|
12704
|
-
outputDefined() {
|
|
12705
|
-
return this.branches.every(([_, out]) => out.outputDefined()) && this.otherwise.outputDefined();
|
|
12706
|
-
}
|
|
12707
|
-
};
|
|
12708
|
-
|
|
12709
|
-
//#region src/expression/definitions/slice.ts
|
|
12710
|
-
var Slice = class Slice {
|
|
12711
|
-
constructor(type, input, beginIndex, key, endIndex) {
|
|
12712
|
-
this.type = type;
|
|
12713
|
-
this.input = input;
|
|
12714
|
-
this.beginIndex = beginIndex;
|
|
12715
|
-
this.key = key;
|
|
12716
|
-
this.endIndex = endIndex;
|
|
12717
|
-
}
|
|
12718
|
-
static parse(args, context) {
|
|
12719
|
-
if (args.length <= 2 || args.length >= 5) return context.error(`Expected 2 or 3 arguments, but found ${args.length - 1} instead.`);
|
|
12720
|
-
const input = context.parse(args[1], 1, ValueType);
|
|
12721
|
-
const beginIndex = context.parse(args[2], 2, NumberType);
|
|
12722
|
-
if (!input || !beginIndex) return null;
|
|
12723
|
-
if (!isValidType(input.type, [
|
|
12724
|
-
array(ValueType),
|
|
12725
|
-
StringType,
|
|
12726
|
-
ValueType
|
|
12727
|
-
])) return context.error(`Expected first argument to be of type array or string, but found ${typeToString(input.type)} instead`);
|
|
12728
|
-
if (args.length === 4) {
|
|
12729
|
-
const endIndex = context.parse(args[3], 3, NumberType);
|
|
12730
|
-
if (!endIndex) return null;
|
|
12731
|
-
return new Slice(input.type, input, beginIndex, context.key, endIndex);
|
|
12732
|
-
} else return new Slice(input.type, input, beginIndex, context.key);
|
|
12733
|
-
}
|
|
12734
|
-
evaluate(ctx) {
|
|
12735
|
-
const input = this.input.evaluate(ctx);
|
|
12736
|
-
const beginIndex = this.beginIndex.evaluate(ctx);
|
|
12737
|
-
let endIndex;
|
|
12738
|
-
if (this.endIndex) endIndex = this.endIndex.evaluate(ctx);
|
|
12739
|
-
if (isValidNativeType(input, ["string"])) return [...input].slice(beginIndex, endIndex).join("");
|
|
12740
|
-
else if (isValidNativeType(input, ["array"])) return input.slice(beginIndex, endIndex);
|
|
12741
|
-
else throw new RuntimeError(`Expected first argument to be of type array or string, but found ${typeToString(typeOf(input))} instead.`, this.key);
|
|
12742
12794
|
}
|
|
12743
12795
|
eachChild(fn) {
|
|
12744
12796
|
fn(this.input);
|
|
12745
|
-
|
|
12746
|
-
if (this.endIndex) fn(this.endIndex);
|
|
12797
|
+
for (const expression of this.outputs) fn(expression);
|
|
12747
12798
|
}
|
|
12748
12799
|
outputDefined() {
|
|
12749
|
-
return
|
|
12800
|
+
return this.outputs.every((out) => out.outputDefined());
|
|
12750
12801
|
}
|
|
12751
12802
|
};
|
|
12803
|
+
/**
|
|
12804
|
+
* Returns a ratio that can be used to interpolate between exponential function
|
|
12805
|
+
* stops.
|
|
12806
|
+
* How it works: Two consecutive stop values define a (scaled and shifted) exponential function `f(x) = a * base^x + b`, where `base` is the user-specified base,
|
|
12807
|
+
* and `a` and `b` are constants affording sufficient degrees of freedom to fit
|
|
12808
|
+
* the function to the given stops.
|
|
12809
|
+
*
|
|
12810
|
+
* Here's a bit of algebra that lets us compute `f(x)` directly from the stop
|
|
12811
|
+
* values without explicitly solving for `a` and `b`:
|
|
12812
|
+
*
|
|
12813
|
+
* First stop value: `f(x0) = y0 = a * base^x0 + b`
|
|
12814
|
+
* Second stop value: `f(x1) = y1 = a * base^x1 + b`
|
|
12815
|
+
* => `y1 - y0 = a(base^x1 - base^x0)`
|
|
12816
|
+
* => `a = (y1 - y0)/(base^x1 - base^x0)`
|
|
12817
|
+
*
|
|
12818
|
+
* Desired value: `f(x) = y = a * base^x + b`
|
|
12819
|
+
* => `f(x) = y0 + a * (base^x - base^x0)`
|
|
12820
|
+
*
|
|
12821
|
+
* From the above, we can replace the `a` in `a * (base^x - base^x0)` and do a
|
|
12822
|
+
* little algebra:
|
|
12823
|
+
* ```
|
|
12824
|
+
* a * (base^x - base^x0) = (y1 - y0)/(base^x1 - base^x0) * (base^x - base^x0)
|
|
12825
|
+
* = (y1 - y0) * (base^x - base^x0) / (base^x1 - base^x0)
|
|
12826
|
+
* ```
|
|
12827
|
+
*
|
|
12828
|
+
* If we let `(base^x - base^x0) / (base^x1 base^x0)`, then we have
|
|
12829
|
+
* `f(x) = y0 + (y1 - y0) * ratio`. In other words, `ratio` may be treated as
|
|
12830
|
+
* an interpolation factor between the two stops' output values.
|
|
12831
|
+
*
|
|
12832
|
+
* (Note: a slightly different form for `ratio`,
|
|
12833
|
+
* `(base^(x-x0) - 1) / (base^(x1-x0) - 1) `, is equivalent, but requires fewer
|
|
12834
|
+
* expensive `Math.pow()` operations.)
|
|
12835
|
+
*
|
|
12836
|
+
* @private
|
|
12837
|
+
*/
|
|
12838
|
+
function exponentialInterpolation(input, base, lowerValue, upperValue) {
|
|
12839
|
+
const difference = upperValue - lowerValue;
|
|
12840
|
+
const progress = input - lowerValue;
|
|
12841
|
+
if (difference === 0) return 0;
|
|
12842
|
+
else if (base === 1) return progress / difference;
|
|
12843
|
+
else return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
|
|
12844
|
+
}
|
|
12845
|
+
const interpolateFactory = {
|
|
12846
|
+
color: Color$1.interpolate,
|
|
12847
|
+
number: interpolateNumber,
|
|
12848
|
+
padding: Padding.interpolate,
|
|
12849
|
+
numberArray: NumberArray.interpolate,
|
|
12850
|
+
colorArray: ColorArray.interpolate,
|
|
12851
|
+
variableAnchorOffsetCollection: VariableAnchorOffsetCollection.interpolate,
|
|
12852
|
+
array: interpolateArray
|
|
12853
|
+
};
|
|
12752
12854
|
|
|
12753
|
-
|
|
12855
|
+
// src/expression/definitions/coalesce.ts
|
|
12754
12856
|
var Coalesce = class Coalesce {
|
|
12755
12857
|
constructor(type, args) {
|
|
12756
12858
|
this.type = type;
|
|
@@ -12795,7 +12897,7 @@ var Coalesce = class Coalesce {
|
|
|
12795
12897
|
}
|
|
12796
12898
|
};
|
|
12797
12899
|
|
|
12798
|
-
|
|
12900
|
+
// src/expression/definitions/comparison.ts
|
|
12799
12901
|
function isComparableType(op, type) {
|
|
12800
12902
|
if (op === "==" || op === "!=") return type.kind === "boolean" || type.kind === "string" || type.kind === "number" || type.kind === "null" || type.kind === "value";
|
|
12801
12903
|
else return type.kind === "string" || type.kind === "number" || type.kind === "value";
|
|
@@ -12918,7 +13020,7 @@ const GreaterThan = makeComparison(">", gt, gtCollate);
|
|
|
12918
13020
|
const LessThanOrEqual = makeComparison("<=", lteq, lteqCollate);
|
|
12919
13021
|
const GreaterThanOrEqual = makeComparison(">=", gteq, gteqCollate);
|
|
12920
13022
|
|
|
12921
|
-
|
|
13023
|
+
// src/expression/definitions/collator.ts
|
|
12922
13024
|
var CollatorExpression = class CollatorExpression {
|
|
12923
13025
|
constructor(caseSensitive, diacriticSensitive, locale) {
|
|
12924
13026
|
this.type = CollatorType;
|
|
@@ -12954,7 +13056,7 @@ var CollatorExpression = class CollatorExpression {
|
|
|
12954
13056
|
}
|
|
12955
13057
|
};
|
|
12956
13058
|
|
|
12957
|
-
|
|
13059
|
+
// src/expression/definitions/number_format.ts
|
|
12958
13060
|
var NumberFormat = class NumberFormat {
|
|
12959
13061
|
constructor(number, locale, currency, unit, minFractionDigits, maxFractionDigits) {
|
|
12960
13062
|
this.type = StringType;
|
|
@@ -13021,7 +13123,88 @@ var NumberFormat = class NumberFormat {
|
|
|
13021
13123
|
}
|
|
13022
13124
|
};
|
|
13023
13125
|
|
|
13024
|
-
|
|
13126
|
+
// src/expression/definitions/format.ts
|
|
13127
|
+
var FormatExpression = class FormatExpression {
|
|
13128
|
+
constructor(sections) {
|
|
13129
|
+
this.type = FormattedType;
|
|
13130
|
+
this.sections = sections;
|
|
13131
|
+
}
|
|
13132
|
+
static parse(args, context) {
|
|
13133
|
+
if (args.length < 2) return context.error("Expected at least one argument.");
|
|
13134
|
+
const firstArg = args[1];
|
|
13135
|
+
if (!Array.isArray(firstArg) && typeof firstArg === "object") return context.error("First argument must be an image or text section.");
|
|
13136
|
+
const sections = [];
|
|
13137
|
+
let nextTokenMayBeObject = false;
|
|
13138
|
+
for (let i = 1; i <= args.length - 1; ++i) {
|
|
13139
|
+
const arg = args[i];
|
|
13140
|
+
if (nextTokenMayBeObject && typeof arg === "object" && !Array.isArray(arg)) {
|
|
13141
|
+
nextTokenMayBeObject = false;
|
|
13142
|
+
let scale = null;
|
|
13143
|
+
if (arg["font-scale"]) {
|
|
13144
|
+
scale = context.parse(arg["font-scale"], 1, NumberType);
|
|
13145
|
+
if (!scale) return null;
|
|
13146
|
+
}
|
|
13147
|
+
let font = null;
|
|
13148
|
+
if (arg["text-font"]) {
|
|
13149
|
+
font = context.parse(arg["text-font"], 1, array(StringType));
|
|
13150
|
+
if (!font) return null;
|
|
13151
|
+
}
|
|
13152
|
+
let textColor = null;
|
|
13153
|
+
if (arg["text-color"]) {
|
|
13154
|
+
textColor = context.parse(arg["text-color"], 1, ColorType);
|
|
13155
|
+
if (!textColor) return null;
|
|
13156
|
+
}
|
|
13157
|
+
let verticalAlign = null;
|
|
13158
|
+
if (arg["vertical-align"]) {
|
|
13159
|
+
if (typeof arg["vertical-align"] === "string" && !VERTICAL_ALIGN_OPTIONS.includes(arg["vertical-align"])) return context.error(`'vertical-align' must be one of: 'bottom', 'center', 'top' but found '${arg["vertical-align"]}' instead.`);
|
|
13160
|
+
verticalAlign = context.parse(arg["vertical-align"], 1, StringType);
|
|
13161
|
+
if (!verticalAlign) return null;
|
|
13162
|
+
}
|
|
13163
|
+
const lastExpression = sections[sections.length - 1];
|
|
13164
|
+
lastExpression.scale = scale;
|
|
13165
|
+
lastExpression.font = font;
|
|
13166
|
+
lastExpression.textColor = textColor;
|
|
13167
|
+
lastExpression.verticalAlign = verticalAlign;
|
|
13168
|
+
} else {
|
|
13169
|
+
const content = context.parse(args[i], 1, ValueType);
|
|
13170
|
+
if (!content) return null;
|
|
13171
|
+
const kind = content.type.kind;
|
|
13172
|
+
if (kind !== "string" && kind !== "value" && kind !== "null" && kind !== "resolvedImage") return context.error("Formatted text type must be 'string', 'value', 'image' or 'null'.");
|
|
13173
|
+
nextTokenMayBeObject = true;
|
|
13174
|
+
sections.push({
|
|
13175
|
+
content,
|
|
13176
|
+
scale: null,
|
|
13177
|
+
font: null,
|
|
13178
|
+
textColor: null,
|
|
13179
|
+
verticalAlign: null
|
|
13180
|
+
});
|
|
13181
|
+
}
|
|
13182
|
+
}
|
|
13183
|
+
return new FormatExpression(sections);
|
|
13184
|
+
}
|
|
13185
|
+
evaluate(ctx) {
|
|
13186
|
+
const evaluateSection = (section) => {
|
|
13187
|
+
const evaluatedContent = section.content.evaluate(ctx);
|
|
13188
|
+
if (typeOf(evaluatedContent) === ResolvedImageType) return new FormattedSection("", evaluatedContent, null, null, null, section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null);
|
|
13189
|
+
return new FormattedSection(valueToString(evaluatedContent), null, section.scale ? section.scale.evaluate(ctx) : null, section.font ? section.font.evaluate(ctx).join(",") : null, section.textColor ? section.textColor.evaluate(ctx) : null, section.verticalAlign ? section.verticalAlign.evaluate(ctx) : null);
|
|
13190
|
+
};
|
|
13191
|
+
return new Formatted(this.sections.map(evaluateSection));
|
|
13192
|
+
}
|
|
13193
|
+
eachChild(fn) {
|
|
13194
|
+
for (const section of this.sections) {
|
|
13195
|
+
fn(section.content);
|
|
13196
|
+
if (section.scale) fn(section.scale);
|
|
13197
|
+
if (section.font) fn(section.font);
|
|
13198
|
+
if (section.textColor) fn(section.textColor);
|
|
13199
|
+
if (section.verticalAlign) fn(section.verticalAlign);
|
|
13200
|
+
}
|
|
13201
|
+
}
|
|
13202
|
+
outputDefined() {
|
|
13203
|
+
return false;
|
|
13204
|
+
}
|
|
13205
|
+
};
|
|
13206
|
+
|
|
13207
|
+
// src/expression/definitions/image.ts
|
|
13025
13208
|
var ImageExpression = class ImageExpression {
|
|
13026
13209
|
constructor(input) {
|
|
13027
13210
|
this.type = ResolvedImageType;
|
|
@@ -13047,7 +13230,7 @@ var ImageExpression = class ImageExpression {
|
|
|
13047
13230
|
}
|
|
13048
13231
|
};
|
|
13049
13232
|
|
|
13050
|
-
|
|
13233
|
+
// src/expression/definitions/length.ts
|
|
13051
13234
|
var Length = class Length {
|
|
13052
13235
|
constructor(input, key) {
|
|
13053
13236
|
this.input = input;
|
|
@@ -13075,7 +13258,7 @@ var Length = class Length {
|
|
|
13075
13258
|
}
|
|
13076
13259
|
};
|
|
13077
13260
|
|
|
13078
|
-
|
|
13261
|
+
// src/util/geometry_util.ts
|
|
13079
13262
|
const EXTENT = 8192;
|
|
13080
13263
|
function getTileCoordinates(p, canonical) {
|
|
13081
13264
|
const x = mercatorXfromLng(p[0]);
|
|
@@ -13171,7 +13354,7 @@ function twoSided(p1, p2, q1, q2) {
|
|
|
13171
13354
|
return false;
|
|
13172
13355
|
}
|
|
13173
13356
|
|
|
13174
|
-
|
|
13357
|
+
// src/expression/definitions/within.ts
|
|
13175
13358
|
function getTilePolygon(coordinates, bbox, canonical) {
|
|
13176
13359
|
const polygon = [];
|
|
13177
13360
|
for (let i = 0; i < coordinates.length; i++) {
|
|
@@ -13333,7 +13516,7 @@ var Within = class Within {
|
|
|
13333
13516
|
}
|
|
13334
13517
|
};
|
|
13335
13518
|
|
|
13336
|
-
|
|
13519
|
+
// node_modules/tinyqueue/index.js
|
|
13337
13520
|
var TinyQueue = class {
|
|
13338
13521
|
constructor(data = [], compare = (a, b) => a < b ? -1 : a > b ? 1 : 0) {
|
|
13339
13522
|
this.data = data;
|
|
@@ -13370,23 +13553,66 @@ var TinyQueue = class {
|
|
|
13370
13553
|
}
|
|
13371
13554
|
data[pos] = item;
|
|
13372
13555
|
}
|
|
13373
|
-
_down(pos) {
|
|
13374
|
-
const { data, compare } = this;
|
|
13375
|
-
const halfLength = this.length >> 1;
|
|
13376
|
-
const item = data[pos];
|
|
13377
|
-
while (pos < halfLength) {
|
|
13378
|
-
let bestChild = (pos << 1) + 1;
|
|
13379
|
-
const right = bestChild + 1;
|
|
13380
|
-
if (right < this.length && compare(data[right], data[bestChild]) < 0) bestChild = right;
|
|
13381
|
-
if (compare(data[bestChild], item) >= 0) break;
|
|
13382
|
-
data[pos] = data[bestChild];
|
|
13383
|
-
pos = bestChild;
|
|
13384
|
-
}
|
|
13385
|
-
data[pos] = item;
|
|
13556
|
+
_down(pos) {
|
|
13557
|
+
const { data, compare } = this;
|
|
13558
|
+
const halfLength = this.length >> 1;
|
|
13559
|
+
const item = data[pos];
|
|
13560
|
+
while (pos < halfLength) {
|
|
13561
|
+
let bestChild = (pos << 1) + 1;
|
|
13562
|
+
const right = bestChild + 1;
|
|
13563
|
+
if (right < this.length && compare(data[right], data[bestChild]) < 0) bestChild = right;
|
|
13564
|
+
if (compare(data[bestChild], item) >= 0) break;
|
|
13565
|
+
data[pos] = data[bestChild];
|
|
13566
|
+
pos = bestChild;
|
|
13567
|
+
}
|
|
13568
|
+
data[pos] = item;
|
|
13569
|
+
}
|
|
13570
|
+
};
|
|
13571
|
+
|
|
13572
|
+
// src/util/classify_rings.ts
|
|
13573
|
+
/**
|
|
13574
|
+
* Classifies an array of rings into polygons with outer rings and holes
|
|
13575
|
+
* @param rings - the rings to classify
|
|
13576
|
+
* @param maxRings - the maximum number of rings to include in a polygon, use 0 to include all rings
|
|
13577
|
+
* @returns an array of polygons with internal rings as holes
|
|
13578
|
+
*/
|
|
13579
|
+
function classifyRings$1(rings, maxRings) {
|
|
13580
|
+
if (rings.length <= 1) return [rings];
|
|
13581
|
+
const polygons = [];
|
|
13582
|
+
let polygon;
|
|
13583
|
+
let ccw;
|
|
13584
|
+
for (const ring of rings) {
|
|
13585
|
+
const area = calculateSignedArea(ring);
|
|
13586
|
+
if (area === 0) continue;
|
|
13587
|
+
ring.area = Math.abs(area);
|
|
13588
|
+
if (ccw === void 0) ccw = area < 0;
|
|
13589
|
+
if (ccw === area < 0) {
|
|
13590
|
+
if (polygon) polygons.push(polygon);
|
|
13591
|
+
polygon = [ring];
|
|
13592
|
+
} else polygon.push(ring);
|
|
13593
|
+
}
|
|
13594
|
+
if (polygon) polygons.push(polygon);
|
|
13595
|
+
return polygons;
|
|
13596
|
+
}
|
|
13597
|
+
/**
|
|
13598
|
+
* Returns the signed area for the polygon ring. Positive areas are exterior rings and
|
|
13599
|
+
* have a clockwise winding. Negative areas are interior rings and have a counter clockwise
|
|
13600
|
+
* ordering.
|
|
13601
|
+
*
|
|
13602
|
+
* @param ring - Exterior or interior ring
|
|
13603
|
+
* @returns Signed area
|
|
13604
|
+
*/
|
|
13605
|
+
function calculateSignedArea(ring) {
|
|
13606
|
+
let sum = 0;
|
|
13607
|
+
for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
|
|
13608
|
+
p1 = ring[i];
|
|
13609
|
+
p2 = ring[j];
|
|
13610
|
+
sum += (p2.x - p1.x) * (p1.y + p2.y);
|
|
13386
13611
|
}
|
|
13387
|
-
|
|
13612
|
+
return sum;
|
|
13613
|
+
}
|
|
13388
13614
|
|
|
13389
|
-
|
|
13615
|
+
// src/util/cheap_ruler.ts
|
|
13390
13616
|
const RE = 6378.137;
|
|
13391
13617
|
const E2 = .0066943799901413165;
|
|
13392
13618
|
const RAD = Math.PI / 180;
|
|
@@ -13469,7 +13695,7 @@ var CheapRuler = class {
|
|
|
13469
13695
|
}
|
|
13470
13696
|
};
|
|
13471
13697
|
|
|
13472
|
-
|
|
13698
|
+
// src/expression/definitions/distance.ts
|
|
13473
13699
|
const MinPointsSize = 100;
|
|
13474
13700
|
const MinLinePointsSize = 50;
|
|
13475
13701
|
function compareDistPair(a, b) {
|
|
@@ -13837,7 +14063,7 @@ var Distance = class Distance {
|
|
|
13837
14063
|
}
|
|
13838
14064
|
};
|
|
13839
14065
|
|
|
13840
|
-
|
|
14066
|
+
// src/expression/definitions/semiliteral.ts
|
|
13841
14067
|
var Semiliteral = class Semiliteral {
|
|
13842
14068
|
constructor(arr) {
|
|
13843
14069
|
let elementType = null;
|
|
@@ -13878,7 +14104,7 @@ var Semiliteral = class Semiliteral {
|
|
|
13878
14104
|
}
|
|
13879
14105
|
};
|
|
13880
14106
|
|
|
13881
|
-
|
|
14107
|
+
// src/expression/definitions/global_state.ts
|
|
13882
14108
|
var GlobalState = class GlobalState {
|
|
13883
14109
|
constructor(key) {
|
|
13884
14110
|
this.key = key;
|
|
@@ -13902,7 +14128,7 @@ var GlobalState = class GlobalState {
|
|
|
13902
14128
|
}
|
|
13903
14129
|
};
|
|
13904
14130
|
|
|
13905
|
-
|
|
14131
|
+
// src/expression/definitions/index.ts
|
|
13906
14132
|
const expressions = {
|
|
13907
14133
|
"==": Equals,
|
|
13908
14134
|
"!=": NotEquals,
|
|
@@ -13944,163 +14170,7 @@ const expressions = {
|
|
|
13944
14170
|
"global-state": GlobalState
|
|
13945
14171
|
};
|
|
13946
14172
|
|
|
13947
|
-
|
|
13948
|
-
var ExpressionParsingError = class extends Error {
|
|
13949
|
-
constructor(key, message) {
|
|
13950
|
-
super(message);
|
|
13951
|
-
this.message = message;
|
|
13952
|
-
this.key = key;
|
|
13953
|
-
}
|
|
13954
|
-
};
|
|
13955
|
-
|
|
13956
|
-
//#region src/expression/scope.ts
|
|
13957
|
-
/**
|
|
13958
|
-
* Tracks `let` bindings during expression parsing.
|
|
13959
|
-
* @private
|
|
13960
|
-
*/
|
|
13961
|
-
var Scope = class Scope {
|
|
13962
|
-
constructor(parent, bindings = []) {
|
|
13963
|
-
this.parent = parent;
|
|
13964
|
-
this.bindings = {};
|
|
13965
|
-
for (const [name, expression] of bindings) this.bindings[name] = expression;
|
|
13966
|
-
}
|
|
13967
|
-
concat(bindings) {
|
|
13968
|
-
return new Scope(this, bindings);
|
|
13969
|
-
}
|
|
13970
|
-
get(name) {
|
|
13971
|
-
if (this.bindings[name]) return this.bindings[name];
|
|
13972
|
-
if (this.parent) return this.parent.get(name);
|
|
13973
|
-
throw new Error(`${name} not found in scope.`);
|
|
13974
|
-
}
|
|
13975
|
-
has(name) {
|
|
13976
|
-
if (this.bindings[name]) return true;
|
|
13977
|
-
return this.parent ? this.parent.has(name) : false;
|
|
13978
|
-
}
|
|
13979
|
-
};
|
|
13980
|
-
|
|
13981
|
-
//#region src/expression/parsing_context.ts
|
|
13982
|
-
/**
|
|
13983
|
-
* State associated parsing at a given point in an expression tree.
|
|
13984
|
-
* @private
|
|
13985
|
-
*/
|
|
13986
|
-
var ParsingContext = class ParsingContext {
|
|
13987
|
-
constructor(registry, isConstantFunc, path = [], expectedType, scope = new Scope(), errors = []) {
|
|
13988
|
-
this.registry = registry;
|
|
13989
|
-
this.path = path;
|
|
13990
|
-
this.key = path.map((part) => `[${part}]`).join("");
|
|
13991
|
-
this.scope = scope;
|
|
13992
|
-
this.errors = errors;
|
|
13993
|
-
this.expectedType = expectedType;
|
|
13994
|
-
this._isConstant = isConstantFunc;
|
|
13995
|
-
}
|
|
13996
|
-
/**
|
|
13997
|
-
* @param expr the JSON expression to parse
|
|
13998
|
-
* @param index the optional argument index if this expression is an argument of a parent expression that's being parsed
|
|
13999
|
-
* @param options
|
|
14000
|
-
* @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.
|
|
14001
|
-
* @private
|
|
14002
|
-
*/
|
|
14003
|
-
parse(expr, index, expectedType, bindings, options = {}) {
|
|
14004
|
-
if (index != null) return this.concat(index, expectedType, bindings)._parse(expr, options);
|
|
14005
|
-
return this._parse(expr, options);
|
|
14006
|
-
}
|
|
14007
|
-
_parse(expr, options) {
|
|
14008
|
-
if (expr === null || typeof expr === "string" || typeof expr === "boolean" || typeof expr === "number") expr = ["literal", expr];
|
|
14009
|
-
const key = this.key;
|
|
14010
|
-
function annotate(parsed, type, typeAnnotation) {
|
|
14011
|
-
if (typeAnnotation === "assert") return new Assertion(type, [parsed], key);
|
|
14012
|
-
else if (typeAnnotation === "coerce") return new Coercion(type, [parsed], key);
|
|
14013
|
-
else return parsed;
|
|
14014
|
-
}
|
|
14015
|
-
if (Array.isArray(expr)) {
|
|
14016
|
-
if (expr.length === 0) return this.error("Expected an array with at least one element. If you wanted a literal array, use [\"literal\", []].");
|
|
14017
|
-
const op = expr[0];
|
|
14018
|
-
if (typeof op !== "string") {
|
|
14019
|
-
this.error(`Expression name must be a string, but found ${typeof op} instead. If you wanted a literal array, use ["literal", [...]].`, 0);
|
|
14020
|
-
return null;
|
|
14021
|
-
}
|
|
14022
|
-
const Expr = this.registry[op];
|
|
14023
|
-
if (Expr) {
|
|
14024
|
-
let parsed = Expr.parse(expr, this);
|
|
14025
|
-
if (!parsed) return null;
|
|
14026
|
-
if (this.expectedType) {
|
|
14027
|
-
const expected = this.expectedType;
|
|
14028
|
-
const actual = parsed.type;
|
|
14029
|
-
if ((expected.kind === "string" || expected.kind === "number" || expected.kind === "boolean" || expected.kind === "object" || expected.kind === "array") && actual.kind === "value") parsed = annotate(parsed, expected, options.typeAnnotation || "assert");
|
|
14030
|
-
else if ("projectionDefinition" === expected.kind && [
|
|
14031
|
-
"string",
|
|
14032
|
-
"array",
|
|
14033
|
-
"value"
|
|
14034
|
-
].includes(actual.kind) || [
|
|
14035
|
-
"color",
|
|
14036
|
-
"formatted",
|
|
14037
|
-
"resolvedImage"
|
|
14038
|
-
].includes(expected.kind) && ["value", "string"].includes(actual.kind) || ["padding", "numberArray"].includes(expected.kind) && [
|
|
14039
|
-
"value",
|
|
14040
|
-
"number",
|
|
14041
|
-
"array"
|
|
14042
|
-
].includes(actual.kind) || "colorArray" === expected.kind && [
|
|
14043
|
-
"value",
|
|
14044
|
-
"string",
|
|
14045
|
-
"array"
|
|
14046
|
-
].includes(actual.kind) || "variableAnchorOffsetCollection" === expected.kind && ["value", "array"].includes(actual.kind)) parsed = annotate(parsed, expected, options.typeAnnotation || "coerce");
|
|
14047
|
-
else if (this.checkSubtype(expected, actual)) return null;
|
|
14048
|
-
}
|
|
14049
|
-
if (!(parsed instanceof Literal) && parsed.type.kind !== "resolvedImage" && this._isConstant(parsed)) {
|
|
14050
|
-
const ec = new EvaluationContext();
|
|
14051
|
-
try {
|
|
14052
|
-
parsed = new Literal(parsed.type, parsed.evaluate(ec));
|
|
14053
|
-
} catch (e) {
|
|
14054
|
-
this.error(e.message);
|
|
14055
|
-
return null;
|
|
14056
|
-
}
|
|
14057
|
-
}
|
|
14058
|
-
return parsed;
|
|
14059
|
-
}
|
|
14060
|
-
return this.error(`Unknown expression "${op}". If you wanted a literal array, use ["literal", [...]].`, 0);
|
|
14061
|
-
} else if (typeof expr === "undefined") return this.error("'undefined' value invalid. Use null instead.");
|
|
14062
|
-
else if (typeof expr === "object") return this.error("Bare objects invalid. Use [\"literal\", {...}] instead.");
|
|
14063
|
-
else return this.error(`Expected an array, but found ${typeof expr} instead.`);
|
|
14064
|
-
}
|
|
14065
|
-
/**
|
|
14066
|
-
* Returns a copy of this context suitable for parsing the subexpression at
|
|
14067
|
-
* index `index`, optionally appending to 'let' binding map.
|
|
14068
|
-
*
|
|
14069
|
-
* Note that `errors` property, intended for collecting errors while
|
|
14070
|
-
* parsing, is copied by reference rather than cloned.
|
|
14071
|
-
* @private
|
|
14072
|
-
*/
|
|
14073
|
-
concat(index, expectedType, bindings) {
|
|
14074
|
-
const path = typeof index === "number" ? this.path.concat(index) : this.path;
|
|
14075
|
-
const scope = bindings ? this.scope.concat(bindings) : this.scope;
|
|
14076
|
-
return new ParsingContext(this.registry, this._isConstant, path, expectedType || null, scope, this.errors);
|
|
14077
|
-
}
|
|
14078
|
-
/**
|
|
14079
|
-
* Push a parsing (or type checking) error into the `this.errors`
|
|
14080
|
-
* @param error The message
|
|
14081
|
-
* @param keys Optionally specify the source of the error at a child
|
|
14082
|
-
* of the current expression at `this.key`.
|
|
14083
|
-
* @private
|
|
14084
|
-
*/
|
|
14085
|
-
error(error, ...keys) {
|
|
14086
|
-
const key = `${this.key}${keys.map((k) => `[${k}]`).join("")}`;
|
|
14087
|
-
this.errors.push(new ExpressionParsingError(key, error));
|
|
14088
|
-
}
|
|
14089
|
-
/**
|
|
14090
|
-
* Returns null if `t` is a subtype of `expected`; otherwise returns an
|
|
14091
|
-
* error message and also pushes it to `this.errors`.
|
|
14092
|
-
* @param expected The expected type
|
|
14093
|
-
* @param t The actual type
|
|
14094
|
-
* @returns null if `t` is a subtype of `expected`; otherwise returns an error message
|
|
14095
|
-
*/
|
|
14096
|
-
checkSubtype(expected, t) {
|
|
14097
|
-
const error = checkSubtype(expected, t);
|
|
14098
|
-
if (error) this.error(error);
|
|
14099
|
-
return error;
|
|
14100
|
-
}
|
|
14101
|
-
};
|
|
14102
|
-
|
|
14103
|
-
//#region src/expression/compound_expression.ts
|
|
14173
|
+
// src/expression/compound_expression.ts
|
|
14104
14174
|
var CompoundExpression = class CompoundExpression {
|
|
14105
14175
|
constructor(name, type, evaluate, args, key) {
|
|
14106
14176
|
this.name = name;
|
|
@@ -14675,7 +14745,21 @@ function isGlobalPropertyConstant(e, properties) {
|
|
|
14675
14745
|
return result;
|
|
14676
14746
|
}
|
|
14677
14747
|
|
|
14678
|
-
|
|
14748
|
+
// src/util/result.ts
|
|
14749
|
+
function success(value) {
|
|
14750
|
+
return {
|
|
14751
|
+
result: "success",
|
|
14752
|
+
value
|
|
14753
|
+
};
|
|
14754
|
+
}
|
|
14755
|
+
function error(value) {
|
|
14756
|
+
return {
|
|
14757
|
+
result: "error",
|
|
14758
|
+
value
|
|
14759
|
+
};
|
|
14760
|
+
}
|
|
14761
|
+
|
|
14762
|
+
// src/util/properties.ts
|
|
14679
14763
|
function supportsPropertyExpression(spec) {
|
|
14680
14764
|
return spec["property-type"] === "data-driven" || spec["property-type"] === "cross-faded-data-driven";
|
|
14681
14765
|
}
|
|
@@ -14686,13 +14770,13 @@ function supportsInterpolation(spec) {
|
|
|
14686
14770
|
return !!spec.expression && spec.expression.interpolated;
|
|
14687
14771
|
}
|
|
14688
14772
|
|
|
14689
|
-
|
|
14773
|
+
// src/util/extend.ts
|
|
14690
14774
|
function extendBy(output, ...inputs) {
|
|
14691
14775
|
for (const input of inputs) for (const k in input) output[k] = input[k];
|
|
14692
14776
|
return output;
|
|
14693
14777
|
}
|
|
14694
14778
|
|
|
14695
|
-
|
|
14779
|
+
// src/util/get_type.ts
|
|
14696
14780
|
function getType(val) {
|
|
14697
14781
|
if (val instanceof Number) return "number";
|
|
14698
14782
|
else if (val instanceof String) return "string";
|
|
@@ -14702,7 +14786,7 @@ function getType(val) {
|
|
|
14702
14786
|
else return typeof val;
|
|
14703
14787
|
}
|
|
14704
14788
|
|
|
14705
|
-
|
|
14789
|
+
// src/function/index.ts
|
|
14706
14790
|
function isFunction(value) {
|
|
14707
14791
|
return typeof value === "object" && value !== null && !Array.isArray(value) && typeOf(value) === ObjectType;
|
|
14708
14792
|
}
|
|
@@ -14911,21 +14995,7 @@ function interpolationFactor(input, base, lowerValue, upperValue) {
|
|
|
14911
14995
|
else return (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1);
|
|
14912
14996
|
}
|
|
14913
14997
|
|
|
14914
|
-
|
|
14915
|
-
function success(value) {
|
|
14916
|
-
return {
|
|
14917
|
-
result: "success",
|
|
14918
|
-
value
|
|
14919
|
-
};
|
|
14920
|
-
}
|
|
14921
|
-
function error(value) {
|
|
14922
|
-
return {
|
|
14923
|
-
result: "error",
|
|
14924
|
-
value
|
|
14925
|
-
};
|
|
14926
|
-
}
|
|
14927
|
-
|
|
14928
|
-
//#region src/expression/index.ts
|
|
14998
|
+
// src/expression/index.ts
|
|
14929
14999
|
var StyleExpression = class {
|
|
14930
15000
|
constructor(expression, rootKey, propertySpec, globalState) {
|
|
14931
15001
|
this.expression = expression;
|
|
@@ -15140,21 +15210,26 @@ function normalizePropertyExpression(value, rootKey, specification, globalState)
|
|
|
15140
15210
|
};
|
|
15141
15211
|
}
|
|
15142
15212
|
}
|
|
15143
|
-
function findZoomCurve(expression) {
|
|
15213
|
+
function findZoomCurve(expression, seen = /* @__PURE__ */ new Map()) {
|
|
15214
|
+
if (seen.has(expression)) return seen.get(expression);
|
|
15144
15215
|
let result = null;
|
|
15145
|
-
if (expression instanceof Let) result = findZoomCurve(expression.result);
|
|
15216
|
+
if (expression instanceof Let) result = findZoomCurve(expression.result, seen);
|
|
15146
15217
|
else if (expression instanceof Coalesce) for (const arg of expression.args) {
|
|
15147
|
-
result = findZoomCurve(arg);
|
|
15218
|
+
result = findZoomCurve(arg, seen);
|
|
15148
15219
|
if (result) break;
|
|
15149
15220
|
}
|
|
15150
15221
|
else if ((expression instanceof Step || expression instanceof Interpolate) && expression.input instanceof CompoundExpression && expression.input.name === "zoom") result = expression;
|
|
15151
|
-
if (result instanceof ExpressionParsingError)
|
|
15222
|
+
if (result instanceof ExpressionParsingError) {
|
|
15223
|
+
seen.set(expression, result);
|
|
15224
|
+
return result;
|
|
15225
|
+
}
|
|
15152
15226
|
expression.eachChild((child) => {
|
|
15153
|
-
const childResult = findZoomCurve(child);
|
|
15227
|
+
const childResult = findZoomCurve(child, seen);
|
|
15154
15228
|
if (childResult instanceof ExpressionParsingError) result = childResult;
|
|
15155
15229
|
else if (!result && childResult) result = new ExpressionParsingError("", "\"zoom\" expression may only be used as input to a top-level \"step\" or \"interpolate\" expression.");
|
|
15156
15230
|
else if (result && childResult && result !== childResult) result = new ExpressionParsingError("", "Only one zoom-based \"step\" or \"interpolate\" subexpression may be used in an expression.");
|
|
15157
15231
|
});
|
|
15232
|
+
seen.set(expression, result);
|
|
15158
15233
|
return result;
|
|
15159
15234
|
}
|
|
15160
15235
|
function findGlobalStateRefs(expression, results = /* @__PURE__ */ new Set()) {
|
|
@@ -15207,7 +15282,7 @@ function addGlobalState(globals, globalState) {
|
|
|
15207
15282
|
};
|
|
15208
15283
|
}
|
|
15209
15284
|
|
|
15210
|
-
|
|
15285
|
+
// src/feature_filter/index.ts
|
|
15211
15286
|
function classifyChildren(children) {
|
|
15212
15287
|
let sawLegacy = false;
|
|
15213
15288
|
for (const child of children) {
|
|
@@ -15420,7 +15495,7 @@ function convertNegation(filter) {
|
|
|
15420
15495
|
return ["!", filter];
|
|
15421
15496
|
}
|
|
15422
15497
|
|
|
15423
|
-
|
|
15498
|
+
// src/expression/visibility.ts
|
|
15424
15499
|
const visibilitySpec = {
|
|
15425
15500
|
type: "enum",
|
|
15426
15501
|
"property-type": "data-constant",
|
|
@@ -15803,6 +15878,174 @@ async function loadGlyphRange(template, fontStack, start, fetchFn) {
|
|
|
15803
15878
|
}
|
|
15804
15879
|
}
|
|
15805
15880
|
|
|
15881
|
+
/**
|
|
15882
|
+
* A PNG file of RGBA pixels, for images that are drawn from a data URI, like the sheets of a
|
|
15883
|
+
* sprite. Without compression: its deflate stream holds the pixels in stored blocks, which needs
|
|
15884
|
+
* no dependency and runs in browsers too. The file is a little larger than the pixels.
|
|
15885
|
+
*/
|
|
15886
|
+
/** The CRC-32 table of PNG chunks, built on first use. */
|
|
15887
|
+
let crcTable;
|
|
15888
|
+
function crc32(bytes, start, end) {
|
|
15889
|
+
if (!crcTable) {
|
|
15890
|
+
crcTable = new Uint32Array(256);
|
|
15891
|
+
for (let n = 0; n < 256; n++) {
|
|
15892
|
+
let c = n;
|
|
15893
|
+
for (let k = 0; k < 8; k++)
|
|
15894
|
+
c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
15895
|
+
crcTable[n] = c >>> 0;
|
|
15896
|
+
}
|
|
15897
|
+
}
|
|
15898
|
+
let crc = 0xffffffff;
|
|
15899
|
+
for (let i = start; i < end; i++)
|
|
15900
|
+
crc = crcTable[(crc ^ bytes[i]) & 0xff] ^ (crc >>> 8);
|
|
15901
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
15902
|
+
}
|
|
15903
|
+
/** The checksum of a zlib stream. */
|
|
15904
|
+
function adler32(bytes) {
|
|
15905
|
+
let a = 1;
|
|
15906
|
+
let b = 0;
|
|
15907
|
+
// sums of up to 5552 bytes cannot overflow before the modulo
|
|
15908
|
+
for (let i = 0; i < bytes.length;) {
|
|
15909
|
+
const end = Math.min(i + 5552, bytes.length);
|
|
15910
|
+
for (; i < end; i++) {
|
|
15911
|
+
a += bytes[i];
|
|
15912
|
+
b += a;
|
|
15913
|
+
}
|
|
15914
|
+
a %= 65521;
|
|
15915
|
+
b %= 65521;
|
|
15916
|
+
}
|
|
15917
|
+
return ((b << 16) | a) >>> 0;
|
|
15918
|
+
}
|
|
15919
|
+
/** The longest stored deflate block. */
|
|
15920
|
+
const MAX_BLOCK = 65535;
|
|
15921
|
+
/** A zlib stream of the bytes in stored deflate blocks. */
|
|
15922
|
+
function zlibStored(raw) {
|
|
15923
|
+
const blocks = Math.max(1, Math.ceil(raw.length / MAX_BLOCK));
|
|
15924
|
+
const out = new Uint8Array(2 + blocks * 5 + raw.length + 4);
|
|
15925
|
+
const view = new DataView(out.buffer);
|
|
15926
|
+
// deflate with a 32 KB window, no dictionary, the fastest level
|
|
15927
|
+
out[0] = 0x78;
|
|
15928
|
+
out[1] = 0x01;
|
|
15929
|
+
let at = 2;
|
|
15930
|
+
for (let block = 0; block < blocks; block++) {
|
|
15931
|
+
const start = block * MAX_BLOCK;
|
|
15932
|
+
const length = Math.min(MAX_BLOCK, raw.length - start);
|
|
15933
|
+
out[at] = block === blocks - 1 ? 1 : 0;
|
|
15934
|
+
view.setUint16(at + 1, length, true);
|
|
15935
|
+
view.setUint16(at + 3, ~length & 0xffff, true);
|
|
15936
|
+
out.set(raw.subarray(start, start + length), at + 5);
|
|
15937
|
+
at += 5 + length;
|
|
15938
|
+
}
|
|
15939
|
+
view.setUint32(at, adler32(raw));
|
|
15940
|
+
return out;
|
|
15941
|
+
}
|
|
15942
|
+
/** A chunk of a PNG file: its length, type, data and CRC. */
|
|
15943
|
+
function chunk(type, data) {
|
|
15944
|
+
const out = new Uint8Array(12 + data.length);
|
|
15945
|
+
const view = new DataView(out.buffer);
|
|
15946
|
+
view.setUint32(0, data.length);
|
|
15947
|
+
for (let i = 0; i < 4; i++)
|
|
15948
|
+
out[4 + i] = type.charCodeAt(i);
|
|
15949
|
+
out.set(data, 8);
|
|
15950
|
+
view.setUint32(8 + data.length, crc32(out, 4, 8 + data.length));
|
|
15951
|
+
return out;
|
|
15952
|
+
}
|
|
15953
|
+
/**
|
|
15954
|
+
* A PNG file of an image of `width` × `height` pixels, given as RGBA, row by row, not
|
|
15955
|
+
* premultiplied: as `ImageData` and MapLibre's `map.addImage` have them.
|
|
15956
|
+
* @throws If `data` does not hold `width * height` pixels.
|
|
15957
|
+
*/
|
|
15958
|
+
function encodePNG(width, height, data) {
|
|
15959
|
+
if (!Number.isInteger(width) || !Number.isInteger(height) || width <= 0 || height <= 0) {
|
|
15960
|
+
throw new Error(`An image must have a positive whole width and height, not ${String(width)} × ${String(height)}`);
|
|
15961
|
+
}
|
|
15962
|
+
if (data.length !== width * height * 4) {
|
|
15963
|
+
throw new Error(`An image of ${String(width)} × ${String(height)} pixels needs ${String(width * height * 4)} bytes, not ${String(data.length)}`);
|
|
15964
|
+
}
|
|
15965
|
+
const header = new Uint8Array(13);
|
|
15966
|
+
const view = new DataView(header.buffer);
|
|
15967
|
+
view.setUint32(0, width);
|
|
15968
|
+
view.setUint32(4, height);
|
|
15969
|
+
// 8 bits per channel, RGBA, no interlace
|
|
15970
|
+
header[8] = 8;
|
|
15971
|
+
header[9] = 6;
|
|
15972
|
+
// each row starts with its filter: none
|
|
15973
|
+
const row = width * 4;
|
|
15974
|
+
const raw = new Uint8Array((row + 1) * height);
|
|
15975
|
+
for (let y = 0; y < height; y++)
|
|
15976
|
+
raw.set(data.subarray(y * row, (y + 1) * row), y * (row + 1) + 1);
|
|
15977
|
+
const parts = [
|
|
15978
|
+
new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
|
|
15979
|
+
chunk('IHDR', header),
|
|
15980
|
+
chunk('IDAT', zlibStored(raw)),
|
|
15981
|
+
chunk('IEND', new Uint8Array(0)),
|
|
15982
|
+
];
|
|
15983
|
+
const png = new Uint8Array(parts.reduce((sum, part) => sum + part.length, 0));
|
|
15984
|
+
let at = 0;
|
|
15985
|
+
for (const part of parts) {
|
|
15986
|
+
png.set(part, at);
|
|
15987
|
+
at += part.length;
|
|
15988
|
+
}
|
|
15989
|
+
return png;
|
|
15990
|
+
}
|
|
15991
|
+
|
|
15992
|
+
/**
|
|
15993
|
+
* The images in an atlas like the sprite's, each on a sheet of its own. An image that cannot be
|
|
15994
|
+
* drawn, e.g. with too few pixels, is left out with a warning.
|
|
15995
|
+
*/
|
|
15996
|
+
function imageAtlas(images, warn) {
|
|
15997
|
+
const atlas = new Map();
|
|
15998
|
+
for (const image of images) {
|
|
15999
|
+
const { id, width, height, data, pixelRatio = 1, sdf = false } = image;
|
|
16000
|
+
if (atlas.has(id)) {
|
|
16001
|
+
warn(`The image "${id}" is given twice in "images": the first one is drawn.`);
|
|
16002
|
+
continue;
|
|
16003
|
+
}
|
|
16004
|
+
if (!(pixelRatio > 0)) {
|
|
16005
|
+
warn(`The image "${id}" in "images" has no positive pixelRatio: it is left out.`);
|
|
16006
|
+
continue;
|
|
16007
|
+
}
|
|
16008
|
+
let png;
|
|
16009
|
+
try {
|
|
16010
|
+
png = encodePNG(width, height, data);
|
|
16011
|
+
}
|
|
16012
|
+
catch (error) {
|
|
16013
|
+
warn(`The image "${id}" in "images" is left out: ${error.message}.`);
|
|
16014
|
+
continue;
|
|
16015
|
+
}
|
|
16016
|
+
const buffer = png.buffer.slice(png.byteOffset, png.byteOffset + png.byteLength);
|
|
16017
|
+
atlas.set(id, {
|
|
16018
|
+
width,
|
|
16019
|
+
height,
|
|
16020
|
+
x: 0,
|
|
16021
|
+
y: 0,
|
|
16022
|
+
pixelRatio,
|
|
16023
|
+
sdf,
|
|
16024
|
+
sheetDataUri: `data:image/png;base64,${arrayBufferToBase64(buffer)}`,
|
|
16025
|
+
sheetWidth: width,
|
|
16026
|
+
sheetHeight: height,
|
|
16027
|
+
});
|
|
16028
|
+
}
|
|
16029
|
+
return atlas;
|
|
16030
|
+
}
|
|
16031
|
+
/**
|
|
16032
|
+
* The sprite's atlas with the images added, like `map.addImage` in MapLibre GL JS, which fails for
|
|
16033
|
+
* an id that the style has already: an image of the sprite keeps its place, with a warning.
|
|
16034
|
+
*/
|
|
16035
|
+
function withImages(sprite, images, warn) {
|
|
16036
|
+
if (images.size === 0)
|
|
16037
|
+
return sprite;
|
|
16038
|
+
const atlas = new Map(sprite);
|
|
16039
|
+
for (const [id, entry] of images) {
|
|
16040
|
+
if (atlas.has(id)) {
|
|
16041
|
+
warn(`The image "${id}" in "images" is in the sprite too: the sprite's is drawn.`);
|
|
16042
|
+
continue;
|
|
16043
|
+
}
|
|
16044
|
+
atlas.set(id, entry);
|
|
16045
|
+
}
|
|
16046
|
+
return atlas;
|
|
16047
|
+
}
|
|
16048
|
+
|
|
15806
16049
|
// DEFLATE is a complex format; to read this code, you should probably check the RFC first:
|
|
15807
16050
|
// https://tools.ietf.org/html/rfc1951
|
|
15808
16051
|
// You may also wish to take a look at the guide I made about this program:
|
|
@@ -21196,6 +21439,9 @@ class SVGMapRenderer {
|
|
|
21196
21439
|
#pmtiles;
|
|
21197
21440
|
#fetch;
|
|
21198
21441
|
#sprite;
|
|
21442
|
+
/** The images of {@link SVGMapRendererOptions.images}, encoded on first use. */
|
|
21443
|
+
#imageList;
|
|
21444
|
+
#images;
|
|
21199
21445
|
#sources;
|
|
21200
21446
|
#glyphRanges = new Map();
|
|
21201
21447
|
#onWarning;
|
|
@@ -21208,6 +21454,7 @@ class SVGMapRenderer {
|
|
|
21208
21454
|
constructor(options) {
|
|
21209
21455
|
this.#style = options.style;
|
|
21210
21456
|
this.#onWarning = options.onWarning ?? ((message) => console.warn(message));
|
|
21457
|
+
this.#imageList = options.images ?? [];
|
|
21211
21458
|
let labels =
|
|
21212
21459
|
// eslint-disable-next-line @typescript-eslint/no-deprecated -- still supported, mapped to `labels`
|
|
21213
21460
|
options.labels ?? (options.renderLabels === true ? 'glyphs-text' : 'none');
|
|
@@ -21335,7 +21582,8 @@ class SVGMapRenderer {
|
|
|
21335
21582
|
const sprite = loadSprite(this.#style, this.#fetch).then(({ atlas, complete }) => {
|
|
21336
21583
|
if (!complete && this.#sprite === sprite)
|
|
21337
21584
|
this.#sprite = undefined;
|
|
21338
|
-
|
|
21585
|
+
this.#images ??= imageAtlas(this.#imageList, (message) => this.#warn(message));
|
|
21586
|
+
return withImages(atlas, this.#images, (message) => this.#warn(message));
|
|
21339
21587
|
});
|
|
21340
21588
|
this.#sprite = sprite;
|
|
21341
21589
|
return sprite;
|
|
@@ -21634,7 +21882,11 @@ class CanvasPatterns {
|
|
|
21634
21882
|
image
|
|
21635
21883
|
.getContext('2d')
|
|
21636
21884
|
.drawImage(sheet, sprite.x, sprite.y, sprite.width, sprite.height, 0, 0, sprite.width, sprite.height);
|
|
21637
|
-
|
|
21885
|
+
// Only an unloaded `Image` gives `null`; a canvas never does.
|
|
21886
|
+
const created = this.#ctx.createPattern(image, 'repeat');
|
|
21887
|
+
if (!created)
|
|
21888
|
+
throw new Error(`could not create a canvas pattern of "${pattern.name}"`);
|
|
21889
|
+
fill = created;
|
|
21638
21890
|
this.#patterns.set(key, fill);
|
|
21639
21891
|
}
|
|
21640
21892
|
const scale = (pattern.scale ?? 1) / sprite.pixelRatio;
|