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
4.6 KiB
JavaScript
93 lines
4.6 KiB
JavaScript
/**
|
|
* plugin-designs/doxa-simple-map/index.js
|
|
*
|
|
* Bundle entry — registers the doxa-simple-map web component(s).
|
|
*
|
|
* Registers TWO custom-element tag names that mount the SAME ProfileLoader
|
|
* (separate defineCustomElement calls so each tag gets its own class):
|
|
* - <doxa-map> legacy production tag (Q1 back-compat — must keep working)
|
|
* - <doxa-simple-map> new explicit tag matching the bundle name
|
|
*
|
|
* Usage from a host page (legacy):
|
|
* <script src="/app/doxa-simple-map.iife.js"></script>
|
|
* <doxa-map profile-config='{"profile":"doxa-simple-map","tk":"pk.eyJ..."}'></doxa-map>
|
|
*
|
|
* Usage (new):
|
|
* <script src="/app/doxa-simple-map.iife.js"></script>
|
|
* <doxa-simple-map profile-config='{"profile":"doxa-simple-map","tk":"pk.eyJ..."}'></doxa-simple-map>
|
|
*
|
|
* The profile-config attribute is parsed by ProfileLoader (in @map).
|
|
* `profile` must match a .vue file in this bundle's folder.
|
|
*
|
|
* Profile registry — Q3 contract from the migration plan: ProfileLoader lives
|
|
* inside @map, so it cannot use import.meta.glob to reach into a
|
|
* bundle's folder. The bundle MUST evaluate import.meta.glob('./*.vue')
|
|
* locally and hand the result to the loader via app.provide('profileModules').
|
|
*
|
|
* Mapbox RTL text plugin: registered ONCE at module init (before any map
|
|
* constructs), lazy-loads when Arabic/Hebrew text appears on the basemap.
|
|
*/
|
|
|
|
import { defineMapElement } from '@map/elements/defineMapElement.js'
|
|
import { registerStrategies } from '@map/colors/_registry.js'
|
|
|
|
// ─── Bundle-private profile registry ─────────────────────────────────────────
|
|
// import.meta.glob is evaluated by Vite at build time relative to THIS file —
|
|
// so it captures only this bundle's profiles. Handed to ProfileLoader via
|
|
// app.provide('profileModules', ...) below.
|
|
const profileModules = import.meta.glob('./*.vue')
|
|
|
|
// ─── Bundle-private color strategies ─────────────────────────────────────────
|
|
// Same seam as profileModules, for colors. Any `<name>.js` a contributor drops in
|
|
// this bundle's `src/colors/` folder is merged OVER the shared library set
|
|
// (same mode key = override; new key = profile-private). This bundle inlines its own
|
|
// copy of the registry (IIFE build), so registering here affects THIS bundle only.
|
|
// No-op today: doxa-simple-map ships no local strategies (empty glob).
|
|
registerStrategies(import.meta.glob('./src/colors/*.js', { eager: true }))
|
|
|
|
// RTL text plugin (Arabic/Hebrew/Persian shaping): installed by useMapInstance through
|
|
// library/maps/rtl-text.js, on BOTH engines, before every map is constructed. Do not re-add a
|
|
// hand-rolled mapboxgl-only block here -- it was a strict subset of that call.
|
|
|
|
/**
|
|
* Build a fresh defineCustomElement-wrapped class.
|
|
*
|
|
* Vue's defineCustomElement returns a class that gets registered with
|
|
* customElements.define exactly once per tag name. Reusing a single class
|
|
* across two tags is undefined behavior, so we call defineCustomElement TWICE
|
|
* with the same component to produce two independent classes.
|
|
*
|
|
* Each instance gets its own Pinia + its own i18n via configureApp — that
|
|
* isolation is important when multiple <doxa-map> embeds share a page.
|
|
*/
|
|
function buildDoxaMapElement() {
|
|
return defineMapElement({
|
|
profileModules,
|
|
configureApp: (app, { pinia, i18n }) => {
|
|
// Install i18n AND hand the instance to ProfileLoader by reference. The
|
|
// defineCustomElement root cannot use useI18n() (see ProfileLoader.vue);
|
|
// it drives locale through this provided instance instead.
|
|
// Hand the bundle's profile registry to ProfileLoader (Q3 contract).
|
|
// ProfileLoader inject('profileModules')s this — see ProfileLoader.vue.
|
|
},
|
|
})
|
|
}
|
|
|
|
const DoxaMapElement = buildDoxaMapElement()
|
|
const DoxaSimpleMapElement = buildDoxaMapElement()
|
|
|
|
// ─── Register both tag names ─────────────────────────────────────────────────
|
|
// Guards prevent "already registered" errors when this IIFE is loaded twice
|
|
// (e.g. on a page that ships both legacy and new <script> tags during a
|
|
// transition window).
|
|
if (typeof customElements !== 'undefined') {
|
|
if (!customElements.get('doxa-map')) {
|
|
customElements.define('doxa-map', DoxaMapElement)
|
|
}
|
|
if (!customElements.get('doxa-simple-map')) {
|
|
customElements.define('doxa-simple-map', DoxaSimpleMapElement)
|
|
}
|
|
}
|
|
|
|
export default DoxaMapElement
|
|
export { DoxaSimpleMapElement }
|