doxa-maps/plugin-designs/doxa-simple-map/index.js
Doxa Maps 1c63481832 Six entries hand-rolled the RTL text plugin; the library already installs it
Every one of these bundle entries carried its own copy of

    if (window.mapboxgl?.setRTLTextPlugin) { setRTLTextPlugin(url, null, true) }

which is a strict SUBSET of what library/maps/rtl-text.js already does, so the
copies could not be covering anything the library misses:

  - useMapInstance calls installRtlTextPlugin(gl) at line 450, before it builds a
    map at 537/567 -- registration still precedes construction, the one ordering
    Mapbox cares about.
  - the call is identical in effect: same v0.3.0 URL, same null callback, same
    lazy flag.
  - the block is mapboxgl-only. The library installs on MapLibre too, so every
    keyless embed was covered by the library and never by these blocks.
  - the single raw `new gl.Map` site (upg-100-list.vue:1894) installs for itself
    at 1835 and never depended on its entry.

I first justified this as deleting DEAD code, on the theory that the engine is
injected lazily so window.mapboxgl would not exist when an entry runs. That is
wrong and the measurement says so: every leaf index.html loads mapbox-gl.js as a
blocking <head> script while ./index.js is a deferred module, so the guard did
pass and the blocks were live. The reason to delete them is redundancy, which is
the weaker and truer claim.

A three-line pointer replaces each block so the next reader does not re-add a
Mapbox-only copy.
2026-09-26 13:35:57 +00:00

100 lines
4.8 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 { defineCustomElement } from 'vue'
import { createPinia } from 'pinia'
import ProfileLoader from '@map/ProfileLoader.vue'
import { createAppI18n } from '@map/i18n/index.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 defineCustomElement(ProfileLoader, {
configureApp(app) {
app.use(createPinia())
// 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.
const i18n = createAppI18n()
app.use(i18n)
app.provide('appI18n', i18n)
// Hand the bundle's profile registry to ProfileLoader (Q3 contract).
// ProfileLoader inject('profileModules')s this — see ProfileLoader.vue.
app.provide('profileModules', profileModules)
}
})
}
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 }