@maplibre/maplibre-gl-style-spec
Version:
a specification for maplibre styles
2,101 lines • 272 kB
JavaScript
#!/usr/bin/env node
import { createRequire } from "node:module";
import { readFileSync } from "node:fs";
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
//#endregion
//#region src/error/validation_error.ts
var import_minimist = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
function hasKey(obj, keys) {
var o = obj;
keys.slice(0, -1).forEach(function(key) {
o = o[key] || {};
});
return keys[keys.length - 1] in o;
}
function isNumber(x) {
if (typeof x === "number") return true;
if (/^0x[0-9a-f]+$/i.test(x)) return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
}
function isConstructorOrProto(obj, key) {
return key === "constructor" && typeof obj[key] === "function" || key === "__proto__";
}
module.exports = function(args, opts) {
if (!opts) opts = {};
var flags = {
bools: {},
strings: {},
unknownFn: null
};
if (typeof opts.unknown === "function") flags.unknownFn = opts.unknown;
if (typeof opts.boolean === "boolean" && opts.boolean) flags.allBools = true;
else [].concat(opts.boolean).filter(Boolean).forEach(function(key) {
flags.bools[key] = true;
});
var aliases = {};
function aliasIsBoolean(key) {
return aliases[key].some(function(x) {
return flags.bools[x];
});
}
Object.keys(opts.alias || {}).forEach(function(key) {
aliases[key] = [].concat(opts.alias[key]);
aliases[key].forEach(function(x) {
aliases[x] = [key].concat(aliases[key].filter(function(y) {
return x !== y;
}));
});
});
[].concat(opts.string).filter(Boolean).forEach(function(key) {
flags.strings[key] = true;
if (aliases[key]) [].concat(aliases[key]).forEach(function(k) {
flags.strings[k] = true;
});
});
var defaults = opts.default || {};
var argv = { _: [] };
function argDefined(key, arg) {
return flags.allBools && /^--[^=]+$/.test(arg) || flags.strings[key] || flags.bools[key] || aliases[key];
}
function setKey(obj, keys, value) {
var o = obj;
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
if (isConstructorOrProto(o, key)) return;
if (o[key] === void 0) o[key] = {};
if (o[key] === Object.prototype || o[key] === Number.prototype || o[key] === String.prototype) o[key] = {};
if (o[key] === Array.prototype) o[key] = [];
o = o[key];
}
var lastKey = keys[keys.length - 1];
if (isConstructorOrProto(o, lastKey)) return;
if (o === Object.prototype || o === Number.prototype || o === String.prototype) o = {};
if (o === Array.prototype) o = [];
if (o[lastKey] === void 0 || flags.bools[lastKey] || typeof o[lastKey] === "boolean") o[lastKey] = value;
else if (Array.isArray(o[lastKey])) o[lastKey].push(value);
else o[lastKey] = [o[lastKey], value];
}
function setArg(key, val, arg) {
if (arg && flags.unknownFn && !argDefined(key, arg)) {
if (flags.unknownFn(arg) === false) return;
}
var value = !flags.strings[key] && isNumber(val) ? Number(val) : val;
setKey(argv, key.split("."), value);
(aliases[key] || []).forEach(function(x) {
setKey(argv, x.split("."), value);
});
}
Object.keys(flags.bools).forEach(function(key) {
setArg(key, defaults[key] === void 0 ? false : defaults[key]);
});
var notFlags = [];
if (args.indexOf("--") !== -1) {
notFlags = args.slice(args.indexOf("--") + 1);
args = args.slice(0, args.indexOf("--"));
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
var key;
var next;
if (/^--.+=/.test(arg)) {
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
key = m[1];
var value = m[2];
if (flags.bools[key]) value = value !== "false";
setArg(key, value, arg);
} else if (/^--no-.+/.test(arg)) {
key = arg.match(/^--no-(.+)/)[1];
setArg(key, false, arg);
} else if (/^--.+/.test(arg)) {
key = arg.match(/^--(.+)/)[1];
next = args[i + 1];
if (next !== void 0 && !/^(-|--)[^-]/.test(next) && !flags.bools[key] && !flags.allBools && (aliases[key] ? !aliasIsBoolean(key) : true)) {
setArg(key, next, arg);
i += 1;
} else if (/^(true|false)$/.test(next)) {
setArg(key, next === "true", arg);
i += 1;
} else setArg(key, flags.strings[key] ? "" : true, arg);
} else if (/^-[^-]+/.test(arg)) {
var letters = arg.slice(1, -1).split("");
var broken = false;
for (var j = 0; j < letters.length; j++) {
next = arg.slice(j + 2);
if (next === "-") {
setArg(letters[j], next, arg);
continue;
}
if (/[A-Za-z]/.test(letters[j]) && next[0] === "=") {
setArg(letters[j], next.slice(1), arg);
broken = true;
break;
}
if (/[A-Za-z]/.test(letters[j]) && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next, arg);
broken = true;
break;
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
setArg(letters[j], arg.slice(j + 2), arg);
broken = true;
break;
} else setArg(letters[j], flags.strings[letters[j]] ? "" : true, arg);
}
key = arg.slice(-1)[0];
if (!broken && key !== "-") if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1]) && !flags.bools[key] && (aliases[key] ? !aliasIsBoolean(key) : true)) {
setArg(key, args[i + 1], arg);
i += 1;
} else if (args[i + 1] && /^(true|false)$/.test(args[i + 1])) {
setArg(key, args[i + 1] === "true", arg);
i += 1;
} else setArg(key, flags.strings[key] ? "" : true, arg);
} else {
if (!flags.unknownFn || flags.unknownFn(arg) !== false) argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg));
if (opts.stopEarly) {
argv._.push.apply(argv._, args.slice(i + 1));
break;
}
}
}
Object.keys(defaults).forEach(function(k) {
if (!hasKey(argv, k.split("."))) {
setKey(argv, k.split("."), defaults[k]);
(aliases[k] || []).forEach(function(x) {
setKey(argv, x.split("."), defaults[k]);
});
}
});
if (opts["--"]) argv["--"] = notFlags.slice();
else notFlags.forEach(function(k) {
argv._.push(k);
});
return argv;
};
})))(), 1);
var ValidationError = class {
constructor(key, value, message, identifier) {
this.message = (key ? `${key}: ` : "") + message;
if (identifier) this.identifier = identifier;
if (value !== null && value !== void 0 && value.__line__) this.line = value.__line__;
}
};
//#endregion
//#region src/validate/validate_constants.ts
function validateConstants(options) {
const key = options.key;
const constants = options.value;
if (constants) return [new ValidationError(key, constants, "constants have been deprecated as of v8")];
else return [];
}
//#endregion
//#region src/util/extend.ts
function extendBy(output, ...inputs) {
for (const input of inputs) for (const k in input) output[k] = input[k];
return output;
}
//#endregion
//#region src/util/unbundle_jsonlint.ts
function unbundle(value) {
if (value instanceof Number || value instanceof String || value instanceof Boolean) return value.valueOf();
else return value;
}
function deepUnbundle(value) {
if (Array.isArray(value)) return value.map(deepUnbundle);
else if (value instanceof Object && !(value instanceof Number || value instanceof String || value instanceof Boolean)) {
const unbundledValue = {};
for (const key in value) unbundledValue[key] = deepUnbundle(value[key]);
return unbundledValue;
}
return unbundle(value);
}
//#endregion
//#region src/expression/parsing_error.ts
var ExpressionParsingError = class extends Error {
constructor(key, message) {
super(message);
this.message = message;
this.key = key;
}
};
//#endregion
//#region src/expression/scope.ts
/**
* Tracks `let` bindings during expression parsing.
* @private
*/
var Scope = class Scope {
constructor(parent, bindings = []) {
this.parent = parent;
this.bindings = {};
for (const [name, expression] of bindings) this.bindings[name] = expression;
}
concat(bindings) {
return new Scope(this, bindings);
}
get(name) {
if (this.bindings[name]) return this.bindings[name];
if (this.parent) return this.parent.get(name);
throw new Error(`${name} not found in scope.`);
}
has(name) {
if (this.bindings[name]) return true;
return this.parent ? this.parent.has(name) : false;
}
};
//#endregion
//#region src/expression/types.ts
const NullType = { kind: "null" };
const NumberType = { kind: "number" };
const StringType = { kind: "string" };
const BooleanType = { kind: "boolean" };
const ColorType = { kind: "color" };
const ProjectionDefinitionType = { kind: "projectionDefinition" };
const ObjectType = { kind: "object" };
const ValueType = { kind: "value" };
const ErrorType = { kind: "error" };
const CollatorType = { kind: "collator" };
const FormattedType = { kind: "formatted" };
const PaddingType = { kind: "padding" };
const ColorArrayType = { kind: "colorArray" };
const NumberArrayType = { kind: "numberArray" };
const ResolvedImageType = { kind: "resolvedImage" };
const VariableAnchorOffsetCollectionType = { kind: "variableAnchorOffsetCollection" };
function array(itemType, N) {
return {
kind: "array",
itemType,
N
};
}
function typeToString(type) {
if (type.kind === "array") {
const itemType = typeToString(type.itemType);
return typeof type.N === "number" ? `array<${itemType}, ${type.N}>` : type.itemType.kind === "value" ? "array" : `array<${itemType}>`;
} else return type.kind;
}
const valueMemberTypes = [
NullType,
NumberType,
StringType,
BooleanType,
ColorType,
ProjectionDefinitionType,
FormattedType,
ObjectType,
array(ValueType),
PaddingType,
NumberArrayType,
ColorArrayType,
ResolvedImageType,
VariableAnchorOffsetCollectionType
];
/**
* Returns null if `t` is a subtype of `expected`; otherwise returns an
* error message.
* @private
*/
function checkSubtype(expected, t) {
if (t.kind === "error") return null;
else if (expected.kind === "array") {
if (t.kind === "array" && (t.N === 0 && t.itemType.kind === "value" || !checkSubtype(expected.itemType, t.itemType)) && (typeof expected.N !== "number" || expected.N === t.N)) return null;
} else if (expected.kind === t.kind) return null;
else if (expected.kind === "value") {
for (const memberType of valueMemberTypes) if (!checkSubtype(memberType, t)) return null;
}
return `Expected ${typeToString(expected)} but found ${typeToString(t)} instead.`;
}
function isValidType(provided, allowedTypes) {
return allowedTypes.some((t) => t.kind === provided.kind);
}
function isValidNativeType(provided, allowedTypes) {
return allowedTypes.some((t) => {
if (t === "null") return provided === null;
else if (t === "array") return Array.isArray(provided);
else if (t === "object") return provided && !Array.isArray(provided) && typeof provided === "object";
else return t === typeof provided;
});
}
/**
* Verify whether the specified type is of the same type as the specified sample.
*
* @param provided Type to verify
* @param sample Sample type to reference
* @returns `true` if both objects are of the same type, `false` otherwise
* @example basic types
* if (verifyType(outputType, ValueType)) {
* // type narrowed to:
* outputType.kind; // 'value'
* }
* @example array types
* if (verifyType(outputType, array(NumberType))) {
* // type narrowed to:
* outputType.kind; // 'array'
* outputType.itemType; // NumberTypeT
* outputType.itemType.kind; // 'number'
* }
*/
function verifyType(provided, sample) {
if (provided.kind === "array" && sample.kind === "array") return provided.itemType.kind === sample.itemType.kind && typeof provided.N === "number";
return provided.kind === sample.kind;
}
//#endregion
//#region src/expression/types/color_spaces.ts
const Xn = .96422, Yn = 1, Zn = .82521, t0 = 4 / 29, t1 = 6 / 29, t2 = 3 * t1 * t1, t3 = t1 * t1 * t1, deg2rad = Math.PI / 180, rad2deg = 180 / Math.PI;
function constrainAngle(angle) {
angle = angle % 360;
if (angle < 0) angle += 360;
return angle;
}
function rgbToLab([r, g, b, alpha]) {
r = rgb2xyz(r);
g = rgb2xyz(g);
b = rgb2xyz(b);
let x, z;
const y = xyz2lab((.2225045 * r + .7168786 * g + .0606169 * b) / Yn);
if (r === g && g === b) x = z = y;
else {
x = xyz2lab((.4360747 * r + .3850649 * g + .1430804 * b) / Xn);
z = xyz2lab((.0139322 * r + .0971045 * g + .7141733 * b) / Zn);
}
const l = 116 * y - 16;
return [
l < 0 ? 0 : l,
500 * (x - y),
200 * (y - z),
alpha
];
}
function rgb2xyz(x) {
return x <= .04045 ? x / 12.92 : Math.pow((x + .055) / 1.055, 2.4);
}
function xyz2lab(t) {
return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
}
function labToRgb([l, a, b, alpha]) {
let y = (l + 16) / 116, x = isNaN(a) ? y : y + a / 500, z = isNaN(b) ? y : y - b / 200;
y = Yn * lab2xyz(y);
x = Xn * lab2xyz(x);
z = Zn * lab2xyz(z);
return [
xyz2rgb(3.1338561 * x - 1.6168667 * y - .4906146 * z),
xyz2rgb(-.9787684 * x + 1.9161415 * y + .033454 * z),
xyz2rgb(.0719453 * x - .2289914 * y + 1.4052427 * z),
alpha
];
}
function xyz2rgb(x) {
x = x <= .00304 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - .055;
return x < 0 ? 0 : x > 1 ? 1 : x;
}
function lab2xyz(t) {
return t > t1 ? t * t * t : t2 * (t - t0);
}
function rgbToHcl(rgbColor) {
const [l, a, b, alpha] = rgbToLab(rgbColor);
const c = Math.sqrt(a * a + b * b);
return [
Math.round(c * 1e4) ? constrainAngle(Math.atan2(b, a) * rad2deg) : NaN,
c,
l,
alpha
];
}
function hclToRgb([h, c, l, alpha]) {
h = isNaN(h) ? 0 : h * deg2rad;
return labToRgb([
l,
Math.cos(h) * c,
Math.sin(h) * c,
alpha
]);
}
function hslToRgb([h, s, l, alpha]) {
h = constrainAngle(h);
s /= 100;
l /= 100;
function f(n) {
const k = (n + h / 30) % 12;
const a = s * Math.min(l, 1 - l);
return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
}
return [
f(0),
f(8),
f(4),
alpha
];
}
//#endregion
//#region src/util/get_own.ts
const hasOwnProperty = Object.hasOwn || function hasOwnProperty(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
};
function getOwn(object, key) {
return hasOwnProperty(object, key) ? object[key] : void 0;
}
//#endregion
//#region src/expression/types/parse_css_color.ts
/**
* CSS color parser compliant with CSS Color 4 Specification.
* Supports: named colors, `transparent` keyword, all rgb hex notations,
* rgb(), rgba(), hsl() and hsla() functions.
* Does not round the parsed values to integers from the range 0..255.
*
* Syntax:
*
* <alpha-value> = <number> | <percentage>
* <hue> = <number> | <angle>
*
* rgb() = rgb( <percentage>{3} [ / <alpha-value> ]? ) | rgb( <number>{3} [ / <alpha-value> ]? )
* rgb() = rgb( <percentage>#{3} , <alpha-value>? ) | rgb( <number>#{3} , <alpha-value>? )
*
* hsl() = hsl( <hue> <percentage> <percentage> [ / <alpha-value> ]? )
* hsl() = hsl( <hue>, <percentage>, <percentage>, <alpha-value>? )
*
* Caveats:
* - <angle> - <number> with optional `deg` suffix; `grad`, `rad`, `turn` are not supported
* - `none` keyword is not supported
* - comments inside rgb()/hsl() are not supported
* - legacy color syntax rgba() is supported with an identical grammar and behavior to rgb()
* - legacy color syntax hsla() is supported with an identical grammar and behavior to hsl()
*
* @param input CSS color string to parse.
* @returns Color in sRGB color space, with `red`, `green`, `blue`
* and `alpha` channels normalized to the range 0..1,
* or `undefined` if the input is not a valid color string.
*/
function parseCssColor(input) {
input = input.toLowerCase().trim();
if (input === "transparent") return [
0,
0,
0,
0
];
const namedColorsMatch = getOwn(namedColors, input);
if (namedColorsMatch) {
const [r, g, b] = namedColorsMatch;
return [
r / 255,
g / 255,
b / 255,
1
];
}
if (input.startsWith("#")) {
if (/^#(?:[0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(input)) {
const step = input.length < 6 ? 1 : 2;
let i = 1;
return [
parseHex(input.slice(i, i += step)),
parseHex(input.slice(i, i += step)),
parseHex(input.slice(i, i += step)),
parseHex(input.slice(i, i + step) || "ff")
];
}
}
if (input.startsWith("rgb")) {
const rgbMatch = input.match(/^rgba?\(\s*([\de.+-]+)(%)?(?:\s+|\s*(,)\s*)([\de.+-]+)(%)?(?:\s+|\s*(,)\s*)([\de.+-]+)(%)?(?:\s*([,\/])\s*([\de.+-]+)(%)?)?\s*\)$/);
if (rgbMatch) {
const [_, r, rp, f1, g, gp, f2, b, bp, f3, a, ap] = rgbMatch;
const argFormat = [
f1 || " ",
f2 || " ",
f3
].join("");
if (argFormat === " " || argFormat === " /" || argFormat === ",," || argFormat === ",,,") {
const valFormat = [
rp,
gp,
bp
].join("");
const maxValue = valFormat === "%%%" ? 100 : valFormat === "" ? 255 : 0;
if (maxValue) {
const rgba = [
clamp(+r / maxValue, 0, 1),
clamp(+g / maxValue, 0, 1),
clamp(+b / maxValue, 0, 1),
a ? parseAlpha(+a, ap) : 1
];
if (validateNumbers(rgba)) return rgba;
}
}
return;
}
}
const hslMatch = input.match(/^hsla?\(\s*([\de.+-]+)(?:deg)?(?:\s+|\s*(,)\s*)([\de.+-]+)%(?:\s+|\s*(,)\s*)([\de.+-]+)%(?:\s*([,\/])\s*([\de.+-]+)(%)?)?\s*\)$/);
if (hslMatch) {
const [_, h, f1, s, f2, l, f3, a, ap] = hslMatch;
const argFormat = [
f1 || " ",
f2 || " ",
f3
].join("");
if (argFormat === " " || argFormat === " /" || argFormat === ",," || argFormat === ",,,") {
const hsla = [
+h,
clamp(+s, 0, 100),
clamp(+l, 0, 100),
a ? parseAlpha(+a, ap) : 1
];
if (validateNumbers(hsla)) return hslToRgb(hsla);
}
}
}
function parseHex(hex) {
return parseInt(hex.padEnd(2, hex), 16) / 255;
}
function parseAlpha(a, asPercentage) {
return clamp(asPercentage ? a / 100 : a, 0, 1);
}
function clamp(n, min, max) {
return Math.min(Math.max(min, n), max);
}
/**
* The regular expression for numeric values is not super specific, and it may
* happen that it will accept a value that is not a valid number. In order to
* detect and eliminate such values this function exists.
*
* @param array Array of uncertain numbers.
* @returns `true` if the specified array contains only valid numbers, `false` otherwise.
*/
function validateNumbers(array) {
return !array.some(Number.isNaN);
}
/**
* To generate:
* - visit {@link https://www.w3.org/TR/css-color-4/#named-colors}
* - run in the console:
* @example
* copy(`{\n${[...document.querySelector('.named-color-table tbody').children].map((tr) => `${tr.cells[2].textContent.trim()}: [${tr.cells[4].textContent.trim().split(/\s+/).join(', ')}],`).join('\n')}\n}`);
*/
const namedColors = {
aliceblue: [
240,
248,
255
],
antiquewhite: [
250,
235,
215
],
aqua: [
0,
255,
255
],
aquamarine: [
127,
255,
212
],
azure: [
240,
255,
255
],
beige: [
245,
245,
220
],
bisque: [
255,
228,
196
],
black: [
0,
0,
0
],
blanchedalmond: [
255,
235,
205
],
blue: [
0,
0,
255
],
blueviolet: [
138,
43,
226
],
brown: [
165,
42,
42
],
burlywood: [
222,
184,
135
],
cadetblue: [
95,
158,
160
],
chartreuse: [
127,
255,
0
],
chocolate: [
210,
105,
30
],
coral: [
255,
127,
80
],
cornflowerblue: [
100,
149,
237
],
cornsilk: [
255,
248,
220
],
crimson: [
220,
20,
60
],
cyan: [
0,
255,
255
],
darkblue: [
0,
0,
139
],
darkcyan: [
0,
139,
139
],
darkgoldenrod: [
184,
134,
11
],
darkgray: [
169,
169,
169
],
darkgreen: [
0,
100,
0
],
darkgrey: [
169,
169,
169
],
darkkhaki: [
189,
183,
107
],
darkmagenta: [
139,
0,
139
],
darkolivegreen: [
85,
107,
47
],
darkorange: [
255,
140,
0
],
darkorchid: [
153,
50,
204
],
darkred: [
139,
0,
0
],
darksalmon: [
233,
150,
122
],
darkseagreen: [
143,
188,
143
],
darkslateblue: [
72,
61,
139
],
darkslategray: [
47,
79,
79
],
darkslategrey: [
47,
79,
79
],
darkturquoise: [
0,
206,
209
],
darkviolet: [
148,
0,
211
],
deeppink: [
255,
20,
147
],
deepskyblue: [
0,
191,
255
],
dimgray: [
105,
105,
105
],
dimgrey: [
105,
105,
105
],
dodgerblue: [
30,
144,
255
],
firebrick: [
178,
34,
34
],
floralwhite: [
255,
250,
240
],
forestgreen: [
34,
139,
34
],
fuchsia: [
255,
0,
255
],
gainsboro: [
220,
220,
220
],
ghostwhite: [
248,
248,
255
],
gold: [
255,
215,
0
],
goldenrod: [
218,
165,
32
],
gray: [
128,
128,
128
],
green: [
0,
128,
0
],
greenyellow: [
173,
255,
47
],
grey: [
128,
128,
128
],
honeydew: [
240,
255,
240
],
hotpink: [
255,
105,
180
],
indianred: [
205,
92,
92
],
indigo: [
75,
0,
130
],
ivory: [
255,
255,
240
],
khaki: [
240,
230,
140
],
lavender: [
230,
230,
250
],
lavenderblush: [
255,
240,
245
],
lawngreen: [
124,
252,
0
],
lemonchiffon: [
255,
250,
205
],
lightblue: [
173,
216,
230
],
lightcoral: [
240,
128,
128
],
lightcyan: [
224,
255,
255
],
lightgoldenrodyellow: [
250,
250,
210
],
lightgray: [
211,
211,
211
],
lightgreen: [
144,
238,
144
],
lightgrey: [
211,
211,
211
],
lightpink: [
255,
182,
193
],
lightsalmon: [
255,
160,
122
],
lightseagreen: [
32,
178,
170
],
lightskyblue: [
135,
206,
250
],
lightslategray: [
119,
136,
153
],
lightslategrey: [
119,
136,
153
],
lightsteelblue: [
176,
196,
222
],
lightyellow: [
255,
255,
224
],
lime: [
0,
255,
0
],
limegreen: [
50,
205,
50
],
linen: [
250,
240,
230
],
magenta: [
255,
0,
255
],
maroon: [
128,
0,
0
],
mediumaquamarine: [
102,
205,
170
],
mediumblue: [
0,
0,
205
],
mediumorchid: [
186,
85,
211
],
mediumpurple: [
147,
112,
219
],
mediumseagreen: [
60,
179,
113
],
mediumslateblue: [
123,
104,
238
],
mediumspringgreen: [
0,
250,
154
],
mediumturquoise: [
72,
209,
204
],
mediumvioletred: [
199,
21,
133
],
midnightblue: [
25,
25,
112
],
mintcream: [
245,
255,
250
],
mistyrose: [
255,
228,
225
],
moccasin: [
255,
228,
181
],
navajowhite: [
255,
222,
173
],
navy: [
0,
0,
128
],
oldlace: [
253,
245,
230
],
olive: [
128,
128,
0
],
olivedrab: [
107,
142,
35
],
orange: [
255,
165,
0
],
orangered: [
255,
69,
0
],
orchid: [
218,
112,
214
],
palegoldenrod: [
238,
232,
170
],
palegreen: [
152,
251,
152
],
paleturquoise: [
175,
238,
238
],
palevioletred: [
219,
112,
147
],
papayawhip: [
255,
239,
213
],
peachpuff: [
255,
218,
185
],
peru: [
205,
133,
63
],
pink: [
255,
192,
203
],
plum: [
221,
160,
221
],
powderblue: [
176,
224,
230
],
purple: [
128,
0,
128
],
rebeccapurple: [
102,
51,
153
],
red: [
255,
0,
0
],
rosybrown: [
188,
143,
143
],
royalblue: [
65,
105,
225
],
saddlebrown: [
139,
69,
19
],
salmon: [
250,
128,
114
],
sandybrown: [
244,
164,
96
],
seagreen: [
46,
139,
87
],
seashell: [
255,
245,
238
],
sienna: [
160,
82,
45
],
silver: [
192,
192,
192
],
skyblue: [
135,
206,
235
],
slateblue: [
106,
90,
205
],
slategray: [
112,
128,
144
],
slategrey: [
112,
128,
144
],
snow: [
255,
250,
250
],
springgreen: [
0,
255,
127
],
steelblue: [
70,
130,
180
],
tan: [
210,
180,
140
],
teal: [
0,
128,
128
],
thistle: [
216,
191,
216
],
tomato: [
255,
99,
71
],
turquoise: [
64,
224,
208
],
violet: [
238,
130,
238
],
wheat: [
245,
222,
179
],
white: [
255,
255,
255
],
whitesmoke: [
245,
245,
245
],
yellow: [
255,
255,
0
],
yellowgreen: [
154,
205,
50
]
};
//#endregion
//#region src/util/interpolate-primitives.ts
function interpolateNumber(from, to, t) {
return from + t * (to - from);
}
function interpolateArray(from, to, t) {
return from.map((d, i) => {
return interpolateNumber(d, to[i], t);
});
}
//#endregion
//#region src/expression/types/color.ts
/**
* Color representation used by WebGL.
* Defined in sRGB color space and pre-blended with alpha.
* @private
*/
var Color = class Color {
/**
* @param r Red component premultiplied by `alpha` 0..1
* @param g Green component premultiplied by `alpha` 0..1
* @param b Blue component premultiplied by `alpha` 0..1
* @param [alpha=1] Alpha component 0..1
* @param [premultiplied=true] Whether the `r`, `g` and `b` values have already
* been multiplied by alpha. If `true` nothing happens if `false` then they will
* be multiplied automatically.
*/
constructor(r, g, b, alpha = 1, premultiplied = true) {
this.r = r;
this.g = g;
this.b = b;
this.a = alpha;
if (!premultiplied) {
this.r *= alpha;
this.g *= alpha;
this.b *= alpha;
if (!alpha) this.overwriteGetter("rgb", [
r,
g,
b,
alpha
]);
}
}
static {
this.black = new Color(0, 0, 0, 1);
}
static {
this.white = new Color(1, 1, 1, 1);
}
static {
this.transparent = new Color(0, 0, 0, 0);
}
static {
this.red = new Color(1, 0, 0, 1);
}
/**
* Parses CSS color strings and converts colors to sRGB color space if needed.
* Officially supported color formats:
* - keyword, e.g. 'aquamarine' or 'steelblue'
* - hex (with 3, 4, 6 or 8 digits), e.g. '#f0f' or '#e9bebea9'
* - rgb and rgba, e.g. 'rgb(0,240,120)' or 'rgba(0%,94%,47%,0.1)' or 'rgb(0 240 120 / .3)'
* - hsl and hsla, e.g. 'hsl(0,0%,83%)' or 'hsla(0,0%,83%,.5)' or 'hsl(0 0% 83% / 20%)'
*
* @param input CSS color string to parse.
* @returns A `Color` instance, or `undefined` if the input is not a valid color string.
*/
static parse(input) {
if (input instanceof Color) return input;
if (typeof input !== "string") return;
const rgba = parseCssColor(input);
if (rgba) return new Color(...rgba, false);
}
/**
* Used in color interpolation and by 'to-rgba' expression.
*
* @returns Gien color, with reversed alpha blending, in sRGB color space.
*/
get rgb() {
const { r, g, b, a } = this;
const f = a || Infinity;
return this.overwriteGetter("rgb", [
r / f,
g / f,
b / f,
a
]);
}
/**
* Used in color interpolation.
*
* @returns Gien color, with reversed alpha blending, in HCL color space.
*/
get hcl() {
return this.overwriteGetter("hcl", rgbToHcl(this.rgb));
}
/**
* Used in color interpolation.
*
* @returns Gien color, with reversed alpha blending, in LAB color space.
*/
get lab() {
return this.overwriteGetter("lab", rgbToLab(this.rgb));
}
/**
* Lazy getter pattern. When getter is called for the first time lazy value
* is calculated and then overwrites getter function in given object instance.
*
* @example:
* const redColor = Color.parse('red');
* let x = redColor.hcl; // this will invoke `get hcl()`, which will calculate
* // the value of red in HCL space and invoke this `overwriteGetter` function
* // which in turn will set a field with a key 'hcl' in the `redColor` object.
* // In other words it will override `get hcl()` from its `Color` prototype
* // with its own property: hcl = [calculated red value in hcl].
* let y = redColor.hcl; // next call will no longer invoke getter but simply
* // return the previously calculated value
* x === y; // true - `x` is exactly the same object as `y`
*
* @param getterKey Getter key
* @param lazyValue Lazily calculated value to be memoized by current instance
* @private
*/
overwriteGetter(getterKey, lazyValue) {
Object.defineProperty(this, getterKey, { value: lazyValue });
return lazyValue;
}
/**
* Used by 'to-string' expression.
*
* @returns Serialized color in format `rgba(r,g,b,a)`
* where r,g,b are numbers within 0..255 and alpha is number within 1..0
*
* @example
* var purple = new Color.parse('purple');
* purple.toString; // = "rgba(128,0,128,1)"
* var translucentGreen = new Color.parse('rgba(26, 207, 26, .73)');
* translucentGreen.toString(); // = "rgba(26,207,26,0.73)"
*/
toString() {
const [r, g, b, a] = this.rgb;
return `rgba(${[
r,
g,
b
].map((n) => Math.round(n * 255)).join(",")},${a})`;
}
static interpolate(from, to, t, spaceKey = "rgb") {
switch (spaceKey) {
case "rgb": {
const [r, g, b, alpha] = interpolateArray(from.rgb, to.rgb, t);
return new Color(r, g, b, alpha, false);
}
case "hcl": {
const [hue0, chroma0, light0, alphaF] = from.hcl;
const [hue1, chroma1, light1, alphaT] = to.hcl;
let hue, chroma;
if (!isNaN(hue0) && !isNaN(hue1)) {
let dh = hue1 - hue0;
if (hue1 > hue0 && dh > 180) dh -= 360;
else if (hue1 < hue0 && hue0 - hue1 > 180) dh += 360;
hue = hue0 + t * dh;
} else if (!isNaN(hue0)) {
hue = hue0;
if (light1 === 1 || light1 === 0) chroma = chroma0;
} else if (!isNaN(hue1)) {
hue = hue1;
if (light0 === 1 || light0 === 0) chroma = chroma1;
} else hue = NaN;
const [r, g, b, alpha] = hclToRgb([
hue,
chroma ?? interpolateNumber(chroma0, chroma1, t),
interpolateNumber(light0, light1, t),
interpolateNumber(alphaF, alphaT, t)
]);
return new Color(r, g, b, alpha, false);
}
case "lab": {
const [r, g, b, alpha] = labToRgb(interpolateArray(from.lab, to.lab, t));
return new Color(r, g, b, alpha, false);
}
}
}
};
//#endregion
//#region src/expression/types/collator.ts
var Collator = class {
constructor(caseSensitive, diacriticSensitive, locale) {
if (caseSensitive) this.sensitivity = diacriticSensitive ? "variant" : "case";
else this.sensitivity = diacriticSensitive ? "accent" : "base";
this.locale = locale;
this.collator = new Intl.Collator(this.locale ? this.locale : [], {
sensitivity: this.sensitivity,
usage: "search"
});
}
compare(lhs, rhs) {
return this.collator.compare(lhs, rhs);
}
resolvedLocale() {
return new Intl.Collator(this.locale ? this.locale : []).resolvedOptions().locale;
}
};
//#endregion
//#region src/expression/types/formatted.ts
const VERTICAL_ALIGN_OPTIONS = [
"bottom",
"center",
"top"
];
var FormattedSection = class {
constructor(text, image, scale, fontStack, textColor, verticalAlign) {
this.text = text;
this.image = image;
this.scale = scale;
this.fontStack = fontStack;
this.textColor = textColor;
this.verticalAlign = verticalAlign;
}
};
var Formatted = class Formatted {
constructor(sections) {
this.sections = sections;
}
static fromString(unformatted) {
return new Formatted([new FormattedSection(unformatted, null, null, null, null, null)]);
}
isEmpty() {
if (this.sections.length === 0) return true;
return !this.sections.some((section) => section.text.length !== 0 || section.image && section.image.name.length !== 0);
}
static factory(text) {
if (text instanceof Formatted) return text;
else return Formatted.fromString(text);
}
toString() {
if (this.sections.length === 0) return "";
return this.sections.map((section) => section.text).join("");
}
};
//#endregion
//#region src/expression/types/padding.ts
/**
* A set of four numbers representing padding around a box. Create instances from
* bare arrays or numeric values using the static method `Padding.parse`.
* @private
*/
var Padding = class Padding {
constructor(values) {
this.values = values.slice();
}
/**
* Numeric padding values
* @param input A padding value
* @returns A `Padding` instance, or `undefined` if the input is not a valid padding value.
*/
static parse(input) {
if (input instanceof Padding) return input;
if (typeof input === "number") return new Padding([
input,
input,
input,
input
]);
if (!Array.isArray(input)) return;
if (input.length < 1 || input.length > 4) return;
for (const val of input) if (typeof val !== "number") return;
switch (input.length) {
case 1:
input = [
input[0],
input[0],
input[0],
input[0]
];
break;
case 2:
input = [
input[0],
input[1],
input[0],
input[1]
];
break;
case 3:
input = [
input[0],
input[1],
input[2],
input[1]
];
break;
}
return new Padding(input);
}
toString() {
return JSON.stringify(this.values);
}
static interpolate(from, to, t) {
return new Padding(interpolateArray(from.values, to.values, t));
}
};
//#endregion
//#region src/expression/types/number_array.ts
/**
* An array of numbers. Create instances from
* bare arrays or numeric values using the static method `NumberArray.parse`.
* @private
*/
var NumberArray = class NumberArray {
constructor(values) {
this.values = values.slice();
}
/**
* Numeric NumberArray values
* @param input A NumberArray value
* @returns A `NumberArray` instance, or `undefined` if the input is not a valid NumberArray value.
*/
static parse(input) {
if (input instanceof NumberArray) return input;
if (typeof input === "number") return new NumberArray([input]);
if (!Array.isArray(input)) return;
for (const val of input) if (typeof val !== "number") return;
return new NumberArray(input);
}
toString() {
return JSON.stringify(this.values);
}
static interpolate(from, to, t) {
return new NumberArray(interpolateArray(from.values, to.values, t));
}
};
//#endregion
//#region src/expression/types/color_array.ts
/**
* An array of colors. Create instances from
* bare arrays or strings using the static method `ColorArray.parse`.
* @private
*/
var ColorArray = class ColorArray {
constructor(values) {
this.values = values.slice();
}
/**
* ColorArray values
* @param input A ColorArray value
* @returns A `ColorArray` instance, or `undefined` if the input is not a valid ColorArray value.
*/
static parse(input) {
if (input instanceof ColorArray) return input;
if (typeof input === "string") {
const parsed_val = Color.parse(input);
if (!parsed_val) return;
return new ColorArray([parsed_val]);
}
if (!Array.isArray(input)) return;
const colors = [];
for (const val of input) {
if (typeof val !== "string") return;
const parsed_val = Color.parse(val);
if (!parsed_val) return;
colors.push(parsed_val);
}
return new ColorArray(colors);
}
toString() {
return JSON.stringify(this.values);
}
static interpolate(from, to, t, spaceKey = "rgb") {
const colors = [];
if (from.values.length != to.values.length) throw new Error(`colorArray: Arrays have mismatched length (${from.values.length} vs. ${to.values.length}), cannot interpolate.`);
for (let i = 0; i < from.values.length; i++) colors.push(Color.interpolate(from.values[i], to.values[i], t, spaceKey));
return new ColorArray(colors);
}
};
//#endregion
//#region src/expression/runtime_error.ts
var RuntimeError = class extends Error {
constructor(message) {
super(message);
this.name = "RuntimeError";
}
toJSON() {
return this.message;
}
};
//#endregion
//#region src/expression/types/variable_anchor_offset_collection.ts
/** Set of valid anchor positions, as a set for validation */
const anchors = /* @__PURE__ */ new Set([
"center",
"left",
"right",
"top",
"bottom",
"top-left",
"top-right",
"bottom-left",
"bottom-right"
]);
/**
* Utility class to assist managing values for text-variable-anchor-offset property. Create instances from
* bare arrays using the static method `VariableAnchorOffsetCollection.parse`.
* @private
*/
var VariableAnchorOffsetCollection = class VariableAnchorOffsetCollection {
constructor(values) {
this.values = values.slice();
}
static parse(input) {
if (input instanceof VariableAnchorOffsetCollection) return input;
if (!Array.isArray(input) || input.length < 1 || input.length % 2 !== 0) return;
for (let i = 0; i < input.length; i += 2) {
const anchorValue = input[i];
const offsetValue = input[i + 1];
if (typeof anchorValue !== "string" || !anchors.has(anchorValue)) return;
if (!Array.isArray(offsetValue) || offsetValue.length !== 2 || typeof offsetValue[0] !== "number" || typeof offsetValue[1] !== "number") return;
}
return new VariableAnchorOffsetCollection(input);
}
toString() {
return JSON.stringify(this.values);
}
static interpolate(from, to, t) {
const fromValues = from.values;
const toValues = to.values;
if (fromValues.length !== toValues.length) throw new RuntimeError(`Cannot interpolate values of different length. from: ${from.toString()}, to: ${to.toString()}`);
const output = [];
for (let i = 0; i < fromValues.length; i += 2) {
if (fromValues[i] !== toValues[i]) throw new RuntimeError(`Cannot interpolate values containing mismatched anchors. from[${i}]: ${fromValues[i]}, to[${i}]: ${toValues[i]}`);
output.push(fromValues[i]);
const [fx, fy] = fromValues[i + 1];
const [tx, ty] = toValues[i + 1];
output.push([interpolateNumber(fx, tx, t), interpolateNumber(fy, ty, t)]);
}
return new VariableAnchorOffsetCollection(output);
}
};
//#endregion
//#region src/expression/types/resolved_image.ts
var ResolvedImage = class ResolvedImage {
constructor(options) {
this.name = options.name;
this.available = options.available;
}
toString() {
return this.name;
}
static fromString(name) {
if (!name) return null;
return new ResolvedImage({
name,
available: false
});
}
};
//#endregion
//#region src/expression/types/projection_definition.ts
var ProjectionDefinition = class ProjectionDefinition {
constructor(from, to, transition) {
this.from = from;
this.to = to;
this.transition = transition;
}
static interpolate(from, to, t) {
return new ProjectionDefinition(from, to, t);
}
static parse(input) {
if (input instanceof ProjectionDefinition) return input;
if (Array.isArray(input) && input.length === 3 && typeof input[0] === "string" && typeof input[1] === "string" && typeof input[2] === "number") return new ProjectionDefinition(input[0], input[1], input[2]);
if (typeof input === "object" && typeof input.from === "string" && typeof input.to === "string" && typeof input.transition === "number") return new ProjectionDefinition(input.from, input.to, input.transition);
if (typeof input === "string") return new ProjectionDefinition(input, input, 1);
}
};
//#endregion
//#region src/expression/values.ts
function validateRGBA(r, g, b, a) {
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" ? [
r,
g,
b,
a
] : [
r,
g,
b
]).join(", ")}]: 'r', 'g', and 'b' must be between 0 and 255.`;
if (!(typeof a === "undefined" || typeof a === "number" && a >= 0 && a <= 1)) return `Invalid rgba value [${[
r,
g,
b,
a
].join(", ")}]: 'a' must be between 0 and 1.`;
return null;
}
function isValue(mixed) {
if (mixed === null || typeof mixed === "string" || typeof mixed === "boolean" || typeof mixed === "number" || mixed instanceof ProjectionDefinition || mixed instanceof Color || mixed instanceof Collator || mixed instanceof Formatted || mixed instanceof Padding || mixed instanceof NumberArray || mixed instanceof ColorArray || mixed instanceof VariableAnchorOffsetCollection || mixed instanceof ResolvedImage) return true;
else if (Array.isArray(mixed)) {
for (const item of mixed) if (!isValue(item)) return false;
return true;
} else if (typeof mixed === "object") {
for (const key in mixed) if (!isValue(mixed[key])) return false;
return true;
} else return false;
}
function typeOf(value) {
if (value === null) return NullType;
else if (typeof value === "string") return StringType;
else if (typeof value === "boolean") return BooleanType;
else if (typeof value === "number") return NumberType;
else if (value instanceof Color) return ColorType;
else if (value instanceof ProjectionDefinition) return ProjectionDefinitionType;
else if (value instanceof Collator) return CollatorType;
else if (value instanceof Formatted) return FormattedType;
else if (value instanceof Padding) return PaddingType;
else if (value instanceof NumberArray) return NumberArrayType;
else if (value instanceof ColorArray) return ColorArrayType;
else if (value instanceof VariableAnchorOffsetCollection) return VariableAnchorOffsetCollectionType;
else if (value instanceof ResolvedImage) return ResolvedImageType;
else if (Array.isArray(value)) {
const length = value.length;
let itemType;
for (const item of value) {
const t = typeOf(item);
if (!itemType) itemType = t;
else if (itemType === t) continue;
else {
itemType = ValueType;
break;
}
}
return array(itemType || ValueType, length);
} else return ObjectType;
}
function valueToString(value) {
const type = typeof value;
if (value === null) return "";
else if (type === "string" || type === "number" || type === "boolean") return String(value);
else if (value instanceof Color || value instanceof ProjectionDefinition || value instanceof Formatted || value instanceof Padding || value instanceof NumberArray || value instanceof ColorArray || value instanceof VariableAnchorOffsetCollection || value instanceof ResolvedImage) return value.toString();
else return JSON.stringify(value);
}
//#endregion
//#region src/expression/definitions/literal.ts
var Literal = class Literal {
constructor(type, value) {
this.type = type;
this.value = value;
}
static parse(args, context) {
if (args.length !== 2) return context.error(`'literal' expression requires exactly one argument, but found ${args.length - 1} instead.`);
if (!isValue(args[1])) return context.error("invalid value");
const value = args[1];
let type = typeOf(value);
const expected = context.expectedType;
if (type.kind === "array" && type.N === 0 && expected && expected.kind === "array" && (typeof expected.N !== "number" || expected.N === 0)) type = expected;
return new Literal(type, value);
}
evaluate() {
return this.value;
}
eachChild() {}
outputDefined() {
return true;
}
};
//#endregion
//#region src/expression/definitions/assertion.ts
const types$1 = {
string: StringType,
number: NumberType,
boolean: BooleanType,
object: ObjectType
};
var Assertion = class Assertion {
constructor(type, args) {
this.type = type;
this.args = args;
}
static parse(args, context) {
if (args.length < 2) return context.error("Expected at least one argument.");
let i = 1;
let type;
const name = args[0];
if (name === "array") {
let itemType;
if (args.length > 2) {
const type = args[1];
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);
itemType = types$1[type];
i++;
} else itemType = ValueType;
let N;
if (args.length > 3) {
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);
N = args[2];
i++;
}
type = array(itemType, N);
} else {
if (!types$1[name]) throw new Error(`Types doesn't contain name = ${name}`);
type = types$1[name];
}
const parsed = [];
for (; i < args.length; i++) {
const input = context.parse(args[i], i, ValueType);
if (!input) return null;
parsed.push(input);
}
return new Assertion(type, parsed);
}
evaluate(ctx) {
for (let i = 0; i < this.args.length; i++) {
const value = this.args[i].evaluate(ctx);
if (!checkSubtype(this.type, typeOf(value))) return value;
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.`);
}
throw new Error();
}
eachChild(fn) {
this.args.forEach(fn);
}
outputDefined() {
return this.args.every((arg) => arg.outputDefined());
}
};
//#endregion
//#region src/expression/definitions/coercion.ts
const types = {
"to-boolean": BooleanType,
"to-color": ColorType,
"to-number": NumberType,
"to-string": StringType
};
/**
* Special form for error-coalescing coercion expressions "to-number",
* "to-color". Since these coercions can fail at runtime, they accept multiple
* arguments, only evaluating one at a time until one succeeds.
*
* @private
*/
var Coercion = class Coercion {
constructor(type, args) {
this.type = type;
this.args = args;
}
static parse(args, context) {
if (args.length < 2) return context.error("Expected at least one argument.");
const name = args[0];
if (!types[name]) throw new Error(`Can't parse ${name} as it is not part of the known types`);
if ((name === "to-boolean" || name === "to-string") && args.length !== 2) return context.error("Expected one argument.");
const type = types[name];
const parsed = [];
for (let i = 1; i < args.length; i++) {
const input = context.parse(args[i], i, ValueType);
if (!input) return null;
parsed.push(input);
}
return new Coercion(type, parsed);
}
evaluate(ctx) {
switch (this.type.kind) {
case "boolean": return Boolean(this.args[0].evaluate(ctx));
case "color": {
let input;
let error;
for (const arg of this.args) {
input = arg.evaluate(ctx);
error = null;
if (input instanceof Color) return input;
else if (typeof input === "string") {
const c = ctx.parseColor(input);
if (c) return c;
} else if (Array.isArray(input)) {
if (input.length < 3 || input.length > 4) error = `Invalid rgba value ${JSON.stringify(input)}: expected an array containing either three or four numeric values.`;
else error = validateRGBA(input[0], input[1], input[2], input[3]);
if (!error) return new Color(input[0] / 255, input[1] / 255, input[2] / 255, input[3]);
}
}
throw new RuntimeError(error || `Could not parse color from value '${typeof input === "string" ? input : JSON.stringify(input)}'`);
}
case "padding": {
let input;
for (const arg of this.args) {
input = arg.evaluate(ctx);
const pad = Padding.parse(input);
if (pad) return pad;
}
throw new RuntimeError(`Could not parse padding from value '${typeof input === "string" ? input : JSON.stringify(input)}'`);
}
case "numberArray": {
let input;
for (const arg of this.args) {
input = arg.evaluate(ctx);
const val = NumberArray.parse(input);
if (val) return val;
}
throw new RuntimeError(`Could not parse numberArray from value '${typeof input === "string" ? input : JSON.stringify(input)}'`);
}
case "colorArray": {
let input;
for (const arg of this.args) {
input = arg.evaluate(ctx);
const val = ColorArray.parse(input);
if (val) return val;
}
throw new RuntimeError(`Could not parse colorArray from value '${typeof input === "string" ? input : JSON.stringify(input)}'`);
}
case "variableAnchorOffsetCollection": {
let input;
for (const arg of this.args) {
input = arg.evaluate(ctx);
const coll = VariableAnchorOffsetCollection.parse(input);
if (coll) return coll;
}
throw new RuntimeError(`Could not parse variableAnchorOffsetCollection from value '${typeof input === "string" ? input : JSON.stringify(input)}'`);
}
case "number": {
let value = null;
for (const arg of this.args) {
value = arg.evaluate(ctx);
if (value === null) return 0;
const num = Number(value);
if (isNaN(num)) continue;
return num;
}
throw new RuntimeError(`Could not convert ${JSON.stringify(value)} to number.`);
}
case "formatted": return Formatted.fromString(valueToString(this.args[0].evaluate(ctx)));
case "resolvedImage": return ResolvedImage.fromString(valueToString(this.args[0].evaluate(ctx)));
case "projectionDefinition": return this.args[0].evaluate(ctx);
default: return valueToString(this.args[0].evaluate(ctx));
}
}
eachChild(fn) {
this.args.forEach(fn);
}
outputDefined() {
return this.args.every((arg) => arg.outputDefined());
}
};
//#endregion
//#region src/expression/evaluation_context.ts
const geometryTypes = [
"Unknown",
"Point",
"LineString",
"Polygon"
];
var EvaluationContext = class {
constructor() {
this.globals = null;
this.feature = null;
this.featureState = null;
this.formattedSection = null;
this._parseColorCache = /* @__PURE__ */ new Map();
this.availableImages = null;
this.canonical = null;
}
id() {
return this.feature && "id" in this.feature ? this.feature.id : null;
}
geometryType() {
return this.feature ? typeof this.feature.type === "number" ? geometryTypes[this.feature.type] : this.feature.type : null;
}
geometry() {
return this.feature && "geometry" in this.feature ? thi