@tileflow/core 0.1.0-alpha.33 → 0.1.0-alpha.34
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 +3 -0
- package/dist/browser.d.ts +478 -150
- package/dist/browser.js +6810 -4170
- package/dist/build.d.ts +12 -4
- package/dist/build.js +609 -222
- package/dist/config-reference.json +2413 -829
- package/dist/{icon-composition-CSnN2-Xt.d.ts → icon-composition-DqoZWQuz.d.ts} +189 -2
- package/dist/index.d.ts +76 -5
- package/dist/index.js +945 -250
- package/dist/{manifest-types-E7m23eXL.d.ts → manifest-types-hmzy2bBX.d.ts} +20 -1
- package/dist/manifest.d.ts +2 -2
- package/dist/runtime.d.ts +1 -1
- package/docs/application-tile-reading.md +3 -0
- package/docs/authoring-model.md +2 -1
- package/docs/buildings-3d.md +66 -62
- package/docs/street-lights.md +32 -5
- package/docs/trees-3d.md +211 -0
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -850,98 +850,6 @@ function cloneJson(value) {
|
|
|
850
850
|
return JSON.parse(JSON.stringify(value));
|
|
851
851
|
}
|
|
852
852
|
|
|
853
|
-
// src/cartography/contributions.ts
|
|
854
|
-
var tileflowLayerSlots = [
|
|
855
|
-
"background",
|
|
856
|
-
"land",
|
|
857
|
-
"terrain",
|
|
858
|
-
"hydro",
|
|
859
|
-
"building-areas",
|
|
860
|
-
"transport-areas",
|
|
861
|
-
"transport-tunnel-shadow",
|
|
862
|
-
"transport-tunnel-casing",
|
|
863
|
-
"transport-tunnel-fill",
|
|
864
|
-
"transport-pedestrian-areas",
|
|
865
|
-
"aeroways",
|
|
866
|
-
"transport-surface-shadow",
|
|
867
|
-
"transport-surface-casing",
|
|
868
|
-
"transport-surface-fill",
|
|
869
|
-
"transport-bridge-shadow",
|
|
870
|
-
"transport-bridge-casing",
|
|
871
|
-
"transport-bridge-fill",
|
|
872
|
-
"transport-symbols",
|
|
873
|
-
"boundaries",
|
|
874
|
-
"buildings",
|
|
875
|
-
"vegetation",
|
|
876
|
-
"symbols"
|
|
877
|
-
];
|
|
878
|
-
var tileflowLayerBands = [
|
|
879
|
-
"land",
|
|
880
|
-
"relief",
|
|
881
|
-
"water",
|
|
882
|
-
"roads",
|
|
883
|
-
"boundaries",
|
|
884
|
-
"buildings",
|
|
885
|
-
"vegetation",
|
|
886
|
-
"labels"
|
|
887
|
-
];
|
|
888
|
-
var bandSlots = {
|
|
889
|
-
land: ["background", "land"],
|
|
890
|
-
relief: ["terrain", "terrain"],
|
|
891
|
-
water: ["hydro", "hydro"],
|
|
892
|
-
roads: ["transport-areas", "transport-symbols"],
|
|
893
|
-
boundaries: ["boundaries", "boundaries"],
|
|
894
|
-
buildings: ["buildings", "buildings"],
|
|
895
|
-
vegetation: ["vegetation", "vegetation"],
|
|
896
|
-
labels: ["symbols", "symbols"]
|
|
897
|
-
};
|
|
898
|
-
var tileflowBandPlacements = tileflowLayerBands.flatMap(
|
|
899
|
-
(band) => [`below-${band}`, `above-${band}`]
|
|
900
|
-
);
|
|
901
|
-
function tileflowBandPlacementSlot(placement) {
|
|
902
|
-
const [side, band] = splitBandPlacement(placement);
|
|
903
|
-
return bandSlots[band][side === "below" ? 0 : 1];
|
|
904
|
-
}
|
|
905
|
-
function tileflowBandPlacementIndex(slotRanks, placement) {
|
|
906
|
-
const [side, band] = splitBandPlacement(placement);
|
|
907
|
-
const [first, last] = bandSlots[band];
|
|
908
|
-
const threshold = side === "below" ? tileflowLayerSlots.indexOf(first) : tileflowLayerSlots.indexOf(last) + 1;
|
|
909
|
-
const index = slotRanks.findIndex((rank) => rank !== void 0 && rank >= threshold);
|
|
910
|
-
return index < 0 ? slotRanks.length : index;
|
|
911
|
-
}
|
|
912
|
-
function splitBandPlacement(placement) {
|
|
913
|
-
const separator = placement.indexOf("-");
|
|
914
|
-
return [
|
|
915
|
-
placement.slice(0, separator),
|
|
916
|
-
placement.slice(separator + 1)
|
|
917
|
-
];
|
|
918
|
-
}
|
|
919
|
-
var tileflowSemanticTargetPattern = /^[a-z][a-z0-9-]*(?:\.[A-Za-z0-9_-]+)*$/u;
|
|
920
|
-
var tileflowRenderStackOperationNamePattern = /^[a-z][A-Za-z0-9_-]*$/u;
|
|
921
|
-
var tileflowCompilerMetadataKeys = Object.freeze({
|
|
922
|
-
owner: "tileflow:compiler-owner",
|
|
923
|
-
slot: "tileflow:compiler-slot",
|
|
924
|
-
target: "tileflow:compiler-target"
|
|
925
|
-
});
|
|
926
|
-
|
|
927
|
-
// src/modules/addresses/index.ts
|
|
928
|
-
function addresses(options = {}) {
|
|
929
|
-
return { type: "addresses", ...cloneJson2(options) };
|
|
930
|
-
}
|
|
931
|
-
function cloneJson2(value) {
|
|
932
|
-
return JSON.parse(JSON.stringify(value));
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
// src/cartography/context.ts
|
|
936
|
-
function typographyTextStyle(typography) {
|
|
937
|
-
return {
|
|
938
|
-
font: typography.font,
|
|
939
|
-
...typography.fallbacks ? { fallbacks: typography.fallbacks } : {},
|
|
940
|
-
...typography.letterSpacing === void 0 ? {} : { letterSpacing: typography.letterSpacing },
|
|
941
|
-
...typography.transform === void 0 ? {} : { transform: typography.transform }
|
|
942
|
-
};
|
|
943
|
-
}
|
|
944
|
-
|
|
945
853
|
// src/cartography/layer-style.ts
|
|
946
854
|
import { Color as Color2 } from "@maplibre/maplibre-gl-style-spec";
|
|
947
855
|
|
|
@@ -1169,11 +1077,11 @@ var zoom = {
|
|
|
1169
1077
|
};
|
|
1170
1078
|
function expression(value) {
|
|
1171
1079
|
validateExpressionArray(value, "expression");
|
|
1172
|
-
return { kind: "expression", value:
|
|
1080
|
+
return { kind: "expression", value: cloneJson2(value) };
|
|
1173
1081
|
}
|
|
1174
1082
|
function toMapLibreStyleValue(value) {
|
|
1175
1083
|
if (isTileflowExpression(value)) {
|
|
1176
|
-
return
|
|
1084
|
+
return cloneJson2(value.value);
|
|
1177
1085
|
}
|
|
1178
1086
|
if (isTileflowZoomValue(value)) {
|
|
1179
1087
|
if (value.interpolation === "step") {
|
|
@@ -1181,8 +1089,8 @@ function toMapLibreStyleValue(value) {
|
|
|
1181
1089
|
return [
|
|
1182
1090
|
"step",
|
|
1183
1091
|
["zoom"],
|
|
1184
|
-
|
|
1185
|
-
...rest.flatMap(([stop, stopValue]) => [stop,
|
|
1092
|
+
cloneJson2(firstValue),
|
|
1093
|
+
...rest.flatMap(([stop, stopValue]) => [stop, cloneJson2(stopValue)])
|
|
1186
1094
|
];
|
|
1187
1095
|
}
|
|
1188
1096
|
const interpolation = value.interpolation === "exponential" ? ["exponential", value.base] : [value.interpolation];
|
|
@@ -1190,13 +1098,13 @@ function toMapLibreStyleValue(value) {
|
|
|
1190
1098
|
"interpolate",
|
|
1191
1099
|
interpolation,
|
|
1192
1100
|
["zoom"],
|
|
1193
|
-
...value.stops.flatMap(([stop, stopValue]) => [stop,
|
|
1101
|
+
...value.stops.flatMap(([stop, stopValue]) => [stop, cloneJson2(stopValue)])
|
|
1194
1102
|
];
|
|
1195
1103
|
}
|
|
1196
1104
|
if (isTileflowThemeValueNode(value)) {
|
|
1197
1105
|
throw new Error("Tileflow theme values must be resolved before MapLibre style compilation.");
|
|
1198
1106
|
}
|
|
1199
|
-
return
|
|
1107
|
+
return cloneJson2(value);
|
|
1200
1108
|
}
|
|
1201
1109
|
function isTileflowExpression(value) {
|
|
1202
1110
|
return isRecord(value) && value.kind === "expression" && Array.isArray(value.value);
|
|
@@ -1233,7 +1141,7 @@ function createZoomValue(interpolation, stops, base) {
|
|
|
1233
1141
|
throw new Error("Tileflow zoom stops must be strictly increasing.");
|
|
1234
1142
|
}
|
|
1235
1143
|
previous = stop;
|
|
1236
|
-
return [stop,
|
|
1144
|
+
return [stop, cloneJson2(value)];
|
|
1237
1145
|
});
|
|
1238
1146
|
return {
|
|
1239
1147
|
kind: "zoom",
|
|
@@ -1249,9 +1157,9 @@ function validateExpressionArray(value, name) {
|
|
|
1249
1157
|
if (!isMapLibreExpressionOperator(value[0])) {
|
|
1250
1158
|
throw new Error(`Unknown MapLibre expression operator: ${value[0]}`);
|
|
1251
1159
|
}
|
|
1252
|
-
|
|
1160
|
+
cloneJson2(value);
|
|
1253
1161
|
}
|
|
1254
|
-
function
|
|
1162
|
+
function cloneJson2(value) {
|
|
1255
1163
|
const serialized = JSON.stringify(value);
|
|
1256
1164
|
if (serialized === void 0) {
|
|
1257
1165
|
throw new Error("Tileflow style values must be JSON-serializable.");
|
|
@@ -1571,30 +1479,30 @@ function asRecord(value) {
|
|
|
1571
1479
|
|
|
1572
1480
|
// src/cartography/merge.ts
|
|
1573
1481
|
function mergeTileflowDesign(base, ...overlays) {
|
|
1574
|
-
let resolved =
|
|
1482
|
+
let resolved = cloneJson3(base);
|
|
1575
1483
|
for (const overlay of overlays) {
|
|
1576
1484
|
resolved = mergeValue(resolved, overlay);
|
|
1577
1485
|
}
|
|
1578
1486
|
return resolved;
|
|
1579
1487
|
}
|
|
1580
1488
|
function mergeValue(base, overlay) {
|
|
1581
|
-
if (overlay === void 0) return
|
|
1489
|
+
if (overlay === void 0) return cloneJson3(base);
|
|
1582
1490
|
if (Array.isArray(overlay) || isTileflowExpression(overlay) || isTileflowThemeValueNode(overlay) || isTileflowZoomValue(overlay) || !isRecord2(overlay)) {
|
|
1583
|
-
return
|
|
1491
|
+
return cloneJson3(overlay);
|
|
1584
1492
|
}
|
|
1585
1493
|
const baseRecord = isRecord2(base) ? base : {};
|
|
1586
1494
|
const result = {};
|
|
1587
1495
|
for (const key of /* @__PURE__ */ new Set([...Object.keys(baseRecord), ...Object.keys(overlay)])) {
|
|
1588
1496
|
const overlayValue = overlay[key];
|
|
1589
1497
|
if (overlayValue === void 0) {
|
|
1590
|
-
if (key in baseRecord) result[key] =
|
|
1498
|
+
if (key in baseRecord) result[key] = cloneJson3(baseRecord[key]);
|
|
1591
1499
|
continue;
|
|
1592
1500
|
}
|
|
1593
1501
|
result[key] = mergeValue(baseRecord[key], overlayValue);
|
|
1594
1502
|
}
|
|
1595
1503
|
return result;
|
|
1596
1504
|
}
|
|
1597
|
-
function
|
|
1505
|
+
function cloneJson3(value) {
|
|
1598
1506
|
if (value === void 0) return value;
|
|
1599
1507
|
return JSON.parse(JSON.stringify(value));
|
|
1600
1508
|
}
|
|
@@ -1602,6 +1510,402 @@ function isRecord2(value) {
|
|
|
1602
1510
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
1603
1511
|
}
|
|
1604
1512
|
|
|
1513
|
+
// src/trees-3d.ts
|
|
1514
|
+
var tileflowWorldTreeFields = Object.freeze({
|
|
1515
|
+
height: "height",
|
|
1516
|
+
diameterCrown: "diameter_crown",
|
|
1517
|
+
circumference: "circumference",
|
|
1518
|
+
genus: "genus",
|
|
1519
|
+
species: "species",
|
|
1520
|
+
leafType: "leaf_type",
|
|
1521
|
+
taxon: "taxon",
|
|
1522
|
+
canopyRank: "rank",
|
|
1523
|
+
canopyClearance: "clearance_px_z15",
|
|
1524
|
+
canopyCover: "cover_pct",
|
|
1525
|
+
canopyHeight: "height_m"
|
|
1526
|
+
});
|
|
1527
|
+
var tileflowDefaultUnknownTreeForms = Object.freeze({
|
|
1528
|
+
round: 1,
|
|
1529
|
+
open: 1,
|
|
1530
|
+
tall: 1
|
|
1531
|
+
});
|
|
1532
|
+
var broadleaves = Object.freeze({
|
|
1533
|
+
...Object.fromEntries(
|
|
1534
|
+
[
|
|
1535
|
+
"acacia",
|
|
1536
|
+
"albizia",
|
|
1537
|
+
"arbutus",
|
|
1538
|
+
"bursera",
|
|
1539
|
+
"ceratonia",
|
|
1540
|
+
"delonix",
|
|
1541
|
+
"ficus",
|
|
1542
|
+
"gleditsia",
|
|
1543
|
+
"jacaranda",
|
|
1544
|
+
"olea",
|
|
1545
|
+
"quercus",
|
|
1546
|
+
"robinia",
|
|
1547
|
+
"schinus",
|
|
1548
|
+
"sophora",
|
|
1549
|
+
"styphnolobium",
|
|
1550
|
+
"tamarix"
|
|
1551
|
+
].map((genus) => [genus, "open"])
|
|
1552
|
+
),
|
|
1553
|
+
...Object.fromEntries(
|
|
1554
|
+
[
|
|
1555
|
+
"betula",
|
|
1556
|
+
"celtis",
|
|
1557
|
+
"fraxinus",
|
|
1558
|
+
"ginkgo",
|
|
1559
|
+
"liquidambar",
|
|
1560
|
+
"liriodendron",
|
|
1561
|
+
"magnolia",
|
|
1562
|
+
"platanus",
|
|
1563
|
+
"populus",
|
|
1564
|
+
"pyrus",
|
|
1565
|
+
"ulmus",
|
|
1566
|
+
"zelkova"
|
|
1567
|
+
].map((genus) => [genus, "tall"])
|
|
1568
|
+
),
|
|
1569
|
+
...Object.fromEntries(
|
|
1570
|
+
[
|
|
1571
|
+
"acer",
|
|
1572
|
+
"aesculus",
|
|
1573
|
+
"carpinus",
|
|
1574
|
+
"castanea",
|
|
1575
|
+
"catalpa",
|
|
1576
|
+
"cercis",
|
|
1577
|
+
"citrus",
|
|
1578
|
+
"fagus",
|
|
1579
|
+
"lagerstroemia",
|
|
1580
|
+
"malus",
|
|
1581
|
+
"melia",
|
|
1582
|
+
"morus",
|
|
1583
|
+
"prunus",
|
|
1584
|
+
"sorbus",
|
|
1585
|
+
"tilia"
|
|
1586
|
+
].map((genus) => [genus, "round"])
|
|
1587
|
+
)
|
|
1588
|
+
});
|
|
1589
|
+
var tileflowTreeModelIdPattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
1590
|
+
var tileflowVegetationMetadataKey = "tileflow:vegetation";
|
|
1591
|
+
function tileflowVegetationMetadata(vegetation2) {
|
|
1592
|
+
return { version: 1, ...vegetation2 };
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// src/modules/vegetation/compiler.ts
|
|
1596
|
+
function compileVegetation(request, context) {
|
|
1597
|
+
const minZoom = request?.flat?.minZoom ?? 16;
|
|
1598
|
+
const mode = request?.mode ?? "3d";
|
|
1599
|
+
const config = mergeTileflowDesign(
|
|
1600
|
+
{
|
|
1601
|
+
type: "vegetation",
|
|
1602
|
+
enabled: true,
|
|
1603
|
+
flat: {
|
|
1604
|
+
color: context.colors.landcover.wood,
|
|
1605
|
+
minZoom,
|
|
1606
|
+
opacity: mode === "3d" ? 0.82 : 0.9,
|
|
1607
|
+
pitchAlignment: "map",
|
|
1608
|
+
pitchScale: "map",
|
|
1609
|
+
radius: minZoom < 24 ? zoom.linear([
|
|
1610
|
+
[minZoom, 2.2],
|
|
1611
|
+
[minZoom < 20 ? 20 : 24, 8]
|
|
1612
|
+
]) : 2.2,
|
|
1613
|
+
strokeColor: context.colors.park,
|
|
1614
|
+
strokeOpacity: 0.55,
|
|
1615
|
+
strokeWidth: 0.8
|
|
1616
|
+
},
|
|
1617
|
+
mode,
|
|
1618
|
+
threeDimensional: {
|
|
1619
|
+
barkColor: context.colors.vegetation.tree.bark,
|
|
1620
|
+
broadleafColors: context.colors.vegetation.tree.broadleaf,
|
|
1621
|
+
coniferColors: context.colors.vegetation.tree.conifer,
|
|
1622
|
+
palmColors: context.colors.vegetation.tree.palm,
|
|
1623
|
+
crownScale: 1,
|
|
1624
|
+
heightScale: 1
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
request
|
|
1628
|
+
);
|
|
1629
|
+
if (config.enabled === false || !context.data.schema.layers.tree) return [];
|
|
1630
|
+
const resolvedMode = config.mode ?? "3d";
|
|
1631
|
+
return [
|
|
1632
|
+
{
|
|
1633
|
+
kind: "layer",
|
|
1634
|
+
layer: applyCircleStyle(
|
|
1635
|
+
{
|
|
1636
|
+
id: "tileflow-vegetation-trees",
|
|
1637
|
+
type: "circle",
|
|
1638
|
+
source: context.data.sourceId,
|
|
1639
|
+
"source-layer": context.data.schema.layers.tree,
|
|
1640
|
+
// The layer also holds rows of trees as lines; a circle on each vertex would misdraw them.
|
|
1641
|
+
filter: ["==", ["geometry-type"], "Point"],
|
|
1642
|
+
metadata: {
|
|
1643
|
+
"tileflow:vegetation-mode": resolvedMode,
|
|
1644
|
+
...resolvedMode === "3d" ? { "tileflow:vegetation-fallback": "flat-circle" } : {}
|
|
1645
|
+
}
|
|
1646
|
+
},
|
|
1647
|
+
config.flat ?? {}
|
|
1648
|
+
),
|
|
1649
|
+
localOrder: 1,
|
|
1650
|
+
owner: "vegetation",
|
|
1651
|
+
slot: "vegetation",
|
|
1652
|
+
target: "vegetation.trees"
|
|
1653
|
+
}
|
|
1654
|
+
];
|
|
1655
|
+
}
|
|
1656
|
+
function tileflowVegetationDescription(request, context) {
|
|
1657
|
+
const { schema } = context.data;
|
|
1658
|
+
if (request?.enabled === false || (request?.mode ?? "3d") !== "3d" || !schema.layers.tree)
|
|
1659
|
+
return void 0;
|
|
1660
|
+
const tree = context.colors.vegetation.tree;
|
|
1661
|
+
const style = request?.threeDimensional ?? {};
|
|
1662
|
+
const colours = (value, fallback) => Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string") ? value : [...fallback];
|
|
1663
|
+
const number = (value) => {
|
|
1664
|
+
const resolved = value === void 0 ? void 0 : toMapLibreStyleValue(value);
|
|
1665
|
+
return typeof resolved === "number" && resolved > 0 ? resolved : 1;
|
|
1666
|
+
};
|
|
1667
|
+
const field2 = (name, fallback) => schema.fields[name] ?? fallback;
|
|
1668
|
+
return {
|
|
1669
|
+
source: context.data.sourceId,
|
|
1670
|
+
layers: {
|
|
1671
|
+
tree: schema.layers.tree,
|
|
1672
|
+
...schema.layers.canopy ? { canopy: schema.layers.canopy } : {}
|
|
1673
|
+
},
|
|
1674
|
+
fields: {
|
|
1675
|
+
...tileflowWorldTreeFields,
|
|
1676
|
+
height: field2("height", tileflowWorldTreeFields.height),
|
|
1677
|
+
diameterCrown: field2("diameterCrown", tileflowWorldTreeFields.diameterCrown),
|
|
1678
|
+
genus: field2("genus", tileflowWorldTreeFields.genus),
|
|
1679
|
+
species: field2("species", tileflowWorldTreeFields.species),
|
|
1680
|
+
leafType: field2("leafType", tileflowWorldTreeFields.leafType),
|
|
1681
|
+
canopyRank: field2("canopyRank", tileflowWorldTreeFields.canopyRank),
|
|
1682
|
+
canopyClearance: field2("canopyClearanceAtZoom15", tileflowWorldTreeFields.canopyClearance),
|
|
1683
|
+
canopyCover: field2("canopyCoverPercent", tileflowWorldTreeFields.canopyCover)
|
|
1684
|
+
},
|
|
1685
|
+
colors: {
|
|
1686
|
+
bark: typeof style.barkColor === "string" ? style.barkColor : tree.bark,
|
|
1687
|
+
broadleaf: colours(style.broadleafColors, tree.broadleaf),
|
|
1688
|
+
conifer: colours(style.coniferColors, tree.conifer),
|
|
1689
|
+
palm: colours(style.palmColors, tree.palm)
|
|
1690
|
+
},
|
|
1691
|
+
heightScale: number(style.heightScale),
|
|
1692
|
+
crownScale: number(style.crownScale),
|
|
1693
|
+
forms: Object.fromEntries(
|
|
1694
|
+
Object.entries(style.forms ?? {}).map(([form, own]) => [
|
|
1695
|
+
form,
|
|
1696
|
+
{
|
|
1697
|
+
heightScale: number(own?.heightScale),
|
|
1698
|
+
crownScale: number(own?.crownScale),
|
|
1699
|
+
...own?.models?.length ? { models: [...own.models] } : {}
|
|
1700
|
+
}
|
|
1701
|
+
])
|
|
1702
|
+
),
|
|
1703
|
+
// Filled by the compiler from the map's prepared models.
|
|
1704
|
+
models: {},
|
|
1705
|
+
finish: style.finish ?? "faceted",
|
|
1706
|
+
edges: (() => {
|
|
1707
|
+
const edges = toMapLibreStyleValue(style.edges ?? 0);
|
|
1708
|
+
return typeof edges === "number" ? edges : 0;
|
|
1709
|
+
})(),
|
|
1710
|
+
...(() => {
|
|
1711
|
+
const edgeColor = style.edgeColor === void 0 ? void 0 : toMapLibreStyleValue(style.edgeColor);
|
|
1712
|
+
return typeof edgeColor === "string" ? { edgeColor } : {};
|
|
1713
|
+
})(),
|
|
1714
|
+
unknownForms: style.unknownForms ?? tileflowDefaultUnknownTreeForms,
|
|
1715
|
+
regions: style.regions ?? [],
|
|
1716
|
+
// Filled by the compiler once the style's layers are final.
|
|
1717
|
+
flatLayers: []
|
|
1718
|
+
};
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
// src/buildings-3d-design.ts
|
|
1722
|
+
var tileflowBuildingsMetadataKey = "tileflow:buildings";
|
|
1723
|
+
var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
1724
|
+
source: "tileflow",
|
|
1725
|
+
layers: Object.freeze({ building: "building", places: "poi" }),
|
|
1726
|
+
color: "#d8d0c0",
|
|
1727
|
+
edges: 1,
|
|
1728
|
+
nightLight: 1,
|
|
1729
|
+
windows: false,
|
|
1730
|
+
shadows: true,
|
|
1731
|
+
occlusion: true
|
|
1732
|
+
});
|
|
1733
|
+
function tileflowBuildingsMetadata(design) {
|
|
1734
|
+
return { version: 1, ...design };
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
// src/street-lights.ts
|
|
1738
|
+
var tileflowStreetLightsMetadataKey = "tileflow:street-lights";
|
|
1739
|
+
var tileflowDefaultStreetLightsDesign = Object.freeze({
|
|
1740
|
+
source: "tileflow",
|
|
1741
|
+
layers: Object.freeze({
|
|
1742
|
+
streetFurniture: "street_furniture",
|
|
1743
|
+
transportation: "transportation",
|
|
1744
|
+
sidewalk: "sidewalk"
|
|
1745
|
+
}),
|
|
1746
|
+
estimate: "lit",
|
|
1747
|
+
color: "#ffcf8f",
|
|
1748
|
+
intensity: 1
|
|
1749
|
+
});
|
|
1750
|
+
function tileflowStreetLightsMetadata(design) {
|
|
1751
|
+
return { version: 1, ...design };
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// src/cartography/scene-3d-metadata.ts
|
|
1755
|
+
var colourSources = [
|
|
1756
|
+
["tileflow-buildings-render-extrusion", "fill-extrusion-color"],
|
|
1757
|
+
["tileflow-buildings-3d", "fill-extrusion-color"],
|
|
1758
|
+
["tileflow-buildings-fill", "fill-color"]
|
|
1759
|
+
];
|
|
1760
|
+
function tileflowBuildings3DDesignOf(module, context, layers) {
|
|
1761
|
+
const config = isRecord3(module) ? module : {};
|
|
1762
|
+
if (config.enabled === false) return void 0;
|
|
1763
|
+
const style = config.threeDimensional ?? {};
|
|
1764
|
+
let color2;
|
|
1765
|
+
for (const [id2, property] of colourSources) {
|
|
1766
|
+
const value = layers.find((layer) => layer.id === id2)?.paint?.[property];
|
|
1767
|
+
if (typeof value === "string" || Array.isArray(value)) {
|
|
1768
|
+
color2 = value;
|
|
1769
|
+
break;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
const number = (value, fallback) => {
|
|
1773
|
+
const resolved = value === void 0 ? void 0 : toMapLibreStyleValue(value);
|
|
1774
|
+
return typeof resolved === "number" ? resolved : fallback;
|
|
1775
|
+
};
|
|
1776
|
+
const edgeColor = style.edgeColor === void 0 ? void 0 : toMapLibreStyleValue(style.edgeColor);
|
|
1777
|
+
return {
|
|
1778
|
+
source: context.data.sourceId,
|
|
1779
|
+
layers: {
|
|
1780
|
+
building: context.data.schema.layers.building,
|
|
1781
|
+
...context.data.schema.layers.poi ? { places: context.data.schema.layers.poi } : {}
|
|
1782
|
+
},
|
|
1783
|
+
color: color2 ?? context.colors.buildings.generic,
|
|
1784
|
+
edges: number(style.edges, 1),
|
|
1785
|
+
...typeof edgeColor === "string" ? { edgeColor } : {},
|
|
1786
|
+
nightLight: number(style.nightLight, 1),
|
|
1787
|
+
windows: style.windows === true,
|
|
1788
|
+
shadows: style.shadows !== false,
|
|
1789
|
+
occlusion: style.occlusion !== false
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
function tileflowStreetLightsDesignOf(module, context) {
|
|
1793
|
+
const config = isRecord3(module) ? module : {};
|
|
1794
|
+
const layers = context.data.schema.layers;
|
|
1795
|
+
const style = config.streetLights ?? {};
|
|
1796
|
+
if (config.enabled === false || style.enabled === false || !layers.streetFurniture)
|
|
1797
|
+
return void 0;
|
|
1798
|
+
const color2 = style.color === void 0 ? void 0 : toMapLibreStyleValue(style.color);
|
|
1799
|
+
const intensity = style.intensity === void 0 ? void 0 : toMapLibreStyleValue(style.intensity);
|
|
1800
|
+
const estimate = style.estimate;
|
|
1801
|
+
return {
|
|
1802
|
+
source: context.data.sourceId,
|
|
1803
|
+
layers: {
|
|
1804
|
+
streetFurniture: layers.streetFurniture,
|
|
1805
|
+
transportation: layers.road,
|
|
1806
|
+
...layers.sidewalk ? { sidewalk: layers.sidewalk } : {}
|
|
1807
|
+
},
|
|
1808
|
+
estimate: estimate === "streets" || estimate === "none" || estimate === "lit" ? estimate : "lit",
|
|
1809
|
+
color: typeof color2 === "string" ? color2 : tileflowDefaultStreetLightsDesign.color,
|
|
1810
|
+
intensity: typeof intensity === "number" ? intensity : 1
|
|
1811
|
+
};
|
|
1812
|
+
}
|
|
1813
|
+
function isRecord3(value) {
|
|
1814
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
// src/cartography/contributions.ts
|
|
1818
|
+
var tileflowLayerSlots = [
|
|
1819
|
+
"background",
|
|
1820
|
+
"land",
|
|
1821
|
+
"terrain",
|
|
1822
|
+
"hydro",
|
|
1823
|
+
"building-areas",
|
|
1824
|
+
"transport-areas",
|
|
1825
|
+
"transport-tunnel-shadow",
|
|
1826
|
+
"transport-tunnel-casing",
|
|
1827
|
+
"transport-tunnel-fill",
|
|
1828
|
+
"transport-pedestrian-areas",
|
|
1829
|
+
"aeroways",
|
|
1830
|
+
"transport-surface-shadow",
|
|
1831
|
+
"transport-surface-casing",
|
|
1832
|
+
"transport-surface-fill",
|
|
1833
|
+
"transport-bridge-shadow",
|
|
1834
|
+
"transport-bridge-casing",
|
|
1835
|
+
"transport-bridge-fill",
|
|
1836
|
+
"transport-symbols",
|
|
1837
|
+
"boundaries",
|
|
1838
|
+
"buildings",
|
|
1839
|
+
"vegetation",
|
|
1840
|
+
"symbols"
|
|
1841
|
+
];
|
|
1842
|
+
var tileflowLayerBands = [
|
|
1843
|
+
"land",
|
|
1844
|
+
"relief",
|
|
1845
|
+
"water",
|
|
1846
|
+
"roads",
|
|
1847
|
+
"boundaries",
|
|
1848
|
+
"buildings",
|
|
1849
|
+
"vegetation",
|
|
1850
|
+
"labels"
|
|
1851
|
+
];
|
|
1852
|
+
var bandSlots = {
|
|
1853
|
+
land: ["background", "land"],
|
|
1854
|
+
relief: ["terrain", "terrain"],
|
|
1855
|
+
water: ["hydro", "hydro"],
|
|
1856
|
+
roads: ["transport-areas", "transport-symbols"],
|
|
1857
|
+
boundaries: ["boundaries", "boundaries"],
|
|
1858
|
+
buildings: ["buildings", "buildings"],
|
|
1859
|
+
vegetation: ["vegetation", "vegetation"],
|
|
1860
|
+
labels: ["symbols", "symbols"]
|
|
1861
|
+
};
|
|
1862
|
+
var tileflowBandPlacements = tileflowLayerBands.flatMap(
|
|
1863
|
+
(band) => [`below-${band}`, `above-${band}`]
|
|
1864
|
+
);
|
|
1865
|
+
function tileflowBandPlacementSlot(placement) {
|
|
1866
|
+
const [side, band] = splitBandPlacement(placement);
|
|
1867
|
+
return bandSlots[band][side === "below" ? 0 : 1];
|
|
1868
|
+
}
|
|
1869
|
+
function tileflowBandPlacementIndex(slotRanks, placement) {
|
|
1870
|
+
const [side, band] = splitBandPlacement(placement);
|
|
1871
|
+
const [first, last] = bandSlots[band];
|
|
1872
|
+
const threshold = side === "below" ? tileflowLayerSlots.indexOf(first) : tileflowLayerSlots.indexOf(last) + 1;
|
|
1873
|
+
const index = slotRanks.findIndex((rank) => rank !== void 0 && rank >= threshold);
|
|
1874
|
+
return index < 0 ? slotRanks.length : index;
|
|
1875
|
+
}
|
|
1876
|
+
function splitBandPlacement(placement) {
|
|
1877
|
+
const separator = placement.indexOf("-");
|
|
1878
|
+
return [
|
|
1879
|
+
placement.slice(0, separator),
|
|
1880
|
+
placement.slice(separator + 1)
|
|
1881
|
+
];
|
|
1882
|
+
}
|
|
1883
|
+
var tileflowSemanticTargetPattern = /^[a-z][a-z0-9-]*(?:\.[A-Za-z0-9_-]+)*$/u;
|
|
1884
|
+
var tileflowRenderStackOperationNamePattern = /^[a-z][A-Za-z0-9_-]*$/u;
|
|
1885
|
+
var tileflowCompilerMetadataKeys = Object.freeze({
|
|
1886
|
+
owner: "tileflow:compiler-owner",
|
|
1887
|
+
slot: "tileflow:compiler-slot",
|
|
1888
|
+
target: "tileflow:compiler-target"
|
|
1889
|
+
});
|
|
1890
|
+
|
|
1891
|
+
// src/modules/addresses/index.ts
|
|
1892
|
+
function addresses(options = {}) {
|
|
1893
|
+
return { type: "addresses", ...cloneJson4(options) };
|
|
1894
|
+
}
|
|
1895
|
+
function cloneJson4(value) {
|
|
1896
|
+
return JSON.parse(JSON.stringify(value));
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
// src/cartography/context.ts
|
|
1900
|
+
function typographyTextStyle(typography) {
|
|
1901
|
+
return {
|
|
1902
|
+
font: typography.font,
|
|
1903
|
+
...typography.fallbacks ? { fallbacks: typography.fallbacks } : {},
|
|
1904
|
+
...typography.letterSpacing === void 0 ? {} : { letterSpacing: typography.letterSpacing },
|
|
1905
|
+
...typography.transform === void 0 ? {} : { transform: typography.transform }
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1605
1909
|
// src/modules/addresses/compiler.ts
|
|
1606
1910
|
function compileAddresses(request, context) {
|
|
1607
1911
|
if (request?.enabled === false) return [];
|
|
@@ -4463,7 +4767,7 @@ function auditTileflowThemeValues(value, path = "value", context = inferAuditCon
|
|
|
4463
4767
|
return diagnostics.sort(compareAuditDiagnostics);
|
|
4464
4768
|
}
|
|
4465
4769
|
function auditTileflowMapThemeValues(map) {
|
|
4466
|
-
const modules =
|
|
4770
|
+
const modules = isRecord4(map.modules) ? map.modules : void 0;
|
|
4467
4771
|
const moduleDiagnostics = modules ? Object.keys(modules).sort(compareCodeUnits2).flatMap(
|
|
4468
4772
|
(owner) => auditTileflowThemeValues(modules[owner], `modules.${owner}`, {
|
|
4469
4773
|
owner,
|
|
@@ -4566,7 +4870,7 @@ function isThemePrimitiveForCategory(value, category) {
|
|
|
4566
4870
|
return category === "number" ? typeof value === "number" && Number.isFinite(value) || Array.isArray(value) && value.every((entry) => typeof entry === "number" && Number.isFinite(entry)) : typeof value === "string" && value.length > 0;
|
|
4567
4871
|
}
|
|
4568
4872
|
function isThemeValueCandidate(value) {
|
|
4569
|
-
return
|
|
4873
|
+
return isRecord4(value) && (value.kind === "theme-token" || value.kind === "theme-fixed" || value.kind === "theme-color");
|
|
4570
4874
|
}
|
|
4571
4875
|
function visitAuditableValue(value, path, category, state, intentRequired = false) {
|
|
4572
4876
|
if (isThemeStructuralPath(path)) category = void 0;
|
|
@@ -4582,7 +4886,7 @@ function visitAuditableValue(value, path, category, state, intentRequired = fals
|
|
|
4582
4886
|
visitAuditableArray(value, path, category, state, false, intentRequired);
|
|
4583
4887
|
return;
|
|
4584
4888
|
}
|
|
4585
|
-
if (!
|
|
4889
|
+
if (!isRecord4(value)) return;
|
|
4586
4890
|
if (value.kind === "expression" && Array.isArray(value.value)) {
|
|
4587
4891
|
visitAuditableArray(value.value, `${path}.value`, category, state, true, intentRequired);
|
|
4588
4892
|
return;
|
|
@@ -4897,7 +5201,7 @@ var ThemeValueResolver = class {
|
|
|
4897
5201
|
if (Array.isArray(value)) {
|
|
4898
5202
|
return value.map((entry, index) => this.resolveTree(entry, `${path}[${index}]`, category));
|
|
4899
5203
|
}
|
|
4900
|
-
if (!
|
|
5204
|
+
if (!isRecord4(value)) return value;
|
|
4901
5205
|
if (value.kind === "expression" && Array.isArray(value.value)) {
|
|
4902
5206
|
return {
|
|
4903
5207
|
...value,
|
|
@@ -5209,7 +5513,7 @@ function assertThemeLighting(value, path) {
|
|
|
5209
5513
|
}
|
|
5210
5514
|
}
|
|
5211
5515
|
function assertThemeCategoryValue(value, expectedCategory, path) {
|
|
5212
|
-
if (!
|
|
5516
|
+
if (!isRecord4(value)) {
|
|
5213
5517
|
assertTokenPrimitive(expectedCategory, value, path);
|
|
5214
5518
|
return;
|
|
5215
5519
|
}
|
|
@@ -5561,11 +5865,11 @@ function cloneJson14(value) {
|
|
|
5561
5865
|
if (serialized === void 0) throw new Error("Tileflow themes must be JSON-serializable.");
|
|
5562
5866
|
return JSON.parse(serialized);
|
|
5563
5867
|
}
|
|
5564
|
-
function
|
|
5868
|
+
function isRecord4(value) {
|
|
5565
5869
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
5566
5870
|
}
|
|
5567
5871
|
function isPlainRecord(value) {
|
|
5568
|
-
if (!
|
|
5872
|
+
if (!isRecord4(value)) return false;
|
|
5569
5873
|
const prototype = Object.getPrototypeOf(value);
|
|
5570
5874
|
return prototype === Object.prototype || prototype === null;
|
|
5571
5875
|
}
|
|
@@ -5757,7 +6061,8 @@ function resolveColors(overrides = {}, defaults4 = defaultColors, moduleOverride
|
|
|
5757
6061
|
resolved.landcover.grass,
|
|
5758
6062
|
resolved.landcover.meadow
|
|
5759
6063
|
],
|
|
5760
|
-
conifer: [resolved.landcover.protected, resolved.landcover.scrub, resolved.landcover.wood]
|
|
6064
|
+
conifer: [resolved.landcover.protected, resolved.landcover.scrub, resolved.landcover.wood],
|
|
6065
|
+
palm: [resolved.landcover.urbanPark, resolved.landcover.grass, resolved.landcover.meadow]
|
|
5761
6066
|
}
|
|
5762
6067
|
}
|
|
5763
6068
|
};
|
|
@@ -5924,6 +6229,11 @@ function resolveThemeColors(theme) {
|
|
|
5924
6229
|
optionalColor("vegetation.tree.conifer.a", colors.vegetation.tree.conifer[0]),
|
|
5925
6230
|
optionalColor("vegetation.tree.conifer.b", colors.vegetation.tree.conifer[1]),
|
|
5926
6231
|
optionalColor("vegetation.tree.conifer.c", colors.vegetation.tree.conifer[2])
|
|
6232
|
+
],
|
|
6233
|
+
palm: [
|
|
6234
|
+
optionalColor("vegetation.tree.palm.a", colors.vegetation.tree.palm[0]),
|
|
6235
|
+
optionalColor("vegetation.tree.palm.b", colors.vegetation.tree.palm[1]),
|
|
6236
|
+
optionalColor("vegetation.tree.palm.c", colors.vegetation.tree.palm[2])
|
|
5927
6237
|
]
|
|
5928
6238
|
}
|
|
5929
6239
|
}
|
|
@@ -7272,76 +7582,6 @@ function cloneJson16(value) {
|
|
|
7272
7582
|
return JSON.parse(JSON.stringify(value));
|
|
7273
7583
|
}
|
|
7274
7584
|
|
|
7275
|
-
// src/modules/vegetation/compiler.ts
|
|
7276
|
-
function compileVegetation(request, context) {
|
|
7277
|
-
const minZoom = request?.flat?.minZoom ?? 16;
|
|
7278
|
-
const mode = request?.mode ?? "3d";
|
|
7279
|
-
const config = mergeTileflowDesign(
|
|
7280
|
-
{
|
|
7281
|
-
type: "vegetation",
|
|
7282
|
-
enabled: true,
|
|
7283
|
-
flat: {
|
|
7284
|
-
color: context.colors.landcover.wood,
|
|
7285
|
-
minZoom,
|
|
7286
|
-
opacity: mode === "3d" ? 0.82 : 0.9,
|
|
7287
|
-
pitchAlignment: "map",
|
|
7288
|
-
pitchScale: "map",
|
|
7289
|
-
radius: minZoom < 24 ? zoom.linear([
|
|
7290
|
-
[minZoom, 2.2],
|
|
7291
|
-
[minZoom < 20 ? 20 : 24, 8]
|
|
7292
|
-
]) : 2.2,
|
|
7293
|
-
strokeColor: context.colors.park,
|
|
7294
|
-
strokeOpacity: 0.55,
|
|
7295
|
-
strokeWidth: 0.8
|
|
7296
|
-
},
|
|
7297
|
-
mode,
|
|
7298
|
-
threeDimensional: {
|
|
7299
|
-
barkColor: context.colors.vegetation.tree.bark,
|
|
7300
|
-
broadleafColors: context.colors.vegetation.tree.broadleaf,
|
|
7301
|
-
coniferColors: context.colors.vegetation.tree.conifer,
|
|
7302
|
-
crownScale: 1,
|
|
7303
|
-
heightScale: 1
|
|
7304
|
-
}
|
|
7305
|
-
},
|
|
7306
|
-
request
|
|
7307
|
-
);
|
|
7308
|
-
if (config.enabled === false || !context.data.schema.layers.tree) return [];
|
|
7309
|
-
const resolvedMode = config.mode ?? "3d";
|
|
7310
|
-
const threeDimensional = config.threeDimensional;
|
|
7311
|
-
return [
|
|
7312
|
-
{
|
|
7313
|
-
kind: "layer",
|
|
7314
|
-
layer: applyCircleStyle(
|
|
7315
|
-
{
|
|
7316
|
-
id: "tileflow-vegetation-trees",
|
|
7317
|
-
type: "circle",
|
|
7318
|
-
source: context.data.sourceId,
|
|
7319
|
-
"source-layer": context.data.schema.layers.tree,
|
|
7320
|
-
metadata: {
|
|
7321
|
-
"tileflow:vegetation-mode": resolvedMode,
|
|
7322
|
-
...resolvedMode === "3d" ? { "tileflow:vegetation-fallback": "flat-circle" } : {},
|
|
7323
|
-
"tileflow:tree-bark-color": threeDimensional.barkColor,
|
|
7324
|
-
"tileflow:tree-broadleaf-colors": threeDimensional.broadleafColors,
|
|
7325
|
-
"tileflow:tree-conifer-colors": threeDimensional.coniferColors,
|
|
7326
|
-
"tileflow:tree-crown-field": context.data.schema.fields.diameterCrown,
|
|
7327
|
-
"tileflow:tree-crown-scale": threeDimensional.crownScale,
|
|
7328
|
-
"tileflow:tree-genus-field": context.data.schema.fields.genus,
|
|
7329
|
-
"tileflow:tree-height-field": context.data.schema.fields.height,
|
|
7330
|
-
"tileflow:tree-height-scale": threeDimensional.heightScale,
|
|
7331
|
-
"tileflow:tree-leaf-type-field": context.data.schema.fields.leafType,
|
|
7332
|
-
"tileflow:tree-species-field": context.data.schema.fields.species
|
|
7333
|
-
}
|
|
7334
|
-
},
|
|
7335
|
-
config.flat ?? {}
|
|
7336
|
-
),
|
|
7337
|
-
localOrder: 1,
|
|
7338
|
-
owner: "vegetation",
|
|
7339
|
-
slot: "vegetation",
|
|
7340
|
-
target: "vegetation.trees"
|
|
7341
|
-
}
|
|
7342
|
-
];
|
|
7343
|
-
}
|
|
7344
|
-
|
|
7345
7585
|
// src/modules/water/index.ts
|
|
7346
7586
|
function water(options = {}) {
|
|
7347
7587
|
return { type: "water", ...cloneJson17(options) };
|
|
@@ -9054,21 +9294,21 @@ function bindSemanticValue(value, schema, sourceId) {
|
|
|
9054
9294
|
}
|
|
9055
9295
|
if (isDataSourceReference(value)) return sourceId;
|
|
9056
9296
|
if (Array.isArray(value)) return value.map((item) => bindSemanticValue(item, schema, sourceId));
|
|
9057
|
-
if (!
|
|
9297
|
+
if (!isRecord5(value)) return value;
|
|
9058
9298
|
return Object.fromEntries(
|
|
9059
9299
|
Object.entries(value).map(([key, item]) => [key, bindSemanticValue(item, schema, sourceId)])
|
|
9060
9300
|
);
|
|
9061
9301
|
}
|
|
9062
9302
|
function isDataFieldReference2(value) {
|
|
9063
|
-
return
|
|
9303
|
+
return isRecord5(value) && value.kind === "tileflow-data-field" && typeof value.name === "string";
|
|
9064
9304
|
}
|
|
9065
9305
|
function isDataLayerReference(value) {
|
|
9066
|
-
return
|
|
9306
|
+
return isRecord5(value) && value.kind === "tileflow-data-layer" && typeof value.name === "string";
|
|
9067
9307
|
}
|
|
9068
9308
|
function isDataSourceReference(value) {
|
|
9069
|
-
return
|
|
9309
|
+
return isRecord5(value) && value.kind === "tileflow-data-source" && value.name === "primary";
|
|
9070
9310
|
}
|
|
9071
|
-
function
|
|
9311
|
+
function isRecord5(value) {
|
|
9072
9312
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
9073
9313
|
}
|
|
9074
9314
|
function compareCodeUnits5(left, right) {
|
|
@@ -9172,8 +9412,8 @@ function createTileflowLayerTemplateIR(layer, semanticKey) {
|
|
|
9172
9412
|
renderer: type,
|
|
9173
9413
|
...filter === void 0 ? {} : { selector: cloneJson20(filter) },
|
|
9174
9414
|
style: Object.freeze({
|
|
9175
|
-
...
|
|
9176
|
-
...
|
|
9415
|
+
...isRecord6(layout) ? { placement: Object.freeze(cloneJson20(layout)) } : {},
|
|
9416
|
+
...isRecord6(paint) ? { appearance: Object.freeze(cloneJson20(paint)) } : {}
|
|
9177
9417
|
})
|
|
9178
9418
|
});
|
|
9179
9419
|
}
|
|
@@ -9413,21 +9653,21 @@ function visitReferences(value, counts, visited = /* @__PURE__ */ new WeakSet())
|
|
|
9413
9653
|
}
|
|
9414
9654
|
}
|
|
9415
9655
|
function isSemanticFieldReference(value) {
|
|
9416
|
-
return
|
|
9656
|
+
return isRecord6(value) && value.kind === "tileflow-data-field";
|
|
9417
9657
|
}
|
|
9418
9658
|
function isSemanticLayerReference(value) {
|
|
9419
|
-
return
|
|
9659
|
+
return isRecord6(value) && value.kind === "tileflow-data-layer";
|
|
9420
9660
|
}
|
|
9421
9661
|
function isSemanticSourceReference(value) {
|
|
9422
|
-
return
|
|
9662
|
+
return isRecord6(value) && value.kind === "tileflow-data-source";
|
|
9423
9663
|
}
|
|
9424
9664
|
function cloneJson20(value) {
|
|
9425
9665
|
return JSON.parse(JSON.stringify(value));
|
|
9426
9666
|
}
|
|
9427
9667
|
function asRecord3(value) {
|
|
9428
|
-
return
|
|
9668
|
+
return isRecord6(value) ? value : {};
|
|
9429
9669
|
}
|
|
9430
|
-
function
|
|
9670
|
+
function isRecord6(value) {
|
|
9431
9671
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
9432
9672
|
}
|
|
9433
9673
|
|
|
@@ -9479,7 +9719,7 @@ function validateTileflowRenderSelectorConstraints(input) {
|
|
|
9479
9719
|
};
|
|
9480
9720
|
while (pending.length > 0) {
|
|
9481
9721
|
const current = pending.pop();
|
|
9482
|
-
if (!
|
|
9722
|
+
if (!isRecord7(current.selector) || typeof current.selector.kind !== "string") {
|
|
9483
9723
|
addIssue(
|
|
9484
9724
|
"invalid-selector",
|
|
9485
9725
|
"a render selector must be a semantic selector node",
|
|
@@ -9540,7 +9780,7 @@ function validateTileflowRenderSelectorConstraints(input) {
|
|
|
9540
9780
|
}
|
|
9541
9781
|
for (const [index, branch] of current.selector.branches.entries()) {
|
|
9542
9782
|
const branchPath = [...branchesPath, index];
|
|
9543
|
-
if (!
|
|
9783
|
+
if (!isRecord7(branch)) {
|
|
9544
9784
|
addIssue("invalid-selector", "match selector branch must be an object", branchPath);
|
|
9545
9785
|
continue;
|
|
9546
9786
|
}
|
|
@@ -9571,14 +9811,14 @@ function validateTileflowRenderSelectorConstraints(input) {
|
|
|
9571
9811
|
for (let index = current.selector.stops.length - 1; index >= 0; index -= 1) {
|
|
9572
9812
|
const stop = current.selector.stops[index];
|
|
9573
9813
|
const stopPath = [...stopsPath, index];
|
|
9574
|
-
if (!
|
|
9814
|
+
if (!isRecord7(stop)) {
|
|
9575
9815
|
addIssue("invalid-selector", "step selector stop must be an object", stopPath);
|
|
9576
9816
|
continue;
|
|
9577
9817
|
}
|
|
9578
9818
|
pushChild(stop.selector, current.depth + 1, [...stopPath, "selector"]);
|
|
9579
9819
|
}
|
|
9580
9820
|
for (const [index, stop] of current.selector.stops.entries()) {
|
|
9581
|
-
if (!
|
|
9821
|
+
if (!isRecord7(stop)) continue;
|
|
9582
9822
|
const zoom3 = stop.zoom;
|
|
9583
9823
|
const zoomPath = [...stopsPath, index, "zoom"];
|
|
9584
9824
|
if (typeof zoom3 !== "number" || !Number.isFinite(zoom3) || zoom3 < 0 || zoom3 > 24) {
|
|
@@ -9903,7 +10143,7 @@ function applyRendererStyle(layer, renderer, style) {
|
|
|
9903
10143
|
};
|
|
9904
10144
|
}
|
|
9905
10145
|
function lowerSelector(selector, data) {
|
|
9906
|
-
if (!
|
|
10146
|
+
if (!isRecord7(selector) || typeof selector.kind !== "string") {
|
|
9907
10147
|
throw renderStackError(
|
|
9908
10148
|
"invalid-selector",
|
|
9909
10149
|
"A render selector must be a semantic selector node."
|
|
@@ -10106,7 +10346,7 @@ function requireRenderer(value) {
|
|
|
10106
10346
|
function requirePlacement(value) {
|
|
10107
10347
|
if (typeof value === "string") {
|
|
10108
10348
|
if (tileflowBandPlacements.includes(value)) return;
|
|
10109
|
-
} else if (
|
|
10349
|
+
} else if (isRecord7(value)) {
|
|
10110
10350
|
const keys = Object.keys(value);
|
|
10111
10351
|
if (keys.length === 1 && (keys[0] === "above" || keys[0] === "below")) {
|
|
10112
10352
|
requirePortableTarget(value[keys[0]], "render placement target");
|
|
@@ -10133,7 +10373,7 @@ function validateRefinementShape(operation) {
|
|
|
10133
10373
|
validateStyle(operation.renderer, operation.style);
|
|
10134
10374
|
}
|
|
10135
10375
|
function validateStyle(renderer, style) {
|
|
10136
|
-
if (!
|
|
10376
|
+
if (!isRecord7(style)) {
|
|
10137
10377
|
throw renderStackError(
|
|
10138
10378
|
"invalid-style",
|
|
10139
10379
|
`A ${renderer} render operation requires a style object.`
|
|
@@ -10235,7 +10475,7 @@ function normalizeRequirements(requirements) {
|
|
|
10235
10475
|
return [...requirements];
|
|
10236
10476
|
}
|
|
10237
10477
|
function requireRenderStackEntries(stack) {
|
|
10238
|
-
if (!
|
|
10478
|
+
if (!isRecord7(stack)) {
|
|
10239
10479
|
throw renderStackError("invalid-stack", "A render stack must be a named operation record.");
|
|
10240
10480
|
}
|
|
10241
10481
|
const entries = Object.entries(stack);
|
|
@@ -10382,9 +10622,9 @@ function cloneJson21(value) {
|
|
|
10382
10622
|
return JSON.parse(JSON.stringify(value));
|
|
10383
10623
|
}
|
|
10384
10624
|
function asRecord4(value) {
|
|
10385
|
-
return
|
|
10625
|
+
return isRecord7(value) ? value : {};
|
|
10386
10626
|
}
|
|
10387
|
-
function
|
|
10627
|
+
function isRecord7(value) {
|
|
10388
10628
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
10389
10629
|
}
|
|
10390
10630
|
|
|
@@ -11408,6 +11648,17 @@ var waterModuleSchema = z5.object({
|
|
|
11408
11648
|
stream: lineStyleSchema.optional()
|
|
11409
11649
|
}).strict().optional()
|
|
11410
11650
|
}).strict();
|
|
11651
|
+
function boundedThemeNumberSchema(min, max) {
|
|
11652
|
+
return z5.union([
|
|
11653
|
+
z5.number().finite().min(min).max(max),
|
|
11654
|
+
themeNumberReferenceSchema,
|
|
11655
|
+
z5.object({
|
|
11656
|
+
kind: z5.literal("theme-fixed"),
|
|
11657
|
+
reason: z5.string().trim().min(1),
|
|
11658
|
+
value: z5.number().finite().min(min).max(max)
|
|
11659
|
+
}).strict()
|
|
11660
|
+
]);
|
|
11661
|
+
}
|
|
11411
11662
|
var buildingsModuleSchema = z5.object({
|
|
11412
11663
|
type: z5.literal("buildings"),
|
|
11413
11664
|
businessCorridor: areaStyleSchema.optional(),
|
|
@@ -11415,7 +11666,15 @@ var buildingsModuleSchema = z5.object({
|
|
|
11415
11666
|
extrusion: extrusionStyleSchema.optional(),
|
|
11416
11667
|
flat: areaStyleSchema.optional(),
|
|
11417
11668
|
mode: z5.enum(["3d", "flat"]).optional(),
|
|
11418
|
-
renderStack: renderStackSchema.optional()
|
|
11669
|
+
renderStack: renderStackSchema.optional(),
|
|
11670
|
+
threeDimensional: z5.object({
|
|
11671
|
+
edges: boundedThemeNumberSchema(0, 1).optional(),
|
|
11672
|
+
edgeColor: themeColorValueSchema.optional(),
|
|
11673
|
+
nightLight: boundedThemeNumberSchema(0, 2).optional(),
|
|
11674
|
+
occlusion: z5.boolean().optional(),
|
|
11675
|
+
shadows: z5.boolean().optional(),
|
|
11676
|
+
windows: z5.boolean().optional()
|
|
11677
|
+
}).strict().optional()
|
|
11419
11678
|
}).strict();
|
|
11420
11679
|
var addressesModuleSchema = z5.object({
|
|
11421
11680
|
type: z5.literal("addresses"),
|
|
@@ -11528,6 +11787,12 @@ var roadsModuleSchema = z5.object({
|
|
|
11528
11787
|
pattern: fillStyleSchema.optional(),
|
|
11529
11788
|
surface: fillStyleSchema.optional()
|
|
11530
11789
|
}).strict().optional(),
|
|
11790
|
+
streetLights: z5.object({
|
|
11791
|
+
color: themeColorValueSchema.optional(),
|
|
11792
|
+
enabled: z5.boolean().optional(),
|
|
11793
|
+
estimate: z5.enum(["lit", "streets", "none"]).optional(),
|
|
11794
|
+
intensity: boundedThemeNumberSchema(0, 2).optional()
|
|
11795
|
+
}).strict().optional(),
|
|
11531
11796
|
structures: roadStructureMapSchema.optional(),
|
|
11532
11797
|
weight: z5.enum(["thin", "regular", "bold"]).optional(),
|
|
11533
11798
|
widthScale: z5.partialRecord(roadClassSchema, themeNumberValueSchema).optional()
|
|
@@ -11616,6 +11881,16 @@ var nauticalModuleSchema = z5.object({
|
|
|
11616
11881
|
wreckAreas: areaStyleSchema.optional(),
|
|
11617
11882
|
wrecks: markerSymbolStyleSchema.optional()
|
|
11618
11883
|
}).strict();
|
|
11884
|
+
var treeFormMixSchema = z5.object({
|
|
11885
|
+
round: z5.number().finite().min(0).optional(),
|
|
11886
|
+
open: z5.number().finite().min(0).optional(),
|
|
11887
|
+
tall: z5.number().finite().min(0).optional(),
|
|
11888
|
+
conifer: z5.number().finite().min(0).optional(),
|
|
11889
|
+
columnar: z5.number().finite().min(0).optional(),
|
|
11890
|
+
palm: z5.number().finite().min(0).optional()
|
|
11891
|
+
}).strict().refine((mix2) => Object.values(mix2).some((weight) => (weight ?? 0) > 0), {
|
|
11892
|
+
message: "Expected at least one tree form with a weight above 0"
|
|
11893
|
+
});
|
|
11619
11894
|
var modulesSchema = z5.object({
|
|
11620
11895
|
addresses: addressesModuleSchema.optional(),
|
|
11621
11896
|
aeroways: aerowaysModuleSchema.optional(),
|
|
@@ -11638,6 +11913,39 @@ var modulesSchema = z5.object({
|
|
|
11638
11913
|
barkColor: themeColorValueSchema.optional(),
|
|
11639
11914
|
broadleafColors: z5.array(themeColorValueSchema).min(1).max(8).optional(),
|
|
11640
11915
|
coniferColors: z5.array(themeColorValueSchema).min(1).max(8).optional(),
|
|
11916
|
+
palmColors: z5.array(themeColorValueSchema).min(1).max(8).optional(),
|
|
11917
|
+
finish: z5.enum(["faceted", "smooth", "toon"]).optional(),
|
|
11918
|
+
edges: boundedThemeNumberSchema(0, 1).optional(),
|
|
11919
|
+
edgeColor: themeColorValueSchema.optional(),
|
|
11920
|
+
forms: z5.partialRecord(
|
|
11921
|
+
z5.enum(["round", "open", "tall", "conifer", "columnar", "palm"]),
|
|
11922
|
+
z5.object({
|
|
11923
|
+
crownScale: boundedThemeNumberSchema(0.1, 10).optional(),
|
|
11924
|
+
heightScale: boundedThemeNumberSchema(0.1, 10).optional(),
|
|
11925
|
+
models: z5.array(
|
|
11926
|
+
z5.string().max(64).regex(
|
|
11927
|
+
tileflowTreeModelIdPattern,
|
|
11928
|
+
"Expected a model id: its .glb file name in lowercase letters, digits and hyphens"
|
|
11929
|
+
)
|
|
11930
|
+
).min(1).max(4).refine((ids) => new Set(ids).size === ids.length, {
|
|
11931
|
+
message: "Expected each model once"
|
|
11932
|
+
}).optional()
|
|
11933
|
+
}).strict()
|
|
11934
|
+
).optional(),
|
|
11935
|
+
unknownForms: treeFormMixSchema.optional(),
|
|
11936
|
+
regions: z5.array(
|
|
11937
|
+
z5.object({
|
|
11938
|
+
bounds: z5.tuple([
|
|
11939
|
+
z5.number().finite().min(-180).max(180),
|
|
11940
|
+
z5.number().finite().min(-90).max(90),
|
|
11941
|
+
z5.number().finite().min(-180).max(180),
|
|
11942
|
+
z5.number().finite().min(-90).max(90)
|
|
11943
|
+
]).refine(([, south, , north]) => south <= north, {
|
|
11944
|
+
message: "Expected bounds as [west, south, east, north] with south below north"
|
|
11945
|
+
}),
|
|
11946
|
+
unknownForms: treeFormMixSchema
|
|
11947
|
+
}).strict()
|
|
11948
|
+
).max(16).optional(),
|
|
11641
11949
|
crownScale: z5.union([
|
|
11642
11950
|
z5.number().finite().positive().max(10),
|
|
11643
11951
|
themeNumberReferenceSchema,
|
|
@@ -11970,6 +12278,7 @@ var iconDirectoriesSchema = z5.array(
|
|
|
11970
12278
|
}
|
|
11971
12279
|
});
|
|
11972
12280
|
var fontDirectoriesSchema = z5.array(assetDirectorySchema).max(16);
|
|
12281
|
+
var modelDirectoriesSchema = z5.array(assetDirectorySchema).max(16);
|
|
11973
12282
|
var fontStacksSchema = z5.array(
|
|
11974
12283
|
z5.string().min(1).max(200).refine(
|
|
11975
12284
|
(value) => value === value.trim() && value === value.normalize("NFC") && !/[\p{Cc}\\/]/u.test(value),
|
|
@@ -12191,6 +12500,7 @@ var resolvedTileflowMapSchema = z5.object({
|
|
|
12191
12500
|
icons: iconDirectoriesSchema.optional(),
|
|
12192
12501
|
id: tileflowMapIdSchema,
|
|
12193
12502
|
marine: marineSchema.optional(),
|
|
12503
|
+
models: modelDirectoriesSchema.optional(),
|
|
12194
12504
|
modules: modulesSchema.optional(),
|
|
12195
12505
|
name: z5.string().trim().min(1),
|
|
12196
12506
|
overlays: overlaysSchema.optional(),
|
|
@@ -13099,11 +13409,11 @@ function isTileflowPoiCategory(value) {
|
|
|
13099
13409
|
return typeof value === "string" && tileflowPoiCategories.includes(value);
|
|
13100
13410
|
}
|
|
13101
13411
|
function semanticTarget(layer) {
|
|
13102
|
-
if (!
|
|
13412
|
+
if (!isRecord8(layer.metadata)) return void 0;
|
|
13103
13413
|
const value = layer.metadata[tileflowCompilerMetadataKeys.target];
|
|
13104
13414
|
return typeof value === "string" ? value : void 0;
|
|
13105
13415
|
}
|
|
13106
|
-
function
|
|
13416
|
+
function isRecord8(value) {
|
|
13107
13417
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
13108
13418
|
}
|
|
13109
13419
|
function isSafeArtifactName(value) {
|
|
@@ -14127,8 +14437,19 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
|
|
|
14127
14437
|
"domains",
|
|
14128
14438
|
() => compileSemanticDomains(modules, context)
|
|
14129
14439
|
);
|
|
14440
|
+
const vegetation3D = runCompilationPhase(
|
|
14441
|
+
"domains",
|
|
14442
|
+
() => withPreparedTreeModels(
|
|
14443
|
+
tileflowVegetationDescription(
|
|
14444
|
+
modules.vegetation,
|
|
14445
|
+
context
|
|
14446
|
+
),
|
|
14447
|
+
config,
|
|
14448
|
+
options.preparedAssets
|
|
14449
|
+
)
|
|
14450
|
+
);
|
|
14130
14451
|
const renderStackModules = Object.values(modules).filter(
|
|
14131
|
-
(module) =>
|
|
14452
|
+
(module) => isRecord9(module) && module.enabled !== false && "renderStack" in module && isRecord9(module.renderStack)
|
|
14132
14453
|
);
|
|
14133
14454
|
const renderOperations = runCompilationPhase(
|
|
14134
14455
|
"render-stack",
|
|
@@ -14288,6 +14609,15 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
|
|
|
14288
14609
|
() => createTileflowOverlayPlacementManifest(plannedLayers)
|
|
14289
14610
|
);
|
|
14290
14611
|
const layers = runCompilationPhase("finalization", () => finalizeTileflowLayers(plannedLayers));
|
|
14612
|
+
const buildings3D = tileflowBuildings3DDesignOf(
|
|
14613
|
+
modules.buildings,
|
|
14614
|
+
context,
|
|
14615
|
+
layers
|
|
14616
|
+
);
|
|
14617
|
+
const streetLights = tileflowStreetLightsDesignOf(
|
|
14618
|
+
modules.roads,
|
|
14619
|
+
context
|
|
14620
|
+
);
|
|
14291
14621
|
runCompilationPhase(
|
|
14292
14622
|
"finalization",
|
|
14293
14623
|
() => assertTileflowInteractionManifestLayers(interactionManifest, layers)
|
|
@@ -14360,13 +14690,33 @@ function compileSemanticStyleInternal(input, options, inspect, onReport) {
|
|
|
14360
14690
|
"tileflow:colorScheme": resolvedTheme.colorScheme,
|
|
14361
14691
|
[tileflowRouteMetadataKey]: tileflowRouteMetadata(resolveTileflowRouteInks(resolvedTheme)),
|
|
14362
14692
|
...resolvedTheme.sun ? { [tileflowSunMetadataKey]: tileflowSunMetadata(resolvedTheme.sun) } : {},
|
|
14693
|
+
...buildings3D ? {
|
|
14694
|
+
[tileflowBuildingsMetadataKey]: tileflowBuildingsMetadata(
|
|
14695
|
+
bindSemanticReferences(buildings3D, semanticData)
|
|
14696
|
+
)
|
|
14697
|
+
} : {},
|
|
14698
|
+
...streetLights ? {
|
|
14699
|
+
[tileflowStreetLightsMetadataKey]: tileflowStreetLightsMetadata(
|
|
14700
|
+
bindSemanticReferences(streetLights, semanticData)
|
|
14701
|
+
)
|
|
14702
|
+
} : {},
|
|
14703
|
+
...vegetation3D ? {
|
|
14704
|
+
[tileflowVegetationMetadataKey]: tileflowVegetationMetadata({
|
|
14705
|
+
...bindSemanticReferences(vegetation3D, semanticData),
|
|
14706
|
+
// The layers that draw the trees flat: the module's own and its render passes.
|
|
14707
|
+
flatLayers: layers.filter((layer) => {
|
|
14708
|
+
const metadata = layer.metadata;
|
|
14709
|
+
return metadata?.["tileflow:vegetation-mode"] !== void 0 || metadata?.["tileflow:domain"] === "vegetation";
|
|
14710
|
+
}).map((layer) => String(layer.id))
|
|
14711
|
+
})
|
|
14712
|
+
} : {},
|
|
14363
14713
|
"tileflow:data": data.identity,
|
|
14364
14714
|
"tileflow:sources": sourceIdentities,
|
|
14365
14715
|
...Object.keys(loweredOverlays.identities).length > 0 ? { "tileflow:overlays": loweredOverlays.identities } : {},
|
|
14366
14716
|
"tileflow:sourceRequirements": sourceRequirements,
|
|
14367
14717
|
...interactionManifest ? { [tileflowInteractionManifestMetadataKey]: interactionManifest } : {},
|
|
14368
14718
|
[tileflowOverlayPlacementManifestMetadataKey]: overlayPlacementManifest,
|
|
14369
|
-
"tileflow:modules": Object.entries(modules).filter(([, module]) => !
|
|
14719
|
+
"tileflow:modules": Object.entries(modules).filter(([, module]) => !isRecord9(module) || module.enabled !== false).map(([name]) => name).sort(),
|
|
14370
14720
|
...config.view ? { "tileflow:view": config.view } : {}
|
|
14371
14721
|
}
|
|
14372
14722
|
};
|
|
@@ -14418,7 +14768,7 @@ function finalizeTileflowLayers(input) {
|
|
|
14418
14768
|
if (typeof minimum2 === "number" && typeof maximum2 === "number" && minimum2 > maximum2) {
|
|
14419
14769
|
throw new Error(`Compiled Tileflow layer ${id2} requires minzoom <= maxzoom.`);
|
|
14420
14770
|
}
|
|
14421
|
-
const metadata =
|
|
14771
|
+
const metadata = isRecord9(layer.metadata) ? { ...layer.metadata } : void 0;
|
|
14422
14772
|
if (metadata) {
|
|
14423
14773
|
const owner = metadata[tileflowCompilerMetadataKeys.owner];
|
|
14424
14774
|
delete metadata[tileflowCompilerProvenanceMetadataKey];
|
|
@@ -14452,13 +14802,32 @@ function assertMapLibreStyle(style, mapId) {
|
|
|
14452
14802
|
}
|
|
14453
14803
|
);
|
|
14454
14804
|
}
|
|
14455
|
-
function
|
|
14805
|
+
function isRecord9(value) {
|
|
14456
14806
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
14457
14807
|
}
|
|
14458
14808
|
function resolveGlyphs(config) {
|
|
14459
14809
|
if (config.fonts !== void 0) return void 0;
|
|
14460
14810
|
return config.glyphs?.url;
|
|
14461
14811
|
}
|
|
14812
|
+
function withPreparedTreeModels(vegetation2, config, prepared) {
|
|
14813
|
+
if (!vegetation2) return void 0;
|
|
14814
|
+
const referenced = [
|
|
14815
|
+
...new Set(Object.values(vegetation2.forms).flatMap((form) => form?.models ?? []))
|
|
14816
|
+
].sort();
|
|
14817
|
+
if (referenced.length === 0) return vegetation2;
|
|
14818
|
+
const available = prepared?.models ?? {};
|
|
14819
|
+
const missing = referenced.filter((id2) => !Object.hasOwn(available, id2));
|
|
14820
|
+
if (missing.length > 0) {
|
|
14821
|
+
const authoring = config.models?.length ? `Add ${missing.map((id2) => `${id2}.glb`).join(", ")} to a map.models directory, or run the Node build so the directories are prepared.` : "Declare map.models with directories containing those .glb files.";
|
|
14822
|
+
throw new Error(
|
|
14823
|
+
`Tileflow map "${config.id}" draws missing 3D models: ${missing.join(", ")}. ${authoring}`
|
|
14824
|
+
);
|
|
14825
|
+
}
|
|
14826
|
+
return {
|
|
14827
|
+
...vegetation2,
|
|
14828
|
+
models: Object.fromEntries(referenced.map((id2) => [id2, available[id2]]))
|
|
14829
|
+
};
|
|
14830
|
+
}
|
|
14462
14831
|
function assertPreparedIconReferences(style, config, prepared) {
|
|
14463
14832
|
const references = collectStyleImageReferences(style);
|
|
14464
14833
|
if (references.size === 0) return;
|
|
@@ -14473,8 +14842,8 @@ function assertPreparedIconReferences(style, config, prepared) {
|
|
|
14473
14842
|
function collectStyleImageReferences(style) {
|
|
14474
14843
|
const result = /* @__PURE__ */ new Set();
|
|
14475
14844
|
for (const layer of style.layers) {
|
|
14476
|
-
const layout =
|
|
14477
|
-
const paint =
|
|
14845
|
+
const layout = isRecord9(layer.layout) ? layer.layout : {};
|
|
14846
|
+
const paint = isRecord9(layer.paint) ? layer.paint : {};
|
|
14478
14847
|
const layerId = typeof layer.id === "string" ? layer.id : "<unknown>";
|
|
14479
14848
|
for (const [property, value] of [
|
|
14480
14849
|
["icon-image", layout["icon-image"]],
|
|
@@ -14563,7 +14932,7 @@ function assertGlyphFontStacks(style, config) {
|
|
|
14563
14932
|
const declared = new Set(config.glyphs.fontStacks);
|
|
14564
14933
|
const missing = /* @__PURE__ */ new Set();
|
|
14565
14934
|
for (const layer of style.layers) {
|
|
14566
|
-
const layout =
|
|
14935
|
+
const layout = isRecord9(layer.layout) ? layer.layout : void 0;
|
|
14567
14936
|
const font = layout?.["text-font"];
|
|
14568
14937
|
if (!Array.isArray(font) || !font.every((entry) => typeof entry === "string")) continue;
|
|
14569
14938
|
const stack = font.join(",");
|
|
@@ -14579,7 +14948,7 @@ function assertGlyphFontStacks(style, config) {
|
|
|
14579
14948
|
function assertTextAssets(style, config) {
|
|
14580
14949
|
const textLayers = [];
|
|
14581
14950
|
for (const layer of style.layers) {
|
|
14582
|
-
const layout =
|
|
14951
|
+
const layout = isRecord9(layer.layout) ? layer.layout : void 0;
|
|
14583
14952
|
if (layout?.["text-field"] === void 0) continue;
|
|
14584
14953
|
textLayers.push(typeof layer.id === "string" ? layer.id : "<unknown>");
|
|
14585
14954
|
const font = layout["text-font"];
|
|
@@ -14592,7 +14961,7 @@ function assertTextAssets(style, config) {
|
|
|
14592
14961
|
if (textLayers.length === 0) return;
|
|
14593
14962
|
if (config.fonts !== void 0) {
|
|
14594
14963
|
const backed = style.layers.find((layer) => {
|
|
14595
|
-
const font =
|
|
14964
|
+
const font = isRecord9(layer.layout) ? layer.layout["text-font"] : void 0;
|
|
14596
14965
|
return Array.isArray(font) && font.length === 1 && typeof font[0] === "string" && parseTileflowLineBackgroundFontStack(font[0]) !== void 0;
|
|
14597
14966
|
});
|
|
14598
14967
|
if (backed) {
|
|
@@ -14618,7 +14987,7 @@ function runCompilationPhase(phase, operation) {
|
|
|
14618
14987
|
}
|
|
14619
14988
|
}
|
|
14620
14989
|
function withCompilationPhase(error, phase) {
|
|
14621
|
-
const record3 =
|
|
14990
|
+
const record3 = isRecord9(error) ? error : {};
|
|
14622
14991
|
if (typeof record3.phase === "string") return error;
|
|
14623
14992
|
if (error instanceof Error && Object.isExtensible(error)) {
|
|
14624
14993
|
Object.defineProperty(error, "phase", { configurable: true, enumerable: true, value: phase });
|
|
@@ -15178,6 +15547,7 @@ var tileflowMapMergeStrategies = {
|
|
|
15178
15547
|
icons: "icons",
|
|
15179
15548
|
id: "identity",
|
|
15180
15549
|
marine: "atomic",
|
|
15550
|
+
models: "atomic",
|
|
15181
15551
|
modules: "modules",
|
|
15182
15552
|
name: "identity",
|
|
15183
15553
|
overlays: "keyed-resources",
|
|
@@ -15523,11 +15893,11 @@ function cloneDesign(value) {
|
|
|
15523
15893
|
function describeMap(value) {
|
|
15524
15894
|
return typeof value.id === "string" && value.id ? value.id : "<anonymous>";
|
|
15525
15895
|
}
|
|
15526
|
-
function
|
|
15896
|
+
function isRecord10(value) {
|
|
15527
15897
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
15528
15898
|
}
|
|
15529
15899
|
function isPlainRecord4(value) {
|
|
15530
|
-
if (!
|
|
15900
|
+
if (!isRecord10(value)) return false;
|
|
15531
15901
|
const prototype = Object.getPrototypeOf(value);
|
|
15532
15902
|
return prototype === Object.prototype || prototype === null;
|
|
15533
15903
|
}
|
|
@@ -16045,6 +16415,7 @@ async function hashTileflowMapRevision(input, sourceAssets) {
|
|
|
16045
16415
|
const {
|
|
16046
16416
|
fonts: _fonts,
|
|
16047
16417
|
icons: _icons,
|
|
16418
|
+
models: _models,
|
|
16048
16419
|
id: _id,
|
|
16049
16420
|
name: _name,
|
|
16050
16421
|
version: _version,
|
|
@@ -16140,10 +16511,26 @@ function normalizeSourceAssets(input) {
|
|
|
16140
16511
|
if (new Set(fonts.map(fontIdentity)).size !== fonts.length) {
|
|
16141
16512
|
throw new Error("Effective Tileflow font source identities must have unique faces.");
|
|
16142
16513
|
}
|
|
16514
|
+
const models = [...input.models ?? []].map((model) => {
|
|
16515
|
+
assertSha256(model.sha256, `model ${model.id}`);
|
|
16516
|
+
if (model.level !== "near" && model.level !== "far")
|
|
16517
|
+
throw new Error(`Tileflow model ${model.id} is near or far.`);
|
|
16518
|
+
return { id: model.id, level: model.level, sha256: model.sha256 };
|
|
16519
|
+
}).sort(
|
|
16520
|
+
(left, right) => compareCodeUnits8(`${left.id}\0${left.level}`, `${right.id}\0${right.level}`)
|
|
16521
|
+
);
|
|
16522
|
+
if (new Set(models.map((model) => `${model.id}\0${model.level}`)).size !== models.length) {
|
|
16523
|
+
throw new Error("Effective Tileflow model source identities must be unique.");
|
|
16524
|
+
}
|
|
16143
16525
|
const iconComposition = input.iconComposition === void 0 ? void 0 : parseTileflowIconComposition(input.iconComposition);
|
|
16144
16526
|
if (icons.some((icon) => icon.kind === "rendered-icon") && !iconComposition)
|
|
16145
16527
|
throw new Error("Rendered icon identities require an explicit composition receipt");
|
|
16146
|
-
return {
|
|
16528
|
+
return {
|
|
16529
|
+
fonts,
|
|
16530
|
+
icons,
|
|
16531
|
+
...iconComposition ? { iconComposition } : {},
|
|
16532
|
+
...models.length > 0 ? { models } : {}
|
|
16533
|
+
};
|
|
16147
16534
|
}
|
|
16148
16535
|
function fontIdentity(font) {
|
|
16149
16536
|
return `${font.family}\0${font.style}\0${font.weight}`;
|