The country outline never drew on MapLibre: the worldview clause emptied its layer
Second site of the defect rega found on regions-mfe, and this one is shared by three plugins — country-posters, doxa-simple-map and doxa-research-map. The source asymmetry here was already handled carefully: MapLibre gets a geojson source instead of the mapbox:// tileset, the loader bridges iso3 -> iso_3166_1_alpha_3, and the layer drops 'source-layer' because MapLibre rejects it on geojson. What was missed is one field deeper. countryFilter() also ANDs a worldview clause, which exists because the tileset repeats a country once per worldview and the outline would otherwise draw two or three times over. world-adm0.geojson has no such duplication and carries no worldview property, so ['get','worldview'] is null, both sides of the `any` are false on every feature, and the `all` admits nothing. The outline is absent with no error, which looks exactly like boundary data that failed to load. Unlike the ISO field this cannot be bridged in the loader: there is no worldview to invent. It is a fact about the tileset's shape, so only the Mapbox path asks for it. The engine sniff already in the file moves UP, above the filter. It sat inside the try block, below the line that built the filter, so the filter could not have consulted it; the fast path at the top (setFilter on an existing layer) reuses the same filter and is now covered by the same branch. MEASURED, fail-first, against the real 162 features with MapLibre's own style-spec parser: the worldview clause admits 0 / 162 the MapLibre branch admits 1 / 1 (== one country, this composable's shape) the Mapbox path still collapses a duplicate worldview copy to 1 The check also REGISTERS both worldview sites in the tree and fails on a new unlisted one, so the class cannot come back quietly in a component nobody re-shoots. Not landed here: three consumer bundles compile this, so it needs their rebuild.
This commit is contained in:
parent
7c131f3aba
commit
b483606054
1 changed files with 24 additions and 11 deletions
|
|
@ -73,10 +73,28 @@ export function resolveCountryIso(evt, pgs) {
|
|||
// 'all', 'US', 'CN', 'IN'); without a worldview filter an outline would be
|
||||
// drawn 2-3× over itself. Mirror the homepage CountryMap.vue filter: keep the
|
||||
// 'all' worldview plus the US-recognized worldview.
|
||||
function countryFilter(code) {
|
||||
// The ENGINE is read off the live map rather than guessed from config: the container carries
|
||||
// maplibregl-map or mapboxgl-map, which is a fact about the instance in hand. Consumers call
|
||||
// useCountryOutline(() => map.value) with no options, so there is no provider to pass in.
|
||||
function isMaplibreMap(m) {
|
||||
try { return !!m?.getContainer?.()?.classList?.contains('maplibregl-map') } catch (_) { return false }
|
||||
}
|
||||
|
||||
function countryFilter(code, isMaplibre) {
|
||||
const byCode = ['==', ['get', 'iso_3166_1_alpha_3'], code]
|
||||
// ★ THE WORLDVIEW CLAUSE IS MAPBOX-ONLY, AND ANDING IT ON MAPLIBRE EMPTIES THE LAYER.
|
||||
// The clause exists for the tileset above; world-adm0.geojson, the MapLibre source added below,
|
||||
// has no worldview property and no per-worldview duplicates. So ['get','worldview'] is null,
|
||||
// both sides of the `any` are false on every feature, and the `all` admits NOTHING — the outline
|
||||
// is absent with no error, exactly as if the boundary data had failed to load. Unlike the ISO
|
||||
// field, this cannot be bridged in the loader: there is no worldview to invent. It is a fact
|
||||
// about the Mapbox tileset's shape, so only the Mapbox path asks for it.
|
||||
// MEASURED: against the real 162 features, the clause admits 0 and the branch below admits its
|
||||
// country — _qa-cycle/02-builder-cycle/_chk-worldview-clause-guarded-per-engine.mjs.
|
||||
if (isMaplibre) return byCode
|
||||
return [
|
||||
'all',
|
||||
['==', ['get', 'iso_3166_1_alpha_3'], code],
|
||||
byCode,
|
||||
['any', ['==', ['get', 'worldview'], 'all'], ['in', 'US', ['get', 'worldview']]]
|
||||
]
|
||||
}
|
||||
|
|
@ -116,7 +134,9 @@ export function useCountryOutline(getMap, opts = {}) {
|
|||
const m = typeof getMap === 'function' ? getMap() : null
|
||||
if (!m) return
|
||||
|
||||
const filter = countryFilter(code)
|
||||
// Engine FIRST: the filter's shape depends on it, and the fast path below reuses this filter.
|
||||
const isMaplibre = isMaplibreMap(m)
|
||||
const filter = countryFilter(code, isMaplibre)
|
||||
|
||||
// Fast path: source/layer already present from a prior pick — just swap the
|
||||
// filter so the highlight moves to the new country with zero teardown.
|
||||
|
|
@ -136,14 +156,7 @@ export function useCountryOutline(getMap, opts = {}) {
|
|||
// the console. THREE consumers share this composable — doxa-simple-map, countries-map and
|
||||
// research-map — so the fix belongs here, once, not three times.
|
||||
// Same shape already proven in DashboardMapPanel and RegionCountryMap.
|
||||
//
|
||||
// The ENGINE is read off the live map rather than guessed from config: the container carries
|
||||
// maplibregl-map or mapboxgl-map, which is a fact about the instance in hand. Consumers call
|
||||
// useCountryOutline(() => map.value) with no options, so there is no provider to pass in.
|
||||
const isMaplibre = (() => {
|
||||
try { return !!m.getContainer?.()?.classList?.contains('maplibregl-map') } catch (_) { return false }
|
||||
})()
|
||||
|
||||
// isMaplibre is resolved above, before the filter is built — see countryFilter().
|
||||
if (isMaplibre) {
|
||||
// Add EMPTY first, then setData after the fetch, so addLayer below stays SYNCHRONOUS and
|
||||
// the outline keeps its place in the layer order.
|
||||
|
|
|
|||
Loading…
Reference in a new issue