Six views set dataReady (which removes the LoadingGlobe) straight after addSource(). The engine
then still tiles tens of thousands of points in its worker, so the globe vanished and the map sat
empty with a full legend. Measured on the DX-life gallery: 0 features for 20 s, then 19,376.
whenGeojsonDrawn(map) resolves once every GeoJSON source is loaded AND a frame has rendered
(not 'idle', which an animating map may never reach), with a 45 s cap so it can never hang.
Religion, pins, coverage, translations, language families and Rosetta cards await it before
dataReady. Plugin-local: pplrData.js has no consumer outside pplr-data-maps.
Headless proof: a fake-map unit test (already loaded / last source late / never loads -> false at
the cap / style mid-swap / no map), 9/9 pass; BUNDLE=pplr-data-maps build + tree + check:sri PASS.
Every generated leaf <head> preloaded mapbox-gl.js whatever the provider, so code that used the
bare `mapboxgl` global always found one, even on a MapLibre map. Removing that peer (it sends
every visitor's IP to Mapbox under provider=maplibre) turns each such site into an error.
engineFor(map), next to isMapboxMap in useMapProvider.js, asks the map which engine built it:
- useSelectedPin: the selected-pin Marker
- useMapEvents: the pin-fallback and region Popups
- useMapPoster: main already builds the hidden map with the source map's engine (1cbfb3aa);
its choice now goes through this one helper instead of a second inline sniff
- pplr-data-maps: glFor is now this helper; the geocoder awaits ensureEngineScript first
- key-cities: ensureEngineScript('mapbox') before reading the global
Measured with every api.mapbox.com tag stripped from the served leaf (no peer at all for
key-cities), before -> after:
pin select under MapLibre, on cities-internet, country-posters, doxa-research-map and
doxa-simple-map: "reading 'Marker'" -> marker drawn; country-posters region popup: none ->
popup; PPLR search: no input -> suggestions (both engines); key-cities: "mapbox-gl not
loaded" -> map loaded. Mapbox rows unchanged (they passed before and after).
The poster UI could not be driven: PosterDialog never opens in country-posters or
doxa-research-map (they pass props it does not declare and no modelValue/getMap), reported
separately. useMapPoster itself was rendered from a real map with only its engine on the page:
MapLibre "mapboxgl global not found" on the pre-1cbfb3aa library -> a 400x300 PNG with 88 colours.
Under provider=maplibre (the keyless gallery) four of the seven map views never
finished loading. They built `new mapboxgl.NavigationControl` in the load
handler, and that global does not exist under MapLibre, so they sat on
"Loading…". Popups and the pin marker had the same fault. Every such call now
goes through glFor(map), the namespace of the engine that built the map. The
views' styles and the Dark/Satellite/Light switch now use registry names (ink,
hybrid, paper), which are the same Mapbox styles under Mapbox and OpenFreeMap
under MapLibre.
The search box loads its geocoder by engine, as GeocoderComponent does. Under
MapLibre it is MaplibreGeocoder over this map's own local index, so the keyless
gallery makes no request to api.mapbox.com at all.
The legend's row caret, clear chip and collapse/reopen buttons carry accessible
names and aria-expanded from legend.a11y.* and aria.* (optional i18n, English
fallback), the keys the library legend uses. check:shared-reached now counts
pplr-data-maps as carrying legend-a11y-keys.
window.__pplrMap() reports what the active view's map did (engine, load fired,
style layers, this bundle's data sources), so "loaded" is asserted, not inferred.
Measured on a served built tree, host page on another origin: all ten views
loaded under MapLibre and under Mapbox (load fired, style layers and data
sources present, canvas not blank, 0 errors), with 0 api.mapbox.com requests
under MapLibre. The same check on the parent build fails four map views under
MapLibre. A control with no provider makes 13 Mapbox requests.
PPLR renamed the aCountry fields upstream (GENCalpha3 -> GENCAlpha3, CtryNm -> Name,
ctryNmDisp -> DisplayName, ISOalpha2 -> ISOAlpha2). The query asked for the old
names, ArcGIS answered HTTP 200 with { error }, and the loop read that as "no
features". Every view that draws country polygons silently lost them. The
query now asks for the new names and gives each feature the old ones back, and an
{ error } body throws.
Paging also stopped after one page: f=geojson carries exceededTransferLimit under
data.properties, so only 200 of 251 countries loaded. A full page now means ask
for more.
Coverage: the status no longer claims a 6,000-row sample, and a __pplrCoverage()
handle reports how many polygons matched a coverage row.
Not for main yet. All ten views mount on the dev server with real data and no
page errors. Left: the coverage view's status still says 'sample of 6,000',
its choropleth needs checking, and the bundle is not built or tree-verified.