doxa-maps/library
doxa-maps-88655c70 4fb8176b00 Shape Arabic, Hebrew and Persian map labels on MapLibre maps too
library/maps/rtl-text.js installed the RTL text plugin for MAPBOX only
(window.mapboxgl, from api.mapbox.com). So every MapLibre map, i.e. every
keyless embed, drew RTL place names as disconnected, reversed glyphs.
Measured on the Prayer Walk Planner's printed Arabic sheet.

Under it was a second gap. Bundle entries call the installer at LOAD
time, before useMapInstance has lazily injected a MapLibre engine, so even
an engine-aware installer found nothing to install into.

- rtl-text.js is engine-aware. Mapbox is unchanged (same URL, same lazy
  call). MapLibre gets the same plugin package from jsDelivr, keyless and
  not api.mapbox.com, so keyless pages still make zero Mapbox requests.
  New ensureRtlTextPlugin(gl) waits until it is LOADED, for callers that
  capture a single frame (print).
- useMapInstance installs it the moment an engine global exists, the one
  point every map passes through.
- The planner drops its private copy for the shared helper.

Measured: a print map of downtown Cairo (MapLibre, keyless) shows shaped
Arabic street and place names (شارع التحرير, مسجد الطباخ …); plugin
status "loaded", fetched from jsDelivr. check:gallery-embed passes js,
iframe, neighbour and linked (14 tabs); :maplibre passes;
check:prayer-walk-planner passes.

The shared change reaches all 11 bundles that compile initializeMap, and
all are rebuilt here. check:shared-reached gains an rtl-text-maplibre
marker (10/10 consumers carry it; cities-internet, gospel-resources and
my-upg-100-list boot maps another way and are not affected).

Also: the new Experimental bundle pplr-data-maps loads the Mapbox geocoder
under maplibre (pplrData.js:38). It is an owned, printed MAPBOX_KNOWN entry
routed to its owner; delete it in their fix commit.
2026-09-25 08:20:12 +00:00
..
api Add the Gospel Access filter, the ladder the binary flag was flattening 2026-09-23 13:19:22 +00:00
colors Adopt the research map's region colours, and pin the one unit that wasn't px 2026-09-24 20:48:27 +00:00
components Merge main into bundler-2/work 2026-09-25 07:14:11 +00:00
composables Shape Arabic, Hebrew and Persian map labels on MapLibre maps too 2026-09-25 08:20:12 +00:00
constants doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
data Regions: expand a region to its country posters, reusing the shared wall 2026-09-24 04:26:29 +00:00
i18n Take main 2026-09-25 07:20:35 +00:00
layouts Move internal files out of the repo; fix five dead links; a fuller delegation diagram 2026-09-25 05:14:10 +00:00
maps Shape Arabic, Hebrew and Persian map labels on MapLibre maps too 2026-09-25 08:20:12 +00:00
packet packet: a partial translation renders 12 prayer points, not 3 2026-09-24 12:20:38 +00:00
scripts All People Groups loads fast on a light map; the Vision Card becomes a true funnel from data 2026-09-25 07:18:30 +00:00
stores fix(spa): make embedded maps survive the sandboxed plugin iframe 2026-09-12 21:07:26 +00:00
styles Fiord: the MapLibre dark that actually looks like the map it replaces 2026-09-24 02:26:14 +00:00
utils embedBase: the asset pool is INSIDE the tree, not beside it 2026-09-25 01:30:56 +00:00
index.js Move internal files out of the repo; fix five dead links; a fuller delegation diagram 2026-09-25 05:14:10 +00:00
ProfileLoader.vue One page, one map token — and the nested search bar comes back 2026-09-24 01:14:37 +00:00
README.md Complete app-profiles->plugin-designs sweep across comments/docs; build green; layouts kept at root (load-bearing) 2026-09-17 18:18:19 +00:00

library/ (@map) — the shared map template

The other half of the architecture (see ../plugin-designs/README.md): every map in plugin-designs/<your-map>/ composes the reusable, parameterized pieces that live here. Fix something here and every map benefits on the next build; break something here and every map breaks — read components/WARNING.md before touching shared pieces.

Folder What lives there
ProfileLoader.vue The root of every bundle: parses profile-config, loads the profile, provides the stores + config
components/ Shared UI — map, legends, controls, popup (PeopleGroupDetail), tables, charts, hints (README)
composables/ Shared logic — map engine (useMapInstance), provider switch, shadow-DOM styles, theming
stores/ Per-instance Pinia stores (ui / map / data) — provided by ProfileLoader, injected by children
api/ Data-source registry (sources.json) + fetch layer — the JAMstack runtime wiring
colors/ Color sets maps opt into via profile-config.colorSet
i18n/ The shared string catalogs (all maps speak the same languages)
data/ Small shared datasets baked at build time (big served data lives in ../data/)
constants/ Shared constants
scripts/ Maintainer pipelines (posters, research) — not part of any bundle

The rule of thumb (same as WARNING.md): custom code in your app-profile, reusable code here — and things only move from the first to the second once they've earned it.