doxa-maps/library/utils
Doxa Maps 3d7ad038a9 A relative share link works when you click it, which is why nobody caught it
DRV1650-SR-EMBED-URL-RUNTIME-ORIGIN. The Driver copied
`research-map-plus-grid/research-map-plus-grid/index.html` from a page at
http://127.0.0.1:5192/, a link that works on no other site.

resolveShareUrl's tier 1 returns its input VERBATIM, correctly: a host handing over a
whole url has already decided. So a composite that BUILDS a tier-1 url takes on tier 2's
job, and both of mine wrote the same thing:

    base ? base + '/' + leaf : leaf

On any host where the tree root cannot be derived from the script url — a dev server, an
ESM build, a tree served from a path that does not match `<name>/<name>.js` — base is ''
and the else branch hands tier 1 a bare relative path, which it then returns unresolved.

★ IT LOOKS RIGHT IN THE ONE PLACE ANYONE CHECKS. A relative share link WORKS WHEN
CLICKED, because the browser resolves it against the page you copied it from. It is the
EMBED that breaks — an <iframe src="…"> on a partner's page resolves against THEIRS — so
the failure is invisible exactly where it is tested and visible only where it ships.
research-map-plus-grid.vue:174 even documents the requirement ("It MUST be absolute,
which is the non-obvious part") four lines above the branch that violates it.

absoluteEmbedUrl() is tier 2's resolution made available to tier-1 builders: the
configured base when known, otherwise resolved against document.baseURI, which yields the
runtime origin. Never relative in a browser. The ladder is unchanged; only its last rung
is.

The gate has both arms, because either alone would rot: the RESOLVER must be absolute
with no base (the failing case, not the passing one), and no plugin may rebuild the
`: leaf` fallback. Negative-tested: removing the origin fallback, and re-introducing the
ternary in a plugin, each turn it red.

"Copy link didn't work" is most likely the same defect rather than a second one —
ShareButton's copy already falls back from navigator.clipboard to execCommand for
insecure contexts, so the copy almost certainly succeeded and produced a useless URL. If
it still fails after this, it is a separate bug and needs a browser to see.
2026-09-28 17:40:34 +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 A relative share link works when you click it, which is why nobody caught it 2026-09-28 17:40:34 +00:00
embedScript.js Both library layouts load nested bundles through the shared embedScript, which fixes VerticalTabsLayout on the dev server 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
languageLabel.js The packet's generated description, and the language name it prints was index-ordered 2026-09-28 13:56:06 +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/.