Goal (c), and it turned into a goal (d) fix. Every profile element is
defineCustomElement(ProfileLoader, { configureApp }), and the configureApp has four
steps. The fourth, app.provide('appI18n', i18n), is the one that gets dropped.
ProfileLoader injects that instance (ProfileLoader.vue:176) to drive its locale from
profile-config. Without the provide the watcher holds null and the drive NEVER RUNS --
while setRuntimeLocale() on the next line still fires, so tStatic strings DO follow the
host. The element renders a convincing MIXTURE of the reader's language and English, and
nothing throws, because the t() shim falls back to its key. It reads as "a few strings
not translated yet".
SHIPPING THAT TODAY: country-posters, key-cities, gospel-resources, cities-internet and
my-upg-100-list. regions-plugin censused all 19 entry files independently and found the
same five and no sixth. The measurement is regions-dashboard's, from when they hit it:
a Spanish catalogue present, es set, and every t() string still English.
All sixteen entries now call library/elements/defineMapElement.js, so the five are fixed
by construction rather than by five separate edits. Behaviour is otherwise identical --
same options, same element names, same per-plugin extras. wall-of-people-groups needed
the helper to hand its pinia back, because it takes a store off its own instance and a
helper that hid pinia would have given it a second one: two stores and a silent state
split.
★ AND THE CENSUS THAT RECOMMENDED THIS SAW FOUR OF SIXTEEN. My detector hashed function
BODIES; eleven sites are not `function buildXElement()` at all, they are
`const El = defineCustomElement(...)`. I wrote "every number here is a lower bound" in
the census as a caveat and it was the headline within the hour -- a 4x undercount of the
item it recommended. So this gate greps for the SHAPE, not for a known list: a check
written around the four that matched would have passed the twelve that did not.
check-element-bootstrap has two arms. No entry may build a profile element by hand, and
the helper itself must provide appI18n -- PLANTED as a negative case, so the regression
cannot return by editing library instead of a plugin. It also fails if it finds fewer
than ten entries, because a detection that stops matching reports the same green as a
tree with no problems.
THE PLANT CAUGHT TWO BUGS IN THIS GATE BEFORE IT CAUGHT ANYTHING ELSE. The predicate
matched the helper's DOCSTRING, so it would have passed a helper that only mentions the
provide in prose -- comments are stripped now, because a check that reads comments is
reading the author's intentions rather than the program. And the plant itself used /m
instead of /gm, so it deleted the documentation and left the code, then reported that it
could not detect an absence that was not there.
93 lines
5.2 KiB
JavaScript
93 lines
5.2 KiB
JavaScript
/**
|
|
* research-dashboard / index.js — Bundle entry (DOXA-LIB-2)
|
|
*
|
|
* Vite multi-entry build target. Emits app/research-dashboard.js.
|
|
*
|
|
* Mirrors plugin-designs/doxa-research-map/index.js (same ProfileLoader plumbing).
|
|
* Registers a SINGLE tag (UNCHANGED from the original profile — only the bundle folder
|
|
* is now plural so it can host N dashboard profiles tomorrow):
|
|
* - <research-dashboard-map> config-driven people-group research dashboard
|
|
*
|
|
* The dashboard mounts a Mapbox map in its center cell (Mapbox GL is loaded globally by
|
|
* index.html and the token arrives via profile-config.tk), so the RTL-text plugin is
|
|
* loaded once here, exactly like the map bundles.
|
|
*
|
|
* Profile registry — same Q3 contract as the map bundles: ProfileLoader lives in @map and
|
|
* cannot import.meta.glob across the package boundary, so the bundle evaluates
|
|
* import.meta.glob('./*.vue') HERE and hands the result to the loader via
|
|
* app.provide('profileModules'). The library panels live in @map/components/dashboards and
|
|
* are imported by the profile .vue — the glob only registers the profile screen(s).
|
|
*/
|
|
|
|
import { defineMapElement } from '@map/elements/defineMapElement.js'
|
|
import { registerStrategies } from '@map/colors/_registry.js'
|
|
import { installRtlTextPlugin } from '@map/maps/rtl-text.js'
|
|
// ★ WAS A CROSS-PLUGIN RELATIVE IMPORT into another plugin's PRIVATE folder
|
|
// ('../doxa-research-map/src/colors/...'). Both modules now live in library/colors/ (C1), so this
|
|
// bundle no longer depends on doxa-research-map's internal layout -- which is the coupling the
|
|
// library exists to remove, and the reason this migration had four consumers rather than the two
|
|
// the spec counted.
|
|
import affinityBlock from '@map/colors/affinity-block.js'
|
|
import doxaRegion from '@map/colors/doxa-region.js'
|
|
|
|
// ─── Bundle-private profile registry ─────────────────────────────────────────
|
|
const profileModules = import.meta.glob('./*.vue')
|
|
|
|
// ─── Bundle-private color strategies (card BUILD-STACKED-TREE-LEGEND) ────────
|
|
// The stacked tree legend colours its People and Place trees from the cap-3 research map's
|
|
// palettes, so the legend can never drift from the map's pins. Those two strategies are
|
|
// PROFILE-LOCAL to doxa-research-map (registered there by its own src/colors glob — see
|
|
// plugin-designs/doxa-research-map/index.js:38), so the dashboard bundle's registry does not
|
|
// contain them unless we register them here too.
|
|
//
|
|
// This MATTERS because the failure is silent: getColorStrategy() falls back to language-family
|
|
// for an unregistered mode, and useAffinityBlockLegendData.js:57 guards on propertyKey and
|
|
// returns {} — so without this, every People swatch would quietly be neutral grey and nothing
|
|
// would error. Registering the SAME modules means one palette, not a copied one.
|
|
//
|
|
// Imported EXPLICITLY rather than via import.meta.glob: a glob is resolved relative to this
|
|
// file by Vite and a cross-bundle relative glob that stops matching fails silently (zero
|
|
// strategies registered, grey swatches), whereas a named import fails loudly at build time.
|
|
registerStrategies({
|
|
'./affinity-block.js': { default: affinityBlock },
|
|
'./doxa-region.js': { default: doxaRegion },
|
|
})
|
|
|
|
// ─── Mapbox RTL text plugin — load ONCE before any map instance ──────────────
|
|
installRtlTextPlugin()
|
|
|
|
/**
|
|
* Build a fresh defineCustomElement-wrapped class. Each instance gets its own Pinia + i18n
|
|
* so multiple embeds on the same page don't bleed state.
|
|
*/
|
|
function buildDoxaResearchDashboardElement() {
|
|
return defineMapElement({
|
|
profileModules,
|
|
configureApp: (app, { pinia, i18n }) => {
|
|
// ★ HAND THE INSTANCE TO ProfileLoader, DON'T JUST INSTALL IT.
|
|
// ProfileLoader is the root of this custom element, and vue-i18n's useI18n() cannot resolve
|
|
// its injection at a custom-element root — so ProfileLoader takes the i18n INSTANCE by
|
|
// reference through inject('appI18n') and drives its global locale from the host's
|
|
// profile-config. With nothing provided under that key the inject returns null and the
|
|
// watchEffect that applies the locale quietly does nothing.
|
|
//
|
|
// MEASURED with check:host-locale-contract: this leaf answered 0 Arabic characters against a
|
|
// reference of 1,891 for the same page asked for in Arabic by URL. Not a missing catalogue and
|
|
// not a missing i18n install — the install was here all along, one line short of being usable.
|
|
// The sibling map entry (plugin-designs/doxa-research-map/index.js:66) has always provided it;
|
|
// this entry's own header calls itself a mirror of that file, which is how the divergence
|
|
// survived: the two read as the same plumbing until you diff them.
|
|
},
|
|
})
|
|
}
|
|
|
|
const DoxaResearchDashboardElement = buildDoxaResearchDashboardElement()
|
|
|
|
// ─── Register ONE tag — <research-dashboard-map> ────────────────────────────
|
|
if (typeof customElements !== 'undefined') {
|
|
if (!customElements.get('research-dashboard-map')) {
|
|
customElements.define('research-dashboard-map', DoxaResearchDashboardElement)
|
|
}
|
|
}
|
|
|
|
export default DoxaResearchDashboardElement
|