Update from source 13e0e02c
13
README.md
|
|
@ -10,6 +10,19 @@ Made by Vibe Coders for Vibe Coders to prepare the way of the Lord and make His
|
|||
iframe, script embed, mobile app — or open every map at once as one app. Five plugin
|
||||
capabilities, three outputs, one shared library, one build.
|
||||
|
||||
### What the library gives every map
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 🗺️ **Two map engines** | Every map draws with **Mapbox** or **MapLibre** (free, no key) — switch with `"provider"` in its settings or `?provider=maplibre` in the address. Mapbox is the default. |
|
||||
| 🔑 **A key or a key service** | Give Mapbox a public token, or the address of a token service that hands one out — set once in the Plugin Studio header. |
|
||||
| 🌍 **11 languages** | `?lang=` or `"locale"`, with Arabic right to left — [Languages](#languages). |
|
||||
| 🧩 **Web components** | Each map is its own HTML tag, like `<all-people-groups>`, that works on any page — no framework needed. |
|
||||
| 🔗 **Maps that talk to each other** | Maps share props and events, so one app can nest them and a click in one can move another. |
|
||||
| 🪶 **Small bundles** | Each map's file carries only the parts of the shared library it uses (tree-shaken). |
|
||||
| ⚙️ **One build step** | `bun run build` makes every map at once. |
|
||||
| 📦 **Three outputs** | A web folder (iframe, script embed), a mobile app, a desktop app — [the 3 outputs](#what-the-build-makes--3-outputs). |
|
||||
|
||||
| What dx-maps set out to do | Proof |
|
||||
|---|---|
|
||||
| **One build → one folder** you can drop on any host | `bun run check:drop` |
|
||||
|
|
|
|||
9464
data/tables/country-languages.json
Normal file
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 2 MiB After Width: | Height: | Size: 2 MiB |
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 317 KiB |
|
Before Width: | Height: | Size: 954 KiB After Width: | Height: | Size: 954 KiB |
|
Before Width: | Height: | Size: 760 KiB After Width: | Height: | Size: 728 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 205 KiB After Width: | Height: | Size: 205 KiB |
|
|
@ -1,23 +1,23 @@
|
|||
{
|
||||
"cap1-single-element": {
|
||||
"bundle": "all-people-groups",
|
||||
"sha256": "1a2ddbee5f7ade4c59be1e729334fbaabb9a4bb52fe91aaae70df0b8a3e817a2"
|
||||
"sha256": "483a04b2ae46e00b0e0530c9291070b30c9baeaddf2940cd61e04cdffb382095"
|
||||
},
|
||||
"cap2-adoption": {
|
||||
"bundle": "doxa-simple-map",
|
||||
"sha256": "01973724b4f6b656d4f4743cf2167b8d5a984f48401e4738cec83fb3719d289b"
|
||||
"sha256": "646efc14670963e1d3e1b1982ff2130562f28183a5908ef3c0c5dbd8d7f9597a"
|
||||
},
|
||||
"cap2-engagement": {
|
||||
"bundle": "doxa-simple-map",
|
||||
"sha256": "01973724b4f6b656d4f4743cf2167b8d5a984f48401e4738cec83fb3719d289b"
|
||||
"sha256": "646efc14670963e1d3e1b1982ff2130562f28183a5908ef3c0c5dbd8d7f9597a"
|
||||
},
|
||||
"cap2-prayer": {
|
||||
"bundle": "doxa-simple-map",
|
||||
"sha256": "01973724b4f6b656d4f4743cf2167b8d5a984f48401e4738cec83fb3719d289b"
|
||||
"sha256": "646efc14670963e1d3e1b1982ff2130562f28183a5908ef3c0c5dbd8d7f9597a"
|
||||
},
|
||||
"cap3-monolithic-research": {
|
||||
"bundle": "doxa-research-map",
|
||||
"sha256": "5f73cb71c0a374a5506df426ac4b43648f28d7128b9583da1b358c1ca7519bda"
|
||||
"sha256": "9a7161f8337ff9efffcf4c8092157b5a8932de91c69fb541672f92c040033716"
|
||||
},
|
||||
"cap4-upg100-list": {
|
||||
"bundle": "my-upg-100-list",
|
||||
|
|
@ -49,7 +49,7 @@
|
|||
},
|
||||
"exp-wall-of-people-groups": {
|
||||
"bundle": "wall-of-people-groups",
|
||||
"sha256": "2dfc3a3c4918b574862c07271d8594e56b6d1d7ef96553fe67359bbe58c2cad2"
|
||||
"sha256": "1ce6d49a495aa794200b97005e620db37fca3ade59325fa359d3a59d200cbcba"
|
||||
},
|
||||
"lang-arabic-upg100": {
|
||||
"bundle": "my-upg-100-list",
|
||||
|
|
@ -61,11 +61,11 @@
|
|||
},
|
||||
"prod-cities-internet": {
|
||||
"bundle": "cities-internet",
|
||||
"sha256": "65e98efcd79016282460e3141ccb2995ad5a11d7039c3303d7c4ae2a7a5ee32d"
|
||||
"sha256": "236a1a98ec06562224f77af8ca8290e4381b4df8e81aa143ecb886f5f14f7113"
|
||||
},
|
||||
"prod-cities-internet-phone": {
|
||||
"bundle": "cities-internet",
|
||||
"sha256": "65e98efcd79016282460e3141ccb2995ad5a11d7039c3303d7c4ae2a7a5ee32d"
|
||||
"sha256": "236a1a98ec06562224f77af8ca8290e4381b4df8e81aa143ecb886f5f14f7113"
|
||||
},
|
||||
"prod-gospel-resources": {
|
||||
"bundle": "gospel-resources",
|
||||
|
|
@ -77,15 +77,15 @@
|
|||
},
|
||||
"prod-prayer-phone": {
|
||||
"bundle": "doxa-simple-map",
|
||||
"sha256": "01973724b4f6b656d4f4743cf2167b8d5a984f48401e4738cec83fb3719d289b"
|
||||
"sha256": "646efc14670963e1d3e1b1982ff2130562f28183a5908ef3c0c5dbd8d7f9597a"
|
||||
},
|
||||
"prod-regions": {
|
||||
"bundle": "regions-dashboard",
|
||||
"sha256": "8766e709cbc4e49a30590ce57c4322d54912e3749bfa44b1c58afeb41bae4d67"
|
||||
"sha256": "85a9367643be850d554fbcc704ab57f850e30388ef6cfe5e001032bc3f323f0c"
|
||||
},
|
||||
"prod-regions-phone": {
|
||||
"bundle": "regions-dashboard",
|
||||
"sha256": "8766e709cbc4e49a30590ce57c4322d54912e3749bfa44b1c58afeb41bae4d67"
|
||||
"sha256": "85a9367643be850d554fbcc704ab57f850e30388ef6cfe5e001032bc3f323f0c"
|
||||
},
|
||||
"prod-research-gallery-phone": {
|
||||
"bundle": "doxa-maps-spa",
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* "Answers 200" and "is serving this checkout" are different questions. This asks the second.
|
||||
*
|
||||
* THE FINGERPRINT is public/doxa-maps/manifest.json, which generate-tree rewrites on every
|
||||
* THE FINGERPRINT is public/<TREE_NAME>/manifest.json, which generate-tree rewrites on every
|
||||
* build and which names every bundle and profile in the tree. If the bytes served differ
|
||||
* from the bytes on disk, it is a different build — a different worktree, or a stale server
|
||||
* someone forgot to restart, both of which produce the same lie.
|
||||
|
|
@ -27,7 +27,7 @@ import { TREE_NAME, TREE_NAME_RE } from './_tree-name.mjs'
|
|||
const MANIFEST = `${TREE_NAME}/manifest.json`
|
||||
|
||||
/**
|
||||
* @param {string} base e.g. http://127.0.0.1:4173 (a trailing /doxa-maps/ is tolerated)
|
||||
* @param {string} base e.g. http://127.0.0.1:4173 (a trailing /<TREE_NAME>/ is tolerated)
|
||||
* @param {string} repo absolute path to the repo root
|
||||
* @param {{assets?: string[]}} [opts] data files this gate JUDGES (tree-relative, e.g.
|
||||
* 'assets/tables/doxa-gospel-access.json'); their served bytes must equal disk too
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ const TREE = join(ROOT, 'public', TREE_NAME)
|
|||
const argv = process.argv.slice(2)
|
||||
const oi = argv.indexOf('--only')
|
||||
const ONLY = oi >= 0 && argv[oi + 1] ? new Set(argv[oi + 1].split(',')) : null
|
||||
// NOT ONLY COMPOSITES (rega, 2026-09-25): a library change merged into main reached prayer-walk-planner,
|
||||
// which composes nothing, so this gate could not see it was stale. --all checks EVERY bundle; --bundles a,b
|
||||
// checks those (the landing precondition passes the ones a landing can have changed).
|
||||
const ALL = argv.includes('--all')
|
||||
const bi = argv.indexOf('--bundles')
|
||||
const EXTRA = bi >= 0 && argv[bi + 1] ? new Set(argv[bi + 1].split(',').filter(Boolean)) : new Set()
|
||||
|
||||
if (!existsSync(join(TREE, 'manifest.json'))) {
|
||||
console.log(`COMPOSITE-FRESHNESS: SKIP — no built tree (public/${TREE_NAME}/manifest.json).`)
|
||||
|
|
@ -78,8 +84,8 @@ try {
|
|||
for (const f of readdirSync(join(DESIGNS, bundle)).filter((f) => f.endsWith('.meta.json'))) {
|
||||
try { const c = JSON.parse(readFileSync(join(DESIGNS, bundle, f), 'utf8')).composes; if (Array.isArray(c) && c.length) composes = (composes || []).concat(c) } catch { /* not JSON: not a declaration */ }
|
||||
}
|
||||
if (!composes) continue
|
||||
for (const e of composes) if (!resolveEntry(e, bundle)) unresolved.push(`${bundle} composes "${e}" — resolves to no bundle`)
|
||||
if (!composes && !ALL && !EXTRA.has(bundle)) continue
|
||||
for (const e of composes || []) if (!resolveEntry(e, bundle)) unresolved.push(`${bundle} composes "${e}" — resolves to no bundle`)
|
||||
composites++
|
||||
const committed = join(TREE, bundle, `${bundle}.js`)
|
||||
if (!existsSync(committed)) { failures.push(`${bundle}: no committed bundle at public/${TREE_NAME}/${bundle}/${bundle}.js`); continue }
|
||||
|
|
@ -96,7 +102,7 @@ try {
|
|||
}
|
||||
} finally { rmSync(tmp, { recursive: true, force: true }) }
|
||||
|
||||
console.log(`COMPOSITE-FRESHNESS: ${composites} composite(s) rebuilt into a temp dir and compared byte for byte with the committed bundle.`)
|
||||
console.log(`COMPOSITE-FRESHNESS: ${composites} bundle(s) rebuilt into a temp dir and compared byte for byte with the committed bundle.`)
|
||||
if (fresh.length) console.log(` ✓ ${fresh.join(', ')}`)
|
||||
for (const u of unresolved) console.log(` ! UNRESOLVED ${u}`)
|
||||
if (failures.length) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
* { key:'map', element:'doxa-research-map', src:'../../doxa-research-map/doxa-research-map.js' }
|
||||
*
|
||||
* That `src` is resolved BY THE BROWSER, relative to the composite's generated leaf page, which is
|
||||
* served two levels deep (doxa-maps/<bundle>/<profile>/index.html). So a sibling bundle is reached
|
||||
* served two levels deep (<TREE_NAME>/<bundle>/<profile>/index.html). So a sibling bundle is reached
|
||||
* with `../../<bundle>/<bundle>.js`. Get the depth wrong by one and you get a 404.
|
||||
*
|
||||
* ★ THE FAILURE IS SILENT, WHICH IS WHY IT NEEDS A GATE. StackLayout mounts each section inside a
|
||||
|
|
|
|||
102
internal/check-dev-assets.mjs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* check-dev-assets — under the DEV SERVER, every plugin reaches the shared asset pool.
|
||||
*
|
||||
* WHY (2026-09-25, reported from a laptop running `bun run dev`): under the Plugin Studio, Big Picture,
|
||||
* Regions, UPG-100 (and its posters), Cities with Internet and Gospel drew with NO boundary polygons.
|
||||
* The built tree was fine, and every gate measured the built tree. In dev, a plugin that falls back to
|
||||
* the page-relative './assets' on a /__leaf/<bundle>/<profile> page asked for /__leaf/<bundle>/assets/…,
|
||||
* which the dev server answered with the leaf's own HTML at HTTP 200: JSON.parse failed, and the map
|
||||
* drew with no polygons, previews, fonts or tables. One cause, four faces.
|
||||
*
|
||||
* WHAT IS ASSERTED, on a dev server whose identity is printed first:
|
||||
* HTTP boundaries/, previews/, fonts/, images/ and tables/ each resolve (200, not HTML) at every
|
||||
* prefix a dev page can produce: /assets/, /__plugin-gallery/assets/, /<tree>/assets/,
|
||||
* /__leaf/<bundle>/assets/ and /__leaf/<bundle>/<profile>/assets/.
|
||||
* LEAVES every leaf of the seven studio maps (Big Picture, Simple Research, Regions, UPG-100, Prayer
|
||||
* Progress, Cities, Gospel): its dev page hands the element assetsBase "/assets" (as a built
|
||||
* leaf hands "../../assets"); a boundary file and a table under THAT base answer 200 with bytes
|
||||
* that JSON.parse, and a bogus file under it is a real 404, not HTML.
|
||||
* HEADLESS by project rule (browsers are one agent's, on this machine): whether each map then DRAWS
|
||||
* its polygons is a visual check, handed over as "needs eyes".
|
||||
*
|
||||
* USAGE node internal/check-dev-assets.mjs [--url http://127.0.0.1:5190]
|
||||
* Without --url it starts a SHORT-LIVED dev server for THIS checkout on a free port and stops it.
|
||||
* EXIT 0 pass · 1 an asset does not resolve · 75 not measured.
|
||||
*/
|
||||
import { spawn, spawnSync } from 'node:child_process'
|
||||
import { createServer } from 'node:http'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { TREE_NAME } from './_tree-name.mjs'
|
||||
|
||||
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const argv = process.argv.slice(2)
|
||||
const arg = (k, d) => { const i = argv.indexOf(k); return i >= 0 && argv[i + 1] ? argv[i + 1] : d }
|
||||
const MAP_BUNDLES = ['dashboard-plus-grid', 'doxa-research-map', 'regions-dashboard', 'my-upg-100-list', 'doxa-simple-map', 'cities-internet', 'gospel-resources']
|
||||
const JSON_SAMPLES = ['boundaries/world-adm0.geojson', 'tables/country-connectivity.json']
|
||||
const SAMPLES = ['boundaries/world-adm0.geojson', 'previews/andean-caribbean.webp', 'fonts/bebas-neue/bebas-neue-latin.woff2', 'images/worldmap.svg', 'tables/arclight-index.json']
|
||||
|
||||
let BASE = arg('--url', ''), dev = null
|
||||
const stop = () => { if (dev) { try { process.kill(-dev.pid) } catch { try { dev.kill() } catch { /* gone */ } } } }
|
||||
if (!BASE) {
|
||||
const port = await new Promise((ok) => { const s = createServer().listen(0, '127.0.0.1', () => { const n = s.address().port; s.close(() => ok(n)) }) })
|
||||
dev = spawn('bun', ['x', 'vite', '--port', String(port), '--strictPort', '--host', '127.0.0.1'], { cwd: ROOT, stdio: 'ignore', detached: true })
|
||||
BASE = `http://127.0.0.1:${port}`
|
||||
let up = false
|
||||
for (let i = 0; i < 120 && !up; i++) { await new Promise((r) => setTimeout(r, 500)); up = await fetch(BASE + '/').then((r) => r.ok).catch(() => false) }
|
||||
if (!up) { stop(); console.log(`DEV-ASSETS: NOT MEASURED — the dev server did not come up on ${BASE}`); process.exit(75) }
|
||||
const sha = spawnSync('git', ['rev-parse', '--short', 'HEAD'], { cwd: ROOT, encoding: 'utf8' }).stdout.trim()
|
||||
const dirty = spawnSync('git', ['status', '--porcelain', '--', 'library', 'plugin-designs', 'internal', 'vite.config.js'], { cwd: ROOT, encoding: 'utf8' }).stdout.trim()
|
||||
console.log(`DEV-ASSETS: measuring a dev server started for THIS checkout — ${ROOT} @ ${sha}${dirty ? ' + uncommitted changes' : ''} on ${BASE}`)
|
||||
} else {
|
||||
const id = await fetch(BASE + '/__dev-sha').then((r) => (r.ok ? r.text() : '')).catch(() => '')
|
||||
console.log(`DEV-ASSETS: measuring ${BASE}${id ? ` — serving ${id.trim()}` : ' — (it does not report which commit it serves)'}`)
|
||||
}
|
||||
|
||||
let bad = 0
|
||||
try {
|
||||
// ── HTTP ──
|
||||
const prefixes = ['/assets/', '/__plugin-gallery/assets/', `/${TREE_NAME}/assets/`, '/__leaf/regions-dashboard/assets/', '/__leaf/my-upg-100-list/upg-100-list/assets/']
|
||||
for (const p of prefixes) {
|
||||
const res = []
|
||||
for (const s of SAMPLES) {
|
||||
const r = await fetch(BASE + p + s).catch(() => null)
|
||||
const ct = r ? r.headers.get('content-type') || '' : ''
|
||||
const ok = r && r.status === 200 && !/text\/html/.test(ct)
|
||||
if (!ok) { bad++; res.push(`${s.split('/')[0]} ${r ? r.status : 'ERR'}${/html/.test(ct) ? ' (HTML)' : ''}`) }
|
||||
}
|
||||
console.log(` ${res.length ? 'FAIL' : 'ok '} ${p.padEnd(44)} ${res.length ? res.join(', ') : SAMPLES.map((s) => s.split('/')[0]).join(' ') + ' all 200'}`)
|
||||
}
|
||||
|
||||
// ── EVERY LEAF OF THE SEVEN MAPS: the base its page hands the element serves REAL, parseable data ──
|
||||
// (bytes + JSON.parse, never an HTML fallback), and a bogus path under the same base is a real 404.
|
||||
const reg = await fetch(BASE + '/__plugin-gallery/registry.json').then((r) => r.json()).catch(() => [])
|
||||
const leaves = []
|
||||
for (const b of reg) if (MAP_BUNDLES.includes(b.bundle)) for (const it of b.items || []) leaves.push(`/__leaf/${b.bundle}/${it.profile}`)
|
||||
if (leaves.length < MAP_BUNDLES.length) { bad++; console.log(` FAIL registry lists ${leaves.length} leaves for the ${MAP_BUNDLES.length} map bundles`) }
|
||||
for (const leaf of leaves) {
|
||||
const html = await fetch(BASE + leaf).then((r) => r.text()).catch(() => '')
|
||||
const m = /profile-config='([^']*)'/.exec(html)
|
||||
let base = ''
|
||||
try { base = JSON.parse(m[1]).assetsBase || '' } catch { /* no config */ }
|
||||
const out = []
|
||||
let ok = base === '/assets'
|
||||
if (!ok) out.push(`assetsBase ${JSON.stringify(base)}`)
|
||||
const at = (f) => base ? BASE + base + '/' + f : new URL('assets/' + f, BASE + leaf).href
|
||||
for (const f of JSON_SAMPLES) {
|
||||
const r = await fetch(at(f)).catch(() => null)
|
||||
const body = r ? await r.text() : ''
|
||||
let parsed = false
|
||||
try { JSON.parse(body); parsed = true } catch { /* not JSON */ }
|
||||
if (!r || r.status !== 200 || !parsed) { ok = false; out.push(`${f} ${r ? r.status : 'ERR'}${parsed ? '' : ' NOT JSON'}`) } else out.push(`${f.split('/').pop()} ${body.length} B`)
|
||||
}
|
||||
const ctl = await fetch(at('boundaries/no-such-file.geojson')).catch(() => null)
|
||||
if (!ctl || ctl.status !== 404) { ok = false; out.push(`bogus path ${ctl ? ctl.status : 'ERR'} (want 404)`) }
|
||||
if (!ok) bad++
|
||||
console.log(` ${ok ? 'ok ' : 'FAIL'} ${leaf.padEnd(52)} assetsBase ${base || '(none)'}: ${out.join(', ')}${ok ? ', bogus 404' : ''}`)
|
||||
}
|
||||
} finally { stop() }
|
||||
|
||||
if (bad) { console.log(`DEV-ASSETS: FAIL — ${bad} check(s): the dev server does not hand every plugin the asset pool.`); process.exit(1) }
|
||||
console.log('DEV-ASSETS: PASS — the pool resolves at every prefix a dev page can produce, and dev leaves hand it to their element.')
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
* USAGE
|
||||
* node internal/check-facet-changes-map.mjs # against BASE_URL (default dev 5173)
|
||||
* node internal/check-facet-changes-map.mjs --self-test # NEGATIVE test: the gate must FAIL
|
||||
* BASE_URL=http://127.0.0.1:4173 PROBE_PATH=/doxa-maps/... node internal/check-facet-changes-map.mjs
|
||||
* BASE_URL=http://127.0.0.1:4173 PROBE_PATH=/<TREE_NAME>/... node internal/check-facet-changes-map.mjs
|
||||
*/
|
||||
import { chromium } from 'playwright'
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ import { chromium } from 'playwright'
|
|||
//
|
||||
// SO: when you need a trustworthy answer rather than a quick one, run it against the BUILT tree:
|
||||
// BASE_URL=http://127.0.0.1:4173 \
|
||||
// PROBE_PATH=/doxa-maps/research-dashboard/research-dashboard/index.html \
|
||||
// PROBE_PATH=/<TREE_NAME>/research-dashboard/research-dashboard/index.html \
|
||||
// node internal/check-facet-changes-map.mjs
|
||||
// The built tree can be stale — that is the trade — but it is DETERMINISTIC, which is what a gate
|
||||
// needs. The dev default is kept because it is right for hand-running against uncommitted source.
|
||||
|
|
@ -76,7 +76,7 @@ const PATH_ = process.env.PROBE_PATH || '/'
|
|||
// run on one machine and a default port belongs to whichever started first — measured
|
||||
// 2026-09-24 on :4173. This gate reports on how a map's source data changes when a facet is
|
||||
// picked, so a run against another tree describes somebody else's data flow. The fingerprint
|
||||
// is public/doxa-maps/manifest.json; a dev server serves it straight off disk, so this stays
|
||||
// is public/<TREE_NAME>/manifest.json; a dev server serves it straight off disk, so this stays
|
||||
// quiet in the normal `bun run dev` case and only speaks when the bytes really differ.
|
||||
{
|
||||
const { servesThisTree } = await import('./_serves-this-tree.mjs')
|
||||
|
|
|
|||
|
|
@ -106,7 +106,18 @@ try {
|
|||
const sr = document.querySelector('gospel-resources-map')?.shadowRoot
|
||||
if (!sr) return []
|
||||
const out = new Set()
|
||||
/* ═══ A TABLE CELL IS DATA, NOT CHROME — fifth correction ════════════════════════
|
||||
/* ═══ SETTLED: ORGANISATION AND PRODUCT NAMES STAY ENGLISH ═══════════════════════
|
||||
* Ruled 2026-09-25, not inferred here: proper nouns are published as proper nouns in a
|
||||
* localised product, exactly as res.bibleStories (Open Bible Stories, unfoldingWord)
|
||||
* and res.scriptureEarth are already exempted in check-i18n-never-translated. Scope of
|
||||
* the ruling is the Source column and product names ONLY.
|
||||
* It is a VERDICT, not a bookmark — nothing here is waiting on anyone.
|
||||
* Note what it does NOT cover: res.jesusFilm still has to render translated where it is
|
||||
* used as a resource-type LABEL, and does. The structural rule below is what lets both
|
||||
* be true at once — the same words are a name in a Source cell and a label in the
|
||||
* chrome, and only the position tells them apart.
|
||||
*
|
||||
* ═══ A TABLE CELL IS DATA, NOT CHROME — fifth correction ════════════════════════
|
||||
* This gate's own heading says it reads the CHROME. Table cells are the data, and
|
||||
* judging them produced two false findings that were each a real English string
|
||||
* sitting exactly where it belongs:
|
||||
|
|
@ -172,10 +183,33 @@ try {
|
|||
looking for a rendering bug that did not exist. */
|
||||
if (!labels.length) { unmeasured.push(leaf + ' ' + lc + ': the walk collected no labels'); continue }
|
||||
const labelSet = new Set(labels)
|
||||
/* ═══ AN INTERPOLATED STRING NEVER EQUALS ITS CATALOGUE ENTRY ════════════════════
|
||||
* Whole-label equality is the right unit for a fixed label and blind to a sentence
|
||||
* carrying a number: the catalogue holds "Across all {n} languages in the corpus." and
|
||||
* the screen shows "Across all 5,067 languages in the corpus." Those are never equal, so
|
||||
* three chart subtitles could have shipped untranslated in eleven locales with this gate
|
||||
* reporting PASS — coverage I would have claimed and not had.
|
||||
* So a placeholder becomes a wildcard and the comparison is by pattern. Everything else
|
||||
* is still compared by equality, which is what keeps a word inside a sentence from
|
||||
* impersonating a label. */
|
||||
const PLACEHOLDER = /\{\w+\}/
|
||||
const asPattern = (str) => new RegExp('^' + str.split(/\{\w+\}/)
|
||||
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('.{1,40}') + '$')
|
||||
const someLabelMatches = (str) => {
|
||||
const re = asPattern(str)
|
||||
for (const l of labelSet) if (re.test(l)) return true
|
||||
return false
|
||||
}
|
||||
for (const [key, e] of Object.entries(en)) {
|
||||
const t = loc[key]
|
||||
if (!t || t === e) continue
|
||||
compared++
|
||||
if (PLACEHOLDER.test(e)) {
|
||||
if (someLabelMatches(e) && !someLabelMatches(t)) {
|
||||
leaks.push(leaf + ' ' + lc + ' ' + key + ': an interpolated label reads English "' + e.slice(0, 40) + '"')
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (labelSet.has(e) && !labelSet.has(t)) leaks.push(leaf + ' ' + lc + ' ' + key + ': a label reads English "' + e.slice(0, 40) + '"')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
*/
|
||||
import { chromium } from 'playwright'
|
||||
import { serveReaped } from './_serve-reaped.mjs'
|
||||
import { TREE_NAME } from './_tree-name.mjs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
|
|
@ -42,11 +43,15 @@ const POISON = process.argv.includes('--poison')
|
|||
// (cities-internet, key-cities, upg-100-list, RegionCountryMap) — copying it would give each of
|
||||
// them their own drifting copy of the pan-first logic and the poison arm, which are the two parts
|
||||
// that took corrections to get right. The leaf is the only thing that differs.
|
||||
// node internal/check-gospel-rtl-shaping.mjs [--poison] [--leaf doxa-maps/<bundle>/<profile>/index.html]
|
||||
// node internal/check-gospel-rtl-shaping.mjs [--poison] [--leaf <TREE_NAME>/<bundle>/<profile>/index.html]
|
||||
//
|
||||
// ⚠ AND THE DEFAULT READS THE TREE NAME RATHER THAN SPELLING IT. The tree was renamed
|
||||
// doxa-maps -> dx-maps; a default of "doxa-maps/..." 404s, and a probe reporting "0 problems"
|
||||
// against a 404 reads exactly like success. The build config is the one place that knows.
|
||||
const leafArg = process.argv.indexOf('--leaf')
|
||||
const LEAF = (leafArg > -1 && process.argv[leafArg + 1])
|
||||
|| process.env.RTL_SHAPE_LEAF
|
||||
|| 'doxa-maps/gospel-resources/resources-map/index.html'
|
||||
|| `${TREE_NAME}/gospel-resources/resources-map/index.html`
|
||||
/* Arabia: the densest concentration of rendered Arabic on the basemap. */
|
||||
const RTL_VIEW = { center: [39.2, 24.5], zoom: 5 }
|
||||
|
||||
|
|
|
|||
138
internal/check-leaf-engine-per-provider.mjs
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* check-leaf-engine-per-provider — a leaf loads the engine its PROVIDER asks for, and no other.
|
||||
*
|
||||
* THE BUG (card BUG-LEAF-PAGES-PRELOAD-MAPBOX-EVEN-UNDER-MAPLIBRE; measured by exp-shepherd at
|
||||
* 577149af). generate-tree chose a leaf's engine peer at BUILD time, from the instance config, and
|
||||
* baked it into <head> as static tags: mapbox-gl.css, the geocoder css, mapbox-gl.js and the geocoder
|
||||
* js, all from api.mapbox.com. The provider is chosen at RUNTIME (resolveMapProvider:
|
||||
* profile-config.provider → ?provider= → window.MAP_PROVIDER → mapbox). So a partner that embeds a
|
||||
* leaf with ?provider=maplibre still made its visitors' browsers fetch 4 files from Mapbox, sending
|
||||
* every visitor's IP to a company the partner chose not to use. No project rule permits that.
|
||||
*
|
||||
* WHAT IS ASSERTED, on THIS checkout's served tree (every leaf in the manifest, instances included):
|
||||
* MAPLIBRE every leaf at ?provider=maplibre makes ZERO requests to any *.mapbox.com host; a MAP
|
||||
* leaf must also still draw (a canvas with a live GL context, window.maplibregl defined),
|
||||
* so a fix cannot pass by breaking the map.
|
||||
* DEFAULT every MAP leaf at its default still DRAWS, with the SAME engine it drew with before.
|
||||
* The engine is read from the canvas that drew (mapboxgl-canvas / maplibregl-canvas), not
|
||||
* from which globals exist: some leaves are MapLibre by design (prayer-walk-planner, the
|
||||
* ".../maplibre" instances), and a peer that merely loaded Mapbox proves nothing.
|
||||
* --baseline <tree root> measures that tree too (e.g. main, with the static peer) and requires, per
|
||||
* leaf: the default pass draws with the baseline's engine, and the maplibre pass draws with
|
||||
* MapLibre wherever the baseline drew a map at all. Without it, a map leaf must simply draw.
|
||||
* Paint here is a floor, not the verdict on looks: verify-map-paint and check:gospel-map-paints judge
|
||||
* the map itself.
|
||||
*
|
||||
* USAGE node internal/check-leaf-engine-per-provider.mjs [--dir <tree root>] [--only a/b,c/d]
|
||||
* Run through internal/browser-slot.sh.
|
||||
* @browser-slot-max-hold 2700
|
||||
* EXIT 0 pass · 1 a leaf calls Mapbox under maplibre, or a map stopped drawing · 75 not measured.
|
||||
*/
|
||||
import { chromium } from 'playwright'
|
||||
import { spawn } from 'node:child_process'
|
||||
import { createServer } from 'node:http'
|
||||
import { readFileSync, existsSync } from 'node:fs'
|
||||
import { resolve, dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { TREE_NAME } from './_tree-name.mjs'
|
||||
|
||||
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
|
||||
const argv = process.argv.slice(2)
|
||||
const arg = (k, d) => { const i = argv.indexOf(k); return i >= 0 && argv[i + 1] ? argv[i + 1] : d }
|
||||
const DIR = resolve(arg('--dir', resolve(ROOT, 'public')))
|
||||
const ONLY = arg('--only', '') ? new Set(arg('--only', '').split(',')) : null
|
||||
const BASELINE = arg('--baseline', '') ? resolve(arg('--baseline', '')) : null
|
||||
const CONCURRENCY = 3
|
||||
const MAPBOX_HOST = /(^|\.)mapbox\.com$/i
|
||||
|
||||
const manifestPath = join(DIR, TREE_NAME, 'manifest.json')
|
||||
if (!existsSync(manifestPath)) { console.log(`LEAF-ENGINE: NOT MEASURED — no ${manifestPath}`); process.exit(75) }
|
||||
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'))
|
||||
const leaves = []
|
||||
for (const b of manifest.bundles || []) for (const p of b.profiles || []) {
|
||||
const base = `${b.bundle}/${p.profile}`
|
||||
const add = (id) => { if ((!ONLY || ONLY.has(id)) && existsSync(join(DIR, TREE_NAME, id, 'index.html'))) leaves.push({ id, isMap: !!p.isMap }) }
|
||||
add(base)
|
||||
for (const inst of p.instances || []) add(`${base}/${inst.id}`)
|
||||
}
|
||||
if (!leaves.length) { console.log('LEAF-ENGINE: NOT MEASURED — no leaves matched'); process.exit(75) }
|
||||
|
||||
async function serve(dir) {
|
||||
const port = await new Promise((ok) => { const s = createServer().listen(0, '127.0.0.1', () => { const n = s.address().port; s.close(() => ok(n)) }) })
|
||||
const srv = spawn(process.execPath, [resolve(ROOT, 'internal/serve-strict.mjs'), '--port', String(port), '--directory', dir], { stdio: 'ignore' })
|
||||
let up = false
|
||||
for (let i = 0; i < 40 && !up; i++) { await new Promise((r) => setTimeout(r, 150)); up = await fetch(`http://127.0.0.1:${port}/${TREE_NAME}/manifest.json`).then((r) => r.ok).catch(() => false) }
|
||||
if (!up) { try { srv.kill() } catch { /* gone */ } return null }
|
||||
return { port, stop: () => { try { srv.kill() } catch { /* already gone */ } } }
|
||||
}
|
||||
const cur = await serve(DIR)
|
||||
const base = BASELINE ? await serve(BASELINE) : null
|
||||
const stop = () => { cur && cur.stop(); base && base.stop() }
|
||||
if (!cur || (BASELINE && !base)) { stop(); console.log(`LEAF-ENGINE: NOT MEASURED — could not serve ${!cur ? DIR : BASELINE}`); process.exit(75) }
|
||||
|
||||
// A drawn map: a canvas, somewhere down the shadow roots, with a live WebGL context.
|
||||
const DRAWN = `(() => {
|
||||
const canvases = []
|
||||
const walk = (r) => { for (const e of r.querySelectorAll('*')) { if (e.tagName === 'CANVAS') canvases.push(e); if (e.shadowRoot) walk(e.shadowRoot) } }
|
||||
walk(document)
|
||||
const drawing = canvases.filter((c) => { if (c.width < 50 || c.height < 50) return false
|
||||
const gl = c.getContext('webgl2') || c.getContext('webgl'); return !!gl && !gl.isContextLost() })
|
||||
const engines = [...new Set(drawing.map((c) => c.classList.contains('maplibregl-canvas') ? 'maplibre' : c.classList.contains('mapboxgl-canvas') ? 'mapbox' : 'other'))].sort()
|
||||
return { canvases: canvases.length, live: drawing.length > 0, engine: engines.join('+') || 'none', mapboxgl: !!window.mapboxgl, maplibregl: !!window.maplibregl }
|
||||
})()`
|
||||
|
||||
const browser = await chromium.launch({ args: ['--use-gl=swiftshader', '--enable-webgl', '--ignore-gpu-blocklist'] })
|
||||
async function load(srvPort, id, provider) {
|
||||
const ctx = await browser.newContext({ viewport: { width: 1280, height: 860 } })
|
||||
const page = await ctx.newPage()
|
||||
const mapboxReqs = []
|
||||
page.on('request', (r) => { try { if (MAPBOX_HOST.test(new URL(r.url()).hostname)) mapboxReqs.push(r.url()) } catch { /* data: etc */ } })
|
||||
const url = `http://127.0.0.1:${srvPort}/${TREE_NAME}/${id}/index.html${provider === 'maplibre' ? '?provider=maplibre' : ''}`
|
||||
try {
|
||||
await page.goto(url, { waitUntil: 'load', timeout: 45000 })
|
||||
await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {})
|
||||
let d = null
|
||||
for (let i = 0; i < 30; i++) { d = await page.evaluate(DRAWN).catch(() => null); if (d && d.live) break; await page.waitForTimeout(500) }
|
||||
await page.waitForTimeout(1500) // late requests (a lazily injected geocoder) still count
|
||||
return { ...d, mapboxReqs: [...mapboxReqs] }
|
||||
} catch (e) { return { error: String(e.message || e).split('\n')[0], mapboxReqs: [...mapboxReqs] } }
|
||||
finally { await ctx.close() }
|
||||
}
|
||||
|
||||
const rows = []
|
||||
const queue = leaves.slice()
|
||||
await Promise.all(Array.from({ length: CONCURRENCY }, async () => {
|
||||
while (queue.length) {
|
||||
const L = queue.shift()
|
||||
const ml = await load(cur.port, L.id, 'maplibre')
|
||||
const mb = L.isMap ? await load(cur.port, L.id, 'default') : null
|
||||
const bl = base && L.isMap ? await load(base.port, L.id, 'default') : null
|
||||
const problems = []
|
||||
if (ml.error) problems.push(`maplibre load: ${ml.error}`)
|
||||
if (ml.mapboxReqs.length) problems.push(`${ml.mapboxReqs.length} Mapbox request(s) under maplibre: ${[...new Set(ml.mapboxReqs.map((u) => new URL(u).pathname.split('/').slice(0, 3).join('/') || u))].slice(0, 3).join(', ')}`)
|
||||
if (mb && mb.error) problems.push(`default load: ${mb.error}`)
|
||||
if (bl && bl.error) problems.push(`baseline load: ${bl.error}`)
|
||||
// What SHOULD draw: with a baseline, whatever drew there; without one, a map leaf draws something.
|
||||
const baselineDrew = bl ? bl.live : (L.isMap ? true : false)
|
||||
if (L.isMap && !ml.error && baselineDrew && !(ml.live && ml.engine.includes('maplibre'))) problems.push(`under maplibre the map does not draw with MapLibre (drew: ${ml.engine})`)
|
||||
if (mb && !mb.error) {
|
||||
if (bl && !bl.error) {
|
||||
if (mb.engine !== bl.engine) problems.push(`the DEFAULT path changed engine: before ${bl.engine}, now ${mb.engine}`)
|
||||
} else if (!mb.live) problems.push('the DEFAULT path draws no map')
|
||||
}
|
||||
rows.push({ id: L.id, isMap: L.isMap, mlReqs: ml.mapboxReqs.length, def: mb ? mb.engine : '', was: bl ? bl.engine : '', problems, unmeasured: !!(ml.error || (mb && mb.error) || (bl && bl.error)) })
|
||||
}
|
||||
}))
|
||||
await browser.close(); stop()
|
||||
|
||||
rows.sort((a, b) => a.id.localeCompare(b.id))
|
||||
console.log(`LEAF-ENGINE: ${rows.length} leaves (${rows.filter((r) => r.isMap).length} maps) on ${DIR}${BASELINE ? ` — baseline ${BASELINE}` : ''}`)
|
||||
for (const r of rows) console.log(` ${r.problems.length ? (r.unmeasured ? '?? ' : 'FAIL') : 'ok '} ${r.id.padEnd(46)} ${r.isMap ? 'map ' : ' '} mapbox reqs under maplibre: ${String(r.mlReqs).padStart(2)}${r.def ? ` default draws: ${r.def}${r.was ? ` (was ${r.was})` : ''}` : ''}${r.problems.length ? ' — ' + r.problems.join('; ') : ''}`)
|
||||
const fails = rows.filter((r) => r.problems.length && !r.unmeasured)
|
||||
if (fails.length) {
|
||||
console.log(`LEAF-ENGINE: FAIL — ${fails.length} leaf/leaves: under ?provider=maplibre they still call Mapbox, or a map stopped drawing.`)
|
||||
process.exit(1)
|
||||
}
|
||||
if (rows.some((r) => r.unmeasured)) { console.log('LEAF-ENGINE: NOT MEASURED — a leaf did not load.'); process.exit(75) }
|
||||
console.log(`LEAF-ENGINE: PASS — no leaf calls Mapbox under maplibre; every map draws with MapLibre under maplibre and with ${BASELINE ? 'the same engine as the baseline' : 'an engine'} by default.`)
|
||||
|
|
@ -38,6 +38,7 @@ import { readFileSync, readdirSync, existsSync } from 'node:fs'
|
|||
import { resolve, dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { servesThisTree } from './_serves-this-tree.mjs'
|
||||
import { TREE_NAME } from './_tree-name.mjs'
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url))
|
||||
const REPO = resolve(HERE, '..')
|
||||
|
|
@ -82,7 +83,7 @@ const catalogue = (lc) => {
|
|||
}
|
||||
|
||||
let reachable = false
|
||||
try { const r = await fetch(`${BASE}/doxa-maps/manifest.json`, { signal: AbortSignal.timeout(4000) }); reachable = r.ok } catch { /* precondition */ }
|
||||
try { const r = await fetch(`${BASE}/${TREE_NAME}/manifest.json`, { signal: AbortSignal.timeout(4000) }); reachable = r.ok } catch { /* precondition */ }
|
||||
if (!reachable) { console.log(`LEAF-ENGLISH-LEAKS: SKIP — nothing served at ${BASE}.`); process.exit(0) }
|
||||
const treeCheck = await servesThisTree(BASE, REPO)
|
||||
if (!treeCheck.ok) { console.error(`LEAF-ENGLISH-LEAKS: NOT MEASURED — ${treeCheck.why}`); process.exit(2) }
|
||||
|
|
@ -106,7 +107,7 @@ for (const t of TARGETS) {
|
|||
page.on('pageerror', (e) => errs.push(String(e).slice(0, 110)))
|
||||
let labels = []
|
||||
try {
|
||||
const res = await page.goto(`${BASE}/doxa-maps/${t.path}/index.html?lang=${lc}`,
|
||||
const res = await page.goto(`${BASE}/${TREE_NAME}/${t.path}/index.html?lang=${lc}`,
|
||||
{ waitUntil: 'load', timeout: 60000 })
|
||||
if (!res || !res.ok()) { rows.push({ t: t.path, lc, skipped: `HTTP ${res ? res.status() : '?'}` }); await page.close(); continue }
|
||||
await page.waitForTimeout(16000)
|
||||
|
|
|
|||
|
|
@ -78,8 +78,10 @@ if (!reachable) {
|
|||
// ⚠ NOT MEASURED, NOT SKIP, and the distinction is the point. A SKIP reads as "nothing to check
|
||||
// here"; this is "I could not attribute what I saw", which is a different and louder fact. Exit 2
|
||||
// so a caller can tell it apart from both a pass (0) and a real failure (1).
|
||||
// The helper wants the tree's BASE, not a leaf URL — it fetches <base>/doxa-maps/manifest.json.
|
||||
// LEAF is `<base>/doxa-maps/<bundle>/<profile>/index.html`, so cut at the /doxa-maps/ segment.
|
||||
// The helper wants the tree's BASE, not a leaf URL — it fetches <base>/<TREE_NAME>/manifest.json.
|
||||
// LEAF is `<base>/<TREE_NAME>/<bundle>/<profile>/index.html`, so cut at that segment. The name is
|
||||
// a config knob (_tree-name.mjs), and a hardcoded 'doxa-maps' here is how a rename silently makes
|
||||
// a gate measure a folder that no longer exists — which cost me a whole tick of false readings.
|
||||
const TREE_BASE = LEAF.split(`/${TREE_NAME}/`)[0]
|
||||
const treeCheck = await servesThisTree(TREE_BASE, ROOT)
|
||||
if (!treeCheck.ok) {
|
||||
|
|
|
|||
|
|
@ -174,6 +174,16 @@ function fixTree(root) {
|
|||
if (!DRY) writeFileSync(mf, after)
|
||||
st.filesWritten.push(mf)
|
||||
}
|
||||
// The Research Gallery reads a BYTE-IDENTICAL copy of the manifest first when it runs on a foreign
|
||||
// origin (generate-tree writes it; see doxa-maps-spa.vue). Repairing the root manifest alone left the
|
||||
// copy with the OLD integrity, so an embedded gallery refused the rebuilt bundle (rega, 2026-09-25).
|
||||
for (const rel of ['doxa-maps-spa/manifest.json']) {
|
||||
const copy = join(root, rel)
|
||||
if (existsSync(copy) && readFileSync(copy, 'utf8') !== after) {
|
||||
if (!DRY) writeFileSync(copy, after)
|
||||
st.filesWritten.push(copy)
|
||||
}
|
||||
}
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
|
|
|||
|
|
@ -615,7 +615,6 @@ function forgeHtml(o) {
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>${esc(o.title)}</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<style>${FORGE_CSS}</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -693,7 +692,7 @@ function rootHtml(bundles, manifest) {
|
|||
* is precisely why this was nearly missed. "The custom element mounted" is a WEAKER claim than
|
||||
* "the plugin works"; a mounted element with no data is the failure that looks like success.
|
||||
*/
|
||||
function studioRootHtml(bakedToken) {
|
||||
function studioRootHtml(bakedToken, integrity = '') {
|
||||
// THE TREE'S FRONT PAGE (<tree>/index.html) — the agent decision, card
|
||||
// BUILD-PLUGIN-STUDIO-IS-THE-OUTPUT-FRONT-PAGE: the output is ONE folder, and opening it opens the
|
||||
// studio. It used to sit one level ABOVE the tree (public/index.html) with the staging-forge chooser
|
||||
|
|
@ -714,7 +713,7 @@ ${bakedToken ? ` <script>window.MAP_TOKEN=${JSON.stringify(bakedToken)};</scrip
|
|||
</head>
|
||||
<body>
|
||||
<plugin-studio tree-base="."></plugin-studio>
|
||||
<script src="${src}"></script>
|
||||
<script src="${src}"${integrity ? ` integrity="${integrity}" crossorigin="anonymous"` : ''}></script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
|
@ -798,13 +797,14 @@ function mapPageHtml(opts) {
|
|||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin />
|
||||
<link href="https://cdn.jsdelivr.net/npm/maplibre-gl@5/dist/maplibre-gl.css" rel="stylesheet" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5/dist/maplibre-gl.js"></script>`
|
||||
: `<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>`
|
||||
: `<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->`
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
|
@ -868,7 +868,11 @@ ${apiScript}
|
|||
var BASE_CONFIG = ${JSON.stringify(pageConfig)};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = ${JSON.stringify(tokenFree)};
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = ${JSON.stringify(tokenFree)} || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
@ -1366,7 +1370,9 @@ function writeManifestAndHtml(root, bundles, tokenUrlExpr, bakedToken) {
|
|||
}
|
||||
// THE FRONT PAGE IS THE STUDIO (see studioRootHtml). The staging-forge chooser that used to be
|
||||
// written here (rootHtml) is retired with it; nothing is written above the tree any more.
|
||||
writeFileSync(join(root, 'index.html'), studioRootHtml(bakedToken))
|
||||
// …with the studio bundle's integrity, written HERE: it used to be added only by fix:sri, so running
|
||||
// `bun run tree` after fix:sri stripped it again (rega, 2026-09-25).
|
||||
writeFileSync(join(root, 'index.html'), studioRootHtml(bakedToken, (bundles.find((b) => b.bundle === 'plugin-studio') || {}).integrity || ''))
|
||||
|
||||
|
||||
bundles.forEach((b) => {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,17 @@ console.log('LANDING-PRECONDITIONS: 3 sri — every leaf loads the bundle its in
|
|||
if (process.env.DOXA_SKIP_FRESHNESS === '1') {
|
||||
console.log('LANDING-PRECONDITIONS: 4 fresh — SKIPPED (DOXA_SKIP_FRESHNESS=1; dry check only, never set by the merge-queue check)')
|
||||
} else {
|
||||
const fresh = run(process.execPath, ['internal/check-composite-freshness.mjs'])
|
||||
// SCOPE: what can this landing have made stale? A change to shared code (library/, the build config, the
|
||||
// dependencies) reaches ANY bundle — measured 2026-09-25: one Arabic catalogue edit in library/i18n left 12
|
||||
// of 25 bundles stale, most of them not composites, and a composite-only check saw none of it. Otherwise:
|
||||
// every composite, plus each bundle whose own folder the landing touched.
|
||||
const base = run('git', ['merge-base', 'HEAD', `origin/${process.env.MAIN_CAPTURE_BRANCH || 'main'}`]).stdout.trim()
|
||||
const changed = base ? run('git', ['diff', '--name-only', base, 'HEAD']).stdout.split('\n').filter(Boolean) : []
|
||||
const shared = !base || changed.some((f) => /^(library\/|vite\.config\.js$|package\.json$|bun\.lockb?$|vite\.doxa-maps-build-config\.json$)/.test(f))
|
||||
const own = [...new Set(changed.map((f) => (f.match(/^plugin-designs\/([^/]+)\//) || [])[1]).filter(Boolean))]
|
||||
const scope = shared ? ['--all'] : (own.length ? ['--bundles', own.join(',')] : [])
|
||||
console.log(`LANDING-PRECONDITIONS: 4 fresh — scope: ${shared ? 'EVERY bundle (shared code changed' + (base ? '' : '; no merge-base') + ')' : 'composites' + (own.length ? ' + ' + own.join(', ') : '')}`)
|
||||
const fresh = run(process.execPath, ['internal/check-composite-freshness.mjs', ...scope])
|
||||
if (fresh.status !== 0) refuse(
|
||||
'a committed composite is not what its source builds (stale consumers).\n' +
|
||||
'README rule 5: ONE agent owns the full build. If your change touches library/ or anything compiled into\n' +
|
||||
|
|
|
|||
|
|
@ -255,8 +255,19 @@ export function autoSpaDevPlugin(token = '') {
|
|||
// <tree>/assets/* too: a plugin nested in a cap-5 shell resolves its assets against the tree base
|
||||
// the shell hands it (plugin-studio passes /__plugin-gallery/), exactly as it would against
|
||||
// <tree>/assets in the built tree. Only /assets/ was served, so every nested data table 404'd.
|
||||
//
|
||||
// ★ AND ANY /__leaf/…/assets/* (2026-09-25, reported from a laptop dev server: no boundary polygons
|
||||
// on Big Picture, Regions, UPG-100, Cities, Gospel). A dev leaf page is /__leaf/<bundle>/<profile>,
|
||||
// and a plugin that falls back to the PAGE-RELATIVE './assets' asks for /__leaf/<bundle>/assets/…
|
||||
// — which the leaf route below answered with its own HTML at HTTP 200. JSON.parse then failed and
|
||||
// the map drew with no polygons, no previews, no tables. The built leaf never hits this: its page
|
||||
// hands the element assetsBase "../../assets". Serving the pool at every such prefix makes the
|
||||
// page-relative default resolve in dev exactly as it does in the tree (/<tree>/assets included).
|
||||
const leafAsset = /^\/__leaf\/(?:[^/]+\/){0,3}assets\//.exec(path)
|
||||
const assetPrefix = path.startsWith('/assets/') ? '/assets/'
|
||||
: path.startsWith('/__plugin-gallery/assets/') ? '/__plugin-gallery/assets/' : ''
|
||||
: path.startsWith('/__plugin-gallery/assets/') ? '/__plugin-gallery/assets/'
|
||||
: path.startsWith(`/${treeName}/assets/`) ? `/${treeName}/assets/`
|
||||
: leafAsset ? leafAsset[0] : ''
|
||||
if (assetPrefix) {
|
||||
let rel = ''
|
||||
try { rel = decodeURIComponent(path.slice(assetPrefix.length)) } catch { rel = '' }
|
||||
|
|
@ -303,7 +314,9 @@ export function autoSpaDevPlugin(token = '') {
|
|||
const apiBase = leafCfg.apiBaseUrl || ''
|
||||
// profile-config carries the same shape the built leaves pass, so a profile/instance
|
||||
// renders the SAME view here as in production rather than the bundle's default.
|
||||
const pc = JSON.stringify(instance ? { profile, instanceId: instance } : { profile })
|
||||
// assetsBase too, as the built leaf's BASE_CONFIG carries it ("../../assets" there; root-absolute
|
||||
// here, because a /__leaf/ URL's depth differs from the tree's and the pool is served at /assets).
|
||||
const pc = JSON.stringify(instance ? { profile, instanceId: instance, assetsBase: '/assets' } : { profile, assetsBase: '/assets' })
|
||||
// The composition tier of THIS profile, read from the same discovery the gallery uses.
|
||||
// `nested-elements-mfe` (cap-4) is the StackLayout scroll-stack tier — see the style note
|
||||
// below. An unknown profile falls through to the fixed-viewport leaf, the safe default.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
*
|
||||
* USAGE
|
||||
* bun run verify:5-caps # against the live catalog
|
||||
* BASE=http://127.0.0.1:8080/doxa-maps/ node internal/verify-5-capabilities.mjs # a local serve
|
||||
* BASE=http://127.0.0.1:8080/<TREE_NAME>/ node internal/verify-5-capabilities.mjs # a local serve
|
||||
* Exits non-zero if any level fails, so it can gate a release.
|
||||
*/
|
||||
import { chromium } from 'playwright'
|
||||
|
|
|
|||
|
|
@ -214,6 +214,15 @@ try {
|
|||
if (!ALLOWED.test(u)) bad.push(`${c} -> ${u}`)
|
||||
}
|
||||
}
|
||||
/* ★ THE SUN BLOCK IS A THIRD PLACE URLS LIVE (2026-09-25). The Deaf bridge is carried as a
|
||||
single top-level object rather than per-language under codes[], because SUN is one signed
|
||||
language for all of them — so the loop above cannot see it. Scanned here the moment it was
|
||||
added, rather than discovered later the way the access table was. */
|
||||
for (const u of [idx.sun?.scripture?.u, idx.sun?.stories?.u, idx.sun?.about]) {
|
||||
if (!u) continue
|
||||
scanned++
|
||||
if (!ALLOWED.test(u)) bad.push(`sun -> ${u}`)
|
||||
}
|
||||
if (!scanned) fails.push('pin index carries no links at all — this check would pass vacuously')
|
||||
if (bad.length) fails.push(`${bad.length} link(s) on an unscreened publisher (e.g. ${bad[0]})`)
|
||||
linkCount = scanned
|
||||
|
|
|
|||
|
|
@ -166,10 +166,12 @@ const splitErrors = (lines) => {
|
|||
return { env, real }
|
||||
}
|
||||
|
||||
// Opt-in viewport for a phone pass (GATE_VIEWPORT=390x844); the default is unchanged.
|
||||
const GATE_VIEWPORT = (() => { const m = /^(\d+)x(\d+)$/.exec(process.env.GATE_VIEWPORT || ''); return m ? { width: +m[1], height: +m[2] } : null })()
|
||||
let bad = 0
|
||||
for (const url of urls) {
|
||||
const name = url.split(`/${TREE_NAME}/`)[1] || url
|
||||
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } })
|
||||
const page = await browser.newPage({ viewport: GATE_VIEWPORT || { width: 1280, height: 800 } })
|
||||
const errors = []
|
||||
// ⚠ THE STYLESHEET COMPLAINT IS A WARNING, NOT AN ERROR, so filtering to type()==='error' above
|
||||
// meant this gate could never see it. Mapbox emits "This page appears to be missing CSS
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "الكتاب المقدس",
|
||||
"keyFilmStories": "الفيلم / القصص",
|
||||
"keyAudioEtc": "صوتيات / عرض / تدريب",
|
||||
"unresolvedCode": "رمز خارج ISO 639-3 — غير محسوم، لم يُقَس"
|
||||
"unresolvedCode": "رمز خارج ISO 639-3 — غير محسوم، لم يُقَس",
|
||||
"c1Title": "ما الذي وُجد، بحسب نوع المورد",
|
||||
"c1Sub": "عبر جميع اللغات البالغة {n} في مجموعة البيانات. كل عمود يَعُدّ اللغات، لا الشعوب.",
|
||||
"c1Unit": "لغات وُجد فيها المورد ضمن المصادر التي جرى البحث فيها",
|
||||
"c2Title": "أكبر التجمعات السكانية التي لم يُعثر لها على شيء",
|
||||
"c2Sub": "اللغات الـ{n} التي لا يوجد لها كتاب مقدس ولا فيلم في المصادر التي جرى البحث فيها، مرتَّبة بحسب عدد سكان الشعوب التي تتحدثها.",
|
||||
"c2Unit": "أشخاص في الشعوب التي هذه لغتها الأساسية — لا المتحدثين بها عمومًا",
|
||||
"c3Title": "البلدان الأكثر لغاتٍ غير مخدومة",
|
||||
"c3Sub": "البلدان الـ{n} الأكثر لغاتٍ لم يُعثر لها على شيء. طول العمود هو كل لغة موجودة في ذلك البلد.",
|
||||
"c3Unit": "لغات موجودة في البلد (اللغة العابرة للحدود تُحتسب في كل بلد)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "Bibeltext",
|
||||
"keyFilmStories": "Film / Geschichten",
|
||||
"keyAudioEtc": "Audio / Präsentation / Schulung",
|
||||
"unresolvedCode": "Code außerhalb ISO 639-3 — ungeklärt, nicht gemessen"
|
||||
"unresolvedCode": "Code außerhalb ISO 639-3 — ungeklärt, nicht gemessen",
|
||||
"c1Title": "Was GEFUNDEN wurde, nach Ressourcentyp",
|
||||
"c1Sub": "Über alle {n} Sprachen im Datenbestand. Jeder Balken zählt SPRACHEN, nicht Volksgruppen.",
|
||||
"c1Unit": "Sprachen, in denen die Ressource in den geprüften Quellen gefunden wurde",
|
||||
"c2Title": "Größte Bevölkerungen ohne jeden Fund",
|
||||
"c2Sub": "Die {n} Sprachen ohne Bibeltext und ohne Film in den geprüften Quellen, sortiert nach der Bevölkerung der Volksgruppen, die sie sprechen.",
|
||||
"c2Unit": "Menschen in den Volksgruppen, deren PRIMÄRE Sprache dies ist — nicht Sprecher der Sprache",
|
||||
"c3Title": "Länder mit den meisten unversorgten Sprachen",
|
||||
"c3Sub": "Die {n} Länder mit den meisten Sprachen, für die nichts gefunden wurde. Die Balkenlänge ist jede im Land vorhandene Sprache.",
|
||||
"c3Unit": "im Land vorhandene Sprachen (eine grenzüberschreitende Sprache zählt in jedem Land)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "scripture",
|
||||
"keyFilmStories": "film / stories",
|
||||
"keyAudioEtc": "audio / presentation / training",
|
||||
"unresolvedCode": "code outside ISO 639-3 — unresolved, not measured"
|
||||
"unresolvedCode": "code outside ISO 639-3 — unresolved, not measured",
|
||||
"c1Title": "What was FOUND, by resource type",
|
||||
"c1Sub": "Across all {n} languages in the corpus. Each bar counts LANGUAGES, not people groups.",
|
||||
"c1Unit": "languages where the resource was found in the pools checked",
|
||||
"c2Title": "Largest populations with nothing found",
|
||||
"c2Sub": "The {n} languages with no scripture and no film in the pools checked, ranked by the population of the people groups who speak them.",
|
||||
"c2Unit": "people in the people groups whose PRIMARY language this is — not speakers of the language",
|
||||
"c3Title": "Countries with the most unserved languages",
|
||||
"c3Sub": "The {n} countries with the most languages that have nothing found. Bar length is every language present in that country.",
|
||||
"c3Unit": "languages present in the country (a cross-border language counts in each)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "escrituras",
|
||||
"keyFilmStories": "película / historias",
|
||||
"keyAudioEtc": "audio / presentación / formación",
|
||||
"unresolvedCode": "código fuera de ISO 639-3 — sin resolver, no medido"
|
||||
"unresolvedCode": "código fuera de ISO 639-3 — sin resolver, no medido",
|
||||
"c1Title": "Qué se ENCONTRÓ, por tipo de recurso",
|
||||
"c1Sub": "En las {n} lenguas del conjunto de datos. Cada barra cuenta LENGUAS, no etnias.",
|
||||
"c1Unit": "lenguas en las que se encontró el recurso en las fuentes consultadas",
|
||||
"c2Title": "Mayores poblaciones sin nada encontrado",
|
||||
"c2Sub": "Las {n} lenguas sin escrituras ni película en las fuentes consultadas, ordenadas por la población de las etnias que las hablan.",
|
||||
"c2Unit": "personas en las etnias cuya lengua PRINCIPAL es esta — no hablantes de la lengua",
|
||||
"c3Title": "Países con más lenguas desatendidas",
|
||||
"c3Sub": "Los {n} países con más lenguas sin nada encontrado. La longitud de la barra es cada lengua presente en ese país.",
|
||||
"c3Unit": "lenguas presentes en el país (una lengua transfronteriza cuenta en cada uno)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "écritures",
|
||||
"keyFilmStories": "film / histoires",
|
||||
"keyAudioEtc": "audio / présentation / formation",
|
||||
"unresolvedCode": "code hors ISO 639-3 — non résolu, non mesuré"
|
||||
"unresolvedCode": "code hors ISO 639-3 — non résolu, non mesuré",
|
||||
"c1Title": "Ce qui a été TROUVÉ, par type de ressource",
|
||||
"c1Sub": "Sur l'ensemble des {n} langues du corpus. Chaque barre compte des LANGUES, pas des peuples.",
|
||||
"c1Unit": "langues où la ressource a été trouvée dans les sources consultées",
|
||||
"c2Title": "Populations les plus nombreuses sans rien de trouvé",
|
||||
"c2Sub": "Les {n} langues sans Écritures ni film dans les sources consultées, classées selon la population des peuples qui les parlent.",
|
||||
"c2Unit": "personnes dans les peuples dont c'est la langue PRINCIPALE — non les locuteurs de la langue",
|
||||
"c3Title": "Pays comptant le plus de langues non desservies",
|
||||
"c3Sub": "Les {n} pays comptant le plus de langues sans rien de trouvé. La longueur de la barre correspond à chaque langue présente dans ce pays.",
|
||||
"c3Unit": "langues présentes dans le pays (une langue transfrontalière compte dans chacun)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "पवित्र शास्त्र",
|
||||
"keyFilmStories": "फ़िल्म / कहानियाँ",
|
||||
"keyAudioEtc": "ऑडियो / प्रस्तुति / प्रशिक्षण",
|
||||
"unresolvedCode": "ISO 639-3 से बाहर कोड — अनसुलझा, मापा नहीं गया"
|
||||
"unresolvedCode": "ISO 639-3 से बाहर कोड — अनसुलझा, मापा नहीं गया",
|
||||
"c1Title": "क्या मिला, संसाधन के प्रकार के अनुसार",
|
||||
"c1Sub": "डेटा की सभी {n} भाषाओं में। हर बार भाषाओं की गिनती करता है, जनसमूहों की नहीं।",
|
||||
"c1Unit": "भाषाएँ जिनमें जाँचे गए स्रोतों में संसाधन मिला",
|
||||
"c2Title": "सबसे बड़ी आबादी जिनके लिए कुछ नहीं मिला",
|
||||
"c2Sub": "{n} भाषाएँ जिनके लिए जाँचे गए स्रोतों में न पवित्र शास्त्र है न फ़िल्म, उन्हें बोलने वाले जनसमूहों की आबादी के क्रम में।",
|
||||
"c2Unit": "उन जनसमूहों के लोग जिनकी मुख्य भाषा यही है — भाषा के सभी वक्ता नहीं",
|
||||
"c3Title": "सबसे अधिक असेवित भाषाओं वाले देश",
|
||||
"c3Sub": "{n} देश जिनमें सबसे अधिक भाषाओं के लिए कुछ नहीं मिला। बार की लंबाई उस देश में मौजूद हर भाषा है।",
|
||||
"c3Unit": "देश में मौजूद भाषाएँ (सीमा-पार भाषा हर देश में गिनी जाती है)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "scritture",
|
||||
"keyFilmStories": "film / storie",
|
||||
"keyAudioEtc": "audio / presentazione / formazione",
|
||||
"unresolvedCode": "codice fuori ISO 639-3 — non risolto, non misurato"
|
||||
"unresolvedCode": "codice fuori ISO 639-3 — non risolto, non misurato",
|
||||
"c1Title": "Che cosa è stato TROVATO, per tipo di risorsa",
|
||||
"c1Sub": "Su tutte le {n} lingue del corpus. Ogni barra conta LINGUE, non gruppi etnici.",
|
||||
"c1Unit": "lingue in cui la risorsa è stata trovata nelle fonti controllate",
|
||||
"c2Title": "Popolazioni più numerose senza nulla trovato",
|
||||
"c2Sub": "Le {n} lingue senza Scritture né film nelle fonti controllate, ordinate per la popolazione dei gruppi che le parlano.",
|
||||
"c2Unit": "persone nei gruppi la cui lingua PRINCIPALE è questa — non i parlanti della lingua",
|
||||
"c3Title": "Paesi con più lingue non servite",
|
||||
"c3Sub": "I {n} paesi con più lingue per cui non è stato trovato nulla. La lunghezza della barra è ogni lingua presente in quel paese.",
|
||||
"c3Unit": "lingue presenti nel paese (una lingua transfrontaliera conta in ciascuno)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "escrituras",
|
||||
"keyFilmStories": "filme / histórias",
|
||||
"keyAudioEtc": "áudio / apresentação / treinamento",
|
||||
"unresolvedCode": "código fora da ISO 639-3 — não resolvido, não medido"
|
||||
"unresolvedCode": "código fora da ISO 639-3 — não resolvido, não medido",
|
||||
"c1Title": "O que foi ENCONTRADO, por tipo de recurso",
|
||||
"c1Sub": "Em todas as {n} línguas do conjunto de dados. Cada barra conta LÍNGUAS, não etnias.",
|
||||
"c1Unit": "línguas em que o recurso foi encontrado nas fontes consultadas",
|
||||
"c2Title": "Maiores populações sem nada encontrado",
|
||||
"c2Sub": "As {n} línguas sem Escrituras e sem filme nas fontes consultadas, ordenadas pela população das etnias que as falam.",
|
||||
"c2Unit": "pessoas nas etnias cuja língua PRINCIPAL é esta — não falantes da língua",
|
||||
"c3Title": "Países com mais línguas desatendidas",
|
||||
"c3Sub": "Os {n} países com mais línguas sem nada encontrado. O comprimento da barra é cada língua presente nesse país.",
|
||||
"c3Unit": "línguas presentes no país (uma língua transfronteiriça conta em cada um)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "scripturi",
|
||||
"keyFilmStories": "film / povestiri",
|
||||
"keyAudioEtc": "audio / prezentare / instruire",
|
||||
"unresolvedCode": "cod în afara ISO 639-3 — nerezolvat, nemăsurat"
|
||||
"unresolvedCode": "cod în afara ISO 639-3 — nerezolvat, nemăsurat",
|
||||
"c1Title": "Ce s-a GĂSIT, după tipul resursei",
|
||||
"c1Sub": "Pe toate cele {n} limbi din setul de date. Fiecare bară numără LIMBI, nu grupuri etnice.",
|
||||
"c1Unit": "limbi în care resursa a fost găsită în sursele verificate",
|
||||
"c2Title": "Cele mai mari populații fără nimic găsit",
|
||||
"c2Sub": "Cele {n} limbi fără Scripturi și fără film în sursele verificate, ordonate după populația grupurilor care le vorbesc.",
|
||||
"c2Unit": "persoane din grupurile a căror limbă PRINCIPALĂ este aceasta — nu vorbitorii limbii",
|
||||
"c3Title": "Țări cu cele mai multe limbi neservite",
|
||||
"c3Sub": "Cele {n} țări cu cele mai multe limbi pentru care nu s-a găsit nimic. Lungimea barei este fiecare limbă prezentă în acea țară.",
|
||||
"c3Unit": "limbi prezente în țară (o limbă transfrontalieră se numără în fiecare)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "писание",
|
||||
"keyFilmStories": "фильм / истории",
|
||||
"keyAudioEtc": "аудио / презентация / обучение",
|
||||
"unresolvedCode": "код вне ISO 639-3 — не определён, не измерен"
|
||||
"unresolvedCode": "код вне ISO 639-3 — не определён, не измерен",
|
||||
"c1Title": "Что НАЙДЕНО, по типу ресурса",
|
||||
"c1Sub": "По всем {n} языкам в наборе данных. Каждый столбец считает ЯЗЫКИ, а не народы.",
|
||||
"c1Unit": "языки, в которых ресурс найден в проверенных источниках",
|
||||
"c2Title": "Самые многочисленные народы, для которых ничего не найдено",
|
||||
"c2Sub": "{n} языков, для которых в проверенных источниках нет ни Писания, ни фильма, упорядоченные по численности говорящих на них народов.",
|
||||
"c2Unit": "люди в народах, для которых это ОСНОВНОЙ язык, — не все говорящие на нём",
|
||||
"c3Title": "Страны с наибольшим числом неохваченных языков",
|
||||
"c3Sub": "{n} стран с наибольшим числом языков, для которых ничего не найдено. Длина столбца — каждый язык, присутствующий в этой стране.",
|
||||
"c3Unit": "языки, присутствующие в стране (трансграничный язык считается в каждой)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,6 +168,15 @@
|
|||
"keyScripture": "圣经",
|
||||
"keyFilmStories": "影片 / 故事",
|
||||
"keyAudioEtc": "音频 / 简介 / 训练",
|
||||
"unresolvedCode": "ISO 639-3 之外的代码 — 未确定,未测量"
|
||||
"unresolvedCode": "ISO 639-3 之外的代码 — 未确定,未测量",
|
||||
"c1Title": "按资源类型统计已找到的内容",
|
||||
"c1Sub": "涵盖数据中全部 {n} 种语言。每个条形统计的是语言,不是族群。",
|
||||
"c1Unit": "在已检索的资源库中找到该资源的语言",
|
||||
"c2Title": "一无所获的最大人口",
|
||||
"c2Sub": "在已检索的资源库中既无圣经也无影片的 {n} 种语言,按使用这些语言的族群人口排序。",
|
||||
"c2Unit": "以该语言为主要语言的族群人口 — 不是该语言的全部使用者",
|
||||
"c3Title": "未得服事语言最多的国家",
|
||||
"c3Sub": "一无所获语言最多的 {n} 个国家。条形长度为该国存在的全部语言。",
|
||||
"c3Unit": "该国存在的语言(跨境语言在每个国家各计一次)"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ export function resolveEmbedBase(profileConfig) {
|
|||
* 3. bundleTreeRoot() + '/../assets' — derived from this bundle's own script URL, so a tree
|
||||
* dropped on any host resolves correctly with no configuration at all.
|
||||
* 4. './assets' — the historical default; correct on a leaf page and
|
||||
* the only sane answer when nothing above is knowable (dev ESM, a hand-written host).
|
||||
* the only sane answer when nothing above is knowable (a hand-written host). Under the dev
|
||||
* server it is '/assets', where the dev server serves the pool.
|
||||
*
|
||||
* @param {object|null} [profileConfig] the parsed profile-config (already unref'd)
|
||||
* @returns {string}
|
||||
|
|
@ -156,6 +157,10 @@ export function resolveAssetsBase(profileConfig) {
|
|||
}
|
||||
}
|
||||
|
||||
// Under the dev server (Vite: import.meta.env.DEV; false in every build) the pool is served at the
|
||||
// ROOT, /assets, and a dev page's own URL (/__leaf/<bundle>/<profile>) is not tree-shaped, so the
|
||||
// page-relative default missed it. The built tree keeps './assets' (position-independent).
|
||||
if (import.meta.env && import.meta.env.DEV) return '/assets'
|
||||
return './assets'
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,9 +39,11 @@
|
|||
"check:coverage-consistent:poison": "node internal/check-gospel-coverage-consistent.mjs --poison",
|
||||
"check:csv-shape": "node internal/check-csv-export-shape.mjs",
|
||||
"check:csv-shape:self-test": "node internal/check-csv-export-shape.mjs --self-test",
|
||||
"check:dashboard-geocoder-provider": "node plugin-designs/research-dashboard/scripts/check-dashboard-geocoder-provider.mjs",
|
||||
"check:deck-click": "node internal/check-deck-click.mjs",
|
||||
"check:dep-names": "node internal/check-dependency-names.mjs",
|
||||
"check:descriptions": "node internal/check-profile-descriptions.mjs",
|
||||
"check:dev-assets": "node internal/check-dev-assets.mjs",
|
||||
"check:doc-scripts": "node internal/check-doc-quotes-scripts.mjs",
|
||||
"check:doc-scripts:self-test": "node internal/check-doc-quotes-scripts.mjs --self-test",
|
||||
"check:done-evidence": "node internal/check-done-evidence.mjs",
|
||||
|
|
@ -86,6 +88,7 @@
|
|||
"check:i18n-parity": "node internal/check-i18n-parity.mjs",
|
||||
"check:kpi-unit": "node internal/check-kpi-unit-once.mjs",
|
||||
"check:label-joins": "node internal/check-label-joins.mjs",
|
||||
"check:leaf-engine-per-provider": "node internal/check-leaf-engine-per-provider.mjs",
|
||||
"check:leaf-english-leaks": "node internal/check-leaf-english-leaks.mjs",
|
||||
"check:leaf-english-leaks:self-test": "node internal/check-leaf-english-leaks.mjs --self-test",
|
||||
"check:leaves-mount": "node internal/check-gospel-leaves-mount.mjs",
|
||||
|
|
@ -179,7 +182,7 @@
|
|||
"dev": "bun x vite",
|
||||
"fix:sri": "node internal/fix-sri.mjs",
|
||||
"gallery": "node internal/generate-gallery.mjs",
|
||||
"gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence check:script-flags check:backlog-status check:capability-exemplars check:packet-fixture check:packet-browser check:provider-switch check:locale-reachable check:url-resolver check:manifest-covers check:one-palette check:pin-dim-slider check:legend-source check:backlog-refs check:clustering-modes check:composite-embed-knobs check:composite-locale-leaks check:linked-vocabulary check:wp-embed",
|
||||
"gates:post": "node internal/run-parallel.mjs --label=post -- check:drop check:parse verify check:sri check:public-hygiene check:label-joins check:facet-cascade check:facet-one-field check:heartbeat check:kpi-unit check:composite-reg check:descriptions check:no-abs-paths check:no-codename check:dep-names check:composite-srcs check:embed-targets check:nested-token check:i18n-parity check:tabs-localized check:packets-all check:packet-strings-parity check:zone-census check:share-policy check:library-index check:csv-shape check:capability-citations check:catalog-identity check:no-orphan-gates check:quoted-scripts check:done-evidence check:script-flags check:backlog-status check:capability-exemplars check:packet-fixture check:packet-browser check:provider-switch check:locale-reachable check:url-resolver check:manifest-covers check:one-palette check:pin-dim-slider check:legend-source check:backlog-refs check:clustering-modes check:composite-embed-knobs check:composite-locale-leaks check:linked-vocabulary check:wp-embed check:dashboard-geocoder-provider check:leaf-engine-per-provider",
|
||||
"gates:pre": "node internal/run-parallel.mjs --label=pre -- check:template-literal check:mjs-parse check:sfc-parse check:tab-radius check:synced-css check:doc-scripts",
|
||||
"library-index": "node internal/generate-library-index.mjs",
|
||||
"packet-fixture": "node internal/generate-packet-fixture.mjs",
|
||||
|
|
@ -242,6 +245,7 @@
|
|||
"check:composite-locale-leaks": "a composite rendered in a non-English locale must not show a string the catalogue already translates. The criterion is a LOOKUP, not a category: English catalogue holds the string as a value, this locale holds a different value for that key, the page still renders English. The previous sweep split strings into chrome/data/third-party and scored single words like 'Region' and 'Prayer' as data, so 28 leaks on Big Picture and 41 on Simple Research counted as zero. Surfaces that a lookup cannot judge - vendor map chrome, table DATA cells, facet-rail values - are suppressed by NAME with a stated reason, never by word.",
|
||||
"check:coverage-consistent": "the gospel-resources surfaces must agree: no resource on an ISO RESERVED code (und/mul/mis/zxx), every resourced code NAMED, table reach recounted off the pins, no invented URL, tiers reconcile. Static, sub-second. Self-test: `bun run check:coverage-consistent:poison`, all 12 clauses (A-L) must fail. Clause L is the one that is not about consistency: it fails when the link-verification record goes stale, because 'link checked' is a claim about the present tense. Written after the same drift defect was found by hand three times.",
|
||||
"check:csv-shape": "the export must OPEN as a table: header on line 0, every row matching. Run the `check:csv-shape:self-test` script for the NEGATIVE test (forces the provenance comment back to line 0 IN MEMORY and requires this gate to REJECT it) — the header used to claim 'NEGATIVE-TESTED' with no way to re-run it.",
|
||||
"check:dashboard-geocoder-provider": "the research dashboard leaf at ?provider=maplibre makes ZERO requests to api.mapbox.com, and its search bars still suggest (built tree; browser gate). It was kept out of gates:post while the generated leaf hard-linked the Mapbox engine; the leaf now loads only the engine it is asked for.",
|
||||
"check:dep-names": "every declared dep is a REAL package name (a rename once rewrote @capacitor/* and broke bun install in a clone)",
|
||||
"check:descriptions": "every shipped profile must say what it is (reads the BUILT manifest)",
|
||||
"check:done-evidence": "a card may not reach status:done with NO bluf AND NO fields — the Doxa team inherits this board and an evidence-less 'done' cannot be reconciled against the code. 10 pre-existing are baselined by id; the list should only ever SHRINK.",
|
||||
|
|
@ -272,6 +276,7 @@
|
|||
"check:heartbeat:self-test": "THREE regression cases, each required to fire ITS OWN assertion: [literal] resolver replaced by the old hard-coded array -> B; [shipped-default] dashboard.config.js heartbeatThreshold changed -> A2; [shipped-mode] heartbeatMode flipped to quantile -> A2. Poisons IN MEMORY, never the file. Testing that the FEATURE works is not testing that the REGRESSION is caught — this gate shipped with only the first and missed the second.",
|
||||
"check:host-locale-contract": "a HOST's profile-config.locale reaches every leaf: each leaf page is loaded with ONLY \"locale\":\"ar\" added to its profile-config (no ?lang=, the page keeps lang=\"en\") and must draw at least half the Arabic text the same page draws at ?lang=ar. regions-dashboard/regions-list is the positive control (NOT MEASURED if it does not enter Arabic). Guards ProfileLoader's inject('appI18n'): a bundle that never provides appI18n silently ignores the host. --dir <tree> for a before/after, --only a/b,c/d to narrow. Through browser-slot.sh.",
|
||||
"check:i18n-never-translated": "a key PRESENT in all 11 catalogs but IDENTICAL in all of them is copied, not translated. check:i18n-parity asserts presence; presence and translatedness are different properties. Carries an allowlist for keys correctly identical everywhere (pure format strings, brand names, ISO designations) — each with a reason, so the list records decisions rather than silencing findings.",
|
||||
"check:leaf-engine-per-provider": "every leaf in the manifest at ?provider=maplibre makes ZERO requests to any *.mapbox.com host and a map leaf still draws; at its default every map leaf draws with the engine it drew with before (read from the canvas that drew). --baseline <tree> compares against another tree (e.g. main). Browser gate, @browser-slot-max-hold 2700.",
|
||||
"check:leaves-mount": "DID THE ELEMENT ACTUALLY MOUNT, on all five gospel leaves. Exists because a ReferenceError thrown during setup dies INSIDE the custom-element boundary: the page loads, every asset returns 200, pageerror fires zero times, and the element sits there with an empty shadow root. A healthy-looking dead page. This asks the cheap unambiguous question the rich gates are too slow to ask on every leaf — is anything there — in five steps that each name their own failure: tag defined, host present, shadowRoot attached, shadow root non-empty, visible text rendered. It does NOT trust the absence of console errors; zero errors is not the same as working. --poison for the negative test.",
|
||||
"check:legend-export-reachable": "the Export affordance must be reachable at BOTH widths. Selects a leaf row first (the control is gated on selectedNode) and opens the mobile sheet first (it starts closed). Asserts a REAL BOX, not CSS visibility — on mobile the elements report visibility:visible at 0x0. PASSES at both widths since the mobile sheet was given :export-enabled and :tabs. SKIPs when nothing is served.",
|
||||
"check:legend-source": "the numbers the maps SHOW must match the numbers the live SOURCE has. Every other gate checks INTERNAL consistency — a page can agree with itself perfectly while its legend has stopped describing reality. Offline SKIPs (exit 0); only a reachable endpoint that disagrees fails.",
|
||||
|
|
|
|||
|
|
@ -55,10 +55,22 @@ import { useShadowStyles } from '@map/composables/useShadowStyles.js'
|
|||
and the shipped English catalogue is the fallback rather than a broken key. */
|
||||
const enLookup = (key) =>
|
||||
String(key).replace(/^gospel\./, '').split('.').reduce((o, k) => (o == null ? o : o[k]), EN_MESSAGES.gospel || {})
|
||||
let tr = (key) => enLookup(key) ?? String(key)
|
||||
/* ★ NUMBERS ARRIVE AS PARAMETERS, NEVER CONCATENATED. The subtitles carry a count, and a
|
||||
sentence built by gluing a number between two fragments cannot be translated — word order
|
||||
differs and several of these locales put the number where English does not. The catalogue
|
||||
holds the whole sentence with a {n} placeholder instead.
|
||||
THE FALLBACK HAS TO INTERPOLATE TOO. Without it a host that never installed i18n would render
|
||||
the placeholder literally — "Across all {n} languages" on screen — which is worse than the
|
||||
English sentence the fallback exists to protect. */
|
||||
const interpolate = (str, params) =>
|
||||
params ? String(str).replace(/\{(\w+)\}/g, (m, k) => (params[k] != null ? params[k] : m)) : str
|
||||
let tr = (key, params) => interpolate(enLookup(key) ?? String(key), params)
|
||||
try {
|
||||
const i18n = useI18n()
|
||||
tr = (key) => { const v = i18n.t(key); return v === key ? (enLookup(key) ?? key) : v }
|
||||
tr = (key, params) => {
|
||||
const v = params ? i18n.t(key, params) : i18n.t(key)
|
||||
return v === key ? interpolate(enLookup(key) ?? key, params) : v
|
||||
}
|
||||
} catch (_) { /* no i18n on this host */ }
|
||||
|
||||
|
||||
|
|
@ -457,9 +469,9 @@ useShadowStyles(
|
|||
v-if="active === 'coverage'"
|
||||
:series="coverage"
|
||||
:is-dark="isDark"
|
||||
title="What was FOUND, by resource type"
|
||||
:subtitle="`Across all ${fmt(nLang)} languages in the corpus. Each bar counts LANGUAGES, not people groups.`"
|
||||
unit="languages where the resource was found in the pools checked"
|
||||
:title="tr('gospel.charts.c1Title')"
|
||||
:subtitle="tr('gospel.charts.c1Sub', { n: fmt(nLang) })"
|
||||
:unit="tr('gospel.charts.c1Unit')"
|
||||
:max="nLang"
|
||||
:legend="[
|
||||
{ label: tr('gospel.charts.keyScripture'), color: C.scripture },
|
||||
|
|
@ -477,9 +489,9 @@ useShadowStyles(
|
|||
v-else-if="active === 'gap'"
|
||||
:series="topNone"
|
||||
:is-dark="isDark"
|
||||
title="Largest populations with nothing found"
|
||||
:subtitle="`The ${TOP_N} languages with no scripture and no film in the pools checked, ranked by the population of the people groups who speak them.`"
|
||||
unit="people in the people groups whose PRIMARY language this is — not speakers of the language"
|
||||
:title="tr('gospel.charts.c2Title')"
|
||||
:subtitle="tr('gospel.charts.c2Sub', { n: TOP_N })"
|
||||
:unit="tr('gospel.charts.c2Unit')"
|
||||
:legend="[
|
||||
{ label: tr('gospel.charts.noResourceInPools'), color: C.none },
|
||||
{ label: tr('gospel.charts.unresolvedCode'), color: C.unresolved },
|
||||
|
|
@ -495,9 +507,9 @@ useShadowStyles(
|
|||
v-else
|
||||
:series="byCountry"
|
||||
:is-dark="isDark"
|
||||
title="Countries with the most unserved languages"
|
||||
:subtitle="`The ${TOP_N} countries with the most languages that have nothing found. Bar length is every language present in that country.`"
|
||||
unit="languages present in the country (a cross-border language counts in each)"
|
||||
:title="tr('gospel.charts.c3Title')"
|
||||
:subtitle="tr('gospel.charts.c3Sub', { n: TOP_N })"
|
||||
:unit="tr('gospel.charts.c3Unit')"
|
||||
:legend="[
|
||||
{ label: tr('gospel.charts.nothingInPoolsLower'), color: C.none },
|
||||
{ label: tr('gospel.charts.aResourceFound'), color: C.found },
|
||||
|
|
|
|||
|
|
@ -203,6 +203,10 @@ const doxaTotal = ref(0) // every group on Doxa's roster, placed or not
|
|||
const doxaUnplaced = ref(0) // on the roster, no coordinates in this build yet
|
||||
const doxaByCountry = shallowRef({})
|
||||
const pinCodes = ref({})
|
||||
/* SUN — one signed language with Scripture in it, for Deaf groups whose own sign language has
|
||||
nothing. Carried in the pin index beside the spoken bridges so the sheet and the access table
|
||||
cannot disagree. */
|
||||
const pinSun = ref(null)
|
||||
const pinBridges = ref({}) // '<iso639-3>|<ISO3 country>' -> the in-country bridge, if any
|
||||
/* Declared beside pinBridges. The previous edit USED this ref without declaring it —
|
||||
a silent string replace that matched nothing — and the ReferenceError died inside the
|
||||
|
|
@ -571,12 +575,20 @@ const signTally = computed(() => {
|
|||
const pinTally = computed(() => {
|
||||
const t = [0, 0, 0]
|
||||
let hnr = 0
|
||||
/* How many of the groups with NOTHING have somewhere to start anyway — a curated bridge, a
|
||||
language their country actually speaks, or SUN for a Deaf group. Counted in the same pass
|
||||
as the tiers, from the same rows, so the two numbers cannot drift apart. */
|
||||
let wayIn = 0
|
||||
for (const r of pinRows.value) {
|
||||
t[r[6]]++
|
||||
const c = pinCodes.value[r[4]]
|
||||
if (r[6] !== 0 && c && canHear(c) && !hasTextScripture(c)) hnr++
|
||||
if (r[6] === 0) {
|
||||
const key = `${r[4]}|${r[3]}`
|
||||
if (pinBridges.value[key] || pinCandidates.value[key] || (c && c.sg === 1 && pinSun.value)) wayIn++
|
||||
}
|
||||
}
|
||||
return { none: t[0], partial: t[1], both: t[2], hnr, linked: t[1] + t[2], total: pinRows.value.length }
|
||||
return { none: t[0], partial: t[1], both: t[2], hnr, linked: t[1] + t[2], total: pinRows.value.length, wayIn }
|
||||
})
|
||||
|
||||
async function ensurePeopleGroups() {
|
||||
|
|
@ -751,6 +763,34 @@ const groupsForCountry = computed(() => {
|
|||
const withResources = computed(() => groupsForCountry.value.filter(hasAny))
|
||||
const withoutResources = computed(() => groupsForCountry.value.filter((r) => !hasAny(r)))
|
||||
|
||||
/**
|
||||
* ═══ THE COUNTRY'S GAP LIST SHOULD SAY WHERE TO START ═════════════════════════════════════
|
||||
*
|
||||
* The rows under "No resource found" carried a name, a language and a population, and nothing
|
||||
* else — so the one thing a mobiliser opened the country for, "what do I do about these?",
|
||||
* took one click per group. 369 of the 370 groups with nothing now have a way in, and it was
|
||||
* reachable only by opening each pin in turn.
|
||||
*
|
||||
* TEXT, NOT A LINK, and structurally it could not be otherwise: these rows are <button>
|
||||
* drill-ins and HTML forbids an anchor inside a button — the parser hoists it out and it stops
|
||||
* being a link, which is why the rows that DO have resources are plain containers instead. The
|
||||
* row opens the group sheet, and the sheet carries the bridge's real links.
|
||||
*
|
||||
* It names the bridge and nothing more. Saying "Bambara" here does not claim Bambara reaches
|
||||
* this group — that is the local question the sheet spells out — but it does turn a list of
|
||||
* dead ends into a list with a first move against each one.
|
||||
*/
|
||||
const wayInFor = (g) => {
|
||||
const iso3 = selected.value?.iso3 || ''
|
||||
const code = g.iso639_3 || ''
|
||||
if (!code || !iso3) return ''
|
||||
const c = pinCodes.value[code]
|
||||
if (c && c.sg === 1) return pinSun.value ? 'SUN (signed)' : ''
|
||||
const key = `${code}|${iso3}`
|
||||
const b = pinBridges.value[key] || pinCandidates.value[key]
|
||||
return b ? b.l : ''
|
||||
}
|
||||
|
||||
// The header must count the SAME set the list below it shows. It used to read
|
||||
// gospel-by-country.json, which is built from the curated 2,106-record subset, so after
|
||||
// the list moved to the pins the card contradicted itself inside one view: "People
|
||||
|
|
@ -850,6 +890,7 @@ async function load() {
|
|||
pinCodes.value = pinData.codes || {}
|
||||
pinBridges.value = pinData.bridges || {}
|
||||
pinCandidates.value = pinData.bridgeCandidates || {}
|
||||
pinSun.value = pinData.sun || null
|
||||
|
||||
/* Same seven-slot shape the rest of this file already speaks, so narrowing the roster
|
||||
changes WHICH pins exist and nothing about how they are drawn, clicked or filtered. */
|
||||
|
|
@ -1135,6 +1176,70 @@ const fmt = (n) => (Number(n) || 0).toLocaleString()
|
|||
|
||||
// The table lives on a SIBLING page, so "see all of these" is a URL. Built here rather
|
||||
// than inline in the template so the group link and the country link cannot drift apart.
|
||||
/**
|
||||
* ═══ A BRIDGE NOBODY CAN FOLLOW IS NOT A WAY IN ═══════════════════════════════════════════
|
||||
*
|
||||
* Both bridge panels below NAMED a language and stopped there. For a group with nothing, the
|
||||
* only link on the sheet was "Every resource in <their own language>" — which is, by
|
||||
* definition, the empty table. MEASURED by clicking a gap pin: Syenara Senufo offered five
|
||||
* "none found" chips, named Minianka as the way in, and the one thing to click led to nothing.
|
||||
* So the sheet told a mobiliser where to go and then made them go and find it themselves.
|
||||
*
|
||||
* Nothing new has to be fetched. Both bridge records already carry the bridge's ISO 639-3
|
||||
* code, and the pin index already holds that language's own verified links — Minianka is
|
||||
* ebible.org/myk/ and jesusfilm.org/watch/jesus/minianka, on the same screened publishers and
|
||||
* through the same doctrine scan as every other link here. The data was one lookup away.
|
||||
*
|
||||
* Joined on the CODE, never the name, for the reason the whole index is built that way.
|
||||
*/
|
||||
const bridgeResources = (b) => {
|
||||
if (!b || !b.c) return null
|
||||
const c = pinCodes.value[b.c]
|
||||
if (!c) return null
|
||||
/* ⚠ c.s IS NOT THE ONLY PLACE A READABLE SCRIPTURE LIVES, and reading only it lost the very
|
||||
language this fix exists for: Bambara's text Bible is carried on the Faith Comes By Hearing
|
||||
record (au.m names the media it holds), so the panel offered Bambara the film alone while a
|
||||
full 66-book text sat one field away. Same field-list-goes-stale shape as the build script,
|
||||
so the fallback is spelled out here rather than assumed. */
|
||||
const fcbhText = c.au && /text/.test(c.au.m || '') ? c.au : null
|
||||
return {
|
||||
iso: b.c,
|
||||
language: c.l || b.l || '',
|
||||
scripture_url: c.s || (fcbhText ? fcbhText.u : ''),
|
||||
scripture_title: c.sv || (fcbhText ? fcbhText.n : ''),
|
||||
film_url: c.f || '',
|
||||
film_title: c.fT || '',
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Deaf way in, for a group that has nothing filmed in its own sign language.
|
||||
*
|
||||
* WHY IT IS OFFERED ONLY WHEN THERE IS NOTHING. A group that already has Scripture in its own
|
||||
* sign language does not need to learn a second one, and saying otherwise would read as a
|
||||
* recommendation to leave their own language behind. Same rule the spoken bridges follow.
|
||||
*
|
||||
* It is a BRIDGE and says so: SUN has to be learned, and it closes no gap in their own language.
|
||||
*/
|
||||
const deafBridge = computed(() => {
|
||||
const g = selectedGroup.value
|
||||
if (!g || !g.is_sign || !pinSun.value) return null
|
||||
const hasSomething = g.scripture_url || g.film_url || g.audio || g.bible_video ||
|
||||
g.gospel_audio || g.scripture_earth
|
||||
if (hasSomething) return null
|
||||
const key = String(g.countries || '').toLowerCase().replace(/[^a-z]/g, '')
|
||||
return { ...pinSun.value, organisation: pinSun.value.byCountry?.[key] || '' }
|
||||
})
|
||||
|
||||
/* Resolved once per selection rather than on every reference in the template. */
|
||||
const curatedBridgeRes = computed(() => bridgeResources(selectedGroup.value?.bridge))
|
||||
const candidateBridgeRes = computed(() => bridgeResources(selectedGroup.value?.bridge_candidate))
|
||||
/* The runner-up on a near-tie is named in the sentence above, so it needs links for exactly the
|
||||
reason the primary does: a bridge nobody can follow is not a way in. Naming two languages and
|
||||
linking one would make the second look like the lesser option when the whole point is that the
|
||||
map will not choose between them. */
|
||||
const altBridgeRes = computed(() => bridgeResources(selectedGroup.value?.bridge_candidate?.alt))
|
||||
|
||||
const tableLink = (q) => {
|
||||
const p = new URLSearchParams({ tab: 'links', ...q })
|
||||
return `../data-tables/index.html?${p.toString()}`
|
||||
|
|
@ -1210,6 +1315,10 @@ useShadowStyles(
|
|||
'padding:3px 8px;border-radius:6px;cursor:pointer;margin-left:4px;min-height:24px}' +
|
||||
'.gm-pinkey-h{font-size:14px;font-weight:600;margin-bottom:4px}' +
|
||||
'.gm-caveat{margin-top:5px;font-size:13.5px;opacity:.72;line-height:1.4}' +
|
||||
/* Quiet enough that the gap itself still reads first: the row is about what is MISSING, and
|
||||
the way in is the footnote to it, not the headline. */
|
||||
'.gm-pg-way{display:block;font-size:12.5px;color:#3b463d;opacity:.8;margin-top:2px}' +
|
||||
'.is-dark .gm-pg-way{color:#d1d4cd}' +
|
||||
'.gm-prose-note{opacity:.9;font-weight:600}' +
|
||||
// DETAIL: a bottom sheet on a phone, a corner card on desktop.
|
||||
// ON A PHONE THE SHEET IS THE PAGE, and the shared pin hint sits on top of it. The hint
|
||||
|
|
@ -1445,6 +1554,19 @@ useShadowStyles(
|
|||
<i class="gm-dot" :style="{ background: PIN_COLOR[0] }"></i>{{ t('gospel.legend.tier0') }}
|
||||
<b>{{ fmt(pinTally.none) }}</b>
|
||||
</button>
|
||||
<!-- ═══ THE NUMBER BESIDE THE GAP IS THE ONE A MOBILISER CAME FOR ══════════════════
|
||||
"370 with nothing found" is where the map used to stop, and it reads as a wall.
|
||||
Every one of those groups now has somewhere to start — a curated bridge, a
|
||||
language their own country speaks, or SUN for a Deaf group — and none of that was
|
||||
visible without opening 370 pins one at a time.
|
||||
It says "a way in", not "reached": a bridge has to be learnt, it is not Scripture
|
||||
in their language, and the gap the red dot marks is unchanged. Counted from the
|
||||
same rows as the number above it. English prose, like the rest of this block. -->
|
||||
<p v-if="pinTally.none && pinTally.wayIn" class="gm-caveat" dir="ltr" style="margin:2px 0 0">
|
||||
<b>{{ fmt(pinTally.wayIn) }} of those {{ fmt(pinTally.none) }}</b> have a possible way
|
||||
in — a bridge language, or SUN for a Deaf group. Tap one to see it. A way in is not
|
||||
the gospel in their own language; the gap is unchanged.
|
||||
</p>
|
||||
<!-- Not a colour, so it carries no dot: this cuts ACROSS the three tiers rather
|
||||
than naming one of them. It is the translation-priority question. -->
|
||||
<button type="button" class="gm-key gm-kbtn wide" :class="{ on: pinFilter === 'hnr' }"
|
||||
|
|
@ -1826,6 +1948,22 @@ useShadowStyles(
|
|||
<template v-else>the JESUS Film</template>.
|
||||
<br><em>Bridge strength: {{ selectedGroup.bridge.st }}.</em> A second language is a
|
||||
way in, not a translation — the gap in their own language is unchanged.
|
||||
|
||||
<!-- THE LINKS THAT MAKE IT FOLLOWABLE. Same chips, same publishers and the same
|
||||
doctrine scan as the group's own resources above; only the language differs.
|
||||
Rendered only when the index actually holds a URL, so a named bridge with
|
||||
nothing behind it stays a name rather than becoming a dead chip. -->
|
||||
<div v-if="curatedBridgeRes && (curatedBridgeRes.scripture_url || curatedBridgeRes.film_url)" class="gm-chips">
|
||||
<a v-if="curatedBridgeRes.scripture_url" class="gm-chip ok wrap"
|
||||
:href="curatedBridgeRes.scripture_url" target="_blank" rel="noopener">
|
||||
{{ curatedBridgeRes.language }} · {{ curatedBridgeRes.scripture_title || t('gospel.res.scripture') }} ↗</a>
|
||||
<a v-if="curatedBridgeRes.film_url" class="gm-chip ok wrap"
|
||||
:href="curatedBridgeRes.film_url" target="_blank" rel="noopener">
|
||||
{{ curatedBridgeRes.language }} · {{ curatedBridgeRes.film_title || t('gospel.res.jesusFilm') }} ↗</a>
|
||||
<a class="gm-chip wrap"
|
||||
:href="tableLink({ iso: curatedBridgeRes.iso, label: curatedBridgeRes.language })">
|
||||
{{ t('gospel.sheet.everyResource') }} {{ curatedBridgeRes.language }} →</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- THE WEAKER CASE, and it says so on its face. No curated bridge exists for this
|
||||
group, but their country does have a language carrying Scripture and the film.
|
||||
|
|
@ -1839,13 +1977,59 @@ useShadowStyles(
|
|||
&& !selectedGroup.audio && !selectedGroup.gospel_audio && !selectedGroup.scripture_earth"
|
||||
class="gm-sign" style="border-left-color:#d1d4cd" dir="ltr">
|
||||
<b>Possibly a way in — worth checking locally.</b>
|
||||
<br>Nothing was found in {{ selectedGroup.language || 'their language' }}. The largest
|
||||
language in this country that does have Scripture and the JESUS Film is
|
||||
<b>{{ selectedGroup.bridge_candidate.l }}</b>, spoken by
|
||||
{{ selectedGroup.bridge_candidate.n }} people group<template v-if="selectedGroup.bridge_candidate.n !== 1">s</template>
|
||||
here ({{ selectedGroup.bridge_candidate.pct }}% of this country's mapped population).
|
||||
<br>Nothing was found in {{ selectedGroup.language || 'their language' }}.
|
||||
<!-- TWO DIFFERENT DENOMINATORS, SAID PLAINLY. A CLDR candidate's percentage is a
|
||||
share of the COUNTRY, which is what a reader assumes a percentage means. The
|
||||
fallback's is a share of the PINNED population — a much smaller and invisible
|
||||
denominator — so it is never printed as a bare percentage. -->
|
||||
<template v-if="selectedGroup.bridge_candidate.src === 'cldr'">
|
||||
<b>{{ selectedGroup.bridge_candidate.l }}</b> is spoken by
|
||||
{{ selectedGroup.bridge_candidate.pct }}% of this country<template
|
||||
v-if="selectedGroup.bridge_candidate.official"> and is an official language</template>,
|
||||
and has Scripture and the JESUS Film.
|
||||
<!-- A tie is not a ranking. Where a second language is within five points, both
|
||||
are named rather than one being chosen by a rule the reader cannot see. -->
|
||||
<template v-if="selectedGroup.bridge_candidate.alt">
|
||||
So is <b>{{ selectedGroup.bridge_candidate.alt.l }}</b>, at
|
||||
{{ selectedGroup.bridge_candidate.alt.pct }}%<template
|
||||
v-if="selectedGroup.bridge_candidate.alt.official"> and official</template> —
|
||||
the two are close enough that this map will not choose between them.
|
||||
</template>
|
||||
<div v-if="altBridgeRes && (altBridgeRes.scripture_url || altBridgeRes.film_url)" class="gm-chips">
|
||||
<a v-if="altBridgeRes.scripture_url" class="gm-chip ok wrap"
|
||||
:href="altBridgeRes.scripture_url" target="_blank" rel="noopener">
|
||||
{{ altBridgeRes.language }} · {{ altBridgeRes.scripture_title || t('gospel.res.scripture') }} ↗</a>
|
||||
<a v-if="altBridgeRes.film_url" class="gm-chip ok wrap"
|
||||
:href="altBridgeRes.film_url" target="_blank" rel="noopener">
|
||||
{{ altBridgeRes.language }} · {{ altBridgeRes.film_title || t('gospel.res.jesusFilm') }} ↗</a>
|
||||
<a class="gm-chip wrap" :href="tableLink({ iso: altBridgeRes.iso, label: altBridgeRes.language })">
|
||||
{{ t('gospel.sheet.everyResource') }} {{ altBridgeRes.language }} →</a>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
The largest language among the people groups mapped here that does have Scripture
|
||||
and the JESUS Film is <b>{{ selectedGroup.bridge_candidate.l }}</b>, spoken by
|
||||
{{ selectedGroup.bridge_candidate.n }} of them. That is a count of THIS MAP's
|
||||
groups, not of the country — no published figure for the country was available.
|
||||
</template>
|
||||
<br><em>Not ranked and not recommended</em> — whether it actually reaches this group
|
||||
is a local question, and the gap in their own language is unchanged.
|
||||
|
||||
<!-- THE LINKS THAT MAKE IT FOLLOWABLE. Same chips, same publishers and the same
|
||||
doctrine scan as the group's own resources above; only the language differs.
|
||||
Rendered only when the index actually holds a URL, so a named bridge with
|
||||
nothing behind it stays a name rather than becoming a dead chip. -->
|
||||
<div v-if="candidateBridgeRes && (candidateBridgeRes.scripture_url || candidateBridgeRes.film_url)" class="gm-chips">
|
||||
<a v-if="candidateBridgeRes.scripture_url" class="gm-chip ok wrap"
|
||||
:href="candidateBridgeRes.scripture_url" target="_blank" rel="noopener">
|
||||
{{ candidateBridgeRes.language }} · {{ candidateBridgeRes.scripture_title || t('gospel.res.scripture') }} ↗</a>
|
||||
<a v-if="candidateBridgeRes.film_url" class="gm-chip ok wrap"
|
||||
:href="candidateBridgeRes.film_url" target="_blank" rel="noopener">
|
||||
{{ candidateBridgeRes.language }} · {{ candidateBridgeRes.film_title || t('gospel.res.jesusFilm') }} ↗</a>
|
||||
<a class="gm-chip wrap"
|
||||
:href="tableLink({ iso: candidateBridgeRes.iso, label: candidateBridgeRes.language })">
|
||||
{{ t('gospel.sheet.everyResource') }} {{ candidateBridgeRes.language }} →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p v-if="selectedGroup.scripture_title || selectedGroup.scripture_scope" class="gm-scope">
|
||||
|
|
@ -1892,6 +2076,38 @@ useShadowStyles(
|
|||
Society</b> and <b>DOOR International</b>, both of which need a key or an
|
||||
agreement — this gap closes by asking them, not by searching harder.
|
||||
</p>
|
||||
|
||||
<!-- ═══ AND HERE IS THE ONE WAY IN THAT EXISTS TODAY ════════════════════════════
|
||||
The paragraph above explains the gap honestly and then leaves a mobiliser with
|
||||
nothing to do, which for 93 groups and 17.5 million people is every Deaf group
|
||||
on this map. A spoken bridge cannot reach them, so they were the only population
|
||||
here with nothing AND no way in — structurally, not by bad luck.
|
||||
SUN is a signed language built to be learnt ACROSS sign languages, with Scripture
|
||||
in it. It is a bridge in the same sense the spoken ones are: it has to be learnt,
|
||||
and it is no substitute for Scripture in their own sign language — which is why
|
||||
it changes no tier and sits below the gap rather than closing it. -->
|
||||
<div v-if="deafBridge" class="gm-sign" style="border-left-color:#92b195" dir="ltr">
|
||||
<b>There is one signed language with Scripture in it.</b>
|
||||
<br><b>SUN</b> is built to be learnt across sign languages rather than being tied to
|
||||
one country, so it can be learnt by a Deaf community whose own sign language has
|
||||
nothing. Published by {{ deafBridge.publisher }}.
|
||||
<br><em>A bridge, not a translation</em> — it has to be learnt, and the gap in their
|
||||
own sign language is unchanged.
|
||||
<div class="gm-chips">
|
||||
<a v-if="deafBridge.scripture" class="gm-chip ok wrap"
|
||||
:href="deafBridge.scripture.u" target="_blank" rel="noopener">{{ deafBridge.scripture.t }} ↗</a>
|
||||
<a v-if="deafBridge.stories" class="gm-chip ok wrap"
|
||||
:href="deafBridge.stories.u" target="_blank" rel="noopener">{{ deafBridge.stories.t }} ↗</a>
|
||||
<a v-if="deafBridge.about" class="gm-chip wrap"
|
||||
:href="deafBridge.about" target="_blank" rel="noopener">About SUN ↗</a>
|
||||
</div>
|
||||
<!-- A named local partner is the difference between a resource and somebody to
|
||||
call, so it is shown only where SUN itself says the work is already running. -->
|
||||
<p v-if="deafBridge.organisation" class="gm-note" style="margin:6px 0 0">
|
||||
SUN is already being taught in {{ selectedGroup.countries }} by
|
||||
<b>{{ deafBridge.organisation }}</b>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- THE MAP'S OWN PROMPT, ANSWERED. Its toast has always said "someone still needs
|
||||
|
|
@ -2059,6 +2275,7 @@ useShadowStyles(
|
|||
{{ g.language }}<code class="gm-code">{{ g.iso639_3 || 'no code' }}</code>
|
||||
· {{ fmt(g.population) }} people
|
||||
</span>
|
||||
<span v-if="wayInFor(g)" class="gm-pg-way">way in: {{ wayInFor(g) }}</span>
|
||||
</button>
|
||||
<div v-if="withoutResources.length > shown" class="gm-more">
|
||||
Showing {{ shown }} of {{ withoutResources.length }}.
|
||||
|
|
|
|||
|
|
@ -760,6 +760,26 @@ for (const p of slim) {
|
|||
* reason GRN is skipped for them above.
|
||||
*/
|
||||
const bridgeCandidates = {}
|
||||
/**
|
||||
* ONE definition of "this language has a readable Scripture", used by both pickers below.
|
||||
*
|
||||
* ⚠ WRITTEN OUT TWICE FIRST, AND THE SECOND COPY WAS A FIELD SHORT — it checked s, se and d and
|
||||
* forgot that Faith Comes By Hearing carries TEXT on the audio record (au.m says so). MEASURED:
|
||||
* Bambara has the JESUS Film and a 66-book FCBH text Bible, and was filtered out of Mali's
|
||||
* bridge candidates for lack of Scripture, handing the recommendation to French. Bambara is
|
||||
* Mali's vehicular language. That is the field-list-goes-stale bug the surfaces gate exists for,
|
||||
* reproduced inside a build script where no gate was watching.
|
||||
*/
|
||||
const hasReadableScripture = (c) =>
|
||||
!!c && (!!c.s || !!c.se || !!(c.au && /text/.test(c.au.m || '')) ||
|
||||
(c.d || []).some((d) => !/^Open Bible Stories/.test(d.s || '')))
|
||||
|
||||
/* What each country actually speaks, with each language's share OF THE COUNTRY. Absent input is
|
||||
not fatal: every candidate then falls back to the pinned-population proxy, as before. */
|
||||
let countryLangs = {}
|
||||
try {
|
||||
countryLangs = JSON.parse(readFileSync(resolve(REPO, 'data/tables/country-languages.json'), 'utf8')).byCountry || {}
|
||||
} catch { /* no CLDR table in this tree */ }
|
||||
{
|
||||
const pool = {}
|
||||
const cpop = {}
|
||||
|
|
@ -773,7 +793,7 @@ const bridgeCandidates = {}
|
|||
const slot = (e[code] ||= { n: 0, pop: 0, l: c.l || '', s: false, f: false })
|
||||
slot.n += 1
|
||||
slot.pop += pop
|
||||
slot.s = slot.s || !!c.s || !!c.se || (c.d || []).some((d) => !/^Open Bible Stories/.test(d.s || ''))
|
||||
slot.s = slot.s || hasReadableScripture(c)
|
||||
slot.f = slot.f || !!c.f
|
||||
}
|
||||
for (const p of pins) {
|
||||
|
|
@ -782,6 +802,42 @@ const bridgeCandidates = {}
|
|||
if (codes[code] && codes[code].sg === 1) continue
|
||||
const key = `${code}|${iso3}`
|
||||
if (bridges[key] || bridgeCandidates[key]) continue
|
||||
/* ═══ ASK WHAT THE COUNTRY SPEAKS, NOT WHAT THE UNREACHED SPEAK ═══════════════════════
|
||||
* The pin-derived pick below answers "the biggest language among Doxa's UNREACHED groups
|
||||
* here", which is not the language a community shares with its neighbours. For Syenara
|
||||
* Senufo in Mali it proposed Minianka — one people group — while Mali's vehicular language
|
||||
* is Bambara at 46% of the country. CLDR is asked first, and only it can supply a share OF
|
||||
* THE COUNTRY, which is the denominator a reader assumes when they see a percentage.
|
||||
* Still filtered by what this index can actually offer: a bridge with no Scripture and no
|
||||
* film behind it is a name, not a way in. */
|
||||
const spoken = (countryLangs[iso3] || [])
|
||||
.filter((x) => x.c !== code && codes[x.c] && !!codes[x.c].f && hasReadableScripture(codes[x.c]))
|
||||
/* Official status breaks a tie between equal shares — Mali's French and Bambara are both
|
||||
46% — because the official one is the likelier second language to already be taught. */
|
||||
const ranked = spoken.sort((a, b) => (b.pct - a.pct) || (b.official - a.official))
|
||||
const cldrBest = ranked[0]
|
||||
if (cldrBest) {
|
||||
/* ⚠ WHEN TWO LANGUAGES ARE TIED, PICKING ONE IS AN EDITORIAL ACT, NOT A MEASUREMENT.
|
||||
* Mali is exactly this: French 46% and official, Bambara 46% and not. French is the
|
||||
* administrative language, Bambara is what people actually share in a market or a
|
||||
* village, and which one bridges better depends on whether the reader is handing over
|
||||
* a booklet or starting a conversation. The panel already says the choice is a local
|
||||
* question; so where a runner-up is within five points, BOTH are shipped and the reader
|
||||
* decides. A tie-break here would have quietly answered a question nobody asked it. */
|
||||
const alt = ranked[1] && (cldrBest.pct - ranked[1].pct) <= 5 ? ranked[1] : null
|
||||
bridgeCandidates[key] = {
|
||||
l: codes[cldrBest.c]?.l || cldrBest.l,
|
||||
c: cldrBest.c,
|
||||
pct: cldrBest.pct,
|
||||
official: cldrBest.official,
|
||||
src: 'cldr',
|
||||
...(alt ? { alt: { l: codes[alt.c]?.l || alt.l, c: alt.c, pct: alt.pct, official: alt.official } } : {}),
|
||||
}
|
||||
continue
|
||||
}
|
||||
/* FALLBACK, and it says so on the row. CLDR lists no language here that this index can
|
||||
offer, so the old proxy is better than nothing — but its percentage is a share of the
|
||||
PINNED population, a different denominator, and the surfaces read `src` to say which. */
|
||||
const best = Object.entries(pool[iso3] || {})
|
||||
.filter(([cc, s]) => cc !== code && s.s && s.f)
|
||||
.sort((a, b) => b[1].pop - a[1].pop)[0]
|
||||
|
|
@ -790,12 +846,47 @@ const bridgeCandidates = {}
|
|||
bridgeCandidates[key] = {
|
||||
l: best[1].l, c: best[0], n: best[1].n,
|
||||
pct: tot ? Math.round((1000 * best[1].pop) / tot) / 10 : 0,
|
||||
src: 'pins',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ═══ THE DEAF BRIDGE TRAVELS WITH THE INDEX ═══════════════════════════════════════════════
|
||||
*
|
||||
* SUN reached the access table and the CSV first, and the MAP — the surface a mobiliser
|
||||
* actually opens — still showed Deaf groups a panel that explained their situation and offered
|
||||
* no way out of it. That is the largest population on this map with nothing: 93 groups, 17.5
|
||||
* million people.
|
||||
*
|
||||
* Carried here rather than fetched by the leaf, for the same reason the bridges are: one
|
||||
* source, so the sheet and the table cannot disagree about what exists. It is a single small
|
||||
* object, not a per-language join — SUN is ONE signed language for all of them, which is the
|
||||
* whole point of it.
|
||||
*
|
||||
* Absent input is not fatal: the map simply shows what it showed before.
|
||||
*/
|
||||
let sun = null
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(resolve(REPO, 'data/tables/sun-deaf-index.json'), 'utf8'))
|
||||
const pick = (k) => (raw.resources || []).find((r) => r.key === k)
|
||||
const scripture = pick('new_testament') || (raw.resources || [])[0]
|
||||
sun = {
|
||||
publisher: raw.meta?.publisher || '',
|
||||
scripture: scripture ? { u: scripture.url, t: scripture.label } : null,
|
||||
stories: (() => { const r = pick('bible_stories'); return r ? { u: r.url, t: r.label } : null })(),
|
||||
about: (() => { const r = pick('home'); return r ? r.url : '' })(),
|
||||
/* Country -> the local Deaf church or organisation already teaching it. A named partner is
|
||||
the difference between a resource and somebody to call. */
|
||||
byCountry: Object.fromEntries((raw.projects || []).map((p) => [
|
||||
String(p.country || '').toLowerCase().replace(/[^a-z]/g, ''), p.organisation,
|
||||
])),
|
||||
}
|
||||
} catch { /* no SUN index in this tree: the Deaf panel stays as it was */ }
|
||||
|
||||
const out = {
|
||||
sun,
|
||||
bridges,
|
||||
bridgeCandidates,
|
||||
_note: 'Generated by scripts/build-people-group-pins.mjs. pins=[name,lat,lng,iso3,code,pop,tier]; URLs live in codes[] by ISO 639-3. No URL is invented here.',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* fetch-country-languages.mjs — which languages are actually SPOKEN in a country, and by what
|
||||
* share of it.
|
||||
*
|
||||
* WHY THIS EXISTS. The bridge CANDIDATE — the "possibly a way in" offered to a group with
|
||||
* nothing — was chosen from Doxa's own pins: the language with the largest pinned population in
|
||||
* that country that has Scripture and the film. Doxa's roster is 2,107 UNREACHED groups, so that
|
||||
* is the biggest language among the unreached, which is not the language a community actually
|
||||
* shares with its neighbours. Measured: for Syenara Senufo in Mali it proposed MINIANKA, one
|
||||
* people group. Mali's actual vehicular language is Bambara, spoken by most of the country.
|
||||
*
|
||||
* Worse, the number shipped beside it read "8.8% of this country's mapped population" — a share
|
||||
* of Doxa's unreached PINS, which a reader will take for a share of the country. A percentage
|
||||
* measured against a denominator nobody can see is not a caveat, it is a wrong number.
|
||||
*
|
||||
* WHAT THIS USES. CLDR's territoryInfo, which carries, per territory, each language's share of
|
||||
* the population and whether it is official. That is the published answer to "what is spoken
|
||||
* here", maintained by Unicode, and it is the right denominator: the country.
|
||||
*
|
||||
* ⚠ PINNED, NOT `main`. cldr-json's main branch moves; a bridge recommendation changing because
|
||||
* an upstream branch advanced is not something anyone would think to look for.
|
||||
*
|
||||
* THE JOIN. CLDR speaks BCP-47, this build speaks ISO 639-3, and the two meet through the Part1
|
||||
* column of SIL's own iso-639-3 table — 184 languages carry a 639-1 code. A CLDR tag with no
|
||||
* 639-3 equivalent is dropped rather than guessed; a guess here would put a language in a
|
||||
* country on no authority at all.
|
||||
*/
|
||||
import { writeFileSync } from 'node:fs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url))
|
||||
const REPO = resolve(HERE, '../../..')
|
||||
const OUT = resolve(REPO, 'data/tables/country-languages.json')
|
||||
const UA = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36'
|
||||
|
||||
const CLDR = 'https://cdn.jsdelivr.net/npm/cldr-core@46.0.0/supplemental/territoryInfo.json'
|
||||
const ISO = 'https://iso639-3.sil.org/sites/iso639-3/files/downloads/iso-639-3.tab'
|
||||
/* Keyed by ISO3 on the way out, so the pin builder joins on the code it already has. The
|
||||
mapping comes from the SAME pinned CLDR release as the language data, rather than a second
|
||||
host with its own release cycle. */
|
||||
const CODES = 'https://cdn.jsdelivr.net/npm/cldr-core@46.0.0/supplemental/codeMappings.json'
|
||||
|
||||
const get = async (url) => {
|
||||
const r = await fetch(url, { headers: { 'user-agent': UA }, signal: AbortSignal.timeout(90000) })
|
||||
if (!r.ok) throw new Error(`${url} -> ${r.status}`)
|
||||
return r.text()
|
||||
}
|
||||
|
||||
/* Part1 (639-1) -> Id (639-3), plus the reference name, from SIL's own table. */
|
||||
const tab = await get(ISO)
|
||||
const toIso3 = {}
|
||||
const refName = {}
|
||||
for (const line of tab.split('\n').slice(1)) {
|
||||
const f = line.split('\t')
|
||||
if (f.length < 7) continue
|
||||
const [id, , , part1, , , name] = f
|
||||
if (!id) continue
|
||||
refName[id] = (name || '').trim()
|
||||
if (part1 && part1.trim()) toIso3[part1.trim()] = id.trim()
|
||||
}
|
||||
|
||||
const codeMap = JSON.parse(await get(CODES)).supplemental.codeMappings
|
||||
const alpha3 = {}
|
||||
for (const [terr, v] of Object.entries(codeMap)) {
|
||||
if (/^[A-Z]{2}$/.test(terr) && v && v._alpha3) alpha3[terr] = v._alpha3
|
||||
}
|
||||
|
||||
const cldr = JSON.parse(await get(CLDR)).supplemental.territoryInfo
|
||||
const byCountry = {}
|
||||
let dropped = 0
|
||||
let noAlpha3 = 0
|
||||
for (const [terr, info] of Object.entries(cldr)) {
|
||||
/* Two-letter territories only: CLDR also carries numeric macro-regions like 001 (World),
|
||||
which are not countries and would put "spoken in the World" into a bridge recommendation. */
|
||||
if (!/^[A-Z]{2}$/.test(terr)) continue
|
||||
const langs = []
|
||||
for (const [tag, lp] of Object.entries(info.languagePopulation || {})) {
|
||||
/* A tag like en_GB or zh_Hans carries a script or region; the base language is what a
|
||||
speaker shares with a neighbour, so it is taken and the variant dropped. */
|
||||
const base = tag.split(/[-_]/)[0]
|
||||
const iso3 = toIso3[base] || (base.length === 3 ? base : null)
|
||||
if (!iso3) { dropped++; continue }
|
||||
const pct = Number(lp._populationPercent)
|
||||
if (!Number.isFinite(pct)) continue
|
||||
langs.push({
|
||||
c: iso3,
|
||||
l: refName[iso3] || base,
|
||||
pct: Math.round(pct * 10) / 10,
|
||||
official: !!lp._officialStatus,
|
||||
})
|
||||
}
|
||||
if (!langs.length) continue
|
||||
/* Largest share first: that is the order a reader would want to judge a bridge in. */
|
||||
langs.sort((a, b) => b.pct - a.pct)
|
||||
const key = alpha3[terr]
|
||||
if (!key) { noAlpha3++; continue }
|
||||
byCountry[key] = langs
|
||||
}
|
||||
|
||||
const countries = Object.keys(byCountry).length
|
||||
if (countries < 150) {
|
||||
console.error(`COUNTRY-LANGUAGES: REFUSING TO WRITE — only ${countries} countries parsed.`)
|
||||
console.error(' A thin file would silently narrow every bridge recommendation that reads it.')
|
||||
process.exitCode = 1
|
||||
} else {
|
||||
writeFileSync(OUT, `${JSON.stringify({
|
||||
meta: {
|
||||
title: 'Languages spoken per country, with each share of the country',
|
||||
sources: [CLDR, ISO],
|
||||
generated: new Date().toISOString().slice(0, 10),
|
||||
countries,
|
||||
note: 'CLDR territoryInfo joined to ISO 639-3 through SIL\'s Part1 column. Percentages are ' +
|
||||
'of the COUNTRY\'s population, which is the denominator a reader assumes. A CLDR tag ' +
|
||||
'with no ISO 639-3 equivalent is dropped, never guessed.',
|
||||
cldr_tags_dropped_no_iso639_3: dropped,
|
||||
territories_dropped_no_alpha3: noAlpha3,
|
||||
},
|
||||
byCountry,
|
||||
}, null, 1)}\n`)
|
||||
console.log(`country-languages: ${countries} countries (keyed by ISO3), ${dropped} CLDR tag(s) dropped for having no ISO 639-3, ${noAlpha3} territory(ies) with no alpha-3`)
|
||||
console.log(`wrote ${OUT}`)
|
||||
}
|
||||
|
|
@ -173,7 +173,13 @@ const sel = ref({
|
|||
// and their pin popup renders every one of them. Ours fetched neither rop1, religion,
|
||||
// location_description nor the photo, so the popup COULD NOT have been a clone however it was
|
||||
// written — the data was not on the page. Same one request, five more columns.
|
||||
const FIELDS = 'name,slug,rop1,religion,location_description,image_url,has_photo,' + PEOPLE_GROUP_LIST_FIELDS
|
||||
// ★ imb_people_description, NOT location_description. Their CountryMap's PIN_FIELDS names
|
||||
// imb_people_description and the popup binds it (CountryMap.vue:89 and :114 on MASTER); the
|
||||
// doxa-maps-build branch this repo's checkout is parked on still says location_description, and
|
||||
// that is what we had cloned. The two are different prose: location_description says where a
|
||||
// people live, imb_people_description describes the people. So our popup was showing the wrong
|
||||
// paragraph — visible content, not a field-name detail.
|
||||
const FIELDS = 'name,slug,rop1,religion,imb_people_description,image_url,has_photo,' + PEOPLE_GROUP_LIST_FIELDS
|
||||
|
||||
function formatNumber(n) {
|
||||
// THEIRS, RegionDetail.vue:16: `n.toLocaleString(`${locale.value}-u-nu-latn`)` — locale
|
||||
|
|
@ -660,7 +666,7 @@ async function loadRegions() {
|
|||
// has_photo GATE on the image, which is theirs: a row can carry an image_url that is a
|
||||
// placeholder, and they only show it when the flag says there is a real photo.
|
||||
rop1: p.rop1?.label || '', religion: p.religion?.label || '',
|
||||
description: p.location_description || '',
|
||||
description: p.imb_people_description ?? '',
|
||||
imageUrl: (p.has_photo && p.image_url) ? p.image_url : '',
|
||||
})).filter((p) => Number.isFinite(p.lng) && Number.isFinite(p.lat))
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,9 @@
|
|||
*
|
||||
* i.e. the leaf ships Mapbox GL and the Mapbox geocoder to every visitor regardless of the engine
|
||||
* it was asked for. That is the leaf GENERATOR's doing, not this plugin's, and it is why this gate
|
||||
* is deliberately NOT wired into gates:post yet: it would be a red gate about somebody else's file.
|
||||
* Run it by name; it names the exact URLs.
|
||||
* was kept out of gates:post until the generator stopped hard-linking the engine (2026-09-25: the leaf
|
||||
* now loads only the engine its provider asks for). It is wired into gates:post in that same landing,
|
||||
* and still names the exact URLs when it fails.
|
||||
*
|
||||
* ★ ZERO IS THE ASSERTION, not "it rendered". A build that quietly kept the Mapbox geocoder would
|
||||
* look identical: the bars appear, suggestions work, nothing errors. Only the request log tells the
|
||||
|
|
|
|||
|
|
@ -82,9 +82,18 @@ await requireThisTree(TREE, ROOT, TAG)
|
|||
const browser = await chromium.launch({ args: ['--enable-unsafe-swiftshader', '--use-gl=angle', '--use-angle=swiftshader'] })
|
||||
const fails = []
|
||||
const lines = []
|
||||
// ★ THE PROVIDER MATRIX. The same assertions, run once per engine, because interoperability that
|
||||
// holds on one provider and not the other is not interoperability
|
||||
// (BUILD-INTEROP-CONTRACT-GRID-UNDER-MAP-BOTH-PROVIDERS). It is not a formality: the map half of
|
||||
// this link resolves a religion family through its own legend, and the legend is drawn by the map
|
||||
// engine — a MapLibre-only paint or layout mistake drops a whole layer silently, which would show
|
||||
// up here as a link that delivers nothing while the Mapbox run stays green.
|
||||
const PROVIDERS = ['mapbox', 'maplibre']
|
||||
const results = {}
|
||||
try {
|
||||
for (const engine of PROVIDERS) {
|
||||
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } })
|
||||
await page.goto(LEAF, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
await page.goto(`${LEAF}?provider=${engine}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
|
||||
// Everything below runs in ONE evaluate: the totals have to be read from the same live page, and
|
||||
// a `groups-filtered` listener installed from Node would miss events fired between round trips.
|
||||
|
|
@ -186,19 +195,38 @@ try {
|
|||
return { unfiltered, family, letter, direct, linked, mutant, mapVocab, gridVocab: gridVocab.slice(0, 12) }
|
||||
})
|
||||
|
||||
if (out.skip) { await browser.close(); cleanup(); skip(out.skip) }
|
||||
if (out.fail) fails.push(out.fail)
|
||||
else {
|
||||
lines.push(` · vocabulary — the map names ${out.mapVocab.length} religion families, the grid names ${out.gridVocab.length}+; '${out.family}' is shared`)
|
||||
lines.push(` · direct — religion-family="${out.family}" set on the grid itself: ${out.direct} of ${out.unfiltered}`)
|
||||
lines.push(` · linked — the same family over the composite's wire: ${out.linked}`)
|
||||
lines.push(` · mutant — the legend KEY '${out.letter}' over the same wire: ${out.mutant}`)
|
||||
await page.close()
|
||||
if (out.skip) { await browser.close(); cleanup(); skip(`${out.skip} (under ${engine})`) }
|
||||
results[engine] = out
|
||||
if (out.fail) { fails.push(`[${engine}] ${out.fail}`); continue }
|
||||
|
||||
if (out.mutant === out.direct) {
|
||||
fails.push(`NO TEETH — sending the legend key '${out.letter}' narrowed the grid to the same ${out.direct} rows as the family name '${out.family}'. This gate cannot tell a right mapping from a wrong one, so its pass would mean nothing.`)
|
||||
lines.push(` ── ${engine}`)
|
||||
lines.push(` vocabulary — the map names ${out.mapVocab.length} religion families, the grid names ${out.gridVocab.length}+; '${out.family}' is shared`)
|
||||
lines.push(` direct — religion-family="${out.family}" set on the grid itself: ${out.direct} of ${out.unfiltered}`)
|
||||
lines.push(` linked — the same family over the composite's wire: ${out.linked}`)
|
||||
lines.push(` mutant — the legend KEY '${out.letter}' over the same wire: ${out.mutant}`)
|
||||
|
||||
if (out.mutant === out.direct) {
|
||||
fails.push(`[${engine}] NO TEETH — sending the legend key '${out.letter}' narrowed the grid to the same ${out.direct} rows as the family name '${out.family}'. This gate cannot tell a right mapping from a wrong one, so its pass would mean nothing.`)
|
||||
}
|
||||
if (out.linked !== out.direct) {
|
||||
fails.push(`[${engine}] the link does not deliver the facet — '${out.family}' set on the grid gives ${out.direct} rows, the same family over the composite's wire gives ${out.linked}.`)
|
||||
}
|
||||
}
|
||||
|
||||
// ★ AND THE TWO ENGINES MUST AGREE. Each run above only proves the link works within one engine;
|
||||
// identical COUNTS is what proves the contract is the same product on both. A per-engine pass with
|
||||
// different numbers would mean the two builds narrow to different peoples for the same choice.
|
||||
const [a, b] = PROVIDERS
|
||||
if (results[a] && results[b] && !results[a].fail && !results[b].fail) {
|
||||
if (results[a].unfiltered !== results[b].unfiltered) {
|
||||
fails.push(`the two engines start from different data — ${a} lists ${results[a].unfiltered} groups, ${b} lists ${results[b].unfiltered}.`)
|
||||
}
|
||||
if (out.linked !== out.direct) {
|
||||
fails.push(`the link does not deliver the facet — '${out.family}' set on the grid gives ${out.direct} rows, the same family over the composite's wire gives ${out.linked}.`)
|
||||
if (results[a].family === results[b].family && results[a].direct !== results[b].direct) {
|
||||
fails.push(`'${results[a].family}' narrows to ${results[a].direct} rows under ${a} and ${results[b].direct} under ${b} — the same choice gives different peoples on the two engines.`)
|
||||
}
|
||||
if (results[a].linked !== results[b].linked) {
|
||||
fails.push(`the link delivers ${results[a].linked} rows under ${a} and ${results[b].linked} under ${b} — interoperability that holds on one provider and not the other is not interoperability.`)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
|
|
@ -217,4 +245,4 @@ if (fails.length) {
|
|||
console.log(' NAME per row. Both halves must speak the NAME on the wire.')
|
||||
process.exit(1)
|
||||
}
|
||||
console.log(`${TAG}: PASS — the composite's religion link delivers exactly the facet the grid delivers on its own, and a wrong mapping does not.`)
|
||||
console.log(`${TAG}: PASS — on BOTH providers the composite's religion link delivers exactly the facet the grid delivers on its own, a wrong mapping does not, and the two engines agree to the row.`)
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>all-people-groups · all-people-groups</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <all-people-groups> custom element. -->
|
||||
<script src="../all-people-groups.js" integrity="sha384-rYegL22R5zloYSbRnP7eMaV7zFGGoRDQeX8sCSR2Kko/HSOq+N8q8i9YMyXZIOOx" crossorigin="anonymous"></script>
|
||||
<script src="../all-people-groups.js" integrity="sha384-/ccFZBqULYNTyH8CVTLvJk49YTUHp+swTlr+Pr8TKUiOUGlp3ZkaATMsivVY2cvm" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"profile":"all-people-groups","dataSource":"pray-tools","instanceId":"all-people-groups-all-people-groups","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
9464
public/dx-maps/assets/tables/country-languages.json
Normal file
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
|
||||
<script src="../../big-picture.js" integrity="sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo" crossorigin="anonymous"></script>
|
||||
<script src="../../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -56,7 +56,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"big-picture","provider":"maplibre","instanceId":"bp-big-picture"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
|
||||
<script src="../../big-picture.js" integrity="sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo" crossorigin="anonymous"></script>
|
||||
<script src="../../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -56,7 +56,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"big-picture","provider":"maplibre","instanceId":"bp-big-picture-frontier","accent":"#22d3ee","title":"Big Picture — Frontier Focus"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <bp-big-picture> custom element. -->
|
||||
<script src="../big-picture.js" integrity="sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo" crossorigin="anonymous"></script>
|
||||
<script src="../big-picture.js" integrity="sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -56,7 +56,11 @@
|
|||
var BASE_CONFIG = {"profile":"big-picture","dataSource":"pray-tools","instanceId":"big-picture-big-picture","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"connectivity-list","dataSource":"pray-tools","instanceId":"cities-internet-connectivity-list","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>connectivity-map · cities-internet</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"pinHint":false,"profile":"connectivity-map","dataSource":"pray-tools","instanceId":"cities-internet-connectivity-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <cities-internet-map> custom element. -->
|
||||
<script src="../cities-internet.js" integrity="sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6" crossorigin="anonymous"></script>
|
||||
<script src="../cities-internet.js" integrity="sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"data-tables","dataSource":"pray-tools","instanceId":"cities-internet-data-tables","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>countries-map · country-posters</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"profile":"countries-map","dataSource":"pray-tools","instanceId":"country-posters-countries-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"country-poster-wall","dataSource":"pray-tools","instanceId":"country-posters-country-poster-wall","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>country-posters-mfe · country-posters</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* SCROLL-PAGE leaf (cap-4 nested-elements-mfe composite: a StackLayout scroll-stack). The DOCUMENT
|
||||
owns the scroll — the element takes its content's NATURAL height and grows the page, so a reader
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <country-posters-map> custom element. -->
|
||||
<script src="../country-posters.js" integrity="sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam" crossorigin="anonymous"></script>
|
||||
<script src="../country-posters.js" integrity="sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -59,7 +60,11 @@
|
|||
var BASE_CONFIG = {"pinHint":false,"profile":"country-posters-mfe","dataSource":"pray-tools","instanceId":"country-posters-country-posters-mfe","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>default · dashboard-plus-grid</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* SCROLL-PAGE leaf (cap-4 nested-elements-mfe composite: a StackLayout scroll-stack). The DOCUMENT
|
||||
owns the scroll — the element takes its content's NATURAL height and grows the page, so a reader
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
|
||||
<script src="../../dashboard-plus-grid.js" integrity="sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU" crossorigin="anonymous"></script>
|
||||
<script src="../../dashboard-plus-grid.js" integrity="sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -59,7 +60,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"dashboard-plus-grid"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>dashboard-plus-grid · dashboard-plus-grid</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* SCROLL-PAGE leaf (cap-4 nested-elements-mfe composite: a StackLayout scroll-stack). The DOCUMENT
|
||||
owns the scroll — the element takes its content's NATURAL height and grows the page, so a reader
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <dashboard-plus-grid> custom element. -->
|
||||
<script src="../dashboard-plus-grid.js" integrity="sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU" crossorigin="anonymous"></script>
|
||||
<script src="../dashboard-plus-grid.js" integrity="sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -59,7 +60,11 @@
|
|||
var BASE_CONFIG = {"profile":"dashboard-plus-grid","dataSource":"pray-tools","instanceId":"dashboard-plus-grid-dashboard-plus-grid","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>demo-map · demo-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <demo-map> custom element. -->
|
||||
<script src="../demo-map.js" integrity="sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9" crossorigin="anonymous"></script>
|
||||
<script src="../demo-map.js" integrity="sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"profile":"demo-map","dataSource":"pray-tools","instanceId":"demo-map-demo-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <demo-map> custom element. -->
|
||||
<script src="../../demo-map.js" integrity="sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9" crossorigin="anonymous"></script>
|
||||
<script src="../../demo-map.js" integrity="sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -46,7 +46,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"demo-map","provider":"maplibre","instanceId":"demo-maplibre"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-maps-spa","provider":"maplibre","instanceId":"doxa-maps-spa-app","title":"Research Gallery"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"doxa-maps-spa","dataSource":"pray-tools","instanceId":"doxa-maps-spa-doxa-maps-spa","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"bundle": "all-people-groups",
|
||||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"output": "dx-maps/all-people-groups/all-people-groups.js",
|
||||
"integrity": "sha384-rYegL22R5zloYSbRnP7eMaV7zFGGoRDQeX8sCSR2Kko/HSOq+N8q8i9YMyXZIOOx",
|
||||
"integrity": "sha384-/ccFZBqULYNTyH8CVTLvJk49YTUHp+swTlr+Pr8TKUiOUGlp3ZkaATMsivVY2cvm",
|
||||
"elements": [
|
||||
"all-people-groups"
|
||||
],
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./all-people-groups/all-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-rYegL22R5zloYSbRnP7eMaV7zFGGoRDQeX8sCSR2Kko/HSOq+N8q8i9YMyXZIOOx\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-/ccFZBqULYNTyH8CVTLvJk49YTUHp+swTlr+Pr8TKUiOUGlp3ZkaATMsivVY2cvm\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
},
|
||||
"bundle": "all-people-groups"
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
"bundle": "big-picture",
|
||||
"scriptUrl": "./big-picture/big-picture.js",
|
||||
"output": "dx-maps/big-picture/big-picture.js",
|
||||
"integrity": "sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo",
|
||||
"integrity": "sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ",
|
||||
"elements": [
|
||||
"bp-big-picture",
|
||||
"bp-research-header",
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
"scriptUrl": "./big-picture/big-picture.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./big-picture/big-picture/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"bundle": "cities-internet",
|
||||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"output": "dx-maps/cities-internet/cities-internet.js",
|
||||
"integrity": "sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6",
|
||||
"integrity": "sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q",
|
||||
"elements": [
|
||||
"cities-internet-map"
|
||||
],
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
"bundle": "country-posters",
|
||||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"output": "dx-maps/country-posters/country-posters.js",
|
||||
"integrity": "sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam",
|
||||
"integrity": "sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K",
|
||||
"elements": [
|
||||
"country-posters-map"
|
||||
],
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/countries-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-posters-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
"bundle": "dashboard-plus-grid",
|
||||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"integrity": "sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU",
|
||||
"integrity": "sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY",
|
||||
"elements": [
|
||||
"dashboard-plus-grid"
|
||||
],
|
||||
|
|
@ -234,7 +234,7 @@
|
|||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -258,7 +258,7 @@
|
|||
"bundle": "demo-map",
|
||||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"output": "dx-maps/demo-map/demo-map.js",
|
||||
"integrity": "sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9",
|
||||
"integrity": "sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5",
|
||||
"elements": [
|
||||
"demo-map"
|
||||
],
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./demo-map/demo-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
"bundle": "doxa-research-map",
|
||||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
|
||||
"integrity": "sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4",
|
||||
"integrity": "sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud",
|
||||
"elements": [
|
||||
"doxa-research-map"
|
||||
],
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -395,7 +395,7 @@
|
|||
"bundle": "doxa-simple-map",
|
||||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
|
||||
"integrity": "sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5",
|
||||
"integrity": "sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV",
|
||||
"elements": [
|
||||
"doxa-map",
|
||||
"doxa-simple-map"
|
||||
|
|
@ -412,7 +412,7 @@
|
|||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv",
|
||||
"integrity": "sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0",
|
||||
"elements": [
|
||||
"gospel-resources-map"
|
||||
],
|
||||
|
|
@ -598,7 +598,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -612,7 +612,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -640,7 +640,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -654,7 +654,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -663,7 +663,7 @@
|
|||
"bundle": "my-upg-100-list",
|
||||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
|
||||
"integrity": "sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0",
|
||||
"integrity": "sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA",
|
||||
"elements": [
|
||||
"my-upg-100-list-map"
|
||||
],
|
||||
|
|
@ -683,7 +683,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -697,7 +697,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -711,7 +711,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -720,7 +720,7 @@
|
|||
"bundle": "people-groups-grid",
|
||||
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
|
||||
"output": "dx-maps/people-groups-grid/people-groups-grid.js",
|
||||
"integrity": "sha384-P36N4rI/QkK68QpPw1OHfxGIYeYfpr+1tX8Bxve+B98JfWFajRYKQeaRi5TgPVCU",
|
||||
"integrity": "sha384-NxK7wM4VhKnvgdeGmcwCcPGvNkQq4dZRXDkh8eUWhtcEuz4s7EFeQQjxA1PciJVt",
|
||||
"elements": [
|
||||
"people-groups-grid"
|
||||
],
|
||||
|
|
@ -736,7 +736,7 @@
|
|||
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./people-groups-grid/people-groups-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-P36N4rI/QkK68QpPw1OHfxGIYeYfpr+1tX8Bxve+B98JfWFajRYKQeaRi5TgPVCU\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-NxK7wM4VhKnvgdeGmcwCcPGvNkQq4dZRXDkh8eUWhtcEuz4s7EFeQQjxA1PciJVt\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-vFLNggTOuuot4RsQ+/aQBr0XRqBnYWt39zpKY8uksTBdfwAKChSc4yRnWha1QnNg",
|
||||
"integrity": "sha384-J2lpea95fPnplQ5HWhlWQXZV8Ht2YRQZMOOJTPzLqnt8hOSCfeKWBPBi2P9Z7jKp",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -852,7 +852,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-vFLNggTOuuot4RsQ+/aQBr0XRqBnYWt39zpKY8uksTBdfwAKChSc4yRnWha1QnNg\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-J2lpea95fPnplQ5HWhlWQXZV8Ht2YRQZMOOJTPzLqnt8hOSCfeKWBPBi2P9Z7jKp\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
@ -862,7 +862,7 @@
|
|||
"bundle": "prayer-walk-planner",
|
||||
"scriptUrl": "./prayer-walk-planner/prayer-walk-planner.js",
|
||||
"output": "dx-maps/prayer-walk-planner/prayer-walk-planner.js",
|
||||
"integrity": "sha384-R/ybjDe8VDmUbk7hl3Q6KApwLKwSs/8/zkzQVASWM9EpT5TwJpCxoLS33GSV9F8u",
|
||||
"integrity": "sha384-YZUFcXft7eTGJMY4I1FRak276dwfkSNFe6ylcWfRXJAmXWC39CCktE9qmNaZWSKB",
|
||||
"elements": [
|
||||
"prayer-walk-planner"
|
||||
],
|
||||
|
|
@ -878,7 +878,7 @@
|
|||
"scriptUrl": "./prayer-walk-planner/prayer-walk-planner.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./prayer-walk-planner/prayer-walk-planner/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-R/ybjDe8VDmUbk7hl3Q6KApwLKwSs/8/zkzQVASWM9EpT5TwJpCxoLS33GSV9F8u\" crossorigin=\"anonymous\"></script>\n<prayer-walk-planner profile-config='{\"profile\":\"prayer-walk-planner\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></prayer-walk-planner>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-YZUFcXft7eTGJMY4I1FRak276dwfkSNFe6ylcWfRXJAmXWC39CCktE9qmNaZWSKB\" crossorigin=\"anonymous\"></script>\n<prayer-walk-planner profile-config='{\"profile\":\"prayer-walk-planner\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></prayer-walk-planner>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -887,7 +887,7 @@
|
|||
"bundle": "regions-dashboard",
|
||||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
|
||||
"integrity": "sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe",
|
||||
"integrity": "sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS",
|
||||
"elements": [
|
||||
"regions-dashboard"
|
||||
],
|
||||
|
|
@ -907,7 +907,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -921,7 +921,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -935,7 +935,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -944,7 +944,7 @@
|
|||
"bundle": "research-dashboard",
|
||||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"output": "dx-maps/research-dashboard/research-dashboard.js",
|
||||
"integrity": "sha384-8HH1SOeixTcwk2j0Ldl9wLhAt+tLlOucxdVjn7KNyLrYIcB4WlI9J7pzwm3n5KFo",
|
||||
"integrity": "sha384-QKWWr/gy1T9mh5pwVoPuaeE8pWW6GPXDi4L0HLj1S+scQibD9F6ilApWLa6cNNoY",
|
||||
"elements": [
|
||||
"research-dashboard-map"
|
||||
],
|
||||
|
|
@ -960,7 +960,7 @@
|
|||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-dashboard/research-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-8HH1SOeixTcwk2j0Ldl9wLhAt+tLlOucxdVjn7KNyLrYIcB4WlI9J7pzwm3n5KFo\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-QKWWr/gy1T9mh5pwVoPuaeE8pWW6GPXDi4L0HLj1S+scQibD9F6ilApWLa6cNNoY\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
},
|
||||
"bundle": "research-dashboard"
|
||||
}
|
||||
|
|
@ -970,7 +970,7 @@
|
|||
"bundle": "research-map-plus-grid",
|
||||
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
|
||||
"output": "dx-maps/research-map-plus-grid/research-map-plus-grid.js",
|
||||
"integrity": "sha384-XOGLrOs4KZCfyXMDB8SIkx3wrxUfxk84xJkHsYSvZ83GXFjvb4ut8FT89zCgbTg5",
|
||||
"integrity": "sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2",
|
||||
"elements": [
|
||||
"research-map-plus-grid"
|
||||
],
|
||||
|
|
@ -990,7 +990,7 @@
|
|||
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-map-plus-grid/research-map-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-XOGLrOs4KZCfyXMDB8SIkx3wrxUfxk84xJkHsYSvZ83GXFjvb4ut8FT89zCgbTg5\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
"bundle": "upg-neighbor",
|
||||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"output": "dx-maps/upg-neighbor/upg-neighbor.js",
|
||||
"integrity": "sha384-eNZc5rM+EukmMqMxnjnLseMukVmEgdIt4q0N7l7PXYIsNCPLxR4ePkML9D82gdIQ",
|
||||
"integrity": "sha384-c1C0pPxaVk9S8fnp0TVhct1wr0Rv5Dv+yFHWZ3sKl+hlbhrzukmE9YXRc2iG0M4D",
|
||||
"elements": [
|
||||
"upg-neighbor"
|
||||
],
|
||||
|
|
@ -1074,7 +1074,7 @@
|
|||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./upg-neighbor/upg-neighbor/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-eNZc5rM+EukmMqMxnjnLseMukVmEgdIt4q0N7l7PXYIsNCPLxR4ePkML9D82gdIQ\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-c1C0pPxaVk9S8fnp0TVhct1wr0Rv5Dv+yFHWZ3sKl+hlbhrzukmE9YXRc2iG0M4D\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1156,7 +1156,7 @@
|
|||
"bundle": "wall-of-people-groups",
|
||||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"output": "dx-maps/wall-of-people-groups/wall-of-people-groups.js",
|
||||
"integrity": "sha384-MiqAIjghH+xJybAqBA3/CgAHYxI/KhY0APyZynjmDOG+iDbg598tnXZ4oNPi5eQ3",
|
||||
"integrity": "sha384-RbbVrnoWTjZOuwmtGD06LHzoG2RCevS3D78fTTZ1+cfyyfyHLvnH47v8dBUcROxa",
|
||||
"elements": [
|
||||
"wall-of-people-groups"
|
||||
],
|
||||
|
|
@ -1172,7 +1172,7 @@
|
|||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./wall-of-people-groups/wall-of-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-MiqAIjghH+xJybAqBA3/CgAHYxI/KhY0APyZynjmDOG+iDbg598tnXZ4oNPi5eQ3\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-RbbVrnoWTjZOuwmtGD06LHzoG2RCevS3D78fTTZ1+cfyyfyHLvnH47v8dBUcROxa\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
},
|
||||
"bundle": "wall-of-people-groups"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>research-map · doxa-research-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
|
||||
<script src="../doxa-research-map.js" integrity="sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-research-map.js" integrity="sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"profile":"research-map","dataSource":"pray-tools","instanceId":"doxa-research-map-research-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-research-map> custom element. -->
|
||||
<script src="../../doxa-research-map.js" integrity="sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-research-map.js" integrity="sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -46,7 +46,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"research-map","provider":"maplibre","instanceId":"research-map-maplibre"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Adoption Map · doxa-simple-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-simple-map","instanceId":"embed-adoption","dataSource":"pray-tools","tabs":[{"id":"adoption","colorStrategy":"adoption","legend":"adoption","popup":"adoption"}]};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Engagement Map · doxa-simple-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-simple-map","instanceId":"embed-engagement","dataSource":"pray-tools","tabs":[{"id":"engagement","colorStrategy":"engagement","legend":"engagement","popup":"engagement"}]};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>doxa-simple-map · doxa-simple-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../doxa-simple-map.js" integrity="sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5" crossorigin="anonymous"></script>
|
||||
<script src="../doxa-simple-map.js" integrity="sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"profile":"doxa-simple-map","dataSource":"pray-tools","instanceId":"doxa-simple-map-doxa-simple-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Prayer Map · doxa-simple-map</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <doxa-map> custom element. -->
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5" crossorigin="anonymous"></script>
|
||||
<script src="../../doxa-simple-map.js" integrity="sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-simple-map","instanceId":"embed-prayer","dataSource":"pray-tools","tabs":[{"id":"prayer","colorStrategy":"prayer","legend":"prayer","popup":"prayer"}]};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-vision-card","provider":"maplibre","instanceId":"vision-card-default"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"doxa-vision-card","provider":"maplibre","instanceId":"vision-card-frontier","accent":"#22d3ee","title":"The last frontier of the gospel.","tagline":"Frontier people groups: fewer than one person in a thousand is an evangelical believer."};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"doxa-vision-card","dataSource":"pray-tools","instanceId":"doxa-vision-card-doxa-vision-card","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"golden-path-check","dataSource":"pray-tools","instanceId":"golden-path-check-golden-path-check","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"charts","dataSource":"pray-tools","instanceId":"gospel-resources-charts","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"data-tables","dataSource":"pray-tools","instanceId":"gospel-resources-data-tables","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>gospel-dashboard · gospel-resources</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* SCROLL-PAGE leaf (cap-4 nested-elements-mfe composite: a StackLayout scroll-stack). The DOCUMENT
|
||||
owns the scroll — the element takes its content's NATURAL height and grows the page, so a reader
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -59,7 +60,11 @@
|
|||
var BASE_CONFIG = {"profile":"gospel-dashboard","dataSource":"pray-tools","instanceId":"gospel-resources-gospel-dashboard","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -45,7 +45,11 @@
|
|||
var BASE_CONFIG = {"profile":"resources-list","dataSource":"pray-tools","instanceId":"gospel-resources-resources-list","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = true;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = true || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -5,13 +5,14 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>resources-map · gospel-resources</title>
|
||||
<link rel="icon" href="data:,">
|
||||
<!-- Mapbox peer loaded ONCE here; the map custom element mounts in this page and
|
||||
uses window.mapboxgl directly (same realm → no cross-realm container errors). -->
|
||||
<link rel="preconnect" href="https://api.mapbox.com" crossorigin />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.css" rel="stylesheet" />
|
||||
<link href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.css" rel="stylesheet" />
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js"></script>
|
||||
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v5.0.0/mapbox-gl-geocoder.min.js"></script>
|
||||
<!-- NO STATIC ENGINE TAGS (2026-09-25). This leaf used to hard-link mapbox-gl.css, the
|
||||
geocoder css, mapbox-gl.js and the geocoder js from Mapbox's CDN, chosen at BUILD time —
|
||||
so a partner embedding it with ?provider=maplibre still sent every visitor's IP to Mapbox
|
||||
(4 requests per leaf, measured). The provider is chosen at RUNTIME (profile-config.provider
|
||||
→ ?provider= → window.MAP_PROVIDER → mapbox), and the element's own runtime loaders load
|
||||
exactly that engine: ensureEngineScript / ensureEngineCSS (useMapInstance) and the
|
||||
geocoder's on-demand loader — the path composite leaves already run on. Gate:
|
||||
check:leaf-engine-per-provider (0 Mapbox requests under maplibre; Mapbox unchanged). -->
|
||||
<style>
|
||||
/* BARE full-page map — no chrome. The custom element IS the page, so the
|
||||
browser URL shares the map itself. */
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
|
||||
<!-- Bundle IIFE — registers the <gospel-resources-map> custom element. -->
|
||||
<script src="../gospel-resources.js" integrity="sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
@ -48,7 +49,11 @@
|
|||
var BASE_CONFIG = {"pinHint":false,"profile":"resources-map","dataSource":"pray-tools","instanceId":"gospel-resources-resources-map","assetsBase":"../../assets"};
|
||||
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
|
||||
// the ladder below is skipped entirely and the element mounts immediately.
|
||||
var TOKEN_FREE = false;
|
||||
// …and a Mapbox leaf opened with provider=maplibre (config, ?provider= or window.MAP_PROVIDER —
|
||||
// the same ladder as resolveMapProvider) needs no Mapbox token either: without this, the public
|
||||
// copy (no baked token) asked a MapLibre visitor to paste a Mapbox token it would never use.
|
||||
var RUNTIME_PROVIDER = String((BASE_CONFIG && BASE_CONFIG.provider) || new URLSearchParams(location.search).get('provider') || window.MAP_PROVIDER || 'mapbox').toLowerCase();
|
||||
var TOKEN_FREE = false || RUNTIME_PROVIDER === 'maplibre';
|
||||
// A token-free COMPOSITE still nests plugins, and a nested Mapbox map reads window.MAP_TOKEN
|
||||
// rather than this page's profile-config. With no baked token (the public copy), it must get
|
||||
// one from ?tk= or a pasted token, or be asked for one — see the rungs below.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<plugin-studio tree-base="."></plugin-studio>
|
||||
<script src="./plugin-studio/plugin-studio.js"></script>
|
||||
<script src="./plugin-studio/plugin-studio.js" integrity="sha384-qsdqbZIAPpdz6SSiST+8VKvJ/WjM5RDq3lUZyAACcHgLD2p33VuW0hOoKb3lHmaX" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"bundle": "all-people-groups",
|
||||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"output": "dx-maps/all-people-groups/all-people-groups.js",
|
||||
"integrity": "sha384-rYegL22R5zloYSbRnP7eMaV7zFGGoRDQeX8sCSR2Kko/HSOq+N8q8i9YMyXZIOOx",
|
||||
"integrity": "sha384-/ccFZBqULYNTyH8CVTLvJk49YTUHp+swTlr+Pr8TKUiOUGlp3ZkaATMsivVY2cvm",
|
||||
"elements": [
|
||||
"all-people-groups"
|
||||
],
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
"scriptUrl": "./all-people-groups/all-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./all-people-groups/all-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-rYegL22R5zloYSbRnP7eMaV7zFGGoRDQeX8sCSR2Kko/HSOq+N8q8i9YMyXZIOOx\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-/ccFZBqULYNTyH8CVTLvJk49YTUHp+swTlr+Pr8TKUiOUGlp3ZkaATMsivVY2cvm\" crossorigin=\"anonymous\"></script>\n<all-people-groups profile-config='{\"profile\":\"all-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></all-people-groups>"
|
||||
},
|
||||
"bundle": "all-people-groups"
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
"bundle": "big-picture",
|
||||
"scriptUrl": "./big-picture/big-picture.js",
|
||||
"output": "dx-maps/big-picture/big-picture.js",
|
||||
"integrity": "sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo",
|
||||
"integrity": "sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ",
|
||||
"elements": [
|
||||
"bp-big-picture",
|
||||
"bp-research-header",
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
"scriptUrl": "./big-picture/big-picture.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./big-picture/big-picture/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-CaUw4BXi2ILBm6z80vT65HC5TSuDBz4pDGLJkTudRnUTQ0+erjMyPI59vIIwqkgo\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./big-picture/big-picture.js\" integrity=\"sha384-pmc+jltlmIQtPfiI/n9rmjWAZlRd3SVPkTUjJpbv8BNAKC+S6PHyS9Z4YqeIwolQ\" crossorigin=\"anonymous\"></script>\n<bp-big-picture profile-config='{\"profile\":\"big-picture\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></bp-big-picture>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
"bundle": "cities-internet",
|
||||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"output": "dx-maps/cities-internet/cities-internet.js",
|
||||
"integrity": "sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6",
|
||||
"integrity": "sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q",
|
||||
"elements": [
|
||||
"cities-internet-map"
|
||||
],
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -134,7 +134,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/connectivity-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"connectivity-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
"scriptUrl": "./cities-internet/cities-internet.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./cities-internet/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-13UbBfvZtguJ30gBZEAfoJW0A2wzKK+EROhBaV0O8IWEospdh46Dzv/ZX9iaZqB6\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./cities-internet/cities-internet.js\" integrity=\"sha384-oe5Qjt2dlESCJalca1hVKFBAdW7Rb7uNvKGqbPV7O6y7ENl/DQbPBetT1QWCyf/Q\" crossorigin=\"anonymous\"></script>\n<cities-internet-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></cities-internet-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
"bundle": "country-posters",
|
||||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"output": "dx-maps/country-posters/country-posters.js",
|
||||
"integrity": "sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam",
|
||||
"integrity": "sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K",
|
||||
"elements": [
|
||||
"country-posters-map"
|
||||
],
|
||||
|
|
@ -177,7 +177,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/countries-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"countries-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
"scriptUrl": "./country-posters/country-posters.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./country-posters/country-posters-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-PUvTc+iu/zGsUgPxWXfapwsx/8XAtcK4uMD3DNbXaR9S8Nlmi6cuSMCtg4piUpam\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./country-posters/country-posters.js\" integrity=\"sha384-BN+A0+SVeWPToWyQepi3w+PR9IjnwOLHXMqy8f4JbWr+8RdV3BPrcnP0xVl4MJ5K\" crossorigin=\"anonymous\"></script>\n<country-posters-map profile-config='{\"profile\":\"country-posters-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></country-posters-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -214,7 +214,7 @@
|
|||
"bundle": "dashboard-plus-grid",
|
||||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"output": "dx-maps/dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"integrity": "sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU",
|
||||
"integrity": "sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY",
|
||||
"elements": [
|
||||
"dashboard-plus-grid"
|
||||
],
|
||||
|
|
@ -234,7 +234,7 @@
|
|||
"scriptUrl": "./dashboard-plus-grid/dashboard-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./dashboard-plus-grid/dashboard-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-/E4UhCPqZAn+gwwHuwkLrLgbfrTwGp8x6tgsdDo/pqDHttv0z7Ln7r7wfPYSHSAU\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-L6zSKq1tvgdy6CLFedrkA+q9WdLdEtnwe2JCSZBHikYv82IakJTX4kRfkKe9ENIY\" crossorigin=\"anonymous\"></script>\n<dashboard-plus-grid profile-config='{\"profile\":\"dashboard-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></dashboard-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -258,7 +258,7 @@
|
|||
"bundle": "demo-map",
|
||||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"output": "dx-maps/demo-map/demo-map.js",
|
||||
"integrity": "sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9",
|
||||
"integrity": "sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5",
|
||||
"elements": [
|
||||
"demo-map"
|
||||
],
|
||||
|
|
@ -274,7 +274,7 @@
|
|||
"scriptUrl": "./demo-map/demo-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./demo-map/demo-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-4X6F3xHHkQVxQV21kz/HVqBo/m3nPGUSUn9j6DUUotRlFlfz1squbg7DDqcZiDX9\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./demo-map/demo-map.js\" integrity=\"sha384-Haee7iNIb9thxaf8kl/nSj54Kh9BxLLq53Ejqxrwqvq632KUcD7gPjuBUyK4GcW5\" crossorigin=\"anonymous\"></script>\n<demo-map profile-config='{\"profile\":\"demo-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></demo-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -353,7 +353,7 @@
|
|||
"bundle": "doxa-research-map",
|
||||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"output": "dx-maps/doxa-research-map/doxa-research-map.js",
|
||||
"integrity": "sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4",
|
||||
"integrity": "sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud",
|
||||
"elements": [
|
||||
"doxa-research-map"
|
||||
],
|
||||
|
|
@ -369,7 +369,7 @@
|
|||
"scriptUrl": "./doxa-research-map/doxa-research-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-research-map/research-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-/LViIVX7f9xWaikPXOdtRSXLe+C6n/bIAWQFgB8/vVd+QN+WiJ4jU54L+oIJ1mx4\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-alDD45j4eixYXWLXgLr3W7cI8mMeD9EYfGDRbKwAz6cWZvVJnvDcYHeB6Amdbnud\" crossorigin=\"anonymous\"></script>\n<doxa-research-map profile-config='{\"profile\":\"research-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-research-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -395,7 +395,7 @@
|
|||
"bundle": "doxa-simple-map",
|
||||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"output": "dx-maps/doxa-simple-map/doxa-simple-map.js",
|
||||
"integrity": "sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5",
|
||||
"integrity": "sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV",
|
||||
"elements": [
|
||||
"doxa-map",
|
||||
"doxa-simple-map"
|
||||
|
|
@ -412,7 +412,7 @@
|
|||
"scriptUrl": "./doxa-simple-map/doxa-simple-map.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./doxa-simple-map/doxa-simple-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-Qlv0r9IGekLSISzMMtpSegXxirVWDKPnpHDNd4MPDDKxoCx2mc47bK8+zRwyNJI5\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-8mHNJNaVauU3rqOlJvd01fPLAeJGsAxNPbLAeMDkkuMHoMhOSZk9dlJvfypnyhlV\" crossorigin=\"anonymous\"></script>\n<doxa-map profile-config='{\"profile\":\"doxa-simple-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-map>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv",
|
||||
"integrity": "sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0",
|
||||
"elements": [
|
||||
"gospel-resources-map"
|
||||
],
|
||||
|
|
@ -598,7 +598,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/charts/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"charts\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -612,7 +612,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/data-tables/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"data-tables\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -626,7 +626,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/gospel-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"gospel-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -640,7 +640,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -654,7 +654,7 @@
|
|||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./gospel-resources/resources-map/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-J6xm1TkN42QOH0olQWgHWvpkTKr1mLS4nBUfcGCTZjVtPrtl9bxOwTxpCstHu6Sv\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-ylcEho06EnCvuKpO8Vf/LPK89FRV7PVOm9zj/DplnBZUiAK9nUUVzoIF7mz83BH0\" crossorigin=\"anonymous\"></script>\n<gospel-resources-map profile-config='{\"profile\":\"resources-map\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-resources-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -663,7 +663,7 @@
|
|||
"bundle": "my-upg-100-list",
|
||||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"output": "dx-maps/my-upg-100-list/my-upg-100-list.js",
|
||||
"integrity": "sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0",
|
||||
"integrity": "sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA",
|
||||
"elements": [
|
||||
"my-upg-100-list-map"
|
||||
],
|
||||
|
|
@ -683,7 +683,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/poster-wall/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"poster-wall\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -697,7 +697,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -711,7 +711,7 @@
|
|||
"scriptUrl": "./my-upg-100-list/my-upg-100-list.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./my-upg-100-list/upg-100-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-ypq3JAEg5QuU9x47s4eDz/jssEwdPvpaAICFfd6i++dMqt7Vz1kHkGMwt3GQbVB0\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-MI5fm+7wJpXfJulZC4B0MCk5R9aXEBYO//AbllxU9NrP9GIJjMXAzEPLhRv1BEGA\" crossorigin=\"anonymous\"></script>\n<my-upg-100-list-map profile-config='{\"profile\":\"upg-100-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></my-upg-100-list-map>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -720,7 +720,7 @@
|
|||
"bundle": "people-groups-grid",
|
||||
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
|
||||
"output": "dx-maps/people-groups-grid/people-groups-grid.js",
|
||||
"integrity": "sha384-P36N4rI/QkK68QpPw1OHfxGIYeYfpr+1tX8Bxve+B98JfWFajRYKQeaRi5TgPVCU",
|
||||
"integrity": "sha384-NxK7wM4VhKnvgdeGmcwCcPGvNkQq4dZRXDkh8eUWhtcEuz4s7EFeQQjxA1PciJVt",
|
||||
"elements": [
|
||||
"people-groups-grid"
|
||||
],
|
||||
|
|
@ -736,7 +736,7 @@
|
|||
"scriptUrl": "./people-groups-grid/people-groups-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./people-groups-grid/people-groups-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-P36N4rI/QkK68QpPw1OHfxGIYeYfpr+1tX8Bxve+B98JfWFajRYKQeaRi5TgPVCU\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./people-groups-grid/people-groups-grid.js\" integrity=\"sha384-NxK7wM4VhKnvgdeGmcwCcPGvNkQq4dZRXDkh8eUWhtcEuz4s7EFeQQjxA1PciJVt\" crossorigin=\"anonymous\"></script>\n<people-groups-grid profile-config='{\"profile\":\"people-groups-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></people-groups-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -836,7 +836,7 @@
|
|||
"bundle": "pplr-data-maps",
|
||||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"output": "dx-maps/pplr-data-maps/pplr-data-maps.js",
|
||||
"integrity": "sha384-vFLNggTOuuot4RsQ+/aQBr0XRqBnYWt39zpKY8uksTBdfwAKChSc4yRnWha1QnNg",
|
||||
"integrity": "sha384-J2lpea95fPnplQ5HWhlWQXZV8Ht2YRQZMOOJTPzLqnt8hOSCfeKWBPBi2P9Z7jKp",
|
||||
"elements": [
|
||||
"pplr-data-maps"
|
||||
],
|
||||
|
|
@ -852,7 +852,7 @@
|
|||
"scriptUrl": "./pplr-data-maps/pplr-data-maps.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./pplr-data-maps/pplr-data-maps/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-vFLNggTOuuot4RsQ+/aQBr0XRqBnYWt39zpKY8uksTBdfwAKChSc4yRnWha1QnNg\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-J2lpea95fPnplQ5HWhlWQXZV8Ht2YRQZMOOJTPzLqnt8hOSCfeKWBPBi2P9Z7jKp\" crossorigin=\"anonymous\"></script>\n<pplr-data-maps profile-config='{\"profile\":\"pplr-data-maps\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></pplr-data-maps>"
|
||||
},
|
||||
"bundle": "pplr-data-maps"
|
||||
}
|
||||
|
|
@ -862,7 +862,7 @@
|
|||
"bundle": "prayer-walk-planner",
|
||||
"scriptUrl": "./prayer-walk-planner/prayer-walk-planner.js",
|
||||
"output": "dx-maps/prayer-walk-planner/prayer-walk-planner.js",
|
||||
"integrity": "sha384-R/ybjDe8VDmUbk7hl3Q6KApwLKwSs/8/zkzQVASWM9EpT5TwJpCxoLS33GSV9F8u",
|
||||
"integrity": "sha384-YZUFcXft7eTGJMY4I1FRak276dwfkSNFe6ylcWfRXJAmXWC39CCktE9qmNaZWSKB",
|
||||
"elements": [
|
||||
"prayer-walk-planner"
|
||||
],
|
||||
|
|
@ -878,7 +878,7 @@
|
|||
"scriptUrl": "./prayer-walk-planner/prayer-walk-planner.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./prayer-walk-planner/prayer-walk-planner/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-R/ybjDe8VDmUbk7hl3Q6KApwLKwSs/8/zkzQVASWM9EpT5TwJpCxoLS33GSV9F8u\" crossorigin=\"anonymous\"></script>\n<prayer-walk-planner profile-config='{\"profile\":\"prayer-walk-planner\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></prayer-walk-planner>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-YZUFcXft7eTGJMY4I1FRak276dwfkSNFe6ylcWfRXJAmXWC39CCktE9qmNaZWSKB\" crossorigin=\"anonymous\"></script>\n<prayer-walk-planner profile-config='{\"profile\":\"prayer-walk-planner\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></prayer-walk-planner>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -887,7 +887,7 @@
|
|||
"bundle": "regions-dashboard",
|
||||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"output": "dx-maps/regions-dashboard/regions-dashboard.js",
|
||||
"integrity": "sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe",
|
||||
"integrity": "sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS",
|
||||
"elements": [
|
||||
"regions-dashboard"
|
||||
],
|
||||
|
|
@ -907,7 +907,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/region-dashboards/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"region-dashboards\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -921,7 +921,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-list/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-list\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -935,7 +935,7 @@
|
|||
"scriptUrl": "./regions-dashboard/regions-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./regions-dashboard/regions-mfe/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-AvAt5NgJ8d7qbA/1XnP7iLV6QzQfZKoADIZZ306UXxUsToqmZEgTkgQbgoE/SfHe\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-OKFjJQTTdflW1NbNUAdEXFIdQTPwbvrlj9+qUjiFkHKBkuUzCNxbk/zG8dYODZYS\" crossorigin=\"anonymous\"></script>\n<regions-dashboard profile-config='{\"profile\":\"regions-mfe\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></regions-dashboard>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -944,7 +944,7 @@
|
|||
"bundle": "research-dashboard",
|
||||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"output": "dx-maps/research-dashboard/research-dashboard.js",
|
||||
"integrity": "sha384-8HH1SOeixTcwk2j0Ldl9wLhAt+tLlOucxdVjn7KNyLrYIcB4WlI9J7pzwm3n5KFo",
|
||||
"integrity": "sha384-QKWWr/gy1T9mh5pwVoPuaeE8pWW6GPXDi4L0HLj1S+scQibD9F6ilApWLa6cNNoY",
|
||||
"elements": [
|
||||
"research-dashboard-map"
|
||||
],
|
||||
|
|
@ -960,7 +960,7 @@
|
|||
"scriptUrl": "./research-dashboard/research-dashboard.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-dashboard/research-dashboard/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-8HH1SOeixTcwk2j0Ldl9wLhAt+tLlOucxdVjn7KNyLrYIcB4WlI9J7pzwm3n5KFo\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-QKWWr/gy1T9mh5pwVoPuaeE8pWW6GPXDi4L0HLj1S+scQibD9F6ilApWLa6cNNoY\" crossorigin=\"anonymous\"></script>\n<research-dashboard-map profile-config='{\"profile\":\"research-dashboard\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-dashboard-map>"
|
||||
},
|
||||
"bundle": "research-dashboard"
|
||||
}
|
||||
|
|
@ -970,7 +970,7 @@
|
|||
"bundle": "research-map-plus-grid",
|
||||
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
|
||||
"output": "dx-maps/research-map-plus-grid/research-map-plus-grid.js",
|
||||
"integrity": "sha384-XOGLrOs4KZCfyXMDB8SIkx3wrxUfxk84xJkHsYSvZ83GXFjvb4ut8FT89zCgbTg5",
|
||||
"integrity": "sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2",
|
||||
"elements": [
|
||||
"research-map-plus-grid"
|
||||
],
|
||||
|
|
@ -990,7 +990,7 @@
|
|||
"scriptUrl": "./research-map-plus-grid/research-map-plus-grid.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./research-map-plus-grid/research-map-plus-grid/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-XOGLrOs4KZCfyXMDB8SIkx3wrxUfxk84xJkHsYSvZ83GXFjvb4ut8FT89zCgbTg5\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./research-map-plus-grid/research-map-plus-grid.js\" integrity=\"sha384-N12PTsk2HVN2Uh9nhF1R74uZ8+YO1nz92CqD+wlWhq5D+dKdaGy7BUr5QwaHg9C2\" crossorigin=\"anonymous\"></script>\n<research-map-plus-grid profile-config='{\"profile\":\"research-map-plus-grid\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></research-map-plus-grid>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1058,7 +1058,7 @@
|
|||
"bundle": "upg-neighbor",
|
||||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"output": "dx-maps/upg-neighbor/upg-neighbor.js",
|
||||
"integrity": "sha384-eNZc5rM+EukmMqMxnjnLseMukVmEgdIt4q0N7l7PXYIsNCPLxR4ePkML9D82gdIQ",
|
||||
"integrity": "sha384-c1C0pPxaVk9S8fnp0TVhct1wr0Rv5Dv+yFHWZ3sKl+hlbhrzukmE9YXRc2iG0M4D",
|
||||
"elements": [
|
||||
"upg-neighbor"
|
||||
],
|
||||
|
|
@ -1074,7 +1074,7 @@
|
|||
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./upg-neighbor/upg-neighbor/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-eNZc5rM+EukmMqMxnjnLseMukVmEgdIt4q0N7l7PXYIsNCPLxR4ePkML9D82gdIQ\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
"script": "<!-- Mapbox engine, fetched early; remove this line if you set \"provider\":\"maplibre\" -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-c1C0pPxaVk9S8fnp0TVhct1wr0Rv5Dv+yFHWZ3sKl+hlbhrzukmE9YXRc2iG0M4D\" crossorigin=\"anonymous\"></script>\n<upg-neighbor profile-config='{\"profile\":\"upg-neighbor\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></upg-neighbor>"
|
||||
},
|
||||
"instances": [
|
||||
{
|
||||
|
|
@ -1156,7 +1156,7 @@
|
|||
"bundle": "wall-of-people-groups",
|
||||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"output": "dx-maps/wall-of-people-groups/wall-of-people-groups.js",
|
||||
"integrity": "sha384-MiqAIjghH+xJybAqBA3/CgAHYxI/KhY0APyZynjmDOG+iDbg598tnXZ4oNPi5eQ3",
|
||||
"integrity": "sha384-RbbVrnoWTjZOuwmtGD06LHzoG2RCevS3D78fTTZ1+cfyyfyHLvnH47v8dBUcROxa",
|
||||
"elements": [
|
||||
"wall-of-people-groups"
|
||||
],
|
||||
|
|
@ -1172,7 +1172,7 @@
|
|||
"scriptUrl": "./wall-of-people-groups/wall-of-people-groups.js",
|
||||
"embed": {
|
||||
"iframe": "<iframe src=\"./wall-of-people-groups/wall-of-people-groups/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>",
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-MiqAIjghH+xJybAqBA3/CgAHYxI/KhY0APyZynjmDOG+iDbg598tnXZ4oNPi5eQ3\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./wall-of-people-groups/wall-of-people-groups.js\" integrity=\"sha384-RbbVrnoWTjZOuwmtGD06LHzoG2RCevS3D78fTTZ1+cfyyfyHLvnH47v8dBUcROxa\" crossorigin=\"anonymous\"></script>\n<wall-of-people-groups profile-config='{\"profile\":\"wall-of-people-groups\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></wall-of-people-groups>"
|
||||
},
|
||||
"bundle": "wall-of-people-groups"
|
||||
}
|
||||
|
|
|
|||