@tileflow/core 0.1.0-alpha.32 → 0.1.0-alpha.33
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 +33 -1
- package/THIRD_PARTY_NOTICES.md +25 -2
- package/dist/browser.d.ts +889 -1
- package/dist/browser.js +6336 -1486
- package/dist/build.d.ts +5 -4
- package/dist/build.js +625 -205
- package/dist/{capture-scene-BaAJjGq7.d.ts → capture-shot-ChPQvPyi.d.ts} +121 -1
- package/dist/capture.d.ts +1 -1
- package/dist/capture.js +218 -0
- package/dist/config-reference.json +300 -4
- package/dist/{icon-composition-Befmn-zZ.d.ts → icon-composition-CSnN2-Xt.d.ts} +130 -2
- package/dist/index.d.ts +49 -5
- package/dist/index.js +1617 -764
- package/dist/native.js +1893 -1884
- package/docs/application-tile-reading.md +80 -0
- package/docs/authoring-model.md +11 -2
- package/docs/buildings-3d.md +168 -0
- package/docs/camera-moves-and-tile-cache.md +112 -0
- package/docs/capture-scenes.md +4 -0
- package/docs/capture-shots.md +173 -0
- package/docs/depth-markers.md +65 -0
- package/docs/public-api-and-browser-subpath.md +3 -3
- package/docs/route-drawing.md +191 -0
- package/docs/street-lights.md +80 -0
- package/docs/sun-and-light.md +125 -0
- package/docs/themes-and-module-styles.md +7 -0
- package/package.json +4 -1
package/dist/native.js
CHANGED
|
@@ -3493,2046 +3493,2055 @@ var init_runtime_view_schema = __esm({
|
|
|
3493
3493
|
}
|
|
3494
3494
|
});
|
|
3495
3495
|
|
|
3496
|
-
// src/
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3496
|
+
// src/theme-blend.ts
|
|
3497
|
+
function planTileflowThemeBlend(styles, options = {}) {
|
|
3498
|
+
if (styles.length < 2)
|
|
3499
|
+
throw new TileflowThemeBlendError("A theme blend needs two or more themes.");
|
|
3500
|
+
const [base2] = styles;
|
|
3501
|
+
assertSameStructure(styles, base2);
|
|
3502
|
+
const mixedImages = new Set(imageProperties);
|
|
3503
|
+
if (options.iconImages === "switch") mixedImages.delete("icon-image");
|
|
3504
|
+
const paints = [];
|
|
3505
|
+
const switches = [];
|
|
3506
|
+
const imageGroups = collectImageNames(styles, base2, mixedImages);
|
|
3507
|
+
const symbolLayers = /* @__PURE__ */ new Set();
|
|
3508
|
+
const images = /* @__PURE__ */ new Map();
|
|
3509
|
+
let splitLayers = 0;
|
|
3510
|
+
let copiedLayers = 0;
|
|
3511
|
+
let switchedLayers = 0;
|
|
3512
|
+
const layers = [];
|
|
3513
|
+
for (const [index, layer] of base2.layers.entries()) {
|
|
3514
|
+
const variants = styles.map((style) => style.layers[index]);
|
|
3515
|
+
layers.push(...planLayer(variants, String(layer.type)));
|
|
3510
3516
|
}
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
message: "Expected at least one theme",
|
|
3578
|
-
path: ["themes"]
|
|
3579
|
-
});
|
|
3580
|
-
}
|
|
3581
|
-
if (names.length > tileflowThemeLimits.maxThemes) {
|
|
3582
|
-
context.addIssue({
|
|
3583
|
-
code: "too_big",
|
|
3584
|
-
maximum: tileflowThemeLimits.maxThemes,
|
|
3585
|
-
origin: "object",
|
|
3586
|
-
path: ["themes"]
|
|
3587
|
-
});
|
|
3588
|
-
}
|
|
3589
|
-
if (!Object.hasOwn(entry.themes, entry.defaultTheme)) {
|
|
3590
|
-
context.addIssue({
|
|
3591
|
-
code: "custom",
|
|
3592
|
-
message: "defaultTheme must name a declared theme",
|
|
3593
|
-
path: ["defaultTheme"]
|
|
3594
|
-
});
|
|
3595
|
-
}
|
|
3596
|
-
if (entry.systemThemes) {
|
|
3597
|
-
for (const colorScheme of ["light", "dark"]) {
|
|
3598
|
-
const name = entry.systemThemes[colorScheme];
|
|
3599
|
-
const theme = entry.themes[name];
|
|
3600
|
-
if (!theme) {
|
|
3601
|
-
context.addIssue({
|
|
3602
|
-
code: "custom",
|
|
3603
|
-
message: `systemThemes.${colorScheme} must name a declared theme`,
|
|
3604
|
-
path: ["systemThemes", colorScheme]
|
|
3605
|
-
});
|
|
3606
|
-
} else if (theme.colorScheme !== colorScheme) {
|
|
3607
|
-
context.addIssue({
|
|
3608
|
-
code: "custom",
|
|
3609
|
-
message: `systemThemes.${colorScheme} must reference a ${colorScheme} theme`,
|
|
3610
|
-
path: ["systemThemes", colorScheme]
|
|
3611
|
-
});
|
|
3517
|
+
const switchesByLayer = /* @__PURE__ */ new Map();
|
|
3518
|
+
for (const entry of switches) {
|
|
3519
|
+
const list = switchesByLayer.get(entry.layer) ?? [];
|
|
3520
|
+
list.push(entry);
|
|
3521
|
+
switchesByLayer.set(entry.layer, list);
|
|
3522
|
+
}
|
|
3523
|
+
const sky = differingRoot(styles, "sky");
|
|
3524
|
+
const light = differingRoot(styles, "light");
|
|
3525
|
+
const metadata = alignInteractionManifest(base2.metadata, layers);
|
|
3526
|
+
return {
|
|
3527
|
+
themes: styles.length,
|
|
3528
|
+
paints,
|
|
3529
|
+
images: [...images.values()],
|
|
3530
|
+
switches,
|
|
3531
|
+
...sky === void 0 ? {} : { sky },
|
|
3532
|
+
...light === void 0 ? {} : { light },
|
|
3533
|
+
summary: { splitLayers, copiedLayers, switchedLayers, switchedValues: switches.length },
|
|
3534
|
+
styleAt(position) {
|
|
3535
|
+
const at = clampPosition(position, styles.length);
|
|
3536
|
+
const dominant = Math.round(at);
|
|
3537
|
+
const style = {
|
|
3538
|
+
...base2,
|
|
3539
|
+
...metadata === void 0 ? {} : { metadata },
|
|
3540
|
+
// Symbols show the nearest theme, as the label cross-fade leaves them between changes.
|
|
3541
|
+
layers: layers.map(
|
|
3542
|
+
(layer) => fillLayer(
|
|
3543
|
+
layer,
|
|
3544
|
+
symbolLayers.has(String(layer.id)) ? dominant : at,
|
|
3545
|
+
dominant,
|
|
3546
|
+
switchesByLayer.get(String(layer.id))
|
|
3547
|
+
)
|
|
3548
|
+
)
|
|
3549
|
+
};
|
|
3550
|
+
if (sky !== void 0) style.sky = fillTemplate(sky, at);
|
|
3551
|
+
if (light !== void 0) style.light = fillTemplate(light, at);
|
|
3552
|
+
return style;
|
|
3553
|
+
}
|
|
3554
|
+
};
|
|
3555
|
+
function planLayer(variants, type) {
|
|
3556
|
+
const [layer] = variants;
|
|
3557
|
+
const id = String(layer.id);
|
|
3558
|
+
const paint = { ...layer.paint };
|
|
3559
|
+
const layout = { ...layer.layout };
|
|
3560
|
+
const follows = type === "symbol" ? "dominant" : "position";
|
|
3561
|
+
const ownPaints = [];
|
|
3562
|
+
const ownSwitches = [];
|
|
3563
|
+
const driven = [];
|
|
3564
|
+
const paintOf = (variant) => variant.paint ?? {};
|
|
3565
|
+
for (const group of ["layout", "paint"]) {
|
|
3566
|
+
const target = group === "paint" ? paint : layout;
|
|
3567
|
+
for (const property of propertyNames(variants, group)) {
|
|
3568
|
+
const values = variants.map(
|
|
3569
|
+
(variant) => variant[group]?.[property]
|
|
3570
|
+
);
|
|
3571
|
+
if (values.every((value) => same(value, values[0]))) continue;
|
|
3572
|
+
if (mixedImages.has(property)) {
|
|
3573
|
+
const tuples = imageTuples(values);
|
|
3574
|
+
if (tuples && tuples.every((names) => imageGroups.get(names[0])?.size === 1)) {
|
|
3575
|
+
for (const names of tuples) {
|
|
3576
|
+
if (names.every((name) => name === names[0])) continue;
|
|
3577
|
+
images.set(JSON.stringify(names), {
|
|
3578
|
+
names,
|
|
3579
|
+
follows: property === "icon-image" ? "dominant" : "position"
|
|
3580
|
+
});
|
|
3581
|
+
}
|
|
3582
|
+
continue;
|
|
3612
3583
|
}
|
|
3613
3584
|
}
|
|
3585
|
+
if (group === "layout" || values.includes(void 0) || imageProperties.has(property)) {
|
|
3586
|
+
ownSwitches.push({ group, property, values });
|
|
3587
|
+
continue;
|
|
3588
|
+
}
|
|
3589
|
+
if (values.some(isDataDriven)) {
|
|
3590
|
+
driven.push(property);
|
|
3591
|
+
continue;
|
|
3592
|
+
}
|
|
3593
|
+
const template = tryMixTemplate(values);
|
|
3594
|
+
if (template === void 0) {
|
|
3595
|
+
ownSwitches.push({ group, property, values });
|
|
3596
|
+
continue;
|
|
3597
|
+
}
|
|
3598
|
+
ownPaints.push({ property, template });
|
|
3599
|
+
target[property] = template;
|
|
3614
3600
|
}
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3601
|
+
}
|
|
3602
|
+
const planned = { ...layer, paint, layout };
|
|
3603
|
+
let results = [{ layer: planned, extra: [] }];
|
|
3604
|
+
if (driven.length > 0) {
|
|
3605
|
+
const split = type === "symbol" ? void 0 : splitLayer();
|
|
3606
|
+
const copies = split ?? (type === "symbol" ? void 0 : copyLayer());
|
|
3607
|
+
if (copies) results = copies;
|
|
3608
|
+
else
|
|
3609
|
+
for (const property of driven)
|
|
3610
|
+
ownSwitches.push({
|
|
3611
|
+
group: "paint",
|
|
3612
|
+
property,
|
|
3613
|
+
values: variants.map((variant) => paintOf(variant)[property])
|
|
3614
|
+
});
|
|
3615
|
+
}
|
|
3616
|
+
if (options.featureSwitches === "layers" && results.length === 1 && ownSwitches.some((entry) => entry.values.some(isDataDriven)))
|
|
3617
|
+
results = switchLayer();
|
|
3618
|
+
for (const result of results) {
|
|
3619
|
+
const resultId = String(result.layer.id);
|
|
3620
|
+
if (type === "symbol") symbolLayers.add(resultId);
|
|
3621
|
+
const overridden = new Set(result.extra.map((entry) => entry.property));
|
|
3622
|
+
for (const entry of [
|
|
3623
|
+
...ownPaints.filter((own) => !overridden.has(own.property)),
|
|
3624
|
+
...result.extra
|
|
3625
|
+
])
|
|
3626
|
+
paints.push({ layer: resultId, property: entry.property, template: entry.template, follows });
|
|
3627
|
+
if (result.visibility)
|
|
3628
|
+
switches.push({
|
|
3629
|
+
layer: resultId,
|
|
3630
|
+
group: "layout",
|
|
3631
|
+
property: "visibility",
|
|
3632
|
+
values: result.visibility
|
|
3619
3633
|
});
|
|
3620
|
-
}
|
|
3634
|
+
else for (const entry of ownSwitches) switches.push({ layer: resultId, ...entry });
|
|
3621
3635
|
}
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
maximum: tileflowRuntimeManifestLimits.maximumBytes,
|
|
3641
|
-
origin: "string",
|
|
3642
|
-
message: "Manifest JSON exceeds the 1 MiB limit"
|
|
3643
|
-
});
|
|
3644
|
-
}
|
|
3645
|
-
}
|
|
3646
|
-
);
|
|
3647
|
-
const safeManifestInputSchema = operations.superRefine(operations.unknown(), (input, context) => {
|
|
3648
|
-
const unsafe = findUnsafeManifestStructure(input);
|
|
3649
|
-
if (unsafe) {
|
|
3650
|
-
context.addIssue({
|
|
3651
|
-
code: "custom",
|
|
3652
|
-
message: unsafe.reason === "prototype" ? "Expected plain manifest objects" : "Expected no prototype-mutating keys",
|
|
3653
|
-
path: unsafe.path
|
|
3636
|
+
return results.map((result) => result.layer);
|
|
3637
|
+
function switchLayer() {
|
|
3638
|
+
switchedLayers += variants.length;
|
|
3639
|
+
return variants.map((_, theme) => {
|
|
3640
|
+
const copyPaint = { ...paint };
|
|
3641
|
+
const copyLayout = { ...layout };
|
|
3642
|
+
for (const entry of ownSwitches) {
|
|
3643
|
+
const target = entry.group === "paint" ? copyPaint : copyLayout;
|
|
3644
|
+
const value = entry.values[theme];
|
|
3645
|
+
if (value === void 0) delete target[entry.property];
|
|
3646
|
+
else target[entry.property] = value;
|
|
3647
|
+
}
|
|
3648
|
+
const shown = copyLayout.visibility === "none" ? "none" : "visible";
|
|
3649
|
+
return {
|
|
3650
|
+
layer: { ...planned, id: `${id}::theme-${theme}`, paint: copyPaint, layout: copyLayout },
|
|
3651
|
+
extra: [],
|
|
3652
|
+
visibility: variants.map((__, nearest) => nearest === theme ? shown : "none")
|
|
3653
|
+
};
|
|
3654
3654
|
});
|
|
3655
3655
|
}
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3656
|
+
function splitLayer() {
|
|
3657
|
+
if (isLegacyFilter(layer.filter)) return void 0;
|
|
3658
|
+
const branches = splitBranches(
|
|
3659
|
+
Object.fromEntries(
|
|
3660
|
+
driven.map((property) => [
|
|
3661
|
+
property,
|
|
3662
|
+
variants.map((variant) => paintOf(variant)[property])
|
|
3663
|
+
])
|
|
3664
|
+
)
|
|
3665
|
+
);
|
|
3666
|
+
if (!branches) return void 0;
|
|
3667
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3668
|
+
for (const branch of branches) {
|
|
3669
|
+
const key = JSON.stringify(branch.valuesByProperty);
|
|
3670
|
+
let group = groups.get(key);
|
|
3671
|
+
if (!group) {
|
|
3672
|
+
const templates = {};
|
|
3673
|
+
for (const [property, values] of Object.entries(branch.valuesByProperty)) {
|
|
3674
|
+
const template = tryMixTemplate(values);
|
|
3675
|
+
if (template === void 0) return void 0;
|
|
3676
|
+
templates[property] = template;
|
|
3677
|
+
}
|
|
3678
|
+
group = { templates, conditions: [] };
|
|
3679
|
+
groups.set(key, group);
|
|
3680
|
+
}
|
|
3681
|
+
group.conditions.push(
|
|
3682
|
+
branch.conditions.length === 1 ? branch.conditions[0] : ["all", ...branch.conditions]
|
|
3683
|
+
);
|
|
3669
3684
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3685
|
+
splitLayers += groups.size;
|
|
3686
|
+
return [...groups.values()].map((group, number3) => {
|
|
3687
|
+
const chosen = group.conditions.length === 1 ? group.conditions[0] : ["any", ...group.conditions];
|
|
3688
|
+
return {
|
|
3689
|
+
layer: {
|
|
3690
|
+
...planned,
|
|
3691
|
+
id: `${id}::branch-${number3}`,
|
|
3692
|
+
filter: layer.filter === void 0 ? chosen : ["all", layer.filter, chosen],
|
|
3693
|
+
paint: { ...paint, ...group.templates }
|
|
3694
|
+
},
|
|
3695
|
+
extra: Object.entries(group.templates).filter(([, template]) => containsLeaf(template)).map(([property, template]) => ({ property, template }))
|
|
3696
|
+
};
|
|
3697
|
+
});
|
|
3677
3698
|
}
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
return (
|
|
3684
|
-
|
|
3685
|
-
|
|
3699
|
+
function copyLayer() {
|
|
3700
|
+
const opacity = opacityProperties[type];
|
|
3701
|
+
if (!opacity || variants.some((variant) => isDataDriven(paintOf(variant)[opacity])))
|
|
3702
|
+
return void 0;
|
|
3703
|
+
copiedLayers += variants.length;
|
|
3704
|
+
return variants.map((variant, theme) => {
|
|
3705
|
+
const weight = new BlendLeaf(variants.map((_, other) => other === theme ? 1 : 0));
|
|
3706
|
+
const template = scaleByWeight(paint[opacity] ?? 1, weight);
|
|
3707
|
+
const copyPaint = { ...paint, [opacity]: template };
|
|
3708
|
+
for (const property of driven) copyPaint[property] = paintOf(variant)[property];
|
|
3709
|
+
return {
|
|
3710
|
+
layer: { ...planned, id: `${id}::theme-${theme}`, paint: copyPaint },
|
|
3711
|
+
extra: [{ property: opacity, template }]
|
|
3712
|
+
};
|
|
3713
|
+
});
|
|
3686
3714
|
}
|
|
3687
3715
|
}
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3716
|
+
}
|
|
3717
|
+
function fillTileflowThemeBlendTemplate(template, position) {
|
|
3718
|
+
return fillTemplate(template, position);
|
|
3719
|
+
}
|
|
3720
|
+
function fillLayer(layer, position, dominant, layerSwitches) {
|
|
3721
|
+
const filled = { ...layer };
|
|
3722
|
+
for (const group of ["layout", "paint"]) {
|
|
3723
|
+
const values = layer[group];
|
|
3724
|
+
if (!values) continue;
|
|
3725
|
+
const out = {};
|
|
3726
|
+
for (const [key, value] of Object.entries(values)) out[key] = fillTemplate(value, position);
|
|
3727
|
+
for (const entry of layerSwitches ?? []) {
|
|
3728
|
+
if (entry.group !== group) continue;
|
|
3729
|
+
const value = entry.values[dominant];
|
|
3730
|
+
if (value === void 0) delete out[entry.property];
|
|
3731
|
+
else out[entry.property] = value;
|
|
3694
3732
|
}
|
|
3733
|
+
if (Object.keys(out).length > 0) filled[group] = out;
|
|
3734
|
+
else delete filled[group];
|
|
3695
3735
|
}
|
|
3696
|
-
|
|
3697
|
-
|
|
3736
|
+
return filled;
|
|
3737
|
+
}
|
|
3738
|
+
function fillTemplate(node, position) {
|
|
3739
|
+
if (node instanceof BlendLeaf) return mixLeaf(node.values, position);
|
|
3740
|
+
if (Array.isArray(node)) return node.map((item) => fillTemplate(item, position));
|
|
3741
|
+
if (node && typeof node === "object" && containsLeaf(node)) {
|
|
3742
|
+
return Object.fromEntries(
|
|
3743
|
+
Object.entries(node).map(([key, value]) => [key, fillTemplate(value, position)])
|
|
3744
|
+
);
|
|
3698
3745
|
}
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3746
|
+
return node;
|
|
3747
|
+
}
|
|
3748
|
+
function containsLeaf(node) {
|
|
3749
|
+
if (node instanceof BlendLeaf) return true;
|
|
3750
|
+
if (Array.isArray(node)) return node.some(containsLeaf);
|
|
3751
|
+
if (node && typeof node === "object") return Object.values(node).some(containsLeaf);
|
|
3752
|
+
return false;
|
|
3753
|
+
}
|
|
3754
|
+
function mixLeaf(values, position) {
|
|
3755
|
+
const at = clampPosition(position, values.length);
|
|
3756
|
+
const index = Math.min(values.length - 2, Math.floor(at));
|
|
3757
|
+
const t = at - index;
|
|
3758
|
+
const from = values[index];
|
|
3759
|
+
const to = values[index + 1];
|
|
3760
|
+
if (t <= 0 || from === to) return from;
|
|
3761
|
+
if (t >= 1) return to;
|
|
3762
|
+
if (typeof from === "number" && typeof to === "number") return from + (to - from) * t;
|
|
3763
|
+
const a = oklab(String(from));
|
|
3764
|
+
const b = oklab(String(to));
|
|
3765
|
+
if (!a || !b) return t < 0.5 ? from : to;
|
|
3766
|
+
return colourFromOklab(a.map((value, channel) => value + (b[channel] - value) * t));
|
|
3767
|
+
}
|
|
3768
|
+
function clampPosition(position, themes) {
|
|
3769
|
+
if (!Number.isFinite(position)) return 0;
|
|
3770
|
+
return Math.min(themes - 1, Math.max(0, position));
|
|
3771
|
+
}
|
|
3772
|
+
function assertSameStructure(styles, base2) {
|
|
3773
|
+
const ids = (style) => style.layers.map((layer) => layer.id);
|
|
3774
|
+
for (const style of styles) {
|
|
3775
|
+
if (!same(ids(style), ids(base2)))
|
|
3776
|
+
throw new TileflowThemeBlendError(
|
|
3777
|
+
"Blended themes must have the same layers in the same order."
|
|
3778
|
+
);
|
|
3779
|
+
if (!same(style.sources, base2.sources))
|
|
3780
|
+
throw new TileflowThemeBlendError("Blended themes must use the same sources.");
|
|
3781
|
+
if (!same(style.sprite, base2.sprite) || !same(style.glyphs, base2.glyphs))
|
|
3782
|
+
throw new TileflowThemeBlendError("Blended themes must use the same sprite and glyphs.");
|
|
3783
|
+
for (const [index, layer] of style.layers.entries()) {
|
|
3784
|
+
const other = base2.layers[index];
|
|
3785
|
+
for (const key of ["type", "source", "source-layer", "filter", "minzoom", "maxzoom"])
|
|
3786
|
+
if (!same(layer[key], other[key]))
|
|
3787
|
+
throw new TileflowThemeBlendError(
|
|
3788
|
+
`Blended themes differ in ${key} of layer ${JSON.stringify(layer.id)}.`
|
|
3789
|
+
);
|
|
3705
3790
|
}
|
|
3706
3791
|
}
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
];
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3792
|
+
}
|
|
3793
|
+
function propertyNames(variants, group) {
|
|
3794
|
+
const names = /* @__PURE__ */ new Set();
|
|
3795
|
+
for (const variant of variants)
|
|
3796
|
+
for (const name of Object.keys(variant[group] ?? {})) names.add(name);
|
|
3797
|
+
return [...names];
|
|
3798
|
+
}
|
|
3799
|
+
function differingRoot(styles, key) {
|
|
3800
|
+
const values = styles.map((style) => style[key]);
|
|
3801
|
+
if (values.every((value) => same(value, values[0]))) return void 0;
|
|
3802
|
+
return tryMixTemplate(values);
|
|
3803
|
+
}
|
|
3804
|
+
function collectImageNames(styles, base2, properties) {
|
|
3805
|
+
const uses = /* @__PURE__ */ new Map();
|
|
3806
|
+
for (const [index] of base2.layers.entries()) {
|
|
3807
|
+
for (const group of ["layout", "paint"]) {
|
|
3808
|
+
for (const property of properties) {
|
|
3809
|
+
const values = styles.map(
|
|
3810
|
+
(style) => style.layers[index]?.[group]?.[property]
|
|
3811
|
+
);
|
|
3812
|
+
if (values[0] === void 0) continue;
|
|
3813
|
+
for (const names of imageTuples(values) ?? []) {
|
|
3814
|
+
const set = uses.get(names[0]) ?? /* @__PURE__ */ new Set();
|
|
3815
|
+
set.add(JSON.stringify(names));
|
|
3816
|
+
uses.set(names[0], set);
|
|
3721
3817
|
}
|
|
3722
3818
|
}
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
return uses;
|
|
3822
|
+
}
|
|
3823
|
+
function alignInteractionManifest(metadata, layers) {
|
|
3824
|
+
if (!isRecord(metadata)) return void 0;
|
|
3825
|
+
const planned = /* @__PURE__ */ new Map();
|
|
3826
|
+
for (const [index, layer] of layers.entries()) {
|
|
3827
|
+
const id = String(layer.id);
|
|
3828
|
+
const original = /^(.+)::(?:branch|theme)-\d+$/u.exec(id)?.[1] ?? id;
|
|
3829
|
+
planned.set(original, [...planned.get(original) ?? [], { id, index }]);
|
|
3830
|
+
}
|
|
3831
|
+
let aligned;
|
|
3832
|
+
const interactions = metadata["tileflow:interaction-manifest"];
|
|
3833
|
+
const domains = isRecord(interactions) ? interactions.domains : void 0;
|
|
3834
|
+
if (isRecord(interactions) && isRecord(domains) && isRecord(domains.poi)) {
|
|
3835
|
+
const poi = domains.poi;
|
|
3836
|
+
if (Array.isArray(poi.layers)) {
|
|
3837
|
+
const poiLayers = poi.layers.flatMap((entry) => {
|
|
3838
|
+
if (!isRecord(entry) || typeof entry.layerId !== "string") return [entry];
|
|
3839
|
+
const copies = planned.get(entry.layerId);
|
|
3840
|
+
if (!copies) return [entry];
|
|
3841
|
+
return copies.map(({ id, index }) => ({ ...entry, layerId: id, priority: index }));
|
|
3842
|
+
});
|
|
3843
|
+
aligned = {
|
|
3844
|
+
...metadata,
|
|
3845
|
+
"tileflow:interaction-manifest": {
|
|
3846
|
+
...interactions,
|
|
3847
|
+
domains: { ...domains, poi: { ...poi, layers: poiLayers } }
|
|
3729
3848
|
}
|
|
3730
|
-
}
|
|
3849
|
+
};
|
|
3731
3850
|
}
|
|
3732
|
-
return void 0;
|
|
3733
3851
|
}
|
|
3734
|
-
|
|
3852
|
+
const overlays = metadata["tileflow:overlay-placement-manifest"];
|
|
3853
|
+
if (isRecord(overlays) && isRecord(overlays.anchors)) {
|
|
3854
|
+
const anchors = Object.fromEntries(
|
|
3855
|
+
Object.entries(overlays.anchors).map(([placement, anchor]) => [
|
|
3856
|
+
placement,
|
|
3857
|
+
typeof anchor === "string" ? planned.get(anchor)?.[0]?.id ?? anchor : anchor
|
|
3858
|
+
])
|
|
3859
|
+
);
|
|
3860
|
+
aligned = {
|
|
3861
|
+
...aligned ?? metadata,
|
|
3862
|
+
"tileflow:overlay-placement-manifest": { ...overlays, anchors }
|
|
3863
|
+
};
|
|
3864
|
+
}
|
|
3865
|
+
return aligned;
|
|
3735
3866
|
}
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
init_runtime_view_schema();
|
|
3742
|
-
init_model();
|
|
3867
|
+
function imageTuples(values, out = []) {
|
|
3868
|
+
const [first] = values;
|
|
3869
|
+
if (values.every((value) => typeof value === "string")) {
|
|
3870
|
+
out.push(values);
|
|
3871
|
+
return out;
|
|
3743
3872
|
}
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
// src/native-url-policy.ts
|
|
3747
|
-
var tileflowNativeUrlLimits = Object.freeze({ maximumLength: 2048 });
|
|
3748
|
-
var errorMessages = {
|
|
3749
|
-
NATIVE_URL_INVALID: "Expected a bounded HTTP(S) URL without credentials, fragments or backslashes.",
|
|
3750
|
-
NATIVE_URL_ABSOLUTE_REQUIRED: "An explicit absolute HTTP(S) document URL is required.",
|
|
3751
|
-
NATIVE_URL_HTTPS_REQUIRED: "HTTP is allowed only at the explicitly configured development origin.",
|
|
3752
|
-
NATIVE_URL_DEVELOPMENT_ORIGIN_INVALID: "Expected one HTTP origin without a path, credentials, query or fragment.",
|
|
3753
|
-
NATIVE_URL_TEMPLATE_INVALID: "Expected supported URL placeholders in the resource path or query only."
|
|
3754
|
-
};
|
|
3755
|
-
var TileflowNativeUrlError = class extends TypeError {
|
|
3756
|
-
constructor(code, field) {
|
|
3757
|
-
super(errorMessages[code]);
|
|
3758
|
-
__publicField(this, "code");
|
|
3759
|
-
__publicField(this, "field");
|
|
3760
|
-
this.name = "TileflowNativeUrlError";
|
|
3761
|
-
this.code = code;
|
|
3762
|
-
this.field = field;
|
|
3873
|
+
if (!Array.isArray(first) || typeof first[0] !== "string") {
|
|
3874
|
+
return values.every((value) => same(value, first)) ? out : void 0;
|
|
3763
3875
|
}
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
const schemePattern = /^[a-z][a-z\d+.-]*:/iu;
|
|
3770
|
-
function resolveTileflowNativeManifestUrl2(value, options = {}) {
|
|
3771
|
-
assertOptionsObject(options, "developmentOrigin");
|
|
3772
|
-
const developmentOrigin = resolveDevelopmentOrigin(options.developmentOrigin);
|
|
3773
|
-
return resolveDocumentUrl(value, "manifestUrl", developmentOrigin).href;
|
|
3876
|
+
const operator = first[0];
|
|
3877
|
+
if (!values.every(
|
|
3878
|
+
(value) => Array.isArray(value) && value[0] === operator && value.length === first.length
|
|
3879
|
+
)) {
|
|
3880
|
+
return void 0;
|
|
3774
3881
|
}
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
3882
|
+
const at = (index) => values.map((value) => value[index]);
|
|
3883
|
+
const sameAt = (index) => at(index).every((value) => same(value, first[index]));
|
|
3884
|
+
const outputs = [];
|
|
3885
|
+
if (operator === "literal" || operator === "image") outputs.push(1);
|
|
3886
|
+
else if (operator === "coalesce")
|
|
3887
|
+
for (let index = 1; index < first.length; index += 1) outputs.push(index);
|
|
3888
|
+
else if (operator === "match") {
|
|
3889
|
+
if (!sameAt(1)) return void 0;
|
|
3890
|
+
for (let index = 2; index < first.length - 1; index += 2) {
|
|
3891
|
+
if (!sameAt(index)) return void 0;
|
|
3892
|
+
outputs.push(index + 1);
|
|
3787
3893
|
}
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3894
|
+
outputs.push(first.length - 1);
|
|
3895
|
+
} else if (operator === "case") {
|
|
3896
|
+
for (let index = 1; index < first.length - 1; index += 2) {
|
|
3897
|
+
if (!sameAt(index)) return void 0;
|
|
3898
|
+
outputs.push(index + 1);
|
|
3792
3899
|
}
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
return `${prefix}${placeholders.length - 1}__`;
|
|
3801
|
-
});
|
|
3802
|
-
if (/[{}]/u.test(protectedValue)) {
|
|
3803
|
-
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
3900
|
+
outputs.push(first.length - 1);
|
|
3901
|
+
} else if (operator === "step") {
|
|
3902
|
+
if (!sameAt(1)) return void 0;
|
|
3903
|
+
outputs.push(2);
|
|
3904
|
+
for (let index = 3; index < first.length; index += 2) {
|
|
3905
|
+
if (!sameAt(index)) return void 0;
|
|
3906
|
+
outputs.push(index + 1);
|
|
3804
3907
|
}
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
const resourcePath = resolved.href.slice(resolved.origin.length);
|
|
3808
|
-
const suffix = resourcePath.replace(
|
|
3809
|
-
new RegExp(`${prefix}(\\d+)__`, "gu"),
|
|
3810
|
-
(match, index) => placeholders[Number(index)] ?? match
|
|
3811
|
-
);
|
|
3812
|
-
const result = resolved.origin + suffix;
|
|
3813
|
-
assertUrlText(result, "resourceUrl");
|
|
3814
|
-
return result;
|
|
3908
|
+
} else {
|
|
3909
|
+
return values.every((value) => same(value, first)) ? out : void 0;
|
|
3815
3910
|
}
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3911
|
+
for (const index of outputs) if (!imageTuples(at(index), out)) return void 0;
|
|
3912
|
+
return out;
|
|
3913
|
+
}
|
|
3914
|
+
function tryMixTemplate(values) {
|
|
3915
|
+
const [first] = values;
|
|
3916
|
+
if (values.every((value) => same(value, first))) return first;
|
|
3917
|
+
if (Array.isArray(first) && first[0] !== "literal" && values.every((value) => Array.isArray(value) && value.length === first.length)) {
|
|
3918
|
+
const items = [];
|
|
3919
|
+
for (let index = 0; index < first.length; index += 1) {
|
|
3920
|
+
const item = tryMixTemplate(values.map((value) => value[index]));
|
|
3921
|
+
if (item === void 0 && first[index] !== void 0) return void 0;
|
|
3922
|
+
items.push(item);
|
|
3822
3923
|
}
|
|
3924
|
+
return items;
|
|
3823
3925
|
}
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
const
|
|
3831
|
-
if (
|
|
3832
|
-
|
|
3833
|
-
}
|
|
3834
|
-
return url.origin;
|
|
3835
|
-
} catch {
|
|
3836
|
-
throw new TileflowNativeUrlError(
|
|
3837
|
-
"NATIVE_URL_DEVELOPMENT_ORIGIN_INVALID",
|
|
3838
|
-
"developmentOrigin"
|
|
3839
|
-
);
|
|
3926
|
+
if (first && typeof first === "object" && !Array.isArray(first)) {
|
|
3927
|
+
const keys = Object.keys(first);
|
|
3928
|
+
if (!values.every((value) => value && typeof value === "object" && same(Object.keys(value), keys)))
|
|
3929
|
+
return void 0;
|
|
3930
|
+
const out = {};
|
|
3931
|
+
for (const key of keys) {
|
|
3932
|
+
const item = tryMixTemplate(values.map((value) => value[key]));
|
|
3933
|
+
if (item === void 0) return void 0;
|
|
3934
|
+
out[key] = item;
|
|
3840
3935
|
}
|
|
3936
|
+
return out;
|
|
3841
3937
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3938
|
+
if (values.every((value) => typeof value === "number")) return new BlendLeaf(values);
|
|
3939
|
+
if (values.every((value) => typeof value === "string" && oklab(value)))
|
|
3940
|
+
return new BlendLeaf(values);
|
|
3941
|
+
return void 0;
|
|
3942
|
+
}
|
|
3943
|
+
function isDataDriven(value) {
|
|
3944
|
+
if (!Array.isArray(value)) return false;
|
|
3945
|
+
if (typeof value[0] === "string" && featureOperators.has(value[0])) return true;
|
|
3946
|
+
return value.some(isDataDriven);
|
|
3947
|
+
}
|
|
3948
|
+
function decisionOf(node) {
|
|
3949
|
+
if (!Array.isArray(node) || typeof node[0] !== "string") return void 0;
|
|
3950
|
+
const [operator] = node;
|
|
3951
|
+
if (operator === "match" && isDataDriven(node[1])) {
|
|
3952
|
+
const labels = [];
|
|
3953
|
+
const outputs = [];
|
|
3954
|
+
for (let index = 2; index < node.length - 1; index += 2) {
|
|
3955
|
+
labels.push(node[index]);
|
|
3956
|
+
outputs.push(node[index + 1]);
|
|
3854
3957
|
}
|
|
3958
|
+
outputs.push(node.at(-1));
|
|
3959
|
+
return {
|
|
3960
|
+
index: ["match", node[1], ...labels.flatMap((label, index) => [label, index]), labels.length],
|
|
3961
|
+
outputs
|
|
3962
|
+
};
|
|
3855
3963
|
}
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
);
|
|
3964
|
+
if (operator === "case") {
|
|
3965
|
+
const conditions = [];
|
|
3966
|
+
const outputs = [];
|
|
3967
|
+
for (let index = 1; index < node.length - 1; index += 2) {
|
|
3968
|
+
conditions.push(node[index]);
|
|
3969
|
+
outputs.push(node[index + 1]);
|
|
3862
3970
|
}
|
|
3863
|
-
|
|
3864
|
-
if (
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3971
|
+
outputs.push(node.at(-1));
|
|
3972
|
+
if (!conditions.some(isDataDriven)) return void 0;
|
|
3973
|
+
return {
|
|
3974
|
+
index: [
|
|
3975
|
+
"case",
|
|
3976
|
+
...conditions.flatMap((condition, index) => [condition, index]),
|
|
3977
|
+
conditions.length
|
|
3978
|
+
],
|
|
3979
|
+
outputs
|
|
3980
|
+
};
|
|
3871
3981
|
}
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
throw new TileflowNativeUrlError("NATIVE_URL_INVALID", field);
|
|
3879
|
-
}
|
|
3880
|
-
if (/[{}]/u.test(url.hostname)) {
|
|
3881
|
-
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", field);
|
|
3982
|
+
if (operator === "step" && isDataDriven(node[1])) {
|
|
3983
|
+
const outputs = [node[2]];
|
|
3984
|
+
const stops = [];
|
|
3985
|
+
for (let index = 3; index < node.length; index += 2) {
|
|
3986
|
+
stops.push(node[index]);
|
|
3987
|
+
outputs.push(node[index + 1]);
|
|
3882
3988
|
}
|
|
3883
|
-
return
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
if (url.protocol === "http:" && url.origin === developmentOrigin) return;
|
|
3888
|
-
throw new TileflowNativeUrlError("NATIVE_URL_HTTPS_REQUIRED", field);
|
|
3989
|
+
return {
|
|
3990
|
+
index: ["step", node[1], 0, ...stops.flatMap((stop, index) => [stop, index + 1])],
|
|
3991
|
+
outputs
|
|
3992
|
+
};
|
|
3889
3993
|
}
|
|
3890
|
-
return
|
|
3891
|
-
}
|
|
3892
|
-
|
|
3893
|
-
// src/native-url-provider.ts
|
|
3894
|
-
var import_url_state_machine = __toESM(require_url_state_machine(), 1);
|
|
3895
|
-
function parseNativeUrl(value, base2) {
|
|
3896
|
-
const baseURL = base2 === void 0 ? void 0 : (0, import_url_state_machine.basicURLParse)(base2);
|
|
3897
|
-
if (baseURL === null) throw new TypeError("Invalid native URL.");
|
|
3898
|
-
const parsed = (0, import_url_state_machine.basicURLParse)(value, baseURL === void 0 ? void 0 : { baseURL });
|
|
3899
|
-
if (parsed === null) throw new TypeError("Invalid native URL.");
|
|
3900
|
-
return {
|
|
3901
|
-
href: (0, import_url_state_machine.serializeURL)(parsed),
|
|
3902
|
-
origin: (0, import_url_state_machine.serializeURLOrigin)(parsed),
|
|
3903
|
-
protocol: `${parsed.scheme}:`,
|
|
3904
|
-
hostname: parsed.host === null ? "" : (0, import_url_state_machine.serializeHost)(parsed.host),
|
|
3905
|
-
pathname: (0, import_url_state_machine.serializePath)(parsed),
|
|
3906
|
-
search: parsed.query ? `?${parsed.query}` : "",
|
|
3907
|
-
hash: parsed.fragment ? `#${parsed.fragment}` : "",
|
|
3908
|
-
username: parsed.username,
|
|
3909
|
-
password: parsed.password
|
|
3910
|
-
};
|
|
3911
|
-
}
|
|
3912
|
-
|
|
3913
|
-
// src/native-urls.ts
|
|
3914
|
-
var policy = createNativeUrlPolicy(parseNativeUrl);
|
|
3915
|
-
function resolveTileflowNativeManifestUrl(value, options = {}) {
|
|
3916
|
-
return policy.resolveTileflowNativeManifestUrl(value, options);
|
|
3994
|
+
return void 0;
|
|
3917
3995
|
}
|
|
3918
|
-
function
|
|
3919
|
-
|
|
3996
|
+
function firstDecision(value) {
|
|
3997
|
+
const decision = decisionOf(value);
|
|
3998
|
+
if (decision) return decision;
|
|
3999
|
+
if (!Array.isArray(value) || value[0] === "literal") return void 0;
|
|
4000
|
+
for (const item of value) {
|
|
4001
|
+
const found = firstDecision(item);
|
|
4002
|
+
if (found) return found;
|
|
4003
|
+
}
|
|
4004
|
+
return void 0;
|
|
3920
4005
|
}
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/schemas.js
|
|
3929
|
-
init_core2();
|
|
3930
|
-
init_util();
|
|
3931
|
-
var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
3932
|
-
if (!inst._zod)
|
|
3933
|
-
throw new Error("Uninitialized schema in ZodMiniType.");
|
|
3934
|
-
$ZodType.init(inst, def);
|
|
3935
|
-
inst.def = def;
|
|
3936
|
-
inst.type = def.type;
|
|
3937
|
-
inst.parse = (data, params) => parse(inst, data, params, { callee: inst.parse });
|
|
3938
|
-
inst.safeParse = (data, params) => safeParse(inst, data, params);
|
|
3939
|
-
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
3940
|
-
inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
|
|
3941
|
-
inst.check = (...checks) => {
|
|
3942
|
-
return inst.clone({
|
|
3943
|
-
...def,
|
|
3944
|
-
checks: [
|
|
3945
|
-
...def.checks ?? [],
|
|
3946
|
-
...checks.map((ch) => typeof ch === "function" ? {
|
|
3947
|
-
_zod: { check: ch, def: { check: "custom" }, onattach: [] }
|
|
3948
|
-
} : ch)
|
|
3949
|
-
]
|
|
3950
|
-
}, { parent: true });
|
|
3951
|
-
};
|
|
3952
|
-
inst.with = inst.check;
|
|
3953
|
-
inst.clone = (_def, params) => clone(inst, _def, params);
|
|
3954
|
-
inst.brand = () => inst;
|
|
3955
|
-
inst.register = ((reg, meta2) => {
|
|
3956
|
-
reg.add(inst, meta2);
|
|
3957
|
-
return inst;
|
|
3958
|
-
});
|
|
3959
|
-
inst.apply = (fn) => fn(inst);
|
|
3960
|
-
});
|
|
3961
|
-
var ZodMiniString = /* @__PURE__ */ $constructor("ZodMiniString", (inst, def) => {
|
|
3962
|
-
$ZodString.init(inst, def);
|
|
3963
|
-
ZodMiniType.init(inst, def);
|
|
3964
|
-
});
|
|
3965
|
-
// @__NO_SIDE_EFFECTS__
|
|
3966
|
-
function string2(params) {
|
|
3967
|
-
return _string(ZodMiniString, params);
|
|
4006
|
+
function choose(value, key, branch) {
|
|
4007
|
+
const decision = decisionOf(value);
|
|
4008
|
+
if (decision && JSON.stringify(decision.index) === key)
|
|
4009
|
+
return choose(decision.outputs[branch], key, branch);
|
|
4010
|
+
if (!Array.isArray(value) || value[0] === "literal") return value;
|
|
4011
|
+
return value.map((item) => choose(item, key, branch));
|
|
3968
4012
|
}
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
4013
|
+
function splitBranches(valuesByProperty, conditions = []) {
|
|
4014
|
+
let decision;
|
|
4015
|
+
for (const values of Object.values(valuesByProperty)) {
|
|
4016
|
+
decision = firstDecision(values[0]);
|
|
4017
|
+
if (decision) break;
|
|
4018
|
+
}
|
|
4019
|
+
if (!decision) {
|
|
4020
|
+
const residual = Object.values(valuesByProperty).some((values) => values.some(isDataDriven));
|
|
4021
|
+
return residual ? void 0 : [{ conditions, valuesByProperty }];
|
|
4022
|
+
}
|
|
4023
|
+
if (reads(decision.index, "zoom") || reads(decision.index, "feature-state")) return void 0;
|
|
4024
|
+
const key = JSON.stringify(decision.index);
|
|
4025
|
+
const branches = [];
|
|
4026
|
+
for (let branch = 0; branch < decision.outputs.length; branch += 1) {
|
|
4027
|
+
const chosen = Object.fromEntries(
|
|
4028
|
+
Object.entries(valuesByProperty).map(([property, values]) => [
|
|
4029
|
+
property,
|
|
4030
|
+
values.map((value) => choose(value, key, branch))
|
|
4031
|
+
])
|
|
4032
|
+
);
|
|
4033
|
+
const nested = splitBranches(chosen, [...conditions, ["==", decision.index, branch]]);
|
|
4034
|
+
if (!nested) return void 0;
|
|
4035
|
+
branches.push(...nested);
|
|
4036
|
+
if (branches.length > maximumBranches) return void 0;
|
|
4037
|
+
}
|
|
4038
|
+
return branches;
|
|
3976
4039
|
}
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
4040
|
+
function scaleByWeight(opacity, weight) {
|
|
4041
|
+
const input = Array.isArray(opacity) ? opacity[0] === "interpolate" ? opacity[2] : opacity[1] : void 0;
|
|
4042
|
+
if (Array.isArray(opacity) && (opacity[0] === "interpolate" || opacity[0] === "step") && reads(input, "zoom")) {
|
|
4043
|
+
const head = opacity[0] === "interpolate" ? 3 : 2;
|
|
4044
|
+
return opacity.map(
|
|
4045
|
+
(item, index) => index >= head && (index - head) % 2 === (opacity[0] === "interpolate" ? 1 : 0) ? scaleByWeight(item, weight) : item
|
|
4046
|
+
);
|
|
4047
|
+
}
|
|
4048
|
+
if (typeof opacity === "number")
|
|
4049
|
+
return new BlendLeaf(weight.values.map((value) => opacity * Number(value)));
|
|
4050
|
+
return ["*", opacity, weight];
|
|
3984
4051
|
}
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
ZodMiniType.init(inst, def);
|
|
3988
|
-
});
|
|
3989
|
-
// @__NO_SIDE_EFFECTS__
|
|
3990
|
-
function never(params) {
|
|
3991
|
-
return _never(ZodMiniNever, params);
|
|
4052
|
+
function same(a, b) {
|
|
4053
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
3992
4054
|
}
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4055
|
+
function oklab(colour) {
|
|
4056
|
+
const cached2 = oklabCache.get(colour);
|
|
4057
|
+
if (cached2 !== void 0) return cached2;
|
|
4058
|
+
const rgba = parseColour(colour);
|
|
4059
|
+
let result = null;
|
|
4060
|
+
if (rgba) {
|
|
4061
|
+
const [r, g, b] = rgba.slice(0, 3).map((channel) => {
|
|
4062
|
+
const value = channel / 255;
|
|
4063
|
+
return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
4064
|
+
});
|
|
4065
|
+
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
|
|
4066
|
+
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
|
|
4067
|
+
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
|
|
4068
|
+
result = [
|
|
4069
|
+
0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
|
|
4070
|
+
1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
|
|
4071
|
+
0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,
|
|
4072
|
+
rgba[3]
|
|
4073
|
+
];
|
|
4074
|
+
}
|
|
4075
|
+
if (oklabCache.size > 4096) oklabCache.clear();
|
|
4076
|
+
oklabCache.set(colour, result);
|
|
4077
|
+
return result;
|
|
4004
4078
|
}
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4079
|
+
function colourFromOklab([lightness, a, b, alpha]) {
|
|
4080
|
+
const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;
|
|
4081
|
+
const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;
|
|
4082
|
+
const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;
|
|
4083
|
+
const [red, green, blue] = [
|
|
4084
|
+
4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
|
|
4085
|
+
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
|
|
4086
|
+
-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
|
|
4087
|
+
].map((value) => {
|
|
4088
|
+
const clamped = Math.min(1, Math.max(0, value));
|
|
4089
|
+
const encoded = clamped <= 31308e-7 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055;
|
|
4090
|
+
return Math.round(encoded * 255);
|
|
4017
4091
|
});
|
|
4092
|
+
return `rgba(${red}, ${green}, ${blue}, ${Number(alpha.toFixed(3))})`;
|
|
4018
4093
|
}
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
const params = hasRest ? _params : _paramsOrRest;
|
|
4027
|
-
const rest = hasRest ? _paramsOrRest : null;
|
|
4028
|
-
return new ZodMiniTuple({
|
|
4029
|
-
type: "tuple",
|
|
4030
|
-
items,
|
|
4031
|
-
rest,
|
|
4032
|
-
...normalizeParams(params)
|
|
4033
|
-
});
|
|
4034
|
-
}
|
|
4035
|
-
var ZodMiniRecord = /* @__PURE__ */ $constructor("ZodMiniRecord", (inst, def) => {
|
|
4036
|
-
$ZodRecord.init(inst, def);
|
|
4037
|
-
ZodMiniType.init(inst, def);
|
|
4038
|
-
});
|
|
4039
|
-
// @__NO_SIDE_EFFECTS__
|
|
4040
|
-
function record(keyType, valueType, params) {
|
|
4041
|
-
if (!valueType || !valueType._zod) {
|
|
4042
|
-
return new ZodMiniRecord({
|
|
4043
|
-
type: "record",
|
|
4044
|
-
keyType: /* @__PURE__ */ string2(),
|
|
4045
|
-
valueType: keyType,
|
|
4046
|
-
...normalizeParams(valueType)
|
|
4047
|
-
});
|
|
4094
|
+
function parseColour(colour) {
|
|
4095
|
+
const text = colour.trim().toLowerCase();
|
|
4096
|
+
const hex = /^#([\da-f]{3,8})$/u.exec(text)?.[1];
|
|
4097
|
+
if (hex && [3, 4, 6, 8].includes(hex.length)) {
|
|
4098
|
+
const full = hex.length <= 4 ? [...hex].map((digit) => digit + digit).join("") : hex;
|
|
4099
|
+
const channels = full.match(/../gu).map((pair) => Number.parseInt(pair, 16));
|
|
4100
|
+
return [channels[0], channels[1], channels[2], channels.length > 3 ? channels[3] / 255 : 1];
|
|
4048
4101
|
}
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
const
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
}
|
|
4070
|
-
var ZodMiniLiteral = /* @__PURE__ */ $constructor("ZodMiniLiteral", (inst, def) => {
|
|
4071
|
-
$ZodLiteral.init(inst, def);
|
|
4072
|
-
ZodMiniType.init(inst, def);
|
|
4073
|
-
});
|
|
4074
|
-
// @__NO_SIDE_EFFECTS__
|
|
4075
|
-
function literal(value, params) {
|
|
4076
|
-
return new ZodMiniLiteral({
|
|
4077
|
-
type: "literal",
|
|
4078
|
-
values: Array.isArray(value) ? value : [value],
|
|
4079
|
-
...normalizeParams(params)
|
|
4080
|
-
});
|
|
4081
|
-
}
|
|
4082
|
-
var ZodMiniOptional = /* @__PURE__ */ $constructor("ZodMiniOptional", (inst, def) => {
|
|
4083
|
-
$ZodOptional.init(inst, def);
|
|
4084
|
-
ZodMiniType.init(inst, def);
|
|
4085
|
-
});
|
|
4086
|
-
// @__NO_SIDE_EFFECTS__
|
|
4087
|
-
function optional(innerType) {
|
|
4088
|
-
return new ZodMiniOptional({
|
|
4089
|
-
type: "optional",
|
|
4090
|
-
innerType
|
|
4091
|
-
});
|
|
4102
|
+
const functional = /^(rgba?|hsla?)\(([^)]+)\)$/u.exec(text);
|
|
4103
|
+
if (!functional) return null;
|
|
4104
|
+
const parts = functional[2].split(/[\s,/]+/u).filter(Boolean);
|
|
4105
|
+
if (parts.length < 3 || parts.length > 4) return null;
|
|
4106
|
+
const alpha = parts[3] === void 0 ? 1 : parseUnit(parts[3], 1);
|
|
4107
|
+
if (functional[1].startsWith("rgb")) {
|
|
4108
|
+
const [r, g, b] = parts.slice(0, 3).map((part) => parseUnit(part, 255));
|
|
4109
|
+
if ([r, g, b, alpha].some((value) => value === null)) return null;
|
|
4110
|
+
return [r, g, b, alpha];
|
|
4111
|
+
}
|
|
4112
|
+
const hue = Number.parseFloat(parts[0]);
|
|
4113
|
+
const saturation = parseUnit(parts[1], 1);
|
|
4114
|
+
const light = parseUnit(parts[2], 1);
|
|
4115
|
+
if (!Number.isFinite(hue) || saturation === null || light === null || alpha === null) return null;
|
|
4116
|
+
const chroma = (1 - Math.abs(2 * light - 1)) * saturation;
|
|
4117
|
+
const sector = (hue % 360 + 360) % 360 / 60;
|
|
4118
|
+
const x = chroma * (1 - Math.abs(sector % 2 - 1));
|
|
4119
|
+
const [r1, g1, b1] = sector < 1 ? [chroma, x, 0] : sector < 2 ? [x, chroma, 0] : sector < 3 ? [0, chroma, x] : sector < 4 ? [0, x, chroma] : sector < 5 ? [x, 0, chroma] : [chroma, 0, x];
|
|
4120
|
+
const offset = light - chroma / 2;
|
|
4121
|
+
return [(r1 + offset) * 255, (g1 + offset) * 255, (b1 + offset) * 255, alpha];
|
|
4092
4122
|
}
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
function pipe(in_, out) {
|
|
4099
|
-
return new ZodMiniPipe({
|
|
4100
|
-
type: "pipe",
|
|
4101
|
-
in: in_,
|
|
4102
|
-
out
|
|
4103
|
-
});
|
|
4123
|
+
function parseUnit(part, scale) {
|
|
4124
|
+
const percentage = part.endsWith("%");
|
|
4125
|
+
const value = Number.parseFloat(part);
|
|
4126
|
+
if (!Number.isFinite(value)) return null;
|
|
4127
|
+
return percentage ? value / 100 * scale : value;
|
|
4104
4128
|
}
|
|
4105
|
-
var
|
|
4106
|
-
|
|
4107
|
-
|
|
4129
|
+
var TileflowThemeBlendError, BlendLeaf, imageProperties, opacityProperties, featureOperators, maximumBranches, isRecord, reads, isLegacyFilter, oklabCache;
|
|
4130
|
+
var init_theme_blend = __esm({
|
|
4131
|
+
"src/theme-blend.ts"() {
|
|
4132
|
+
"use strict";
|
|
4133
|
+
TileflowThemeBlendError = class extends Error {
|
|
4134
|
+
constructor() {
|
|
4135
|
+
super(...arguments);
|
|
4136
|
+
__publicField(this, "name", "TileflowThemeBlendError");
|
|
4137
|
+
}
|
|
4138
|
+
};
|
|
4139
|
+
BlendLeaf = class {
|
|
4140
|
+
constructor(values) {
|
|
4141
|
+
__publicField(this, "values", values);
|
|
4142
|
+
}
|
|
4143
|
+
};
|
|
4144
|
+
imageProperties = /* @__PURE__ */ new Set([
|
|
4145
|
+
"icon-image",
|
|
4146
|
+
"fill-pattern",
|
|
4147
|
+
"line-pattern",
|
|
4148
|
+
"background-pattern",
|
|
4149
|
+
"fill-extrusion-pattern"
|
|
4150
|
+
]);
|
|
4151
|
+
opacityProperties = {
|
|
4152
|
+
background: "background-opacity",
|
|
4153
|
+
circle: "circle-opacity",
|
|
4154
|
+
fill: "fill-opacity",
|
|
4155
|
+
"fill-extrusion": "fill-extrusion-opacity",
|
|
4156
|
+
heatmap: "heatmap-opacity",
|
|
4157
|
+
line: "line-opacity",
|
|
4158
|
+
raster: "raster-opacity"
|
|
4159
|
+
};
|
|
4160
|
+
featureOperators = /* @__PURE__ */ new Set([
|
|
4161
|
+
"feature-state",
|
|
4162
|
+
"geometry-type",
|
|
4163
|
+
"get",
|
|
4164
|
+
"has",
|
|
4165
|
+
"id",
|
|
4166
|
+
"in",
|
|
4167
|
+
"properties"
|
|
4168
|
+
]);
|
|
4169
|
+
maximumBranches = 24;
|
|
4170
|
+
isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
4171
|
+
reads = (value, operator) => Array.isArray(value) && (value[0] === operator || value.some((item) => reads(item, operator)));
|
|
4172
|
+
isLegacyFilter = (filter) => Array.isArray(filter) && typeof filter[1] === "string" && !Array.isArray(filter[1]);
|
|
4173
|
+
oklabCache = /* @__PURE__ */ new Map();
|
|
4174
|
+
}
|
|
4108
4175
|
});
|
|
4109
|
-
// @__NO_SIDE_EFFECTS__
|
|
4110
|
-
function refine(fn, _params = {}) {
|
|
4111
|
-
return _refine(ZodMiniCustom, fn, _params);
|
|
4112
|
-
}
|
|
4113
|
-
// @__NO_SIDE_EFFECTS__
|
|
4114
|
-
function superRefine(fn, params) {
|
|
4115
|
-
return _superRefine(fn, params);
|
|
4116
|
-
}
|
|
4117
|
-
|
|
4118
|
-
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/checks.js
|
|
4119
|
-
init_core2();
|
|
4120
|
-
|
|
4121
|
-
// src/native-manifest-schema.ts
|
|
4122
|
-
init_manifest_schema();
|
|
4123
|
-
|
|
4124
|
-
// src/manifest-schema-mini.ts
|
|
4125
|
-
function mini(schema2) {
|
|
4126
|
-
return schema2;
|
|
4127
|
-
}
|
|
4128
|
-
var miniManifestSchemaOperations = {
|
|
4129
|
-
string: () => string2(),
|
|
4130
|
-
minLength: (schema2, minimum) => mini(schema2).check(_minLength(minimum)),
|
|
4131
|
-
maxLength: (schema2, maximum) => mini(schema2).check(_maxLength(maximum)),
|
|
4132
|
-
regex: (schema2, pattern, message) => mini(schema2).check(_regex(pattern, { message })),
|
|
4133
|
-
refine: (schema2, check, message) => mini(schema2).check(refine(check, message)),
|
|
4134
|
-
// Zod 4's number parser rejects NaN and infinities; Classic finite() is a no-op.
|
|
4135
|
-
number: (minimum, maximum) => number2().check(_gte(minimum), _lte(maximum)),
|
|
4136
|
-
unknown: () => unknown(),
|
|
4137
|
-
optional: (schema2) => optional(schema2),
|
|
4138
|
-
array: (schema2) => array(schema2),
|
|
4139
|
-
enum(values) {
|
|
4140
|
-
return _enum(values);
|
|
4141
|
-
},
|
|
4142
|
-
literal: (value) => literal(value),
|
|
4143
|
-
tuplePair(left, right) {
|
|
4144
|
-
return tuple([left, right]);
|
|
4145
|
-
},
|
|
4146
|
-
// ZodMiniObject uses the interpreted $ZodObject, not the Classic object JIT constructor.
|
|
4147
|
-
object(shape) {
|
|
4148
|
-
return strictObject(shape);
|
|
4149
|
-
},
|
|
4150
|
-
record(key, value) {
|
|
4151
|
-
return record(key, value);
|
|
4152
|
-
},
|
|
4153
|
-
superRefine: (schema2, check) => mini(schema2).check(superRefine(check)),
|
|
4154
|
-
pipe: (input, output) => pipe(input, output)
|
|
4155
|
-
};
|
|
4156
4176
|
|
|
4157
|
-
// src/
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
}
|
|
4172
|
-
function decodeNativeManifestUtf8(input) {
|
|
4173
|
-
let remaining = 0;
|
|
4174
|
-
let lower = 128;
|
|
4175
|
-
let upper = 191;
|
|
4176
|
-
for (const byte of input) {
|
|
4177
|
-
if (remaining === 0) {
|
|
4178
|
-
if (byte <= 127) continue;
|
|
4179
|
-
if (byte >= 194 && byte <= 223) remaining = 1;
|
|
4180
|
-
else if (byte >= 224 && byte <= 239) {
|
|
4181
|
-
remaining = 2;
|
|
4182
|
-
if (byte === 224) lower = 160;
|
|
4183
|
-
if (byte === 237) upper = 159;
|
|
4184
|
-
} else if (byte >= 240 && byte <= 244) {
|
|
4185
|
-
remaining = 3;
|
|
4186
|
-
if (byte === 240) lower = 144;
|
|
4187
|
-
if (byte === 244) upper = 143;
|
|
4188
|
-
} else throw new TypeError("Invalid manifest UTF-8.");
|
|
4189
|
-
} else {
|
|
4190
|
-
if (byte < lower || byte > upper) throw new TypeError("Invalid manifest UTF-8.");
|
|
4191
|
-
remaining--;
|
|
4192
|
-
lower = 128;
|
|
4193
|
-
upper = 191;
|
|
4194
|
-
}
|
|
4195
|
-
}
|
|
4196
|
-
if (remaining) throw new TypeError("Invalid manifest UTF-8.");
|
|
4197
|
-
const parts = [];
|
|
4198
|
-
let offset = 0;
|
|
4199
|
-
while (offset < input.byteLength) {
|
|
4200
|
-
let end = Math.min(offset + nativeUrlCodecMaximumLength, input.byteLength);
|
|
4201
|
-
while (end < input.byteLength && (input[end] & 192) === 128) end--;
|
|
4202
|
-
parts.push(utf8DecodeWithoutBOM(input.subarray(offset, end)));
|
|
4203
|
-
offset = end;
|
|
4204
|
-
}
|
|
4205
|
-
const text = parts.join("");
|
|
4206
|
-
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
4207
|
-
}
|
|
4208
|
-
function hasBoundedNativeManifestDepth(text, maximumDepth) {
|
|
4209
|
-
let depth = 0;
|
|
4210
|
-
let quoted = false;
|
|
4211
|
-
let escaped = false;
|
|
4212
|
-
for (let index = 0; index < text.length; index++) {
|
|
4213
|
-
const character = text[index];
|
|
4214
|
-
if (quoted) {
|
|
4215
|
-
if (escaped) escaped = false;
|
|
4216
|
-
else if (character === "\\") escaped = true;
|
|
4217
|
-
else if (character === '"') quoted = false;
|
|
4218
|
-
} else if (character === '"') quoted = true;
|
|
4219
|
-
else if (character === "[" || character === "{") {
|
|
4220
|
-
if (++depth > maximumDepth) return false;
|
|
4221
|
-
} else if (character === "]" || character === "}") depth--;
|
|
4177
|
+
// src/themes/model.ts
|
|
4178
|
+
var tileflowThemeLimits, themeTypographyStyleKeys, themeTypographyKeys;
|
|
4179
|
+
var init_model = __esm({
|
|
4180
|
+
"src/themes/model.ts"() {
|
|
4181
|
+
"use strict";
|
|
4182
|
+
tileflowThemeLimits = Object.freeze({ maxThemes: 64 });
|
|
4183
|
+
themeTypographyStyleKeys = ["fallbacks", "font", "letterSpacing", "transform"];
|
|
4184
|
+
themeTypographyKeys = [
|
|
4185
|
+
...themeTypographyStyleKeys,
|
|
4186
|
+
"places",
|
|
4187
|
+
"poi",
|
|
4188
|
+
"roads",
|
|
4189
|
+
"water"
|
|
4190
|
+
];
|
|
4222
4191
|
}
|
|
4223
|
-
|
|
4224
|
-
}
|
|
4192
|
+
});
|
|
4225
4193
|
|
|
4226
|
-
// src/
|
|
4227
|
-
|
|
4228
|
-
{
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
};
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4194
|
+
// src/manifest-schema.ts
|
|
4195
|
+
function createTileflowRuntimeManifestSchema(primitives, operations, identities = createPortableIdentitySchemas(operations)) {
|
|
4196
|
+
const { tileflowPortableIdSchema, tileflowThemeNameSchema } = identities;
|
|
4197
|
+
const safeTextSchema = operations.refine(
|
|
4198
|
+
operations.refine(
|
|
4199
|
+
operations.maxLength(operations.minLength(operations.string(), 1), 2048),
|
|
4200
|
+
(value) => value === value.trim(),
|
|
4201
|
+
"Expected text without surrounding whitespace"
|
|
4202
|
+
),
|
|
4203
|
+
(value) => !/[\p{Cc}\\]/u.test(value),
|
|
4204
|
+
"Expected safe text"
|
|
4205
|
+
);
|
|
4206
|
+
const publicResourceUrlSchema = operations.refine(
|
|
4207
|
+
safeTextSchema,
|
|
4208
|
+
isPublicResourceUrl,
|
|
4209
|
+
"Expected an HTTP(S), root-relative, or path-relative public URL"
|
|
4210
|
+
);
|
|
4211
|
+
const apiOriginSchema = operations.refine(
|
|
4212
|
+
safeTextSchema,
|
|
4213
|
+
isApiOrigin,
|
|
4214
|
+
"Expected an absolute HTTP(S) origin without path, credentials, query, or fragment"
|
|
4215
|
+
);
|
|
4216
|
+
const viewSchema2 = createTileflowRuntimeViewSchema(operations);
|
|
4217
|
+
const fontFaceSchema = operations.object({
|
|
4218
|
+
family: operations.maxLength(safeTextSchema, 100),
|
|
4219
|
+
source: publicResourceUrlSchema,
|
|
4220
|
+
style: operations.optional(operations.enum(["italic", "normal", "oblique"])),
|
|
4221
|
+
weight: operations.optional(
|
|
4222
|
+
operations.enum(["100", "200", "300", "400", "500", "600", "700", "800", "900"])
|
|
4223
|
+
)
|
|
4224
|
+
});
|
|
4225
|
+
const fontFacesSchema = operations.superRefine(
|
|
4226
|
+
operations.maxLength(operations.array(fontFaceSchema), 16),
|
|
4227
|
+
validateUniqueFontFaces
|
|
4228
|
+
);
|
|
4229
|
+
const manifestThemeSchema = operations.object({
|
|
4230
|
+
colorScheme: operations.enum(["dark", "light"]),
|
|
4231
|
+
fontFaces: operations.optional(fontFacesSchema),
|
|
4232
|
+
revision: operations.optional(operations.maxLength(safeTextSchema, 128)),
|
|
4233
|
+
styleId: operations.optional(operations.maxLength(safeTextSchema, 128)),
|
|
4234
|
+
styleUrl: publicResourceUrlSchema
|
|
4235
|
+
});
|
|
4236
|
+
const manifestMapSchema = operations.superRefine(
|
|
4237
|
+
operations.object({
|
|
4238
|
+
apiUrl: operations.optional(apiOriginSchema),
|
|
4239
|
+
defaultTheme: tileflowThemeNameSchema,
|
|
4240
|
+
environment: operations.optional(operations.maxLength(safeTextSchema, 128)),
|
|
4241
|
+
mapId: operations.optional(operations.maxLength(safeTextSchema, 128)),
|
|
4242
|
+
systemThemes: operations.optional(
|
|
4243
|
+
operations.object({
|
|
4244
|
+
dark: tileflowThemeNameSchema,
|
|
4245
|
+
light: tileflowThemeNameSchema
|
|
4246
|
+
})
|
|
4247
|
+
),
|
|
4248
|
+
themes: operations.record(tileflowThemeNameSchema, manifestThemeSchema),
|
|
4249
|
+
usageMode: operations.optional(operations.literal("session")),
|
|
4250
|
+
view: operations.optional(viewSchema2),
|
|
4251
|
+
worldGeneration: operations.optional(operations.literal("v1"))
|
|
4252
|
+
}),
|
|
4253
|
+
(entry, context) => {
|
|
4254
|
+
const names = Object.keys(entry.themes);
|
|
4255
|
+
if (names.length === 0) {
|
|
4256
|
+
context.addIssue({
|
|
4257
|
+
code: "custom",
|
|
4258
|
+
message: "Expected at least one theme",
|
|
4259
|
+
path: ["themes"]
|
|
4260
|
+
});
|
|
4261
|
+
}
|
|
4262
|
+
if (names.length > tileflowThemeLimits.maxThemes) {
|
|
4263
|
+
context.addIssue({
|
|
4264
|
+
code: "too_big",
|
|
4265
|
+
maximum: tileflowThemeLimits.maxThemes,
|
|
4266
|
+
origin: "object",
|
|
4267
|
+
path: ["themes"]
|
|
4268
|
+
});
|
|
4269
|
+
}
|
|
4270
|
+
if (!Object.hasOwn(entry.themes, entry.defaultTheme)) {
|
|
4271
|
+
context.addIssue({
|
|
4272
|
+
code: "custom",
|
|
4273
|
+
message: "defaultTheme must name a declared theme",
|
|
4274
|
+
path: ["defaultTheme"]
|
|
4275
|
+
});
|
|
4276
|
+
}
|
|
4277
|
+
if (entry.systemThemes) {
|
|
4278
|
+
for (const colorScheme of ["light", "dark"]) {
|
|
4279
|
+
const name = entry.systemThemes[colorScheme];
|
|
4280
|
+
const theme = entry.themes[name];
|
|
4281
|
+
if (!theme) {
|
|
4282
|
+
context.addIssue({
|
|
4283
|
+
code: "custom",
|
|
4284
|
+
message: `systemThemes.${colorScheme} must name a declared theme`,
|
|
4285
|
+
path: ["systemThemes", colorScheme]
|
|
4286
|
+
});
|
|
4287
|
+
} else if (theme.colorScheme !== colorScheme) {
|
|
4288
|
+
context.addIssue({
|
|
4289
|
+
code: "custom",
|
|
4290
|
+
message: `systemThemes.${colorScheme} must reference a ${colorScheme} theme`,
|
|
4291
|
+
path: ["systemThemes", colorScheme]
|
|
4292
|
+
});
|
|
4293
|
+
}
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
if (entry.usageMode === void 0 !== (entry.worldGeneration === void 0)) {
|
|
4297
|
+
context.addIssue({
|
|
4298
|
+
code: "custom",
|
|
4299
|
+
message: "usageMode and worldGeneration must be declared together"
|
|
4300
|
+
});
|
|
4277
4301
|
}
|
|
4278
4302
|
}
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
}
|
|
4303
|
+
);
|
|
4304
|
+
const canonicalManifestSchema = operations.superRefine(
|
|
4305
|
+
operations.object({
|
|
4306
|
+
apiUrl: operations.optional(apiOriginSchema),
|
|
4307
|
+
maps: operations.record(tileflowPortableIdSchema, manifestMapSchema),
|
|
4308
|
+
version: operations.literal(tileflowRuntimeManifestVersion)
|
|
4309
|
+
}),
|
|
4310
|
+
(manifest, context) => {
|
|
4311
|
+
const mapCount = Object.keys(manifest.maps).length;
|
|
4312
|
+
if (mapCount === 0) {
|
|
4313
|
+
context.addIssue({ code: "custom", message: "Expected at least one map", path: ["maps"] });
|
|
4314
|
+
}
|
|
4315
|
+
if (mapCount > 1e3) {
|
|
4316
|
+
context.addIssue({ code: "too_big", maximum: 1e3, origin: "object", path: ["maps"] });
|
|
4317
|
+
}
|
|
4318
|
+
if (primitives.utf8ByteLength(JSON.stringify(manifest)) > tileflowRuntimeManifestLimits.maximumBytes) {
|
|
4319
|
+
context.addIssue({
|
|
4320
|
+
code: "too_big",
|
|
4321
|
+
maximum: tileflowRuntimeManifestLimits.maximumBytes,
|
|
4322
|
+
origin: "string",
|
|
4323
|
+
message: "Manifest JSON exceeds the 1 MiB limit"
|
|
4324
|
+
});
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4327
|
+
);
|
|
4328
|
+
const safeManifestInputSchema = operations.superRefine(operations.unknown(), (input, context) => {
|
|
4329
|
+
const unsafe = findUnsafeManifestStructure(input);
|
|
4330
|
+
if (unsafe) {
|
|
4331
|
+
context.addIssue({
|
|
4332
|
+
code: "custom",
|
|
4333
|
+
message: unsafe.reason === "prototype" ? "Expected plain manifest objects" : "Expected no prototype-mutating keys",
|
|
4334
|
+
path: unsafe.path
|
|
4335
|
+
});
|
|
4336
|
+
}
|
|
4337
|
+
});
|
|
4338
|
+
function validateUniqueFontFaces(fontFaces, context) {
|
|
4339
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4340
|
+
for (const [index, fontFace] of fontFaces.entries()) {
|
|
4341
|
+
const identity = `${fontFace.family}\0${fontFace.style ?? "normal"}\0${fontFace.weight ?? "400"}`;
|
|
4342
|
+
const first = seen.get(identity);
|
|
4343
|
+
if (first !== void 0) {
|
|
4344
|
+
context.addIssue({
|
|
4345
|
+
code: "custom",
|
|
4346
|
+
message: `Duplicate font face identity; first declared at index ${first}`,
|
|
4347
|
+
path: [index]
|
|
4348
|
+
});
|
|
4349
|
+
continue;
|
|
4302
4350
|
}
|
|
4351
|
+
seen.set(identity, index);
|
|
4303
4352
|
}
|
|
4304
4353
|
}
|
|
4305
|
-
|
|
4306
|
-
if (
|
|
4354
|
+
function isPublicResourceUrl(value) {
|
|
4355
|
+
if (value.startsWith("//")) return false;
|
|
4356
|
+
if (!value.startsWith("/") && !value.startsWith("./") && !value.startsWith("../") && !isAbsolutePublicUrl(value)) {
|
|
4357
|
+
return false;
|
|
4358
|
+
}
|
|
4359
|
+
return isSafeResolvedPublicUrl(value);
|
|
4307
4360
|
}
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
return ()
|
|
4361
|
+
function isAbsolutePublicUrl(value) {
|
|
4362
|
+
try {
|
|
4363
|
+
const url = primitives.parseUrl(value);
|
|
4364
|
+
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
|
|
4365
|
+
} catch {
|
|
4366
|
+
return false;
|
|
4312
4367
|
}
|
|
4313
|
-
this.listeners.add(listener);
|
|
4314
|
-
return () => {
|
|
4315
|
-
this.listeners.delete(listener);
|
|
4316
|
-
};
|
|
4317
4368
|
}
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
const
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
off();
|
|
4326
|
-
resolve(value);
|
|
4327
|
-
},
|
|
4328
|
-
(error2) => {
|
|
4329
|
-
off();
|
|
4330
|
-
reject(error2);
|
|
4331
|
-
}
|
|
4332
|
-
);
|
|
4333
|
-
});
|
|
4369
|
+
function isSafeResolvedPublicUrl(value) {
|
|
4370
|
+
try {
|
|
4371
|
+
const url = primitives.parseUrl(value, "https://manifest.invalid/owner/manifest.json");
|
|
4372
|
+
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password && !url.hash && !hasEncodedPathSeparator(value);
|
|
4373
|
+
} catch {
|
|
4374
|
+
return false;
|
|
4375
|
+
}
|
|
4334
4376
|
}
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4377
|
+
function hasEncodedPathSeparator(value) {
|
|
4378
|
+
return /%(?:2f|5c)/iu.test(value);
|
|
4379
|
+
}
|
|
4380
|
+
function isApiOrigin(value) {
|
|
4338
4381
|
try {
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
onAbort = () => this.cancel();
|
|
4342
|
-
if (signal.aborted) {
|
|
4343
|
-
this.cancel();
|
|
4344
|
-
return () => void 0;
|
|
4345
|
-
}
|
|
4346
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
4347
|
-
if (signal.aborted) this.cancel();
|
|
4382
|
+
const url = primitives.parseUrl(value);
|
|
4383
|
+
return isAbsolutePublicUrl(value) && url.pathname === "/" && !url.search && value.replace(/\/$/u, "") === url.origin;
|
|
4348
4384
|
} catch {
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4385
|
+
return false;
|
|
4386
|
+
}
|
|
4387
|
+
}
|
|
4388
|
+
function findUnsafeManifestStructure(input) {
|
|
4389
|
+
if (!input || typeof input !== "object") return void 0;
|
|
4390
|
+
const pending = [
|
|
4391
|
+
{ path: [], value: input }
|
|
4392
|
+
];
|
|
4393
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
4394
|
+
while (pending.length > 0) {
|
|
4395
|
+
const current = pending.pop();
|
|
4396
|
+
if (visited.has(current.value)) continue;
|
|
4397
|
+
visited.add(current.value);
|
|
4398
|
+
if (!Array.isArray(current.value)) {
|
|
4399
|
+
const prototype = Object.getPrototypeOf(current.value);
|
|
4400
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
4401
|
+
return { path: current.path, reason: "prototype" };
|
|
4353
4402
|
}
|
|
4354
4403
|
}
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4404
|
+
for (const key of Object.keys(current.value)) {
|
|
4405
|
+
const path = [...current.path, Array.isArray(current.value) ? Number(key) : key];
|
|
4406
|
+
if (key === "__proto__") return { path, reason: "key" };
|
|
4407
|
+
const descriptor = Object.getOwnPropertyDescriptor(current.value, key);
|
|
4408
|
+
if (descriptor && "value" in descriptor && descriptor.value && typeof descriptor.value === "object") {
|
|
4409
|
+
pending.push({ path, value: descriptor.value });
|
|
4410
|
+
}
|
|
4361
4411
|
}
|
|
4362
|
-
};
|
|
4363
|
-
}
|
|
4364
|
-
};
|
|
4365
|
-
function cancelNativeOperation(cancel) {
|
|
4366
|
-
try {
|
|
4367
|
-
void Promise.resolve(cancel()).catch(() => void 0);
|
|
4368
|
-
} catch {
|
|
4369
|
-
}
|
|
4370
|
-
}
|
|
4371
|
-
|
|
4372
|
-
// src/native-source-utils.ts
|
|
4373
|
-
function nativeOwnRecord(value) {
|
|
4374
|
-
try {
|
|
4375
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
4376
|
-
const prototype = Object.getPrototypeOf(value);
|
|
4377
|
-
if (prototype !== null && prototype !== Object.prototype) return void 0;
|
|
4378
|
-
const result = /* @__PURE__ */ Object.create(null);
|
|
4379
|
-
for (const key of Object.keys(value)) {
|
|
4380
|
-
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
4381
|
-
if (!property || !("value" in property)) return void 0;
|
|
4382
|
-
result[key] = property.value;
|
|
4383
4412
|
}
|
|
4384
|
-
return result;
|
|
4385
|
-
} catch {
|
|
4386
4413
|
return void 0;
|
|
4387
4414
|
}
|
|
4415
|
+
return operations.pipe(safeManifestInputSchema, canonicalManifestSchema);
|
|
4388
4416
|
}
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4417
|
+
var init_manifest_schema = __esm({
|
|
4418
|
+
"src/manifest-schema.ts"() {
|
|
4419
|
+
"use strict";
|
|
4420
|
+
init_manifest_types();
|
|
4421
|
+
init_portable_identity_schema();
|
|
4422
|
+
init_runtime_view_schema();
|
|
4423
|
+
init_model();
|
|
4393
4424
|
}
|
|
4394
|
-
return value;
|
|
4395
|
-
}
|
|
4396
|
-
|
|
4397
|
-
// src/native-manifest.ts
|
|
4398
|
-
var tileflowNativeManifestLimits = Object.freeze({
|
|
4399
|
-
maximumBytes: tileflowRuntimeManifestLimits.maximumBytes,
|
|
4400
|
-
maximumChunkBytes: 64 * 1024,
|
|
4401
|
-
maximumDepth: 64
|
|
4402
4425
|
});
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
);
|
|
4418
|
-
|
|
4419
|
-
|
|
4426
|
+
|
|
4427
|
+
// src/native-url-policy.ts
|
|
4428
|
+
var tileflowNativeUrlLimits = Object.freeze({ maximumLength: 2048 });
|
|
4429
|
+
var errorMessages = {
|
|
4430
|
+
NATIVE_URL_INVALID: "Expected a bounded HTTP(S) URL without credentials, fragments or backslashes.",
|
|
4431
|
+
NATIVE_URL_ABSOLUTE_REQUIRED: "An explicit absolute HTTP(S) document URL is required.",
|
|
4432
|
+
NATIVE_URL_HTTPS_REQUIRED: "HTTP is allowed only at the explicitly configured development origin.",
|
|
4433
|
+
NATIVE_URL_DEVELOPMENT_ORIGIN_INVALID: "Expected one HTTP origin without a path, credentials, query or fragment.",
|
|
4434
|
+
NATIVE_URL_TEMPLATE_INVALID: "Expected supported URL placeholders in the resource path or query only."
|
|
4435
|
+
};
|
|
4436
|
+
var TileflowNativeUrlError = class extends TypeError {
|
|
4437
|
+
constructor(code, field) {
|
|
4438
|
+
super(errorMessages[code]);
|
|
4439
|
+
__publicField(this, "code");
|
|
4440
|
+
__publicField(this, "field");
|
|
4441
|
+
this.name = "TileflowNativeUrlError";
|
|
4442
|
+
this.code = code;
|
|
4443
|
+
this.field = field;
|
|
4420
4444
|
}
|
|
4421
|
-
}
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4445
|
+
};
|
|
4446
|
+
function createNativeUrlPolicy(parse2) {
|
|
4447
|
+
const tilePlaceholders = /* @__PURE__ */ new Set(["z", "x", "y", "ratio", "quadkey", "bbox-epsg-3857", "prefix"]);
|
|
4448
|
+
const glyphPlaceholders = /* @__PURE__ */ new Set(["fontstack", "range"]);
|
|
4449
|
+
const absoluteHttpPattern = /^https?:\/\/[^/?#]+/iu;
|
|
4450
|
+
const schemePattern = /^[a-z][a-z\d+.-]*:/iu;
|
|
4451
|
+
function resolveTileflowNativeManifestUrl2(value, options = {}) {
|
|
4452
|
+
assertOptionsObject(options, "developmentOrigin");
|
|
4453
|
+
const developmentOrigin = resolveDevelopmentOrigin(options.developmentOrigin);
|
|
4454
|
+
return resolveDocumentUrl(value, "manifestUrl", developmentOrigin).href;
|
|
4429
4455
|
}
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
)
|
|
4436
|
-
|
|
4437
|
-
throw new Error();
|
|
4456
|
+
function resolveTileflowNativeResourceUrl2(value, options) {
|
|
4457
|
+
assertOptionsObject(options, "documentUrl");
|
|
4458
|
+
const developmentOrigin = resolveDevelopmentOrigin(options.developmentOrigin);
|
|
4459
|
+
const document2 = resolveDocumentUrl(options.documentUrl, "documentUrl", developmentOrigin);
|
|
4460
|
+
assertUrlText(value, "resourceUrl");
|
|
4461
|
+
if (options.template !== void 0 && options.template !== "tile" && options.template !== "glyphs") {
|
|
4462
|
+
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
4438
4463
|
}
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
let reader;
|
|
4444
|
-
let readerCancelled = false;
|
|
4445
|
-
let operationCancelled = false;
|
|
4446
|
-
const cancelReader = () => {
|
|
4447
|
-
if (!reader || readerCancelled) return;
|
|
4448
|
-
readerCancelled = true;
|
|
4449
|
-
cancelNativeOperation(() => reader.cancel());
|
|
4450
|
-
};
|
|
4451
|
-
const cleanup = () => {
|
|
4452
|
-
if (!operationCancelled) {
|
|
4453
|
-
operationCancelled = true;
|
|
4454
|
-
cancelNativeOperation(() => operation.cancel());
|
|
4464
|
+
assertReferenceSyntax(value, "resourceUrl", false);
|
|
4465
|
+
const authority = absoluteHttpPattern.exec(value)?.[0];
|
|
4466
|
+
if (authority && /[{}]/u.test(authority)) {
|
|
4467
|
+
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
4455
4468
|
}
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
const headers = Promise.resolve(operation.response).then(
|
|
4461
|
-
(response2) => {
|
|
4462
|
-
try {
|
|
4463
|
-
if (!response2 || !response2.reader || typeof response2.reader.read !== "function" || typeof response2.reader.cancel !== "function") {
|
|
4464
|
-
throw new Error();
|
|
4465
|
-
}
|
|
4466
|
-
reader = response2.reader;
|
|
4467
|
-
} catch {
|
|
4468
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4469
|
-
}
|
|
4470
|
-
if (cancellation.aborted) cancelReader();
|
|
4471
|
-
cancellation.check();
|
|
4472
|
-
return response2;
|
|
4473
|
-
},
|
|
4474
|
-
() => {
|
|
4475
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
4476
|
-
}
|
|
4477
|
-
);
|
|
4478
|
-
const response = await cancellation.race(headers);
|
|
4479
|
-
cancellation.check();
|
|
4480
|
-
let finalUrl;
|
|
4481
|
-
try {
|
|
4482
|
-
finalUrl = resolveTileflowNativeManifestUrl(response.url, network);
|
|
4483
|
-
} catch {
|
|
4484
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_URL_INVALID", "manifestUrl");
|
|
4469
|
+
let prefix = "__tileflow_native_template_";
|
|
4470
|
+
let attempt = 0;
|
|
4471
|
+
while (value.includes(prefix) || document2.href.includes(prefix)) {
|
|
4472
|
+
prefix = `__tileflow_native_template_${attempt++}_`;
|
|
4485
4473
|
}
|
|
4486
|
-
|
|
4487
|
-
|
|
4474
|
+
const placeholders = [];
|
|
4475
|
+
const allowed = options.template === "tile" ? tilePlaceholders : glyphPlaceholders;
|
|
4476
|
+
const protectedValue = value.replace(/\{([^{}]*)\}/gu, (placeholder, name) => {
|
|
4477
|
+
if (!options.template || !allowed.has(name)) {
|
|
4478
|
+
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
4479
|
+
}
|
|
4480
|
+
placeholders.push(placeholder);
|
|
4481
|
+
return `${prefix}${placeholders.length - 1}__`;
|
|
4482
|
+
});
|
|
4483
|
+
if (/[{}]/u.test(protectedValue)) {
|
|
4484
|
+
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", "resourceUrl");
|
|
4488
4485
|
}
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4486
|
+
const resolved = parseUrl(protectedValue, "resourceUrl", document2.href);
|
|
4487
|
+
assertTransport(resolved, "resourceUrl", developmentOrigin);
|
|
4488
|
+
const resourcePath = resolved.href.slice(resolved.origin.length);
|
|
4489
|
+
const suffix = resourcePath.replace(
|
|
4490
|
+
new RegExp(`${prefix}(\\d+)__`, "gu"),
|
|
4491
|
+
(match, index) => placeholders[Number(index)] ?? match
|
|
4492
|
+
);
|
|
4493
|
+
const result = resolved.origin + suffix;
|
|
4494
|
+
assertUrlText(result, "resourceUrl");
|
|
4495
|
+
return result;
|
|
4496
|
+
}
|
|
4497
|
+
function assertOptionsObject(value, field) {
|
|
4498
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4499
|
+
throw new TileflowNativeUrlError(
|
|
4500
|
+
field === "documentUrl" ? "NATIVE_URL_INVALID" : "NATIVE_URL_DEVELOPMENT_ORIGIN_INVALID",
|
|
4501
|
+
field
|
|
4502
4502
|
);
|
|
4503
|
-
let next;
|
|
4504
|
-
try {
|
|
4505
|
-
const pending = Promise.resolve(reader.read(allowance)).catch(() => {
|
|
4506
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
4507
|
-
});
|
|
4508
|
-
next = await cancellation.race(pending);
|
|
4509
|
-
} catch {
|
|
4510
|
-
cancellation.check();
|
|
4511
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
4512
|
-
}
|
|
4513
|
-
cancellation.check();
|
|
4514
|
-
if (!next || typeof next.done !== "boolean")
|
|
4515
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4516
|
-
if (next.done) {
|
|
4517
|
-
if (next.value !== void 0)
|
|
4518
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4519
|
-
break;
|
|
4520
|
-
}
|
|
4521
|
-
if (!(next.value instanceof Uint8Array) || next.value.byteLength === 0)
|
|
4522
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4523
|
-
if (next.value.byteLength > buffer.byteLength - length)
|
|
4524
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_TOO_LARGE", "body");
|
|
4525
|
-
if (next.value.byteLength > allowance)
|
|
4526
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4527
|
-
buffer.set(next.value, length);
|
|
4528
|
-
length += next.value.byteLength;
|
|
4529
4503
|
}
|
|
4530
|
-
|
|
4504
|
+
}
|
|
4505
|
+
function resolveDevelopmentOrigin(value) {
|
|
4506
|
+
if (value === void 0) return void 0;
|
|
4531
4507
|
try {
|
|
4532
|
-
|
|
4508
|
+
assertUrlText(value, "developmentOrigin");
|
|
4509
|
+
const match = /^(http:\/\/[^/?#]+)\/?$/iu.exec(value);
|
|
4510
|
+
if (!match || /[{}@*]/u.test(value)) throw new Error();
|
|
4511
|
+
const url = parseUrl(value, "developmentOrigin");
|
|
4512
|
+
if (url.protocol !== "http:" || url.pathname !== "/" || url.search || url.hash || url.hostname.includes("*")) {
|
|
4513
|
+
throw new Error();
|
|
4514
|
+
}
|
|
4515
|
+
return url.origin;
|
|
4533
4516
|
} catch {
|
|
4534
|
-
throw new
|
|
4517
|
+
throw new TileflowNativeUrlError(
|
|
4518
|
+
"NATIVE_URL_DEVELOPMENT_ORIGIN_INVALID",
|
|
4519
|
+
"developmentOrigin"
|
|
4520
|
+
);
|
|
4535
4521
|
}
|
|
4536
|
-
|
|
4537
|
-
|
|
4522
|
+
}
|
|
4523
|
+
function resolveDocumentUrl(value, field, developmentOrigin) {
|
|
4524
|
+
assertUrlText(value, field);
|
|
4525
|
+
assertReferenceSyntax(value, field, true);
|
|
4526
|
+
if (/[{}]/u.test(value)) throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", field);
|
|
4527
|
+
const url = parseUrl(value, field);
|
|
4528
|
+
assertTransport(url, field, developmentOrigin);
|
|
4529
|
+
assertUrlText(url.href, field);
|
|
4530
|
+
return url;
|
|
4531
|
+
}
|
|
4532
|
+
function assertUrlText(value, field) {
|
|
4533
|
+
if (typeof value !== "string" || value.length === 0 || value.length > tileflowNativeUrlLimits.maximumLength || value !== value.trim() || /[\p{Cc}\\#]/u.test(value) || /%(?![\da-f]{2})/iu.test(value)) {
|
|
4534
|
+
throw new TileflowNativeUrlError("NATIVE_URL_INVALID", field);
|
|
4538
4535
|
}
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4536
|
+
}
|
|
4537
|
+
function assertReferenceSyntax(value, field, absolute) {
|
|
4538
|
+
if (value.startsWith("//")) {
|
|
4539
|
+
throw new TileflowNativeUrlError(
|
|
4540
|
+
absolute ? "NATIVE_URL_ABSOLUTE_REQUIRED" : "NATIVE_URL_INVALID",
|
|
4541
|
+
field
|
|
4542
|
+
);
|
|
4544
4543
|
}
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
} catch {
|
|
4549
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_INVALID", "body");
|
|
4544
|
+
const authority = absoluteHttpPattern.exec(value)?.[0];
|
|
4545
|
+
if (schemePattern.test(value) && !authority) {
|
|
4546
|
+
throw new TileflowNativeUrlError("NATIVE_URL_INVALID", field);
|
|
4550
4547
|
}
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
const resolved = resolveTileflowNativeResourceUrl(value, { documentUrl: owner, ...network });
|
|
4554
|
-
resolvedBytes += nativeManifestUtf8ByteLength(JSON.stringify(resolved)) - nativeManifestUtf8ByteLength(JSON.stringify(value));
|
|
4555
|
-
if (resolvedBytes > tileflowNativeManifestLimits.maximumBytes) {
|
|
4556
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_TOO_LARGE", "body");
|
|
4557
|
-
}
|
|
4558
|
-
return resolved;
|
|
4559
|
-
};
|
|
4560
|
-
try {
|
|
4561
|
-
for (const name of Object.keys(manifest.maps).sort()) {
|
|
4562
|
-
const map2 = manifest.maps[name];
|
|
4563
|
-
for (const themeName of Object.keys(map2.themes).sort()) {
|
|
4564
|
-
const theme = map2.themes[themeName];
|
|
4565
|
-
theme.styleUrl = resolveResource(theme.styleUrl, finalUrl);
|
|
4566
|
-
for (const face of theme.fontFaces ?? []) {
|
|
4567
|
-
face.source = resolveResource(face.source, theme.styleUrl);
|
|
4568
|
-
}
|
|
4569
|
-
}
|
|
4570
|
-
}
|
|
4571
|
-
} catch (error2) {
|
|
4572
|
-
if (error2 instanceof TileflowNativeSourceError) throw normalizeNativeSourceError(error2);
|
|
4573
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESOURCE_INVALID", "body");
|
|
4548
|
+
if (absolute && !authority) {
|
|
4549
|
+
throw new TileflowNativeUrlError("NATIVE_URL_ABSOLUTE_REQUIRED", field);
|
|
4574
4550
|
}
|
|
4575
|
-
|
|
4576
|
-
return freezeNativeSnapshot({ manifestUrl: finalUrl, manifest });
|
|
4577
|
-
} catch (error2) {
|
|
4578
|
-
cleanup();
|
|
4579
|
-
cancellation.check();
|
|
4580
|
-
throw normalizeNativeSourceError(error2);
|
|
4581
|
-
} finally {
|
|
4582
|
-
unlisten();
|
|
4551
|
+
if (authority?.includes("@")) throw new TileflowNativeUrlError("NATIVE_URL_INVALID", field);
|
|
4583
4552
|
}
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
var defaultTileflowRuntimeView = Object.freeze({
|
|
4592
|
-
bearing: 0,
|
|
4593
|
-
center: [0, 20],
|
|
4594
|
-
pitch: 0,
|
|
4595
|
-
zoom: 2
|
|
4596
|
-
});
|
|
4597
|
-
var tileflowStyleFontFaceLimits = Object.freeze({
|
|
4598
|
-
maximumCount: 16,
|
|
4599
|
-
maximumSourceLength: 2048
|
|
4600
|
-
});
|
|
4601
|
-
var maxStaticImagePixels = 1280 * 1280;
|
|
4602
|
-
var maximumManifestBytes = 1024 * 1024;
|
|
4603
|
-
var maximumSessionGrantBytes = 64 * 1024;
|
|
4604
|
-
var manifestCache = new globalThis.Map();
|
|
4605
|
-
function validateTileflowThemeSelection(value) {
|
|
4606
|
-
return value === "system" || isTileflowThemeName(value);
|
|
4607
|
-
}
|
|
4608
|
-
var tileflowThemeBlendLimits = Object.freeze({ maximumThemes: 8, minimumThemes: 2 });
|
|
4609
|
-
function validateTileflowThemeBlendSelection(value) {
|
|
4610
|
-
if (!value || typeof value !== "object") return false;
|
|
4611
|
-
const { position, themes } = value;
|
|
4612
|
-
return Array.isArray(themes) && themes.length >= tileflowThemeBlendLimits.minimumThemes && themes.length <= tileflowThemeBlendLimits.maximumThemes && themes.every((theme) => isTileflowThemeName(theme)) && typeof position === "number" && Number.isFinite(position) && position >= 0 && position <= themes.length - 1;
|
|
4613
|
-
}
|
|
4614
|
-
function nearestTileflowBlendTheme(blend) {
|
|
4615
|
-
const index = Math.min(blend.themes.length - 1, Math.max(0, Math.round(blend.position)));
|
|
4616
|
-
return blend.themes[index];
|
|
4617
|
-
}
|
|
4618
|
-
function resolveTileflowRuntimeTheme(map2, selection, colorScheme) {
|
|
4619
|
-
let name;
|
|
4620
|
-
if (selection === void 0) {
|
|
4621
|
-
name = map2.defaultTheme;
|
|
4622
|
-
} else if (selection === "system") {
|
|
4623
|
-
if (!map2.systemThemes) {
|
|
4624
|
-
throw new Error(
|
|
4625
|
-
`Tileflow map "${map2.name}" does not declare systemThemes; select a concrete theme.`
|
|
4626
|
-
);
|
|
4553
|
+
function parseUrl(value, field, base2) {
|
|
4554
|
+
let url;
|
|
4555
|
+
try {
|
|
4556
|
+
url = parse2(value, base2);
|
|
4557
|
+
if (!url.hostname || url.username || url.password || url.hash) throw new Error();
|
|
4558
|
+
} catch {
|
|
4559
|
+
throw new TileflowNativeUrlError("NATIVE_URL_INVALID", field);
|
|
4627
4560
|
}
|
|
4628
|
-
if (
|
|
4629
|
-
throw new
|
|
4561
|
+
if (/[{}]/u.test(url.hostname)) {
|
|
4562
|
+
throw new TileflowNativeUrlError("NATIVE_URL_TEMPLATE_INVALID", field);
|
|
4630
4563
|
}
|
|
4631
|
-
|
|
4632
|
-
} else {
|
|
4633
|
-
name = selection;
|
|
4634
|
-
}
|
|
4635
|
-
if (!isTileflowThemeName(name)) {
|
|
4636
|
-
throw new Error(
|
|
4637
|
-
`Tileflow resolved invalid theme ${JSON.stringify(name)} for map "${map2.name}"; expected a concrete portable theme name.`
|
|
4638
|
-
);
|
|
4564
|
+
return url;
|
|
4639
4565
|
}
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
throw new
|
|
4644
|
-
`Unknown Tileflow theme "${name}" for map "${map2.name}". Available themes: ${available}.`
|
|
4645
|
-
);
|
|
4566
|
+
function assertTransport(url, field, developmentOrigin) {
|
|
4567
|
+
if (url.protocol === "https:") return;
|
|
4568
|
+
if (url.protocol === "http:" && url.origin === developmentOrigin) return;
|
|
4569
|
+
throw new TileflowNativeUrlError("NATIVE_URL_HTTPS_REQUIRED", field);
|
|
4646
4570
|
}
|
|
4647
|
-
return {
|
|
4571
|
+
return { resolveTileflowNativeManifestUrl: resolveTileflowNativeManifestUrl2, resolveTileflowNativeResourceUrl: resolveTileflowNativeResourceUrl2 };
|
|
4648
4572
|
}
|
|
4649
|
-
|
|
4650
|
-
|
|
4573
|
+
|
|
4574
|
+
// src/native-url-provider.ts
|
|
4575
|
+
var import_url_state_machine = __toESM(require_url_state_machine(), 1);
|
|
4576
|
+
function parseNativeUrl(value, base2) {
|
|
4577
|
+
const baseURL = base2 === void 0 ? void 0 : (0, import_url_state_machine.basicURLParse)(base2);
|
|
4578
|
+
if (baseURL === null) throw new TypeError("Invalid native URL.");
|
|
4579
|
+
const parsed = (0, import_url_state_machine.basicURLParse)(value, baseURL === void 0 ? void 0 : { baseURL });
|
|
4580
|
+
if (parsed === null) throw new TypeError("Invalid native URL.");
|
|
4651
4581
|
return {
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4582
|
+
href: (0, import_url_state_machine.serializeURL)(parsed),
|
|
4583
|
+
origin: (0, import_url_state_machine.serializeURLOrigin)(parsed),
|
|
4584
|
+
protocol: `${parsed.scheme}:`,
|
|
4585
|
+
hostname: parsed.host === null ? "" : (0, import_url_state_machine.serializeHost)(parsed.host),
|
|
4586
|
+
pathname: (0, import_url_state_machine.serializePath)(parsed),
|
|
4587
|
+
search: parsed.query ? `?${parsed.query}` : "",
|
|
4588
|
+
hash: parsed.fragment ? `#${parsed.fragment}` : "",
|
|
4589
|
+
username: parsed.username,
|
|
4590
|
+
password: parsed.password
|
|
4658
4591
|
};
|
|
4659
4592
|
}
|
|
4660
4593
|
|
|
4661
|
-
// src/native-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
let state;
|
|
4669
|
-
let generation = 0;
|
|
4670
|
-
let disposed = false;
|
|
4671
|
-
let active;
|
|
4672
|
-
const notify = (listener, value) => {
|
|
4673
|
-
try {
|
|
4674
|
-
void Promise.resolve(listener(value)).catch(() => void 0);
|
|
4675
|
-
} catch {
|
|
4676
|
-
}
|
|
4677
|
-
};
|
|
4678
|
-
const publish = (next) => {
|
|
4679
|
-
if (disposed || next.generation !== generation) return;
|
|
4680
|
-
state = freezeNativeSnapshot(next);
|
|
4681
|
-
for (const listener of [...listeners]) {
|
|
4682
|
-
if (disposed || state !== next || generation !== next.generation) break;
|
|
4683
|
-
if (listeners.has(listener)) notify(listener, next);
|
|
4684
|
-
}
|
|
4685
|
-
};
|
|
4686
|
-
return {
|
|
4687
|
-
get state() {
|
|
4688
|
-
return state;
|
|
4689
|
-
},
|
|
4690
|
-
subscribe(listener) {
|
|
4691
|
-
if (typeof listener !== "function")
|
|
4692
|
-
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
4693
|
-
if (disposed) return () => void 0;
|
|
4694
|
-
listeners.add(listener);
|
|
4695
|
-
if (state) notify(listener, state);
|
|
4696
|
-
return () => {
|
|
4697
|
-
listeners.delete(listener);
|
|
4698
|
-
};
|
|
4699
|
-
},
|
|
4700
|
-
async replace(source, options2 = {}) {
|
|
4701
|
-
if (disposed) throw new TileflowNativeSourceError("NATIVE_SOURCE_DISPOSED", "source");
|
|
4702
|
-
if (generation >= Number.MAX_SAFE_INTEGER)
|
|
4703
|
-
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
4704
|
-
const own = { generation: ++generation, cancellation: new NativeSourceCancellation() };
|
|
4705
|
-
const previous = active;
|
|
4706
|
-
active = own;
|
|
4707
|
-
const current = () => !disposed && generation === own.generation;
|
|
4708
|
-
let sourceInput;
|
|
4709
|
-
let selection;
|
|
4710
|
-
let snapshotError;
|
|
4711
|
-
try {
|
|
4712
|
-
sourceInput = nativeOwnRecord(source);
|
|
4713
|
-
selection = nativeOwnRecord(options2);
|
|
4714
|
-
} catch (error2) {
|
|
4715
|
-
snapshotError = normalizeNativeSourceError(error2);
|
|
4716
|
-
}
|
|
4717
|
-
previous?.cancellation.cancel();
|
|
4718
|
-
let detach = () => void 0;
|
|
4719
|
-
try {
|
|
4720
|
-
if (!current()) return;
|
|
4721
|
-
publish({ status: "loading", generation: own.generation });
|
|
4722
|
-
if (!current()) return;
|
|
4723
|
-
if (snapshotError) throw snapshotError;
|
|
4724
|
-
if (!sourceInput || !selection || Object.hasOwn(sourceInput, "kind") || Object.hasOwn(sourceInput, "style") || !isTileflowPortableId(sourceInput.map))
|
|
4725
|
-
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
4726
|
-
if (selection.theme !== void 0 && !validateTileflowThemeSelection(selection.theme) || selection.colorScheme !== void 0 && selection.colorScheme !== "light" && selection.colorScheme !== "dark") {
|
|
4727
|
-
throw new TileflowNativeSourceError("NATIVE_THEME_INVALID", "theme");
|
|
4728
|
-
}
|
|
4729
|
-
const selectedSource = {
|
|
4730
|
-
map: sourceInput.map,
|
|
4731
|
-
manifestUrl: sourceInput.manifestUrl
|
|
4732
|
-
};
|
|
4733
|
-
if (sourceInput.developmentOrigin !== void 0) {
|
|
4734
|
-
try {
|
|
4735
|
-
const developmentOrigin = sourceInput.developmentOrigin;
|
|
4736
|
-
selectedSource.developmentOrigin = resolveTileflowNativeManifestUrl(developmentOrigin, {
|
|
4737
|
-
developmentOrigin
|
|
4738
|
-
}).slice(0, -1);
|
|
4739
|
-
} catch {
|
|
4740
|
-
throw new TileflowNativeSourceError("NATIVE_MANIFEST_URL_INVALID", "manifestUrl");
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
detach = own.cancellation.link(selection.signal);
|
|
4744
|
-
const result = await loadNativeManifest(
|
|
4745
|
-
selectedSource.manifestUrl,
|
|
4746
|
-
acquire,
|
|
4747
|
-
{
|
|
4748
|
-
developmentOrigin: selectedSource.developmentOrigin
|
|
4749
|
-
},
|
|
4750
|
-
own.cancellation
|
|
4751
|
-
);
|
|
4752
|
-
if (!current()) return;
|
|
4753
|
-
if (!Object.hasOwn(result.manifest.maps, selectedSource.map)) {
|
|
4754
|
-
throw new TileflowNativeSourceError("NATIVE_MAP_NOT_FOUND", "map");
|
|
4755
|
-
}
|
|
4756
|
-
const entry = result.manifest.maps[selectedSource.map];
|
|
4757
|
-
const apiUrl = entry.apiUrl ?? result.manifest.apiUrl;
|
|
4758
|
-
const map2 = {
|
|
4759
|
-
...entry,
|
|
4760
|
-
name: selectedSource.map,
|
|
4761
|
-
...apiUrl === void 0 ? {} : { apiUrl }
|
|
4762
|
-
};
|
|
4763
|
-
let theme;
|
|
4764
|
-
try {
|
|
4765
|
-
theme = resolveTileflowRuntimeTheme(
|
|
4766
|
-
map2,
|
|
4767
|
-
selection.theme,
|
|
4768
|
-
selection.colorScheme
|
|
4769
|
-
);
|
|
4770
|
-
} catch {
|
|
4771
|
-
throw new TileflowNativeSourceError("NATIVE_THEME_INVALID", "theme");
|
|
4772
|
-
}
|
|
4773
|
-
publish({
|
|
4774
|
-
status: "ready",
|
|
4775
|
-
generation: own.generation,
|
|
4776
|
-
source: selectedSource,
|
|
4777
|
-
...result,
|
|
4778
|
-
map: map2,
|
|
4779
|
-
theme
|
|
4780
|
-
});
|
|
4781
|
-
} catch (error2) {
|
|
4782
|
-
if (current())
|
|
4783
|
-
publish({
|
|
4784
|
-
status: "error",
|
|
4785
|
-
generation: own.generation,
|
|
4786
|
-
error: normalizeNativeSourceError(error2)
|
|
4787
|
-
});
|
|
4788
|
-
} finally {
|
|
4789
|
-
detach();
|
|
4790
|
-
if (active === own) active = void 0;
|
|
4791
|
-
}
|
|
4792
|
-
},
|
|
4793
|
-
dispose() {
|
|
4794
|
-
if (disposed) return;
|
|
4795
|
-
disposed = true;
|
|
4796
|
-
listeners.clear();
|
|
4797
|
-
const previous = active;
|
|
4798
|
-
active = void 0;
|
|
4799
|
-
previous?.cancellation.cancel();
|
|
4800
|
-
}
|
|
4801
|
-
};
|
|
4594
|
+
// src/native-urls.ts
|
|
4595
|
+
var policy = createNativeUrlPolicy(parseNativeUrl);
|
|
4596
|
+
function resolveTileflowNativeManifestUrl(value, options = {}) {
|
|
4597
|
+
return policy.resolveTileflowNativeManifestUrl(value, options);
|
|
4598
|
+
}
|
|
4599
|
+
function resolveTileflowNativeResourceUrl(value, options) {
|
|
4600
|
+
return policy.resolveTileflowNativeResourceUrl(value, options);
|
|
4802
4601
|
}
|
|
4803
4602
|
|
|
4804
|
-
// src/native-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4603
|
+
// src/native-manifest.ts
|
|
4604
|
+
init_manifest_types();
|
|
4605
|
+
|
|
4606
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/parse.js
|
|
4607
|
+
init_core2();
|
|
4608
|
+
|
|
4609
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/schemas.js
|
|
4610
|
+
init_core2();
|
|
4611
|
+
init_util();
|
|
4612
|
+
var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
4613
|
+
if (!inst._zod)
|
|
4614
|
+
throw new Error("Uninitialized schema in ZodMiniType.");
|
|
4615
|
+
$ZodType.init(inst, def);
|
|
4616
|
+
inst.def = def;
|
|
4617
|
+
inst.type = def.type;
|
|
4618
|
+
inst.parse = (data, params) => parse(inst, data, params, { callee: inst.parse });
|
|
4619
|
+
inst.safeParse = (data, params) => safeParse(inst, data, params);
|
|
4620
|
+
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
4621
|
+
inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
|
|
4622
|
+
inst.check = (...checks) => {
|
|
4623
|
+
return inst.clone({
|
|
4624
|
+
...def,
|
|
4625
|
+
checks: [
|
|
4626
|
+
...def.checks ?? [],
|
|
4627
|
+
...checks.map((ch) => typeof ch === "function" ? {
|
|
4628
|
+
_zod: { check: ch, def: { check: "custom" }, onattach: [] }
|
|
4629
|
+
} : ch)
|
|
4630
|
+
]
|
|
4631
|
+
}, { parent: true });
|
|
4632
|
+
};
|
|
4633
|
+
inst.with = inst.check;
|
|
4634
|
+
inst.clone = (_def, params) => clone(inst, _def, params);
|
|
4635
|
+
inst.brand = () => inst;
|
|
4636
|
+
inst.register = ((reg, meta2) => {
|
|
4637
|
+
reg.add(inst, meta2);
|
|
4638
|
+
return inst;
|
|
4639
|
+
});
|
|
4640
|
+
inst.apply = (fn) => fn(inst);
|
|
4641
|
+
});
|
|
4642
|
+
var ZodMiniString = /* @__PURE__ */ $constructor("ZodMiniString", (inst, def) => {
|
|
4643
|
+
$ZodString.init(inst, def);
|
|
4644
|
+
ZodMiniType.init(inst, def);
|
|
4645
|
+
});
|
|
4646
|
+
// @__NO_SIDE_EFFECTS__
|
|
4647
|
+
function string2(params) {
|
|
4648
|
+
return _string(ZodMiniString, params);
|
|
4649
|
+
}
|
|
4650
|
+
var ZodMiniNumber = /* @__PURE__ */ $constructor("ZodMiniNumber", (inst, def) => {
|
|
4651
|
+
$ZodNumber.init(inst, def);
|
|
4652
|
+
ZodMiniType.init(inst, def);
|
|
4653
|
+
});
|
|
4654
|
+
// @__NO_SIDE_EFFECTS__
|
|
4655
|
+
function number2(params) {
|
|
4656
|
+
return _number(ZodMiniNumber, params);
|
|
4657
|
+
}
|
|
4658
|
+
var ZodMiniUnknown = /* @__PURE__ */ $constructor("ZodMiniUnknown", (inst, def) => {
|
|
4659
|
+
$ZodUnknown.init(inst, def);
|
|
4660
|
+
ZodMiniType.init(inst, def);
|
|
4661
|
+
});
|
|
4662
|
+
// @__NO_SIDE_EFFECTS__
|
|
4663
|
+
function unknown() {
|
|
4664
|
+
return _unknown(ZodMiniUnknown);
|
|
4665
|
+
}
|
|
4666
|
+
var ZodMiniNever = /* @__PURE__ */ $constructor("ZodMiniNever", (inst, def) => {
|
|
4667
|
+
$ZodNever.init(inst, def);
|
|
4668
|
+
ZodMiniType.init(inst, def);
|
|
4669
|
+
});
|
|
4670
|
+
// @__NO_SIDE_EFFECTS__
|
|
4671
|
+
function never(params) {
|
|
4672
|
+
return _never(ZodMiniNever, params);
|
|
4673
|
+
}
|
|
4674
|
+
var ZodMiniArray = /* @__PURE__ */ $constructor("ZodMiniArray", (inst, def) => {
|
|
4675
|
+
$ZodArray.init(inst, def);
|
|
4676
|
+
ZodMiniType.init(inst, def);
|
|
4677
|
+
});
|
|
4678
|
+
// @__NO_SIDE_EFFECTS__
|
|
4679
|
+
function array(element, params) {
|
|
4680
|
+
return new ZodMiniArray({
|
|
4681
|
+
type: "array",
|
|
4682
|
+
element,
|
|
4683
|
+
...normalizeParams(params)
|
|
4684
|
+
});
|
|
4685
|
+
}
|
|
4686
|
+
var ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
|
|
4687
|
+
$ZodObject.init(inst, def);
|
|
4688
|
+
ZodMiniType.init(inst, def);
|
|
4689
|
+
defineLazy(inst, "shape", () => def.shape);
|
|
4690
|
+
});
|
|
4691
|
+
// @__NO_SIDE_EFFECTS__
|
|
4692
|
+
function strictObject(shape, params) {
|
|
4693
|
+
return new ZodMiniObject({
|
|
4694
|
+
type: "object",
|
|
4695
|
+
shape,
|
|
4696
|
+
catchall: /* @__PURE__ */ never(),
|
|
4697
|
+
...normalizeParams(params)
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
var ZodMiniTuple = /* @__PURE__ */ $constructor("ZodMiniTuple", (inst, def) => {
|
|
4701
|
+
$ZodTuple.init(inst, def);
|
|
4702
|
+
ZodMiniType.init(inst, def);
|
|
4703
|
+
});
|
|
4704
|
+
// @__NO_SIDE_EFFECTS__
|
|
4705
|
+
function tuple(items, _paramsOrRest, _params) {
|
|
4706
|
+
const hasRest = _paramsOrRest instanceof $ZodType;
|
|
4707
|
+
const params = hasRest ? _params : _paramsOrRest;
|
|
4708
|
+
const rest = hasRest ? _paramsOrRest : null;
|
|
4709
|
+
return new ZodMiniTuple({
|
|
4710
|
+
type: "tuple",
|
|
4711
|
+
items,
|
|
4712
|
+
rest,
|
|
4713
|
+
...normalizeParams(params)
|
|
4714
|
+
});
|
|
4715
|
+
}
|
|
4716
|
+
var ZodMiniRecord = /* @__PURE__ */ $constructor("ZodMiniRecord", (inst, def) => {
|
|
4717
|
+
$ZodRecord.init(inst, def);
|
|
4718
|
+
ZodMiniType.init(inst, def);
|
|
4719
|
+
});
|
|
4720
|
+
// @__NO_SIDE_EFFECTS__
|
|
4721
|
+
function record(keyType, valueType, params) {
|
|
4722
|
+
if (!valueType || !valueType._zod) {
|
|
4723
|
+
return new ZodMiniRecord({
|
|
4724
|
+
type: "record",
|
|
4725
|
+
keyType: /* @__PURE__ */ string2(),
|
|
4726
|
+
valueType: keyType,
|
|
4727
|
+
...normalizeParams(valueType)
|
|
4827
4728
|
});
|
|
4828
|
-
} catch {
|
|
4829
|
-
return invalid();
|
|
4830
4729
|
}
|
|
4730
|
+
return new ZodMiniRecord({
|
|
4731
|
+
type: "record",
|
|
4732
|
+
keyType,
|
|
4733
|
+
valueType,
|
|
4734
|
+
...normalizeParams(params)
|
|
4735
|
+
});
|
|
4736
|
+
}
|
|
4737
|
+
var ZodMiniEnum = /* @__PURE__ */ $constructor("ZodMiniEnum", (inst, def) => {
|
|
4738
|
+
$ZodEnum.init(inst, def);
|
|
4739
|
+
ZodMiniType.init(inst, def);
|
|
4740
|
+
inst.options = Object.values(def.entries);
|
|
4741
|
+
});
|
|
4742
|
+
// @__NO_SIDE_EFFECTS__
|
|
4743
|
+
function _enum(values, params) {
|
|
4744
|
+
const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
|
|
4745
|
+
return new ZodMiniEnum({
|
|
4746
|
+
type: "enum",
|
|
4747
|
+
entries,
|
|
4748
|
+
...normalizeParams(params)
|
|
4749
|
+
});
|
|
4750
|
+
}
|
|
4751
|
+
var ZodMiniLiteral = /* @__PURE__ */ $constructor("ZodMiniLiteral", (inst, def) => {
|
|
4752
|
+
$ZodLiteral.init(inst, def);
|
|
4753
|
+
ZodMiniType.init(inst, def);
|
|
4754
|
+
});
|
|
4755
|
+
// @__NO_SIDE_EFFECTS__
|
|
4756
|
+
function literal(value, params) {
|
|
4757
|
+
return new ZodMiniLiteral({
|
|
4758
|
+
type: "literal",
|
|
4759
|
+
values: Array.isArray(value) ? value : [value],
|
|
4760
|
+
...normalizeParams(params)
|
|
4761
|
+
});
|
|
4762
|
+
}
|
|
4763
|
+
var ZodMiniOptional = /* @__PURE__ */ $constructor("ZodMiniOptional", (inst, def) => {
|
|
4764
|
+
$ZodOptional.init(inst, def);
|
|
4765
|
+
ZodMiniType.init(inst, def);
|
|
4766
|
+
});
|
|
4767
|
+
// @__NO_SIDE_EFFECTS__
|
|
4768
|
+
function optional(innerType) {
|
|
4769
|
+
return new ZodMiniOptional({
|
|
4770
|
+
type: "optional",
|
|
4771
|
+
innerType
|
|
4772
|
+
});
|
|
4773
|
+
}
|
|
4774
|
+
var ZodMiniPipe = /* @__PURE__ */ $constructor("ZodMiniPipe", (inst, def) => {
|
|
4775
|
+
$ZodPipe.init(inst, def);
|
|
4776
|
+
ZodMiniType.init(inst, def);
|
|
4777
|
+
});
|
|
4778
|
+
// @__NO_SIDE_EFFECTS__
|
|
4779
|
+
function pipe(in_, out) {
|
|
4780
|
+
return new ZodMiniPipe({
|
|
4781
|
+
type: "pipe",
|
|
4782
|
+
in: in_,
|
|
4783
|
+
out
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
var ZodMiniCustom = /* @__PURE__ */ $constructor("ZodMiniCustom", (inst, def) => {
|
|
4787
|
+
$ZodCustom.init(inst, def);
|
|
4788
|
+
ZodMiniType.init(inst, def);
|
|
4789
|
+
});
|
|
4790
|
+
// @__NO_SIDE_EFFECTS__
|
|
4791
|
+
function refine(fn, _params = {}) {
|
|
4792
|
+
return _refine(ZodMiniCustom, fn, _params);
|
|
4793
|
+
}
|
|
4794
|
+
// @__NO_SIDE_EFFECTS__
|
|
4795
|
+
function superRefine(fn, params) {
|
|
4796
|
+
return _superRefine(fn, params);
|
|
4797
|
+
}
|
|
4798
|
+
|
|
4799
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/checks.js
|
|
4800
|
+
init_core2();
|
|
4801
|
+
|
|
4802
|
+
// src/native-manifest-schema.ts
|
|
4803
|
+
init_manifest_schema();
|
|
4804
|
+
|
|
4805
|
+
// src/manifest-schema-mini.ts
|
|
4806
|
+
function mini(schema2) {
|
|
4807
|
+
return schema2;
|
|
4808
|
+
}
|
|
4809
|
+
var miniManifestSchemaOperations = {
|
|
4810
|
+
string: () => string2(),
|
|
4811
|
+
minLength: (schema2, minimum) => mini(schema2).check(_minLength(minimum)),
|
|
4812
|
+
maxLength: (schema2, maximum) => mini(schema2).check(_maxLength(maximum)),
|
|
4813
|
+
regex: (schema2, pattern, message) => mini(schema2).check(_regex(pattern, { message })),
|
|
4814
|
+
refine: (schema2, check, message) => mini(schema2).check(refine(check, message)),
|
|
4815
|
+
// Zod 4's number parser rejects NaN and infinities; Classic finite() is a no-op.
|
|
4816
|
+
number: (minimum, maximum) => number2().check(_gte(minimum), _lte(maximum)),
|
|
4817
|
+
unknown: () => unknown(),
|
|
4818
|
+
optional: (schema2) => optional(schema2),
|
|
4819
|
+
array: (schema2) => array(schema2),
|
|
4820
|
+
enum(values) {
|
|
4821
|
+
return _enum(values);
|
|
4822
|
+
},
|
|
4823
|
+
literal: (value) => literal(value),
|
|
4824
|
+
tuplePair(left, right) {
|
|
4825
|
+
return tuple([left, right]);
|
|
4826
|
+
},
|
|
4827
|
+
// ZodMiniObject uses the interpreted $ZodObject, not the Classic object JIT constructor.
|
|
4828
|
+
object(shape) {
|
|
4829
|
+
return strictObject(shape);
|
|
4830
|
+
},
|
|
4831
|
+
record(key, value) {
|
|
4832
|
+
return record(key, value);
|
|
4833
|
+
},
|
|
4834
|
+
superRefine: (schema2, check) => mini(schema2).check(superRefine(check)),
|
|
4835
|
+
pipe: (input, output) => pipe(input, output)
|
|
4836
|
+
};
|
|
4837
|
+
|
|
4838
|
+
// src/native-manifest-utf8.ts
|
|
4839
|
+
init_native_url_utf8();
|
|
4840
|
+
function nativeManifestUtf8ByteLength(input) {
|
|
4841
|
+
let bytes = 0;
|
|
4842
|
+
for (let index = 0; index < input.length; index++) {
|
|
4843
|
+
const value = input.charCodeAt(index);
|
|
4844
|
+
if (value <= 127) bytes++;
|
|
4845
|
+
else if (value <= 2047) bytes += 2;
|
|
4846
|
+
else if (value >= 55296 && value <= 56319 && input.charCodeAt(index + 1) >= 56320 && input.charCodeAt(index + 1) <= 57343) {
|
|
4847
|
+
bytes += 4;
|
|
4848
|
+
index++;
|
|
4849
|
+
} else bytes += 3;
|
|
4850
|
+
}
|
|
4851
|
+
return bytes;
|
|
4831
4852
|
}
|
|
4832
|
-
function
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4853
|
+
function decodeNativeManifestUtf8(input) {
|
|
4854
|
+
let remaining = 0;
|
|
4855
|
+
let lower = 128;
|
|
4856
|
+
let upper = 191;
|
|
4857
|
+
for (const byte of input) {
|
|
4858
|
+
if (remaining === 0) {
|
|
4859
|
+
if (byte <= 127) continue;
|
|
4860
|
+
if (byte >= 194 && byte <= 223) remaining = 1;
|
|
4861
|
+
else if (byte >= 224 && byte <= 239) {
|
|
4862
|
+
remaining = 2;
|
|
4863
|
+
if (byte === 224) lower = 160;
|
|
4864
|
+
if (byte === 237) upper = 159;
|
|
4865
|
+
} else if (byte >= 240 && byte <= 244) {
|
|
4866
|
+
remaining = 3;
|
|
4867
|
+
if (byte === 240) lower = 144;
|
|
4868
|
+
if (byte === 244) upper = 143;
|
|
4869
|
+
} else throw new TypeError("Invalid manifest UTF-8.");
|
|
4870
|
+
} else {
|
|
4871
|
+
if (byte < lower || byte > upper) throw new TypeError("Invalid manifest UTF-8.");
|
|
4872
|
+
remaining--;
|
|
4873
|
+
lower = 128;
|
|
4874
|
+
upper = 191;
|
|
4875
|
+
}
|
|
4876
|
+
}
|
|
4877
|
+
if (remaining) throw new TypeError("Invalid manifest UTF-8.");
|
|
4878
|
+
const parts = [];
|
|
4879
|
+
let offset = 0;
|
|
4880
|
+
while (offset < input.byteLength) {
|
|
4881
|
+
let end = Math.min(offset + nativeUrlCodecMaximumLength, input.byteLength);
|
|
4882
|
+
while (end < input.byteLength && (input[end] & 192) === 128) end--;
|
|
4883
|
+
parts.push(utf8DecodeWithoutBOM(input.subarray(offset, end)));
|
|
4884
|
+
offset = end;
|
|
4885
|
+
}
|
|
4886
|
+
const text = parts.join("");
|
|
4887
|
+
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
4839
4888
|
}
|
|
4840
|
-
function
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4889
|
+
function hasBoundedNativeManifestDepth(text, maximumDepth) {
|
|
4890
|
+
let depth = 0;
|
|
4891
|
+
let quoted = false;
|
|
4892
|
+
let escaped = false;
|
|
4893
|
+
for (let index = 0; index < text.length; index++) {
|
|
4894
|
+
const character = text[index];
|
|
4895
|
+
if (quoted) {
|
|
4896
|
+
if (escaped) escaped = false;
|
|
4897
|
+
else if (character === "\\") escaped = true;
|
|
4898
|
+
else if (character === '"') quoted = false;
|
|
4899
|
+
} else if (character === '"') quoted = true;
|
|
4900
|
+
else if (character === "[" || character === "{") {
|
|
4901
|
+
if (++depth > maximumDepth) return false;
|
|
4902
|
+
} else if (character === "]" || character === "}") depth--;
|
|
4852
4903
|
}
|
|
4853
|
-
|
|
4854
|
-
return {
|
|
4855
|
-
...parsed.bearing === void 0 ? {} : { bearing: parsed.bearing },
|
|
4856
|
-
...parsed.center === void 0 ? {} : { center: parsed.center },
|
|
4857
|
-
...parsed.pitch === void 0 ? {} : { pitch: parsed.pitch },
|
|
4858
|
-
...parsed.zoom === void 0 ? {} : { zoom: parsed.zoom }
|
|
4859
|
-
};
|
|
4904
|
+
return true;
|
|
4860
4905
|
}
|
|
4861
4906
|
|
|
4862
|
-
// src/
|
|
4863
|
-
var
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
}
|
|
4907
|
+
// src/native-manifest-schema.ts
|
|
4908
|
+
var schema = createTileflowRuntimeManifestSchema(
|
|
4909
|
+
{
|
|
4910
|
+
parseUrl: parseNativeUrl,
|
|
4911
|
+
utf8ByteLength: nativeManifestUtf8ByteLength
|
|
4912
|
+
},
|
|
4913
|
+
miniManifestSchemaOperations
|
|
4914
|
+
);
|
|
4915
|
+
function parseTileflowRuntimeManifest(input) {
|
|
4916
|
+
return parse(schema, input);
|
|
4917
|
+
}
|
|
4918
|
+
|
|
4919
|
+
// src/native-source-types.ts
|
|
4920
|
+
var messages = {
|
|
4921
|
+
NATIVE_SOURCE_INVALID: "Expected a valid native source or renderer-neutral view.",
|
|
4922
|
+
NATIVE_SOURCE_ABORTED: "The source operation was cancelled.",
|
|
4923
|
+
NATIVE_SOURCE_DISPOSED: "The source controller has been disposed.",
|
|
4924
|
+
NATIVE_MANIFEST_URL_INVALID: "Expected a safe absolute manifest URL and an exact development origin.",
|
|
4925
|
+
NATIVE_MANIFEST_REQUEST_FAILED: "Manifest acquisition failed.",
|
|
4926
|
+
NATIVE_MANIFEST_RESPONSE_INVALID: "Expected a bounded byte reader and an explicit final response URL.",
|
|
4927
|
+
NATIVE_MANIFEST_ACCESS_DENIED: "Manifest access was denied.",
|
|
4928
|
+
NATIVE_MANIFEST_NOT_FOUND: "The manifest was not found.",
|
|
4929
|
+
NATIVE_MANIFEST_TOO_LARGE: "The manifest exceeds the 1 MiB limit.",
|
|
4930
|
+
NATIVE_MANIFEST_UTF8_INVALID: "The manifest body is not valid UTF-8.",
|
|
4931
|
+
NATIVE_MANIFEST_JSON_INVALID: "The manifest body is not valid JSON.",
|
|
4932
|
+
NATIVE_MANIFEST_INVALID: "The manifest does not satisfy the version-1 runtime contract.",
|
|
4933
|
+
NATIVE_MANIFEST_RESOURCE_INVALID: "A manifest resource URL is outside the native URL policy.",
|
|
4934
|
+
NATIVE_MAP_NOT_FOUND: "The requested map is not declared by the manifest.",
|
|
4935
|
+
NATIVE_THEME_INVALID: "Expected a declared concrete theme or an explicitly supplied system color scheme."
|
|
4868
4936
|
};
|
|
4869
|
-
var
|
|
4870
|
-
constructor(
|
|
4871
|
-
|
|
4937
|
+
var TileflowNativeSourceError = class extends Error {
|
|
4938
|
+
constructor(code, field) {
|
|
4939
|
+
super(messages[code]);
|
|
4940
|
+
__publicField(this, "code");
|
|
4941
|
+
__publicField(this, "field");
|
|
4942
|
+
__publicField(this, "kind");
|
|
4943
|
+
this.name = "TileflowNativeSourceError";
|
|
4944
|
+
this.code = code;
|
|
4945
|
+
this.field = field;
|
|
4946
|
+
this.kind = code === "NATIVE_SOURCE_ABORTED" || code === "NATIVE_SOURCE_DISPOSED" ? "cancelled" : "terminal";
|
|
4872
4947
|
}
|
|
4873
4948
|
};
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
fill: "fill-opacity",
|
|
4885
|
-
"fill-extrusion": "fill-extrusion-opacity",
|
|
4886
|
-
heatmap: "heatmap-opacity",
|
|
4887
|
-
line: "line-opacity",
|
|
4888
|
-
raster: "raster-opacity"
|
|
4889
|
-
};
|
|
4890
|
-
var featureOperators = /* @__PURE__ */ new Set([
|
|
4891
|
-
"feature-state",
|
|
4892
|
-
"geometry-type",
|
|
4893
|
-
"get",
|
|
4894
|
-
"has",
|
|
4895
|
-
"id",
|
|
4896
|
-
"in",
|
|
4897
|
-
"properties"
|
|
4898
|
-
]);
|
|
4899
|
-
var maximumBranches = 24;
|
|
4900
|
-
function planTileflowThemeBlend(styles, options = {}) {
|
|
4901
|
-
if (styles.length < 2)
|
|
4902
|
-
throw new TileflowThemeBlendError("A theme blend needs two or more themes.");
|
|
4903
|
-
const [base2] = styles;
|
|
4904
|
-
assertSameStructure(styles, base2);
|
|
4905
|
-
const mixedImages = new Set(imageProperties);
|
|
4906
|
-
if (options.iconImages === "switch") mixedImages.delete("icon-image");
|
|
4907
|
-
const paints = [];
|
|
4908
|
-
const switches = [];
|
|
4909
|
-
const imageGroups = collectImageNames(styles, base2, mixedImages);
|
|
4910
|
-
const symbolLayers = /* @__PURE__ */ new Set();
|
|
4911
|
-
const images = /* @__PURE__ */ new Map();
|
|
4912
|
-
let splitLayers = 0;
|
|
4913
|
-
let copiedLayers = 0;
|
|
4914
|
-
let switchedLayers = 0;
|
|
4915
|
-
const layers = [];
|
|
4916
|
-
for (const [index, layer] of base2.layers.entries()) {
|
|
4917
|
-
const variants = styles.map((style) => style.layers[index]);
|
|
4918
|
-
layers.push(...planLayer(variants, String(layer.type)));
|
|
4919
|
-
}
|
|
4920
|
-
const switchesByLayer = /* @__PURE__ */ new Map();
|
|
4921
|
-
for (const entry of switches) {
|
|
4922
|
-
const list = switchesByLayer.get(entry.layer) ?? [];
|
|
4923
|
-
list.push(entry);
|
|
4924
|
-
switchesByLayer.set(entry.layer, list);
|
|
4925
|
-
}
|
|
4926
|
-
const sky = differingRoot(styles, "sky");
|
|
4927
|
-
const light = differingRoot(styles, "light");
|
|
4928
|
-
const metadata = alignInteractionManifest(base2.metadata, layers);
|
|
4929
|
-
return {
|
|
4930
|
-
themes: styles.length,
|
|
4931
|
-
paints,
|
|
4932
|
-
images: [...images.values()],
|
|
4933
|
-
switches,
|
|
4934
|
-
...sky === void 0 ? {} : { sky },
|
|
4935
|
-
...light === void 0 ? {} : { light },
|
|
4936
|
-
summary: { splitLayers, copiedLayers, switchedLayers, switchedValues: switches.length },
|
|
4937
|
-
styleAt(position) {
|
|
4938
|
-
const at = clampPosition(position, styles.length);
|
|
4939
|
-
const dominant = Math.round(at);
|
|
4940
|
-
const style = {
|
|
4941
|
-
...base2,
|
|
4942
|
-
...metadata === void 0 ? {} : { metadata },
|
|
4943
|
-
// Symbols show the nearest theme, as the label cross-fade leaves them between changes.
|
|
4944
|
-
layers: layers.map(
|
|
4945
|
-
(layer) => fillLayer(
|
|
4946
|
-
layer,
|
|
4947
|
-
symbolLayers.has(String(layer.id)) ? dominant : at,
|
|
4948
|
-
dominant,
|
|
4949
|
-
switchesByLayer.get(String(layer.id))
|
|
4950
|
-
)
|
|
4951
|
-
)
|
|
4952
|
-
};
|
|
4953
|
-
if (sky !== void 0) style.sky = fillTemplate(sky, at);
|
|
4954
|
-
if (light !== void 0) style.light = fillTemplate(light, at);
|
|
4955
|
-
return style;
|
|
4949
|
+
function normalizeNativeSourceError(error2) {
|
|
4950
|
+
try {
|
|
4951
|
+
if (error2 instanceof TileflowNativeSourceError) {
|
|
4952
|
+
const code = Object.getOwnPropertyDescriptor(error2, "code")?.value;
|
|
4953
|
+
const field = Object.getOwnPropertyDescriptor(error2, "field")?.value;
|
|
4954
|
+
if (typeof code === "string" && Object.hasOwn(messages, code) && ["source", "signal", "manifestUrl", "response", "body", "map", "theme", "view"].includes(
|
|
4955
|
+
field
|
|
4956
|
+
)) {
|
|
4957
|
+
return new TileflowNativeSourceError(code, field);
|
|
4958
|
+
}
|
|
4956
4959
|
}
|
|
4957
|
-
}
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
images.set(JSON.stringify(names), {
|
|
4981
|
-
names,
|
|
4982
|
-
follows: property === "icon-image" ? "dominant" : "position"
|
|
4983
|
-
});
|
|
4984
|
-
}
|
|
4985
|
-
continue;
|
|
4986
|
-
}
|
|
4987
|
-
}
|
|
4988
|
-
if (group === "layout" || values.includes(void 0) || imageProperties.has(property)) {
|
|
4989
|
-
ownSwitches.push({ group, property, values });
|
|
4990
|
-
continue;
|
|
4991
|
-
}
|
|
4992
|
-
if (values.some(isDataDriven)) {
|
|
4993
|
-
driven.push(property);
|
|
4994
|
-
continue;
|
|
4995
|
-
}
|
|
4996
|
-
const template = tryMixTemplate(values);
|
|
4997
|
-
if (template === void 0) {
|
|
4998
|
-
ownSwitches.push({ group, property, values });
|
|
4999
|
-
continue;
|
|
5000
|
-
}
|
|
5001
|
-
ownPaints.push({ property, template });
|
|
5002
|
-
target[property] = template;
|
|
4960
|
+
} catch {
|
|
4961
|
+
}
|
|
4962
|
+
return new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
4963
|
+
}
|
|
4964
|
+
|
|
4965
|
+
// src/native-source-cancellation.ts
|
|
4966
|
+
var NativeSourceCancellation = class {
|
|
4967
|
+
constructor() {
|
|
4968
|
+
__publicField(this, "cancelled", false);
|
|
4969
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Set());
|
|
4970
|
+
}
|
|
4971
|
+
get aborted() {
|
|
4972
|
+
return this.cancelled;
|
|
4973
|
+
}
|
|
4974
|
+
cancel() {
|
|
4975
|
+
if (this.cancelled) return;
|
|
4976
|
+
this.cancelled = true;
|
|
4977
|
+
const listeners = [...this.listeners];
|
|
4978
|
+
this.listeners.clear();
|
|
4979
|
+
for (const listener of listeners) {
|
|
4980
|
+
try {
|
|
4981
|
+
listener();
|
|
4982
|
+
} catch {
|
|
5003
4983
|
}
|
|
5004
4984
|
}
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
if (
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
ownSwitches.push({
|
|
5014
|
-
group: "paint",
|
|
5015
|
-
property,
|
|
5016
|
-
values: variants.map((variant) => paintOf(variant)[property])
|
|
5017
|
-
});
|
|
5018
|
-
}
|
|
5019
|
-
if (options.featureSwitches === "layers" && results.length === 1 && ownSwitches.some((entry) => entry.values.some(isDataDriven)))
|
|
5020
|
-
results = switchLayer();
|
|
5021
|
-
for (const result of results) {
|
|
5022
|
-
const resultId = String(result.layer.id);
|
|
5023
|
-
if (type === "symbol") symbolLayers.add(resultId);
|
|
5024
|
-
const overridden = new Set(result.extra.map((entry) => entry.property));
|
|
5025
|
-
for (const entry of [
|
|
5026
|
-
...ownPaints.filter((own) => !overridden.has(own.property)),
|
|
5027
|
-
...result.extra
|
|
5028
|
-
])
|
|
5029
|
-
paints.push({ layer: resultId, property: entry.property, template: entry.template, follows });
|
|
5030
|
-
if (result.visibility)
|
|
5031
|
-
switches.push({
|
|
5032
|
-
layer: resultId,
|
|
5033
|
-
group: "layout",
|
|
5034
|
-
property: "visibility",
|
|
5035
|
-
values: result.visibility
|
|
5036
|
-
});
|
|
5037
|
-
else for (const entry of ownSwitches) switches.push({ layer: resultId, ...entry });
|
|
4985
|
+
}
|
|
4986
|
+
check() {
|
|
4987
|
+
if (this.cancelled) throw new TileflowNativeSourceError("NATIVE_SOURCE_ABORTED", "signal");
|
|
4988
|
+
}
|
|
4989
|
+
onCancel(listener) {
|
|
4990
|
+
if (this.cancelled) {
|
|
4991
|
+
listener();
|
|
4992
|
+
return () => void 0;
|
|
5038
4993
|
}
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
4994
|
+
this.listeners.add(listener);
|
|
4995
|
+
return () => {
|
|
4996
|
+
this.listeners.delete(listener);
|
|
4997
|
+
};
|
|
4998
|
+
}
|
|
4999
|
+
race(promise) {
|
|
5000
|
+
return new Promise((resolve, reject) => {
|
|
5001
|
+
const off = this.onCancel(
|
|
5002
|
+
() => reject(new TileflowNativeSourceError("NATIVE_SOURCE_ABORTED", "signal"))
|
|
5003
|
+
);
|
|
5004
|
+
promise.then(
|
|
5005
|
+
(value) => {
|
|
5006
|
+
off();
|
|
5007
|
+
resolve(value);
|
|
5008
|
+
},
|
|
5009
|
+
(error2) => {
|
|
5010
|
+
off();
|
|
5011
|
+
reject(error2);
|
|
5050
5012
|
}
|
|
5051
|
-
const shown = copyLayout.visibility === "none" ? "none" : "visible";
|
|
5052
|
-
return {
|
|
5053
|
-
layer: { ...planned, id: `${id}::theme-${theme}`, paint: copyPaint, layout: copyLayout },
|
|
5054
|
-
extra: [],
|
|
5055
|
-
visibility: variants.map((__, nearest) => nearest === theme ? shown : "none")
|
|
5056
|
-
};
|
|
5057
|
-
});
|
|
5058
|
-
}
|
|
5059
|
-
function splitLayer() {
|
|
5060
|
-
if (isLegacyFilter(layer.filter)) return void 0;
|
|
5061
|
-
const branches = splitBranches(
|
|
5062
|
-
Object.fromEntries(
|
|
5063
|
-
driven.map((property) => [
|
|
5064
|
-
property,
|
|
5065
|
-
variants.map((variant) => paintOf(variant)[property])
|
|
5066
|
-
])
|
|
5067
|
-
)
|
|
5068
5013
|
);
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5014
|
+
});
|
|
5015
|
+
}
|
|
5016
|
+
link(signal) {
|
|
5017
|
+
if (signal === void 0) return () => void 0;
|
|
5018
|
+
let onAbort;
|
|
5019
|
+
try {
|
|
5020
|
+
if (!signal || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")
|
|
5021
|
+
throw new Error();
|
|
5022
|
+
onAbort = () => this.cancel();
|
|
5023
|
+
if (signal.aborted) {
|
|
5024
|
+
this.cancel();
|
|
5025
|
+
return () => void 0;
|
|
5026
|
+
}
|
|
5027
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
5028
|
+
if (signal.aborted) this.cancel();
|
|
5029
|
+
} catch {
|
|
5030
|
+
if (onAbort) {
|
|
5031
|
+
try {
|
|
5032
|
+
signal.removeEventListener("abort", onAbort);
|
|
5033
|
+
} catch {
|
|
5083
5034
|
}
|
|
5084
|
-
group.conditions.push(
|
|
5085
|
-
branch.conditions.length === 1 ? branch.conditions[0] : ["all", ...branch.conditions]
|
|
5086
|
-
);
|
|
5087
5035
|
}
|
|
5088
|
-
|
|
5089
|
-
return [...groups.values()].map((group, number3) => {
|
|
5090
|
-
const chosen = group.conditions.length === 1 ? group.conditions[0] : ["any", ...group.conditions];
|
|
5091
|
-
return {
|
|
5092
|
-
layer: {
|
|
5093
|
-
...planned,
|
|
5094
|
-
id: `${id}::branch-${number3}`,
|
|
5095
|
-
filter: layer.filter === void 0 ? chosen : ["all", layer.filter, chosen],
|
|
5096
|
-
paint: { ...paint, ...group.templates }
|
|
5097
|
-
},
|
|
5098
|
-
extra: Object.entries(group.templates).filter(([, template]) => containsLeaf(template)).map(([property, template]) => ({ property, template }))
|
|
5099
|
-
};
|
|
5100
|
-
});
|
|
5101
|
-
}
|
|
5102
|
-
function copyLayer() {
|
|
5103
|
-
const opacity = opacityProperties[type];
|
|
5104
|
-
if (!opacity || variants.some((variant) => isDataDriven(paintOf(variant)[opacity])))
|
|
5105
|
-
return void 0;
|
|
5106
|
-
copiedLayers += variants.length;
|
|
5107
|
-
return variants.map((variant, theme) => {
|
|
5108
|
-
const weight = new BlendLeaf(variants.map((_, other) => other === theme ? 1 : 0));
|
|
5109
|
-
const template = scaleByWeight(paint[opacity] ?? 1, weight);
|
|
5110
|
-
const copyPaint = { ...paint, [opacity]: template };
|
|
5111
|
-
for (const property of driven) copyPaint[property] = paintOf(variant)[property];
|
|
5112
|
-
return {
|
|
5113
|
-
layer: { ...planned, id: `${id}::theme-${theme}`, paint: copyPaint },
|
|
5114
|
-
extra: [{ property: opacity, template }]
|
|
5115
|
-
};
|
|
5116
|
-
});
|
|
5117
|
-
}
|
|
5118
|
-
}
|
|
5119
|
-
}
|
|
5120
|
-
function fillTileflowThemeBlendTemplate(template, position) {
|
|
5121
|
-
return fillTemplate(template, position);
|
|
5122
|
-
}
|
|
5123
|
-
function fillLayer(layer, position, dominant, layerSwitches) {
|
|
5124
|
-
const filled = { ...layer };
|
|
5125
|
-
for (const group of ["layout", "paint"]) {
|
|
5126
|
-
const values = layer[group];
|
|
5127
|
-
if (!values) continue;
|
|
5128
|
-
const out = {};
|
|
5129
|
-
for (const [key, value] of Object.entries(values)) out[key] = fillTemplate(value, position);
|
|
5130
|
-
for (const entry of layerSwitches ?? []) {
|
|
5131
|
-
if (entry.group !== group) continue;
|
|
5132
|
-
const value = entry.values[dominant];
|
|
5133
|
-
if (value === void 0) delete out[entry.property];
|
|
5134
|
-
else out[entry.property] = value;
|
|
5036
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "signal");
|
|
5135
5037
|
}
|
|
5136
|
-
|
|
5137
|
-
|
|
5038
|
+
return () => {
|
|
5039
|
+
try {
|
|
5040
|
+
signal.removeEventListener("abort", onAbort);
|
|
5041
|
+
} catch {
|
|
5042
|
+
}
|
|
5043
|
+
};
|
|
5138
5044
|
}
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
if (node && typeof node === "object" && containsLeaf(node)) {
|
|
5145
|
-
return Object.fromEntries(
|
|
5146
|
-
Object.entries(node).map(([key, value]) => [key, fillTemplate(value, position)])
|
|
5147
|
-
);
|
|
5045
|
+
};
|
|
5046
|
+
function cancelNativeOperation(cancel) {
|
|
5047
|
+
try {
|
|
5048
|
+
void Promise.resolve(cancel()).catch(() => void 0);
|
|
5049
|
+
} catch {
|
|
5148
5050
|
}
|
|
5149
|
-
return node;
|
|
5150
|
-
}
|
|
5151
|
-
function containsLeaf(node) {
|
|
5152
|
-
if (node instanceof BlendLeaf) return true;
|
|
5153
|
-
if (Array.isArray(node)) return node.some(containsLeaf);
|
|
5154
|
-
if (node && typeof node === "object") return Object.values(node).some(containsLeaf);
|
|
5155
|
-
return false;
|
|
5156
|
-
}
|
|
5157
|
-
function mixLeaf(values, position) {
|
|
5158
|
-
const at = clampPosition(position, values.length);
|
|
5159
|
-
const index = Math.min(values.length - 2, Math.floor(at));
|
|
5160
|
-
const t = at - index;
|
|
5161
|
-
const from = values[index];
|
|
5162
|
-
const to = values[index + 1];
|
|
5163
|
-
if (t <= 0 || from === to) return from;
|
|
5164
|
-
if (t >= 1) return to;
|
|
5165
|
-
if (typeof from === "number" && typeof to === "number") return from + (to - from) * t;
|
|
5166
|
-
const a = oklab(String(from));
|
|
5167
|
-
const b = oklab(String(to));
|
|
5168
|
-
if (!a || !b) return t < 0.5 ? from : to;
|
|
5169
|
-
return colourFromOklab(a.map((value, channel) => value + (b[channel] - value) * t));
|
|
5170
|
-
}
|
|
5171
|
-
function clampPosition(position, themes) {
|
|
5172
|
-
if (!Number.isFinite(position)) return 0;
|
|
5173
|
-
return Math.min(themes - 1, Math.max(0, position));
|
|
5174
5051
|
}
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
const other = base2.layers[index];
|
|
5188
|
-
for (const key of ["type", "source", "source-layer", "filter", "minzoom", "maxzoom"])
|
|
5189
|
-
if (!same(layer[key], other[key]))
|
|
5190
|
-
throw new TileflowThemeBlendError(
|
|
5191
|
-
`Blended themes differ in ${key} of layer ${JSON.stringify(layer.id)}.`
|
|
5192
|
-
);
|
|
5052
|
+
|
|
5053
|
+
// src/native-source-utils.ts
|
|
5054
|
+
function nativeOwnRecord(value) {
|
|
5055
|
+
try {
|
|
5056
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
5057
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5058
|
+
if (prototype !== null && prototype !== Object.prototype) return void 0;
|
|
5059
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
5060
|
+
for (const key of Object.keys(value)) {
|
|
5061
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
5062
|
+
if (!property || !("value" in property)) return void 0;
|
|
5063
|
+
result[key] = property.value;
|
|
5193
5064
|
}
|
|
5065
|
+
return result;
|
|
5066
|
+
} catch {
|
|
5067
|
+
return void 0;
|
|
5194
5068
|
}
|
|
5195
5069
|
}
|
|
5196
|
-
function
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
function differingRoot(styles, key) {
|
|
5203
|
-
const values = styles.map((style) => style[key]);
|
|
5204
|
-
if (values.every((value) => same(value, values[0]))) return void 0;
|
|
5205
|
-
return tryMixTemplate(values);
|
|
5070
|
+
function freezeNativeSnapshot(value) {
|
|
5071
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
5072
|
+
for (const child of Object.values(value)) freezeNativeSnapshot(child);
|
|
5073
|
+
Object.freeze(value);
|
|
5074
|
+
}
|
|
5075
|
+
return value;
|
|
5206
5076
|
}
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5077
|
+
|
|
5078
|
+
// src/native-manifest.ts
|
|
5079
|
+
var tileflowNativeManifestLimits = Object.freeze({
|
|
5080
|
+
maximumBytes: tileflowRuntimeManifestLimits.maximumBytes,
|
|
5081
|
+
maximumChunkBytes: 64 * 1024,
|
|
5082
|
+
maximumDepth: 64
|
|
5083
|
+
});
|
|
5084
|
+
async function loadTileflowNativeManifest(manifestUrl, options) {
|
|
5085
|
+
const input = nativeOwnRecord(options);
|
|
5086
|
+
if (!input || typeof input.acquire !== "function")
|
|
5087
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
5088
|
+
const cancellation = new NativeSourceCancellation();
|
|
5089
|
+
const detach = cancellation.link(input.signal);
|
|
5090
|
+
try {
|
|
5091
|
+
return await loadNativeManifest(
|
|
5092
|
+
manifestUrl,
|
|
5093
|
+
input.acquire,
|
|
5094
|
+
{
|
|
5095
|
+
developmentOrigin: input.developmentOrigin
|
|
5096
|
+
},
|
|
5097
|
+
cancellation
|
|
5098
|
+
);
|
|
5099
|
+
} finally {
|
|
5100
|
+
detach();
|
|
5223
5101
|
}
|
|
5224
|
-
return uses;
|
|
5225
5102
|
}
|
|
5226
|
-
function
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5103
|
+
async function loadNativeManifest(manifestUrl, acquire, network, cancellation) {
|
|
5104
|
+
cancellation.check();
|
|
5105
|
+
let requestUrl;
|
|
5106
|
+
try {
|
|
5107
|
+
requestUrl = resolveTileflowNativeManifestUrl(manifestUrl, network);
|
|
5108
|
+
} catch {
|
|
5109
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_URL_INVALID", "manifestUrl");
|
|
5233
5110
|
}
|
|
5234
|
-
let
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
const copies = planned.get(entry.layerId);
|
|
5243
|
-
if (!copies) return [entry];
|
|
5244
|
-
return copies.map(({ id, index }) => ({ ...entry, layerId: id, priority: index }));
|
|
5245
|
-
});
|
|
5246
|
-
aligned = {
|
|
5247
|
-
...metadata,
|
|
5248
|
-
"tileflow:interaction-manifest": {
|
|
5249
|
-
...interactions,
|
|
5250
|
-
domains: { ...domains, poi: { ...poi, layers: poiLayers } }
|
|
5251
|
-
}
|
|
5252
|
-
};
|
|
5111
|
+
let operation;
|
|
5112
|
+
try {
|
|
5113
|
+
operation = acquire(
|
|
5114
|
+
requestUrl,
|
|
5115
|
+
Object.freeze({ maximumBytes: tileflowNativeManifestLimits.maximumBytes })
|
|
5116
|
+
);
|
|
5117
|
+
if (!operation || typeof operation.cancel !== "function" || !operation.response || typeof operation.response.then !== "function") {
|
|
5118
|
+
throw new Error();
|
|
5253
5119
|
}
|
|
5120
|
+
} catch {
|
|
5121
|
+
if (operation) cancelNativeOperation(() => operation.cancel());
|
|
5122
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
5254
5123
|
}
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5124
|
+
let reader;
|
|
5125
|
+
let readerCancelled = false;
|
|
5126
|
+
let operationCancelled = false;
|
|
5127
|
+
const cancelReader = () => {
|
|
5128
|
+
if (!reader || readerCancelled) return;
|
|
5129
|
+
readerCancelled = true;
|
|
5130
|
+
cancelNativeOperation(() => reader.cancel());
|
|
5131
|
+
};
|
|
5132
|
+
const cleanup = () => {
|
|
5133
|
+
if (!operationCancelled) {
|
|
5134
|
+
operationCancelled = true;
|
|
5135
|
+
cancelNativeOperation(() => operation.cancel());
|
|
5136
|
+
}
|
|
5137
|
+
cancelReader();
|
|
5138
|
+
};
|
|
5139
|
+
const unlisten = cancellation.onCancel(cleanup);
|
|
5140
|
+
try {
|
|
5141
|
+
const headers = Promise.resolve(operation.response).then(
|
|
5142
|
+
(response2) => {
|
|
5143
|
+
try {
|
|
5144
|
+
if (!response2 || !response2.reader || typeof response2.reader.read !== "function" || typeof response2.reader.cancel !== "function") {
|
|
5145
|
+
throw new Error();
|
|
5146
|
+
}
|
|
5147
|
+
reader = response2.reader;
|
|
5148
|
+
} catch {
|
|
5149
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5150
|
+
}
|
|
5151
|
+
if (cancellation.aborted) cancelReader();
|
|
5152
|
+
cancellation.check();
|
|
5153
|
+
return response2;
|
|
5154
|
+
},
|
|
5155
|
+
() => {
|
|
5156
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
5157
|
+
}
|
|
5262
5158
|
);
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5159
|
+
const response = await cancellation.race(headers);
|
|
5160
|
+
cancellation.check();
|
|
5161
|
+
let finalUrl;
|
|
5162
|
+
try {
|
|
5163
|
+
finalUrl = resolveTileflowNativeManifestUrl(response.url, network);
|
|
5164
|
+
} catch {
|
|
5165
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_URL_INVALID", "manifestUrl");
|
|
5166
|
+
}
|
|
5167
|
+
if (!Number.isInteger(response.status) || response.status < 100 || response.status > 599) {
|
|
5168
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5169
|
+
}
|
|
5170
|
+
if (response.status === 401 || response.status === 403)
|
|
5171
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_ACCESS_DENIED", "response");
|
|
5172
|
+
if (response.status === 404)
|
|
5173
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_NOT_FOUND", "response");
|
|
5174
|
+
if (response.status < 200 || response.status >= 300)
|
|
5175
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
5176
|
+
const buffer = new Uint8Array(tileflowNativeManifestLimits.maximumBytes);
|
|
5177
|
+
let length = 0;
|
|
5178
|
+
while (true) {
|
|
5179
|
+
cancellation.check();
|
|
5180
|
+
const allowance = Math.min(
|
|
5181
|
+
tileflowNativeManifestLimits.maximumChunkBytes,
|
|
5182
|
+
buffer.byteLength - length + 1
|
|
5183
|
+
);
|
|
5184
|
+
let next;
|
|
5185
|
+
try {
|
|
5186
|
+
const pending = Promise.resolve(reader.read(allowance)).catch(() => {
|
|
5187
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
5188
|
+
});
|
|
5189
|
+
next = await cancellation.race(pending);
|
|
5190
|
+
} catch {
|
|
5191
|
+
cancellation.check();
|
|
5192
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_REQUEST_FAILED", "response");
|
|
5193
|
+
}
|
|
5194
|
+
cancellation.check();
|
|
5195
|
+
if (!next || typeof next.done !== "boolean")
|
|
5196
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5197
|
+
if (next.done) {
|
|
5198
|
+
if (next.value !== void 0)
|
|
5199
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5200
|
+
break;
|
|
5201
|
+
}
|
|
5202
|
+
if (!(next.value instanceof Uint8Array) || next.value.byteLength === 0)
|
|
5203
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5204
|
+
if (next.value.byteLength > buffer.byteLength - length)
|
|
5205
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_TOO_LARGE", "body");
|
|
5206
|
+
if (next.value.byteLength > allowance)
|
|
5207
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESPONSE_INVALID", "response");
|
|
5208
|
+
buffer.set(next.value, length);
|
|
5209
|
+
length += next.value.byteLength;
|
|
5210
|
+
}
|
|
5211
|
+
let text;
|
|
5212
|
+
try {
|
|
5213
|
+
text = decodeNativeManifestUtf8(buffer.subarray(0, length));
|
|
5214
|
+
} catch {
|
|
5215
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_UTF8_INVALID", "body");
|
|
5216
|
+
}
|
|
5217
|
+
if (!hasBoundedNativeManifestDepth(text, tileflowNativeManifestLimits.maximumDepth)) {
|
|
5218
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_INVALID", "body");
|
|
5219
|
+
}
|
|
5220
|
+
let json;
|
|
5221
|
+
try {
|
|
5222
|
+
json = JSON.parse(text);
|
|
5223
|
+
} catch {
|
|
5224
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_JSON_INVALID", "body");
|
|
5225
|
+
}
|
|
5226
|
+
let manifest;
|
|
5227
|
+
try {
|
|
5228
|
+
manifest = parseTileflowRuntimeManifest(json);
|
|
5229
|
+
} catch {
|
|
5230
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_INVALID", "body");
|
|
5231
|
+
}
|
|
5232
|
+
let resolvedBytes = nativeManifestUtf8ByteLength(JSON.stringify(manifest));
|
|
5233
|
+
const resolveResource = (value, owner) => {
|
|
5234
|
+
const resolved = resolveTileflowNativeResourceUrl(value, { documentUrl: owner, ...network });
|
|
5235
|
+
resolvedBytes += nativeManifestUtf8ByteLength(JSON.stringify(resolved)) - nativeManifestUtf8ByteLength(JSON.stringify(value));
|
|
5236
|
+
if (resolvedBytes > tileflowNativeManifestLimits.maximumBytes) {
|
|
5237
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_TOO_LARGE", "body");
|
|
5238
|
+
}
|
|
5239
|
+
return resolved;
|
|
5266
5240
|
};
|
|
5241
|
+
try {
|
|
5242
|
+
for (const name of Object.keys(manifest.maps).sort()) {
|
|
5243
|
+
const map2 = manifest.maps[name];
|
|
5244
|
+
for (const themeName of Object.keys(map2.themes).sort()) {
|
|
5245
|
+
const theme = map2.themes[themeName];
|
|
5246
|
+
theme.styleUrl = resolveResource(theme.styleUrl, finalUrl);
|
|
5247
|
+
for (const face of theme.fontFaces ?? []) {
|
|
5248
|
+
face.source = resolveResource(face.source, theme.styleUrl);
|
|
5249
|
+
}
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
} catch (error2) {
|
|
5253
|
+
if (error2 instanceof TileflowNativeSourceError) throw normalizeNativeSourceError(error2);
|
|
5254
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_RESOURCE_INVALID", "body");
|
|
5255
|
+
}
|
|
5256
|
+
cancellation.check();
|
|
5257
|
+
return freezeNativeSnapshot({ manifestUrl: finalUrl, manifest });
|
|
5258
|
+
} catch (error2) {
|
|
5259
|
+
cleanup();
|
|
5260
|
+
cancellation.check();
|
|
5261
|
+
throw normalizeNativeSourceError(error2);
|
|
5262
|
+
} finally {
|
|
5263
|
+
unlisten();
|
|
5267
5264
|
}
|
|
5268
|
-
return aligned;
|
|
5269
5265
|
}
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5266
|
+
|
|
5267
|
+
// src/native-source-controller.ts
|
|
5268
|
+
init_portable_identity_rules();
|
|
5269
|
+
|
|
5270
|
+
// src/runtime.ts
|
|
5271
|
+
init_portable_identity_rules();
|
|
5272
|
+
var defaultTileflowRuntimeView = Object.freeze({
|
|
5273
|
+
bearing: 0,
|
|
5274
|
+
center: [0, 20],
|
|
5275
|
+
pitch: 0,
|
|
5276
|
+
zoom: 2
|
|
5277
|
+
});
|
|
5278
|
+
var tileflowStyleFontFaceLimits = Object.freeze({
|
|
5279
|
+
maximumCount: 16,
|
|
5280
|
+
maximumSourceLength: 2048
|
|
5281
|
+
});
|
|
5282
|
+
var maxStaticImagePixels = 1280 * 1280;
|
|
5283
|
+
var maximumManifestBytes = 1024 * 1024;
|
|
5284
|
+
var maximumSessionGrantBytes = 64 * 1024;
|
|
5285
|
+
var manifestCache = new globalThis.Map();
|
|
5286
|
+
function validateTileflowThemeSelection(value) {
|
|
5287
|
+
return value === "system" || isTileflowThemeName(value);
|
|
5288
|
+
}
|
|
5289
|
+
var tileflowThemeBlendLimits = Object.freeze({ maximumThemes: 8, minimumThemes: 2 });
|
|
5290
|
+
function validateTileflowThemeBlendSelection(value) {
|
|
5291
|
+
if (!value || typeof value !== "object") return false;
|
|
5292
|
+
const { position, themes } = value;
|
|
5293
|
+
return Array.isArray(themes) && themes.length >= tileflowThemeBlendLimits.minimumThemes && themes.length <= tileflowThemeBlendLimits.maximumThemes && themes.every((theme) => isTileflowThemeName(theme)) && typeof position === "number" && Number.isFinite(position) && position >= 0 && position <= themes.length - 1;
|
|
5294
|
+
}
|
|
5295
|
+
function nearestTileflowBlendTheme(blend) {
|
|
5296
|
+
const index = Math.min(blend.themes.length - 1, Math.max(0, Math.round(blend.position)));
|
|
5297
|
+
return blend.themes[index];
|
|
5298
|
+
}
|
|
5299
|
+
function resolveTileflowRuntimeTheme(map2, selection, colorScheme) {
|
|
5300
|
+
let name;
|
|
5301
|
+
if (selection === void 0) {
|
|
5302
|
+
name = map2.defaultTheme;
|
|
5303
|
+
} else if (selection === "system") {
|
|
5304
|
+
if (!map2.systemThemes) {
|
|
5305
|
+
throw new Error(
|
|
5306
|
+
`Tileflow map "${map2.name}" does not declare systemThemes; select a concrete theme.`
|
|
5307
|
+
);
|
|
5303
5308
|
}
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
if (!sameAt(1)) return void 0;
|
|
5307
|
-
outputs.push(2);
|
|
5308
|
-
for (let index = 3; index < first.length; index += 2) {
|
|
5309
|
-
if (!sameAt(index)) return void 0;
|
|
5310
|
-
outputs.push(index + 1);
|
|
5309
|
+
if (!colorScheme) {
|
|
5310
|
+
throw new Error('Resolving theme="system" requires an explicit browser color scheme.');
|
|
5311
5311
|
}
|
|
5312
|
+
name = map2.systemThemes[colorScheme];
|
|
5312
5313
|
} else {
|
|
5313
|
-
|
|
5314
|
+
name = selection;
|
|
5314
5315
|
}
|
|
5315
|
-
|
|
5316
|
-
|
|
5317
|
-
}
|
|
5318
|
-
|
|
5319
|
-
const [first] = values;
|
|
5320
|
-
if (values.every((value) => same(value, first))) return first;
|
|
5321
|
-
if (Array.isArray(first) && first[0] !== "literal" && values.every((value) => Array.isArray(value) && value.length === first.length)) {
|
|
5322
|
-
const items = [];
|
|
5323
|
-
for (let index = 0; index < first.length; index += 1) {
|
|
5324
|
-
const item = tryMixTemplate(values.map((value) => value[index]));
|
|
5325
|
-
if (item === void 0 && first[index] !== void 0) return void 0;
|
|
5326
|
-
items.push(item);
|
|
5327
|
-
}
|
|
5328
|
-
return items;
|
|
5316
|
+
if (!isTileflowThemeName(name)) {
|
|
5317
|
+
throw new Error(
|
|
5318
|
+
`Tileflow resolved invalid theme ${JSON.stringify(name)} for map "${map2.name}"; expected a concrete portable theme name.`
|
|
5319
|
+
);
|
|
5329
5320
|
}
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
const item = tryMixTemplate(values.map((value) => value[key]));
|
|
5337
|
-
if (item === void 0) return void 0;
|
|
5338
|
-
out[key] = item;
|
|
5339
|
-
}
|
|
5340
|
-
return out;
|
|
5321
|
+
const theme = Object.hasOwn(map2.themes, name) ? map2.themes[name] : void 0;
|
|
5322
|
+
if (!theme) {
|
|
5323
|
+
const available = Object.keys(map2.themes).sort().join(", ");
|
|
5324
|
+
throw new Error(
|
|
5325
|
+
`Unknown Tileflow theme "${name}" for map "${map2.name}". Available themes: ${available}.`
|
|
5326
|
+
);
|
|
5341
5327
|
}
|
|
5342
|
-
|
|
5343
|
-
if (values.every((value) => typeof value === "string" && oklab(value)))
|
|
5344
|
-
return new BlendLeaf(values);
|
|
5345
|
-
return void 0;
|
|
5328
|
+
return { ...theme, name };
|
|
5346
5329
|
}
|
|
5347
|
-
function
|
|
5348
|
-
|
|
5349
|
-
|
|
5350
|
-
|
|
5330
|
+
function resolveTileflowRuntimeView(options) {
|
|
5331
|
+
const manifestView = options.manifestMap?.view;
|
|
5332
|
+
return {
|
|
5333
|
+
...options.fallback ?? defaultTileflowRuntimeView,
|
|
5334
|
+
...manifestView ?? {},
|
|
5335
|
+
...options.bearing !== void 0 ? { bearing: options.bearing } : {},
|
|
5336
|
+
...options.center !== void 0 ? { center: options.center } : {},
|
|
5337
|
+
...options.pitch !== void 0 ? { pitch: options.pitch } : {},
|
|
5338
|
+
...options.zoom !== void 0 ? { zoom: options.zoom } : {}
|
|
5339
|
+
};
|
|
5351
5340
|
}
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
const
|
|
5356
|
-
if (
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5341
|
+
|
|
5342
|
+
// src/native-source-controller.ts
|
|
5343
|
+
function createTileflowNativeSourceController(options) {
|
|
5344
|
+
const input = nativeOwnRecord(options);
|
|
5345
|
+
if (!input || typeof input.acquire !== "function")
|
|
5346
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
5347
|
+
const acquire = input.acquire;
|
|
5348
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
5349
|
+
let state;
|
|
5350
|
+
let generation = 0;
|
|
5351
|
+
let disposed = false;
|
|
5352
|
+
let active;
|
|
5353
|
+
const notify = (listener, value) => {
|
|
5354
|
+
try {
|
|
5355
|
+
void Promise.resolve(listener(value)).catch(() => void 0);
|
|
5356
|
+
} catch {
|
|
5362
5357
|
}
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
const conditions = [];
|
|
5371
|
-
const outputs = [];
|
|
5372
|
-
for (let index = 1; index < node.length - 1; index += 2) {
|
|
5373
|
-
conditions.push(node[index]);
|
|
5374
|
-
outputs.push(node[index + 1]);
|
|
5358
|
+
};
|
|
5359
|
+
const publish = (next) => {
|
|
5360
|
+
if (disposed || next.generation !== generation) return;
|
|
5361
|
+
state = freezeNativeSnapshot(next);
|
|
5362
|
+
for (const listener of [...listeners]) {
|
|
5363
|
+
if (disposed || state !== next || generation !== next.generation) break;
|
|
5364
|
+
if (listeners.has(listener)) notify(listener, next);
|
|
5375
5365
|
}
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5366
|
+
};
|
|
5367
|
+
return {
|
|
5368
|
+
get state() {
|
|
5369
|
+
return state;
|
|
5370
|
+
},
|
|
5371
|
+
subscribe(listener) {
|
|
5372
|
+
if (typeof listener !== "function")
|
|
5373
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
5374
|
+
if (disposed) return () => void 0;
|
|
5375
|
+
listeners.add(listener);
|
|
5376
|
+
if (state) notify(listener, state);
|
|
5377
|
+
return () => {
|
|
5378
|
+
listeners.delete(listener);
|
|
5379
|
+
};
|
|
5380
|
+
},
|
|
5381
|
+
async replace(source, options2 = {}) {
|
|
5382
|
+
if (disposed) throw new TileflowNativeSourceError("NATIVE_SOURCE_DISPOSED", "source");
|
|
5383
|
+
if (generation >= Number.MAX_SAFE_INTEGER)
|
|
5384
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
5385
|
+
const own = { generation: ++generation, cancellation: new NativeSourceCancellation() };
|
|
5386
|
+
const previous = active;
|
|
5387
|
+
active = own;
|
|
5388
|
+
const current = () => !disposed && generation === own.generation;
|
|
5389
|
+
let sourceInput;
|
|
5390
|
+
let selection;
|
|
5391
|
+
let snapshotError;
|
|
5392
|
+
try {
|
|
5393
|
+
sourceInput = nativeOwnRecord(source);
|
|
5394
|
+
selection = nativeOwnRecord(options2);
|
|
5395
|
+
} catch (error2) {
|
|
5396
|
+
snapshotError = normalizeNativeSourceError(error2);
|
|
5397
|
+
}
|
|
5398
|
+
previous?.cancellation.cancel();
|
|
5399
|
+
let detach = () => void 0;
|
|
5400
|
+
try {
|
|
5401
|
+
if (!current()) return;
|
|
5402
|
+
publish({ status: "loading", generation: own.generation });
|
|
5403
|
+
if (!current()) return;
|
|
5404
|
+
if (snapshotError) throw snapshotError;
|
|
5405
|
+
if (!sourceInput || !selection || Object.hasOwn(sourceInput, "kind") || Object.hasOwn(sourceInput, "style") || !isTileflowPortableId(sourceInput.map))
|
|
5406
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "source");
|
|
5407
|
+
if (selection.theme !== void 0 && !validateTileflowThemeSelection(selection.theme) || selection.colorScheme !== void 0 && selection.colorScheme !== "light" && selection.colorScheme !== "dark") {
|
|
5408
|
+
throw new TileflowNativeSourceError("NATIVE_THEME_INVALID", "theme");
|
|
5409
|
+
}
|
|
5410
|
+
const selectedSource = {
|
|
5411
|
+
map: sourceInput.map,
|
|
5412
|
+
manifestUrl: sourceInput.manifestUrl
|
|
5413
|
+
};
|
|
5414
|
+
if (sourceInput.developmentOrigin !== void 0) {
|
|
5415
|
+
try {
|
|
5416
|
+
const developmentOrigin = sourceInput.developmentOrigin;
|
|
5417
|
+
selectedSource.developmentOrigin = resolveTileflowNativeManifestUrl(developmentOrigin, {
|
|
5418
|
+
developmentOrigin
|
|
5419
|
+
}).slice(0, -1);
|
|
5420
|
+
} catch {
|
|
5421
|
+
throw new TileflowNativeSourceError("NATIVE_MANIFEST_URL_INVALID", "manifestUrl");
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
detach = own.cancellation.link(selection.signal);
|
|
5425
|
+
const result = await loadNativeManifest(
|
|
5426
|
+
selectedSource.manifestUrl,
|
|
5427
|
+
acquire,
|
|
5428
|
+
{
|
|
5429
|
+
developmentOrigin: selectedSource.developmentOrigin
|
|
5430
|
+
},
|
|
5431
|
+
own.cancellation
|
|
5432
|
+
);
|
|
5433
|
+
if (!current()) return;
|
|
5434
|
+
if (!Object.hasOwn(result.manifest.maps, selectedSource.map)) {
|
|
5435
|
+
throw new TileflowNativeSourceError("NATIVE_MAP_NOT_FOUND", "map");
|
|
5436
|
+
}
|
|
5437
|
+
const entry = result.manifest.maps[selectedSource.map];
|
|
5438
|
+
const apiUrl = entry.apiUrl ?? result.manifest.apiUrl;
|
|
5439
|
+
const map2 = {
|
|
5440
|
+
...entry,
|
|
5441
|
+
name: selectedSource.map,
|
|
5442
|
+
...apiUrl === void 0 ? {} : { apiUrl }
|
|
5443
|
+
};
|
|
5444
|
+
let theme;
|
|
5445
|
+
try {
|
|
5446
|
+
theme = resolveTileflowRuntimeTheme(
|
|
5447
|
+
map2,
|
|
5448
|
+
selection.theme,
|
|
5449
|
+
selection.colorScheme
|
|
5450
|
+
);
|
|
5451
|
+
} catch {
|
|
5452
|
+
throw new TileflowNativeSourceError("NATIVE_THEME_INVALID", "theme");
|
|
5453
|
+
}
|
|
5454
|
+
publish({
|
|
5455
|
+
status: "ready",
|
|
5456
|
+
generation: own.generation,
|
|
5457
|
+
source: selectedSource,
|
|
5458
|
+
...result,
|
|
5459
|
+
map: map2,
|
|
5460
|
+
theme
|
|
5461
|
+
});
|
|
5462
|
+
} catch (error2) {
|
|
5463
|
+
if (current())
|
|
5464
|
+
publish({
|
|
5465
|
+
status: "error",
|
|
5466
|
+
generation: own.generation,
|
|
5467
|
+
error: normalizeNativeSourceError(error2)
|
|
5468
|
+
});
|
|
5469
|
+
} finally {
|
|
5470
|
+
detach();
|
|
5471
|
+
if (active === own) active = void 0;
|
|
5472
|
+
}
|
|
5473
|
+
},
|
|
5474
|
+
dispose() {
|
|
5475
|
+
if (disposed) return;
|
|
5476
|
+
disposed = true;
|
|
5477
|
+
listeners.clear();
|
|
5478
|
+
const previous = active;
|
|
5479
|
+
active = void 0;
|
|
5480
|
+
previous?.cancellation.cancel();
|
|
5393
5481
|
}
|
|
5394
|
-
|
|
5395
|
-
index: ["step", node[1], 0, ...stops.flatMap((stop, index) => [stop, index + 1])],
|
|
5396
|
-
outputs
|
|
5397
|
-
};
|
|
5398
|
-
}
|
|
5399
|
-
return void 0;
|
|
5400
|
-
}
|
|
5401
|
-
function firstDecision(value) {
|
|
5402
|
-
const decision = decisionOf(value);
|
|
5403
|
-
if (decision) return decision;
|
|
5404
|
-
if (!Array.isArray(value) || value[0] === "literal") return void 0;
|
|
5405
|
-
for (const item of value) {
|
|
5406
|
-
const found = firstDecision(item);
|
|
5407
|
-
if (found) return found;
|
|
5408
|
-
}
|
|
5409
|
-
return void 0;
|
|
5410
|
-
}
|
|
5411
|
-
function choose(value, key, branch) {
|
|
5412
|
-
const decision = decisionOf(value);
|
|
5413
|
-
if (decision && JSON.stringify(decision.index) === key)
|
|
5414
|
-
return choose(decision.outputs[branch], key, branch);
|
|
5415
|
-
if (!Array.isArray(value) || value[0] === "literal") return value;
|
|
5416
|
-
return value.map((item) => choose(item, key, branch));
|
|
5417
|
-
}
|
|
5418
|
-
function splitBranches(valuesByProperty, conditions = []) {
|
|
5419
|
-
let decision;
|
|
5420
|
-
for (const values of Object.values(valuesByProperty)) {
|
|
5421
|
-
decision = firstDecision(values[0]);
|
|
5422
|
-
if (decision) break;
|
|
5423
|
-
}
|
|
5424
|
-
if (!decision) {
|
|
5425
|
-
const residual = Object.values(valuesByProperty).some((values) => values.some(isDataDriven));
|
|
5426
|
-
return residual ? void 0 : [{ conditions, valuesByProperty }];
|
|
5427
|
-
}
|
|
5428
|
-
if (reads(decision.index, "zoom") || reads(decision.index, "feature-state")) return void 0;
|
|
5429
|
-
const key = JSON.stringify(decision.index);
|
|
5430
|
-
const branches = [];
|
|
5431
|
-
for (let branch = 0; branch < decision.outputs.length; branch += 1) {
|
|
5432
|
-
const chosen = Object.fromEntries(
|
|
5433
|
-
Object.entries(valuesByProperty).map(([property, values]) => [
|
|
5434
|
-
property,
|
|
5435
|
-
values.map((value) => choose(value, key, branch))
|
|
5436
|
-
])
|
|
5437
|
-
);
|
|
5438
|
-
const nested = splitBranches(chosen, [...conditions, ["==", decision.index, branch]]);
|
|
5439
|
-
if (!nested) return void 0;
|
|
5440
|
-
branches.push(...nested);
|
|
5441
|
-
if (branches.length > maximumBranches) return void 0;
|
|
5442
|
-
}
|
|
5443
|
-
return branches;
|
|
5444
|
-
}
|
|
5445
|
-
var isLegacyFilter = (filter) => Array.isArray(filter) && typeof filter[1] === "string" && !Array.isArray(filter[1]);
|
|
5446
|
-
function scaleByWeight(opacity, weight) {
|
|
5447
|
-
const input = Array.isArray(opacity) ? opacity[0] === "interpolate" ? opacity[2] : opacity[1] : void 0;
|
|
5448
|
-
if (Array.isArray(opacity) && (opacity[0] === "interpolate" || opacity[0] === "step") && reads(input, "zoom")) {
|
|
5449
|
-
const head = opacity[0] === "interpolate" ? 3 : 2;
|
|
5450
|
-
return opacity.map(
|
|
5451
|
-
(item, index) => index >= head && (index - head) % 2 === (opacity[0] === "interpolate" ? 1 : 0) ? scaleByWeight(item, weight) : item
|
|
5452
|
-
);
|
|
5453
|
-
}
|
|
5454
|
-
if (typeof opacity === "number")
|
|
5455
|
-
return new BlendLeaf(weight.values.map((value) => opacity * Number(value)));
|
|
5456
|
-
return ["*", opacity, weight];
|
|
5457
|
-
}
|
|
5458
|
-
function same(a, b) {
|
|
5459
|
-
return JSON.stringify(a) === JSON.stringify(b);
|
|
5482
|
+
};
|
|
5460
5483
|
}
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5484
|
+
|
|
5485
|
+
// src/native-initial-view.ts
|
|
5486
|
+
init_runtime_view_schema();
|
|
5487
|
+
var viewSchema = createTileflowRuntimeViewSchema(miniManifestSchemaOperations);
|
|
5488
|
+
var viewKeys = ["bearing", "center", "pitch", "zoom"];
|
|
5489
|
+
var inputKeys = ["view", "mapOptionsView", "manifestView"];
|
|
5490
|
+
var invalid = () => {
|
|
5491
|
+
throw new TileflowNativeSourceError("NATIVE_SOURCE_INVALID", "view");
|
|
5492
|
+
};
|
|
5493
|
+
function resolveTileflowNativeInitialView(options = {}) {
|
|
5494
|
+
try {
|
|
5495
|
+
const input = snapshotRecord(options, inputKeys);
|
|
5496
|
+
const manifestView = snapshotView(input.manifestView);
|
|
5497
|
+
const mapOptionsView = snapshotView(input.mapOptionsView);
|
|
5498
|
+
const view = snapshotView(input.view);
|
|
5499
|
+
const resolved = resolveTileflowRuntimeView({
|
|
5500
|
+
...view,
|
|
5501
|
+
fallback: { ...defaultTileflowRuntimeView, ...manifestView, ...mapOptionsView }
|
|
5471
5502
|
});
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
];
|
|
5503
|
+
return freezeNativeSnapshot({
|
|
5504
|
+
center: [resolved.center[0], resolved.center[1]],
|
|
5505
|
+
zoom: resolved.zoom,
|
|
5506
|
+
bearing: resolved.bearing,
|
|
5507
|
+
pitch: resolved.pitch
|
|
5508
|
+
});
|
|
5509
|
+
} catch {
|
|
5510
|
+
return invalid();
|
|
5481
5511
|
}
|
|
5482
|
-
if (oklabCache.size > 4096) oklabCache.clear();
|
|
5483
|
-
oklabCache.set(colour, result);
|
|
5484
|
-
return result;
|
|
5485
5512
|
}
|
|
5486
|
-
function
|
|
5487
|
-
const
|
|
5488
|
-
|
|
5489
|
-
const
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
|
|
5494
|
-
].map((value) => {
|
|
5495
|
-
const clamped = Math.min(1, Math.max(0, value));
|
|
5496
|
-
const encoded = clamped <= 31308e-7 ? clamped * 12.92 : 1.055 * clamped ** (1 / 2.4) - 0.055;
|
|
5497
|
-
return Math.round(encoded * 255);
|
|
5498
|
-
});
|
|
5499
|
-
return `rgba(${red}, ${green}, ${blue}, ${Number(alpha.toFixed(3))})`;
|
|
5513
|
+
function snapshotRecord(input, keys) {
|
|
5514
|
+
const snapshot = nativeOwnRecord(input);
|
|
5515
|
+
if (!snapshot) return invalid();
|
|
5516
|
+
const ownKeys = Reflect.ownKeys(input);
|
|
5517
|
+
if (ownKeys.length !== Object.keys(snapshot).length || ownKeys.some((key) => typeof key !== "string" || !keys.includes(key)))
|
|
5518
|
+
return invalid();
|
|
5519
|
+
return snapshot;
|
|
5500
5520
|
}
|
|
5501
|
-
function
|
|
5502
|
-
|
|
5503
|
-
const
|
|
5504
|
-
if (
|
|
5505
|
-
const
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
const alpha = parts[3] === void 0 ? 1 : parseUnit(parts[3], 1);
|
|
5514
|
-
if (functional[1].startsWith("rgb")) {
|
|
5515
|
-
const [r, g, b] = parts.slice(0, 3).map((part) => parseUnit(part, 255));
|
|
5516
|
-
if ([r, g, b, alpha].some((value) => value === null)) return null;
|
|
5517
|
-
return [r, g, b, alpha];
|
|
5521
|
+
function snapshotView(input) {
|
|
5522
|
+
if (input === void 0) return {};
|
|
5523
|
+
const snapshot = snapshotRecord(input, viewKeys);
|
|
5524
|
+
if (snapshot.center !== void 0) {
|
|
5525
|
+
const center = snapshot.center;
|
|
5526
|
+
if (!Array.isArray(center) || Object.getPrototypeOf(center) !== Array.prototype || Reflect.ownKeys(center).length !== 3 || Object.getOwnPropertyDescriptor(center, "length")?.value !== 2)
|
|
5527
|
+
return invalid();
|
|
5528
|
+
const longitude = Object.getOwnPropertyDescriptor(center, "0");
|
|
5529
|
+
const latitude = Object.getOwnPropertyDescriptor(center, "1");
|
|
5530
|
+
if (!longitude?.enumerable || !latitude?.enumerable || !("value" in longitude) || !("value" in latitude))
|
|
5531
|
+
return invalid();
|
|
5532
|
+
snapshot.center = [longitude.value, latitude.value];
|
|
5518
5533
|
}
|
|
5519
|
-
const
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
const [r1, g1, b1] = sector < 1 ? [chroma, x, 0] : sector < 2 ? [x, chroma, 0] : sector < 3 ? [0, chroma, x] : sector < 4 ? [0, x, chroma] : sector < 5 ? [x, 0, chroma] : [chroma, 0, x];
|
|
5527
|
-
const offset = light - chroma / 2;
|
|
5528
|
-
return [(r1 + offset) * 255, (g1 + offset) * 255, (b1 + offset) * 255, alpha];
|
|
5529
|
-
}
|
|
5530
|
-
function parseUnit(part, scale) {
|
|
5531
|
-
const percentage = part.endsWith("%");
|
|
5532
|
-
const value = Number.parseFloat(part);
|
|
5533
|
-
if (!Number.isFinite(value)) return null;
|
|
5534
|
-
return percentage ? value / 100 * scale : value;
|
|
5534
|
+
const parsed = parse(viewSchema, snapshot);
|
|
5535
|
+
return {
|
|
5536
|
+
...parsed.bearing === void 0 ? {} : { bearing: parsed.bearing },
|
|
5537
|
+
...parsed.center === void 0 ? {} : { center: parsed.center },
|
|
5538
|
+
...parsed.pitch === void 0 ? {} : { pitch: parsed.pitch },
|
|
5539
|
+
...parsed.zoom === void 0 ? {} : { zoom: parsed.zoom }
|
|
5540
|
+
};
|
|
5535
5541
|
}
|
|
5542
|
+
|
|
5543
|
+
// src/native.ts
|
|
5544
|
+
init_theme_blend();
|
|
5536
5545
|
export {
|
|
5537
5546
|
TileflowNativeSourceError,
|
|
5538
5547
|
TileflowNativeUrlError,
|