The library's pin and region popups (useMapEvents) interpolated data fields raw into the HTML handed to setHTML(); a name like <img src=x onerror=…> from an API or a partner's list would run in the host page (CRITIC-3). library/utils/html.js adds escapeHtml and safeUrl (http(s) only); every field of both popups goes through them. check:popup-escaping (headless, gates:post) mounts the real composable, renders both popups from hostile data and requires no markup, handler or javascript: URL to survive: it FAILs on the previous code (both popups) and PASSes here. check:cdn-pins and check:no-eval join gates:post too. |
||
|---|---|---|
| .. | ||
| .gitkeep | ||
| apiBaseUrl.js | ||
| ClusterHelpers.js | ||
| countries-meta.js | ||
| DataSourceManager.js | ||
| embedBase.js | ||
| geoUtils.js | ||
| html.js | ||
| MSTClusteringUtil.js | ||
| NetworkClusteringUtil.js | ||
| README.md | ||
| viewportScrim.js | ||
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 noimport mapboxglin 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/.