doxa-maps/internal/check-legend-top-offset.mjs
Doxa Maps f7f180df50 The legend held a slot for a toolbar this profile never draws
DRV1650-SR-LEGEND-FILLS-SEARCH-GAP. On Simple Research's Regions and Languages tabs the
search bar is gone but the legend does not rise into the space. The other tabs are fine.

The two-tab split was a predicate, not a coincidence. With no geocoder the legend rises
to 14px UNLESS showsFlyTools() is true, and that returns true for exactly 'doxa-regions',
'language-family' and 'language-families'. It stops at 56px to avoid a MEASURED collision
on country-posters, where LegendTools renders at top:14px — the legend's own slot.

★ BUT showsFlyTools() DESCRIBES THE LEGEND TYPE, NOT WHETHER THE TOOLBAR EXISTS. Fly and
Clusters are leaf-only: the composite — which is what a reader calls "Simple Research" —
passes legendTools:false, so the toolbar is never drawn there and the 56px reserved a
slot for nothing. rega measured it at 1440x900 on main e1d0bc20: the band from the map's
top edge (y 44) to the legend card (y 100) is 56px of EMPTY map on both tabs, with no
LegendTools anywhere in the strip.

So the offset now asks whether the toolbar is RENDERED, not whether the type allows one.
Keying it on the tab name would have closed the Driver's gap and reintroduced the
country-posters collision the moment the tools were shown — the guard is kept, it is
simply asked the right question.

showLegendTools moved ABOVE legendTopVar, which reads it. A computed body is lazy so a
later const would have resolved at runtime, but this file has a TDZ history and
check:setup-order exists because of it; position is cheaper to keep honest than to reason
about.

check-legend-top-offset asserts BOTH inputs are consulted — drop either and it fails —
and that the declaration still precedes its reader. Negative-tested.

This is reading (b) of the two I put to dx-shepherd, chosen because rega measured it
rather than because it was likelier. Reading (a) would have been a cosmetic change to a
toolbar that turned out not to be there.
2026-09-28 17:53:39 +00:00

64 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
/**
* check-legend-top-offset — the legend only reserves room for a toolbar that is actually drawn.
*
* THE DEFECT (Driver, 2026-09-28): on Simple Research's Regions and Languages tabs under MapLibre, the
* search bar is gone but the legend does not rise into the vacated space. The other tabs are fine.
*
* ★ THE TWO-TAB SPLIT WAS A PREDICATE, NOT A COINCIDENCE. With no geocoder the legend rises to 14px
* unless showsFlyTools() is true, and that returns true for exactly 'doxa-regions', 'language-family'
* and 'language-families' — the Driver's two tabs. It stops at 56px to avoid a MEASURED collision on
* country-posters, where LegendTools renders at top:14px, the legend's own slot.
*
* ★ BUT showsFlyTools() DESCRIBES THE LEGEND TYPE, NOT WHETHER THE TOOLBAR EXISTS. Fly + Clusters are
* leaf-only: the composite — which is what a reader calls "Simple Research" — passes legendTools:false,
* so the toolbar is never drawn there and the 56px reserved a slot for nothing. rega measured it at
* 1440x900 on main e1d0bc20: the band from the map's top edge (y 44) to the legend card (y 100) is 56px
* of empty map on both tabs, no toolbar anywhere in the strip.
*
* So the offset must be keyed on the toolbar's PRESENCE. Keying it on the tab name would have fixed the
* Driver's two tabs and reintroduced the country-posters collision the moment the tools were shown.
*
* Exit 0 pass · 1 fail.
*/
import { readFileSync } from 'node:fs'
import { resolve, dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
const TAG = 'LEGEND-TOP-OFFSET'
const fails = []
const src = readFileSync(join(ROOT, 'plugin-designs/doxa-research-map/research-map.vue'), 'utf8')
const m = src.match(/const legendTopVar = computed\(\(\) => \{[\s\S]*?\n\}\)/)
if (!m) {
fails.push('legendTopVar was renamed or restructured — this gate cannot find it and would pass blind.')
} else {
const body = m[0].replace(/\/\*[\s\S]*?\*\//g, '').replace(/^\s*\/\/.*$/gm, '')
if (!/showsFlyTools\s*\(/.test(body)) {
fails.push('legendTopVar no longer asks whether the legend TYPE allows fly tools, so raising the '
+ 'legend would print the toolbar across its header on the profiles that DO draw it '
+ '(the measured country-posters collision).')
}
if (!/showLegendTools/.test(body)) {
fails.push('legendTopVar does not consult showLegendTools, so it reserves space for a toolbar that\n'
+ ' may never be drawn. That is the Driver-reported dead band on the Regions and Languages\n'
+ ' tabs: the composite passes legendTools:false and the 56px held a slot for nothing.\n'
+ ' Key the offset on the toolbar\'s PRESENCE, not on the legend type alone.')
}
}
// The declaration must precede the reader: a lazy computed would resolve anyway, but this file has a
// TDZ history and check:setup-order exists because of it.
const iDecl = src.indexOf('const showLegendTools')
const iUse = src.indexOf('const legendTopVar')
if (iDecl > -1 && iUse > -1 && iDecl > iUse) {
fails.push('showLegendTools is declared BELOW legendTopVar, which reads it.')
}
if (fails.length) {
console.error(`${TAG}: FAIL`)
for (const f of fails) console.error(` ✗ ${f}`)
process.exit(1)
}
console.log(`${TAG}: PASS — the legend's top offset is keyed on whether the toolbar is actually rendered, not on `
+ 'the legend type alone, so the dead band closes without reintroducing the measured collision.')