doxa-maps/library/utils
Doxa Maps d0939c0492 library: one embedScript for the app shells, replacing four private copies
DEDUP-AUDIT.md (measured today: 253 files, 31 cross-plugin duplicate clusters,
622 duplicated lines) ranks this tenth by raw cost and first by suitability. It
is the only cluster where the copies are identical in code, close over nothing,
and sit in two plugins with one owner between them.

loadScriptOnce (13 lines) and whenTagDefined (11) were byte-identical between
doxa-maps-spa and plugin-studio. deriveTreeBase (9) differed by ONE COMMENT LINE
and not one character of code -- drift in the documentation of a shared function,
which is its own argument for having one copy.

They are one concern, not three: load a bundle's script once, wait for its custom
element to register, and work out the tree base to load it from. That is what a
capability-5 app shell does to nest another plugin, and both plugins here ARE the
capability-5 shells. Any future shell needs the same three.

Verbatim move: no parameterisation, no behaviour change, callers import instead
of declaring. The comments travel with the code because each records a
measurement -- particularly the one explaining why onload is not a usable success
signal for a dev-server ES module.

ONE BEHAVIOUR CHANGE, AND IT IS AN IMPROVEMENT: the _loaded cache is now shared.
Two shells on one page previously kept separate caches and each loaded the same
bundle; the second now reuses the first's promise.

deriveTreeBase reads document.currentScript, so it is only valid AT MODULE
EVALUATION TIME. The call sites did not move -- both entries still call it at
module top level -- and the library file documents the constraint, because a
later call silently returns '' and every nested bundle URL would break.

Verified: both bundles build; each built file contains all three functions
exactly once and still derives currentScript; check:sri, check:series-isolation,
check:studio-rail and check:capability-derived all PASS.

library/utils/embedScript.js is the build owner's under rule 5B. The
plugin-designs and public/ changes are in the same commit because they import it
-- landing them apart breaks the build in between.
2026-09-28 07:07:33 +00:00
..
.gitkeep doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
apiBaseUrl.js doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
ClusterHelpers.js consolidate docs into documentation/ and deployment shells into deployment/ 2026-09-21 23:23:23 +00:00
colocation.js The prayer map's legends see the pins it draws 2026-09-27 02:17:35 +00:00
countries-meta.js Regions: one rollup, ported from theirs, instead of two copies 2026-09-24 04:01:34 +00:00
countryName.js Big Picture speaks Arabic where it was still speaking English: chrome and data labels 2026-09-28 02:01:46 +00:00
DataSourceManager.js 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
embedBase.js Dev server: every plugin reaches the asset pool again (no polygons, previews, fonts or tables in dev) 2026-09-25 23:17:35 +00:00
embedScript.js library: one embedScript for the app shells, replacing four private copies 2026-09-28 07:07:33 +00:00
formatCount.js One place decides how a count is punctuated, and it still says en-US 2026-09-27 06:04:08 +00:00
geoUtils.js Research tabs read at 15px; the status red is a step brighter 2026-09-17 02:38:38 -05:00
html.js Map popups show data as text: a people-group name or country field can no longer run script 2026-09-26 05:50:24 +00:00
loadPinnedUmd.js One pinned-UMD loader for PPLR and the Wall: library/utils/loadPinnedUmd.js 2026-09-26 07:24:25 +00:00
MSTClusteringUtil.js "MST" clustering draws again: a true spanning tree in under a second instead of a 12-second freeze 2026-09-26 04:38:59 +00:00
NetworkClusteringUtil.js doxa-maps — portable bundler for embeddable JAMstack maps 2026-09-10 01:53:07 +00:00
README.md Host-agnostic share links, token-endpoint chain, dev playground as reusable modules, share/asset gates, validated profile-type vocabulary 2026-09-16 12:10:38 -05:00
viewportScrim.js Land the prayer facet and the scrim helper 2026-09-22 21:50:32 +00:00

library/utils/ — pure JS helpers

No Vue, no Pinia, no Mapbox. Anything reactive is a composable; anything stateful is a store.

File Purpose
apiBaseUrl.js Resolves the API base URL at runtime (window.MAP_APP_API_URL / VITE_API_BASE_URL)
embedBase.js Share/embed URL ladder — the built bundle derives its tree root from its own script url (profileConfig.shareUrl / embedBaseUrl / window.MAP_EMBED_BASE_URL override) so tree-relative <bundle>/<profile>/index.html links work on any host
geoUtils.js Centroid, bounds, validation, GeoJSON helpers
ClusterHelpers.js Shared helpers for the two clustering utilities below
MSTClusteringUtil.js Minimum-spanning-tree clustering for affinity blocks
NetworkClusteringUtil.js Network-line clustering — connect nearby pins with edges
  • No import { ref } from 'vue' and no import mapboxgl in this folder — operate on plain [lng, lat] arrays.
  • Named exports (for tree-shaking), JSDoc on every export.
  • Writing reactive logic or needing Mapbox APIs? That's a composable — move it to ../composables/.