UPG-100: read pin features through the shared helper, not source._data

Clicking a pin to open the people-group detail panel did nothing under MapLibre,
with no error of any kind.

openPgDetail read `src._data.features`. The two engines store _data differently,
and both bundles say so in the same constructor (this._options = Object.assign
follows in each):

  mapbox-gl v3.24.0   this._data = i.data                           the raw value
  maplibre-gl         this._data = "string"==typeof i.data
                                   ? {url: i.data} : {geojson: i.data}

So `._data.features` resolves under Mapbox and is UNDEFINED under MapLibre.
Every guard in the chain then turned the wrong shape into a no-op: `|| []` made
it an empty list, find() returned undefined, `if (f)` was false. Silent, and
indistinguishable from a missed click -- the same defect class as sr's landed
MapLibre source-read bug.

Now calls readSourceFeatures() from library/maps/pin-selection.js, which falls
back to the public serialize() that both engines expose. One import, one call, no
new API.

The mapbox citation was taken from the exact CDN bundle the app loads
(library/constants/cdn.js pins v3.24.0), fetched and verified against its pinned
SRI hash before reading, then deleted. No browser involved -- downloading and
grepping a bundle never starts one.

Verified in the BUILT output rather than by function name, which minification
renames: the helper's distinctive public fallback `serialize` appears once in the
rebuilt bundle and zero times in main's.
This commit is contained in:
Doxa Maps 2026-09-28 08:53:23 +00:00
parent 0d85e0dfcc
commit ae960e82b5
7 changed files with 81 additions and 71 deletions

View file

@ -419,6 +419,9 @@ import { useShadowStyles } from '@map/composables/useShadowStyles.js'
// non-useMapInstance profiles like this one can use it).
import { useEdgeScrollAffordance } from '@map/composables/useEdgeScrollAffordance.js'
import { resolveAssetsBase } from '@map/utils/embedBase.js'
// Reads a GeoJSON source's features WITHOUT touching the engine-private _data, whose shape differs
// between MapLibre and Mapbox (see openPgDetail).
import { readSourceFeatures } from '@map/maps/pin-selection.js'
useShadowStyles(
'.upg-root{position:absolute;inset:0;background:#0a1410;color:#e5e7eb;' +
"font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif}" +
@ -1097,8 +1100,15 @@ function flyToTarget(t) {
// uiStore.selectPeopleGroup (the SAME call attachPinHandlers makes on a pin click).
function openPgDetail(slug) {
if (!slug || !uiStore || typeof uiStore.selectPeopleGroup !== 'function') return
const src = map && map.getSource && map.getSource('upg')
const feats = (src && src._data && src._data.features) || []
// ⚠ NOT `src._data.features` — THE TWO ENGINES STORE _data DIFFERENTLY, and the old read was
// silently broken under MapLibre. Cited from both bundles, same constructor in each:
// mapbox-gl v3.24.0 this._data = i.data (the raw value)
// maplibre-gl this._data = "string"==typeof i.data ? {url:…} : {geojson: i.data}
// So `._data.features` resolves under Mapbox and is UNDEFINED under MapLibre — whereupon `|| []`
// made it an empty list, find() returned undefined, `if (f)` was false, and CLICKING A PIN OPENED
// NOTHING with no error of any kind. Same defect class as sr's landed MapLibre source-read bug.
// readSourceFeatures falls back to the public serialize(), which both engines expose.
const feats = readSourceFeatures(map, 'upg')
const f = feats.find((x) => x.properties && x.properties.slug === slug)
if (f) uiStore.selectPeopleGroup(f)
}

View file

@ -838,7 +838,7 @@
"bundle": "my-upg-100-list",
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
"integrity": "sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf",
"integrity": "sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP",
"elements": [
"my-upg-100-list-map"
],
@ -861,7 +861,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -877,7 +877,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -893,7 +893,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
}
]

View file

@ -838,7 +838,7 @@
"bundle": "my-upg-100-list",
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
"integrity": "sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf",
"integrity": "sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP",
"elements": [
"my-upg-100-list-map"
],
@ -861,7 +861,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -877,7 +877,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
},
{
@ -893,7 +893,7 @@
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
"embed": {
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
"script": "<!-- Mapbox engine, fetched early. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
}
}
]

File diff suppressed because one or more lines are too long

View file

@ -32,7 +32,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -36,7 +36,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -47,7 +47,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <my-upg-100-list-map> custom element. -->
<script src="../my-upg-100-list.js" integrity="sha384-xoHjtZpopSbvRn3aEUT5JuiZPQsOpSnqiVDKBVI/Xezui5k4W0szM0C+zSM5PBSf" crossorigin="anonymous"></script>
<script src="../my-upg-100-list.js" integrity="sha384-hIwlmueKHRTbrEmSYf3G8nJZiZVy0CGrHsEhFLbilwWkvmybniV1XsAeSsU+ZRjP" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order: