Never hand a keyless page the engine that needs a token
resources-map resolved its engine as `engineGlobal(provider) || window.mapboxgl`. engineGlobal already defaults to mapbox, so that fallback could only ever fire for provider 'maplibre' — and then it returned MAPBOX. A page that chose the keyless engine silently got the one that needs a token, and because the profile only assigns accessToken when the provider is not maplibre, the substitute had no token either: it would have 401'd on every tile. The fix is the deletion. The requested engine or a named failure, with a console warning for whoever is debugging and the reader's line through messages.* (English kept inline until the key lands). check:engine-contract measures it: two providers across engine present, engine blocked and both blocked, with the CDN blocked by request routing the way a proxy or an offline kiosk does it. Three of those six arms first failed for reasons that were mine, not the product's, and each is written down in the gate: Mapbox cannot mount at all on a static tree without a token, 11s was not long enough for a leaf that fetches 4 MB before the map exists, and engine attribution read from a debug handle scored Mapbox-with-a-bad-token as "engine null" — the canvas class cannot lie about who drew it. Also in this landing: the pin caveat is translated in 11 locales from the shared pins.* area, read through this leaf's own guarded t() rather than by mounting library ApproxPinNote.vue — that component calls useI18n() unguarded, and this bundle is embeddable in hosts that never called app.use(i18n), where an unguarded call throws during setup and the shadow boundary swallows it. Same wording either way. Both "Show all groups" buttons now use the key that already exists in 11 locales, and the engine's own control labels get the provider arm.
This commit is contained in:
parent
56c2da26c5
commit
5739818ecc
11 changed files with 247 additions and 55 deletions
160
internal/check-gospel-engine-contract.mjs
Normal file
160
internal/check-gospel-engine-contract.mjs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* check-gospel-engine-contract.mjs — the map must use the engine it was ASKED for, or say nothing
|
||||
* at all. Never a different one.
|
||||
*
|
||||
* THE DEFECT THIS IS WRITTEN AGAINST (regions' C3 read + upg100's addendum, 2026-09-26).
|
||||
* resources-map resolved its engine as `engineGlobal(provider) || window.mapboxgl`. engineGlobal
|
||||
* already defaults to mapbox, so that fallback could only fire for provider 'maplibre' — and then
|
||||
* it returned MAPBOX. A page that chose the keyless engine silently got the one that needs a
|
||||
* token; and since the profile only assigns accessToken when the provider is not maplibre, the
|
||||
* substitute had no token either, so it would 401 on every tile. Two failures compounding, both
|
||||
* invisible to every other gate: the leaf mounts, renders and logs no console error.
|
||||
*
|
||||
* SIX MEASUREMENTS: two providers x three load states.
|
||||
* engine present -> a canvas, drawn by the engine that was asked for
|
||||
* engine blocked -> NO canvas, a visible message naming that engine, and — the assertion
|
||||
* that matters — the OTHER engine's global must not be the one in use
|
||||
* both blocked -> same, and never a blank with nothing said
|
||||
*
|
||||
* The CDN script is blocked with request routing rather than by editing anything: that is exactly
|
||||
* what a corporate proxy, an offline kiosk or a broken CDN does to a partner's embed.
|
||||
*
|
||||
* Self-test: `--poison` restores the old `|| window.mapboxgl` behaviour in the page (by defining
|
||||
* window.mapboxgl before the bundle runs while maplibre is blocked) and requires the maplibre arm
|
||||
* to FAIL — if it passes, this check cannot see the defect it exists for.
|
||||
*/
|
||||
import { chromium } from 'playwright'
|
||||
import { serveReaped } from './_serve-reaped.mjs'
|
||||
import { resolve, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { TREE_NAME } from './_tree-name.mjs'
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url))
|
||||
const PUBLIC = resolve(HERE, '../public')
|
||||
const PORT = Number(process.env.PORT || 5395)
|
||||
const BASE = process.env.BASE_URL || `http://127.0.0.1:${PORT}`
|
||||
const POISON = process.argv.includes('--poison')
|
||||
const TAG = 'gospel-resources-map'
|
||||
const LEAF = `${BASE}/${TREE_NAME}/gospel-resources/resources-map/index.html`
|
||||
const SCRIPT = { mapbox: /mapbox-gl.*\.js/i, maplibre: /maplibre-gl.*\.js/i }
|
||||
|
||||
let srv = null
|
||||
if (!process.env.BASE_URL) srv = serveReaped(PUBLIC, PORT)
|
||||
|
||||
const run = async (browser, provider, block) => {
|
||||
const page = await browser.newPage({ viewport: { width: 1200, height: 800 } })
|
||||
const warns = [], errors = []
|
||||
page.on('console', (m) => { if (m.type() === 'warning' || m.type() === 'error') warns.push(m.text().slice(0, 200)) })
|
||||
page.on('pageerror', (e) => errors.push(String(e).slice(0, 200)))
|
||||
for (const b of block) await page.route(SCRIPT[b], (r) => r.abort())
|
||||
/* ⚠ MAPBOX CANNOT EVEN MOUNT WITHOUT A TOKEN, and that is the environment, not the product: a
|
||||
static tree has no /api/maps/token, so the profile loader never renders the element and the
|
||||
first version of this check read that as "the leaf did not mount". A dummy token gets the
|
||||
element on the page; its tiles 401, which is irrelevant here — this check is about WHICH
|
||||
engine was constructed, and Mapbox GL creates its canvas either way. */
|
||||
if (provider === 'mapbox') await page.addInitScript(() => { window.MAP_TOKEN = 'pk.test.not-a-real-token' })
|
||||
await page.goto(`${LEAF}?provider=${provider}`, { waitUntil: 'domcontentloaded', timeout: 60000 })
|
||||
/* 20s, not 11: this leaf fetches ~4 MB of tables before the map exists, and at 11s three of
|
||||
six runs were still showing the profile loader — the gate was measuring its own impatience. */
|
||||
await page.waitForTimeout(20000)
|
||||
const r = await page.evaluate((tag) => {
|
||||
const sr = document.querySelector(tag)?.shadowRoot
|
||||
const txt = sr ? (sr.textContent || '').replace(/\s+/g, ' ').trim() : ''
|
||||
return {
|
||||
mounted: !!sr,
|
||||
canvas: !!sr?.querySelector('canvas'),
|
||||
text: txt.slice(0, 600),
|
||||
/* The leaf's own error line. Reading the whole shadow text instead caught the stylesheet —
|
||||
".profile-loader .profile-error" — and scored a rendered message as a blank. */
|
||||
errText: (sr?.querySelector('.gm-err')?.textContent || '').trim(),
|
||||
/* WHICH global is actually present on the page — the substitution is invisible in the DOM. */
|
||||
hasMapbox: !!window.mapboxgl,
|
||||
hasMaplibre: !!window.maplibregl,
|
||||
/* WHICH ENGINE DREW IT, read off the canvas's own class — each engine stamps its name
|
||||
(.mapboxgl-canvas / .maplibregl-canvas). Read from window.__grMap first, this scored
|
||||
Mapbox-with-a-dummy-token as "engine null": the canvas exists, the style 401s, and the
|
||||
debug handle is never assigned. The canvas cannot lie about who created it. */
|
||||
engineOfMap: (() => {
|
||||
const c = sr?.querySelector('canvas')
|
||||
const cls = c ? c.className || '' : ''
|
||||
if (/maplibregl/.test(cls)) return 'maplibre'
|
||||
if (/mapboxgl/.test(cls)) return 'mapbox'
|
||||
const m = window.__grMap
|
||||
if (m && window.maplibregl && m instanceof window.maplibregl.Map) return 'maplibre'
|
||||
if (m && window.mapboxgl && m instanceof window.mapboxgl.Map) return 'mapbox'
|
||||
return c ? 'unknown' : null
|
||||
})(),
|
||||
}
|
||||
}, TAG)
|
||||
await page.close()
|
||||
return { ...r, warns, errors }
|
||||
}
|
||||
|
||||
const fails = []
|
||||
|
||||
/* ═══ THE STATIC ARM, AND WHY THE SELF-TEST LIVES HERE ════════════════════════════════════════
|
||||
* The six runtime measurements are the behavioural evidence, but they cannot be made to fail on
|
||||
* demand: with the fallback deleted, planting a substitute engine on the PAGE proves nothing —
|
||||
* the leaf correctly ignores it, so the arms pass and a --poison that expected a failure was
|
||||
* asserting the wrong thing (measured: it reported "this check cannot see the defect", about
|
||||
* itself). The defect is a line of SOURCE, so the falsifiable arm reads the source. */
|
||||
const LEAF_SRC = resolve(HERE, '../plugin-designs/gospel-resources/resources-map.vue')
|
||||
let src = readFileSync(LEAF_SRC, 'utf8')
|
||||
if (POISON) src = src.replace('const gl = engineGlobal(grProvider)\n', 'const gl = engineGlobal(grProvider) || window.mapboxgl\n')
|
||||
/* COMMENTS STRIPPED FIRST. The fix's own comment QUOTES the deleted line — "this used to read
|
||||
`engineGlobal(grProvider) || window.mapboxgl`" — and the first version of this arm read that
|
||||
quotation as the defect, failing the very commit that removed it. A gate that cannot tell code
|
||||
from prose about code will keep flagging the explanation forever. */
|
||||
const code = src.replace(/\/\*[\s\S]*?\*\//g, ' ').replace(/(^|[^:'"\\])\/\/[^\n]*/g, '$1')
|
||||
const BAD = /engineGlobal\([^)]*\)\s*\|\|/
|
||||
if (BAD.test(code)) {
|
||||
fails.push('resources-map.vue falls back from engineGlobal() to another engine global — a page that asked for the keyless engine would silently get the one that needs a token')
|
||||
}
|
||||
if (POISON) {
|
||||
if (!fails.length) { console.error('ENGINE-CONTRACT --poison: the reintroduced `|| window.mapboxgl` was NOT caught — this check cannot see the defect it exists for.'); process.exit(1) }
|
||||
console.log(`ENGINE-CONTRACT --poison: caught it — ${fails[0]}`)
|
||||
console.log('ENGINE-CONTRACT: SELF-TEST PASS — the static arm fails as designed. The six runtime measurements are not re-run here; they cannot be forced to fail without reintroducing the defect in a built bundle.')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
let browser
|
||||
try {
|
||||
browser = await chromium.launch()
|
||||
for (const provider of ['mapbox', 'maplibre']) {
|
||||
/* 1 — the engine is there. It must be the one asked for. */
|
||||
const ok = await run(browser, provider, [])
|
||||
if (!ok.mounted) fails.push(`${provider}/present: the leaf did not mount — errors: ${ok.errors.join(' | ') || 'none'}; warns: ${ok.warns.slice(0,2).join(' | ')}`)
|
||||
else if (!ok.canvas) fails.push(`${provider}/present: no canvas — the map did not draw`)
|
||||
else if (ok.engineOfMap !== provider && ok.engineOfMap !== 'unknown') fails.push(`${provider}/present: the map instance came from ${ok.engineOfMap}`)
|
||||
else console.log(` ok ${provider}/present`.padEnd(30) + `canvas, engine=${ok.engineOfMap}`)
|
||||
|
||||
/* 2 — the engine is blocked. Visible failure, and NEVER the other engine. */
|
||||
const gone = await run(browser, provider, [provider])
|
||||
const other = provider === 'maplibre' ? 'mapbox' : 'maplibre'
|
||||
if (!gone.mounted) fails.push(`${provider}/blocked: the leaf did not mount at all — a missing engine must not kill the element`)
|
||||
else if (gone.canvas) fails.push(`${provider}/blocked: a canvas was drawn with ${provider} blocked — something else drew it (engine=${gone.engineOfMap})`)
|
||||
else if (gone.engineOfMap === other) fails.push(`${provider}/blocked: the map was built from ${other} — a page that asked for ${provider} got the other engine`)
|
||||
else if (!/did not load|engine/i.test(gone.errText)) fails.push(`${provider}/blocked: nothing on screen says the engine failed — the reader gets a blank (.gm-err reads "${gone.errText}")`)
|
||||
else if (!gone.warns.some((w) => /engine global never loaded/.test(w))) fails.push(`${provider}/blocked: no console warning naming the engine`)
|
||||
else console.log(` ok ${provider}/blocked`.padEnd(30) + 'no canvas, names the engine, no substitution')
|
||||
|
||||
/* 3 — neither engine can load. */
|
||||
const both = await run(browser, provider, ['mapbox', 'maplibre'])
|
||||
if (!both.mounted) fails.push(`${provider}/both-blocked: the leaf did not mount`)
|
||||
else if (both.canvas) fails.push(`${provider}/both-blocked: a canvas appeared with both engines blocked`)
|
||||
else if (!/did not load|engine/i.test(both.errText)) fails.push(`${provider}/both-blocked: a blank with nothing said`)
|
||||
else console.log(` ok ${provider}/both-blocked`.padEnd(30) + 'no canvas, message shown')
|
||||
}
|
||||
|
||||
if (fails.length) {
|
||||
console.error(`ENGINE-CONTRACT: FAIL — ${fails.length} of 6 measurement(s):`)
|
||||
for (const f of fails) console.error(` ${f}`)
|
||||
process.exit(1)
|
||||
}
|
||||
console.log('ENGINE-CONTRACT: PASS — the source keeps no cross-engine fallback, and 2 providers x 3 load states: the engine asked for or a named failure, never a substitute.')
|
||||
} finally {
|
||||
try { await browser?.close() } catch (_) {}
|
||||
try { srv?.close?.() } catch (_) {}
|
||||
}
|
||||
process.exit(0)
|
||||
|
|
@ -89,6 +89,8 @@
|
|||
"check:gospel-all": "node internal/check-gospel-all.mjs",
|
||||
"check:gospel-tables-staged": "node internal/check-gospel-tables-staged.mjs",
|
||||
"check:embed-contract": "node internal/check-gospel-embed-contract.mjs",
|
||||
"check:engine-contract": "node internal/check-gospel-engine-contract.mjs",
|
||||
"check:engine-contract:poison": "node internal/check-gospel-engine-contract.mjs --poison",
|
||||
"check:embed-contract:poison": "node internal/check-gospel-embed-contract.mjs --poison",
|
||||
"check:map-attribution": "node internal/check-map-attribution.mjs",
|
||||
"check:studio-rail": "node internal/check-studio-rail.mjs",
|
||||
|
|
@ -370,6 +372,7 @@
|
|||
"check:studio-rail": "the Plugin Studio rail is laid out like plugin-designs/: one folder per bundle with its elements inside, bundles in the section of their highest capability (5 \u2192 1) and in name order, one canonical node per plugin. Runs the studio's real rail code on the built manifest, headless.",
|
||||
"check:translator-contacts": "the credit line LINKS the translating organisation now, and a contact URL is a link this map stands behind. Reads ALLOWED_CONTACT out of internal/verify-gospel-map.mjs rather than restating it (two copies of an allowlist drift, and the drifting copy is the one nobody reads), then asserts every cr.u is on that list, was recorded `verified` by a real fetch, is never also serving a RESOURCE (wycliffe.org is somewhere to write to, not a publisher this map reads text from), and is actually RENDERED as an anchor \u2014 the data can carry 838 URLs while the template shows none. Static, sub-second. Self-test: `bun run check:translator-contacts:poison`.",
|
||||
"check:embed-contract": "the map's URL is a PUBLIC INTERFACE: a partner embeds ?codes=<iso3 list>, ?country=<ISO3> or ?view=zero in an iframe and never touches it again. A refactor breaks those links SILENTLY \u2014 the leaf still mounts, renders and logs no errors, it just shows the whole world to a church that asked for its forty groups. Asserts through the reader's eyes (the partner-list notice's two numbers), with both numbers and the probe codes derived from the roster the leaf itself reads, never typed in. Browser gate; needs no server of its own. Self-test: `bun run check:embed-contract:poison`.",
|
||||
"check:engine-contract": "the map must use the engine it was ASKED for or fail VISIBLY \u2014 never a substitute. resources-map read `engineGlobal(provider) || window.mapboxgl`; engineGlobal already defaults to mapbox, so that could only fire for provider 'maplibre' and then returned MAPBOX \u2014 a keyless page silently handed the engine that needs a token, which the profile then does not give it, so its tiles 401. Invisible to every other gate: the leaf mounts, renders and logs nothing. Six runtime measurements (2 providers x engine present / blocked / both blocked, CDN blocked by request routing the way a proxy or an offline kiosk does) plus a static arm on the source, comments stripped so the fix's own quotation of the deleted line is not read as the defect. Mapbox arms inject a dummy MAP_TOKEN, because without one the element never mounts on a static tree and that is the environment, not the product. Engine attribution is read off the canvas class, not a debug handle. Browser gate. Self-test: `bun run check:engine-contract:poison`.",
|
||||
"check:snapshot-guard": "every gospel-resources catalogue fetcher must write through scripts/_snapshot-guard.mjs, which refuses a write that loses more than a tenth of the previous snapshot. Written after a rate-limited FCBH run silently replaced 1,666 video scopes with 1,103. Static, sub-second. Self-test: `bun run check:snapshot-guard:poison` injects a raw write and the check must fail on it.",
|
||||
"check:spa-tab-order": "the cap-5 SPA must open on Big Picture and keep the Driver's order (Big Picture, UPG-100, Prayer Progress, Gospel Resources) — asserted as PRESENCE + tab-1 + RELATIVE order on the RENDERED rail, because the rail gained three sections and now renders 12 rows with others between them. ⚠ NOT WAVE-WIRED: it FAILS rather than skips when the SPA is unreachable, deliberately (\"a gate that cannot reach its subject has not passed, it has not run\") — correct standalone, but gates:post runs on checkouts with no server. Needs `bun run serve` on 4173.",
|
||||
"check:stale-sweep-claim": "a caveat that has stopped being true is a wrong number. The gospel surfaces carry a paragraph saying which pools were searched; while the GRN sweep ran they truthfully said part of it was unread, the sweep finished, and the sentence stayed for four more commits. The DATA decides here: undecided gap codes mean the claim is allowed, all-decided means it must go, so it re-arms itself for the next slow pool. Does NOT flag a claim rendered under a v-if on the pending count — that form expires on its own. Self-test: `--poison`. Static, sub-second.",
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ import LocationButton from '@map/components/map-controls/LocationButton.vue'
|
|||
import FullscreenButton from '@map/components/map-controls/FullscreenButton.vue'
|
||||
import ShareButton from '@map/components/map-controls/ShareButton.vue'
|
||||
import { resolveAssetsBase } from '@map/utils/embedBase.js'
|
||||
import { resolveMapProvider } from '@map/composables/useMapProvider.js'
|
||||
import { resolveMapProvider, providerLabel } from '@map/composables/useMapProvider.js'
|
||||
import { ensureEngineScript, engineGlobal, engineStylesheetUrl, ensureEngineCSS } from '@map/composables/useMapInstance.js'
|
||||
import { installRtlTextPlugin } from '@map/maps/rtl-text.js'
|
||||
import { resolveNamedStyle } from '@map/styles/registry.js'
|
||||
|
|
@ -782,12 +782,23 @@ const pinsByIso = computed(() => {
|
|||
/* The fallback resolves against the SHIPPED ENGLISH CATALOG (imported at the top), not the
|
||||
key. Returning the last dot-segment would have put "gap" and "deathsDay" on screen — a
|
||||
broken-looking label is not graceful degradation, it just moves the bug. */
|
||||
/* Walks from the ROOT of the catalogue, not from its gospel subtree: this leaf now also reads
|
||||
`pins.*`, the shared people-group-pin wording, and an area-blind lookup would have fallen back
|
||||
to the key name for every one of those on a host with no i18n. */
|
||||
const enLookup = (key) =>
|
||||
String(key).replace(/^gospel\./, '').split('.').reduce((o, k) => (o == null ? o : o[k]), EN_MESSAGES.gospel || {})
|
||||
let t = (key) => enLookup(key) ?? String(key)
|
||||
String(key).split('.').reduce((o, k) => (o == null ? o : o[k]), EN_MESSAGES || {})
|
||||
/* The fallback interpolates too. vue-i18n does it for the translated path; without this the
|
||||
English arm would render "{names} — {n} groups share…" literally. */
|
||||
const fill = (str, params) => (params
|
||||
? String(str).replace(/\{(\w+)\}/g, (m, k) => (params[k] == null ? m : String(params[k])))
|
||||
: str)
|
||||
let t = (key, params) => fill(enLookup(key) ?? String(key), params)
|
||||
try {
|
||||
const i18n = useI18n()
|
||||
t = (key) => { const v = i18n.t(key); return v === key ? (enLookup(key) ?? key) : v }
|
||||
t = (key, params) => {
|
||||
const v = params ? i18n.t(key, params) : i18n.t(key)
|
||||
return v === key ? fill(enLookup(key) ?? key, params) : v
|
||||
}
|
||||
} catch (_) { /* no i18n on this host: the English catalog above is the fallback */ }
|
||||
/* Whether to show the "these notes are in English" line at all. Read from the same i18n
|
||||
instance the labels come from, so the two can never disagree. */
|
||||
|
|
@ -803,7 +814,10 @@ const readerLang = () => {
|
|||
t() falls back to the key when a catalogue has no entry, which on a `title` attribute would
|
||||
put "gospel.legend.hnrTip" in a tooltip: worse than the English it replaced. This keeps the
|
||||
English in the template until the key lands, and switches the moment it does. */
|
||||
const tOr = (key, english) => { const v = t(key); return v && v !== key ? v : english }
|
||||
const tOr = (key, english, params) => {
|
||||
const v = t(key, params)
|
||||
return v && v !== key ? v : fill(english, params)
|
||||
}
|
||||
|
||||
const SE_KIND = { PDF: 'PDF', audio: 'audio', sab: 'app', study: 'study notes', viewer: 'read online' }
|
||||
const seKinds = (k) => (Array.isArray(k) ? k : []).map((x) => SE_KIND[x] || x).join(', ')
|
||||
|
|
@ -1487,8 +1501,21 @@ onMounted(async () => {
|
|||
/* Re-check after the await: this leaf can be unmounted mid-initialise, which is the race
|
||||
that produced "Cannot read properties of null" across the fleet. */
|
||||
if (!mapEl.value) return
|
||||
const gl = engineGlobal(grProvider) || window.mapboxgl
|
||||
if (!gl || !mapEl.value) { err.value = 'map engine not loaded'; return }
|
||||
/* ⚠ NEVER SWITCH ENGINES SILENTLY (regions' C3 read, 2026-09-26). This used to read
|
||||
`engineGlobal(grProvider) || window.mapboxgl`. engineGlobal already defaults to mapbox, so
|
||||
the fallback could only ever fire for provider 'maplibre' — and then it handed back MAPBOX:
|
||||
a page that chose the keyless engine got the one that needs a token, which breaks the
|
||||
keyless contract silently, with a map that looks fine until the token is missing. The
|
||||
requested engine or a visible failure; never a different engine. */
|
||||
const gl = engineGlobal(grProvider)
|
||||
if (!gl) {
|
||||
/* The console line stays English on purpose — it is for whoever is debugging the page, not
|
||||
for the reader. The line the READER sees goes through the catalogue. */
|
||||
console.warn(`[gospel-resources] the ${grProvider} engine global never loaded — refusing to substitute another engine, because that would hand a keyless page the engine that needs a token.`)
|
||||
err.value = tOr('messages.engineMissing', 'The {engine} map engine did not load.', { engine: providerLabel(grProvider) })
|
||||
return
|
||||
}
|
||||
if (!mapEl.value) return
|
||||
/**
|
||||
* ═══ ARABIC, HEBREW AND PERSIAN PLACE NAMES NEED A SHAPER ═══════════════════════════════
|
||||
*
|
||||
|
|
@ -1525,7 +1552,7 @@ onMounted(async () => {
|
|||
the locale map the shared composable passes — "Toggle attribution" and the canvas's
|
||||
accessible name "Map" stayed English under ar while every string we own was Arabic.
|
||||
Set at construction because that is the only time either engine reads it. */
|
||||
locale: engineUiLocale(readerLang()),
|
||||
locale: engineUiLocale(readerLang(), grProvider),
|
||||
/* A starting zoom is a guess about the canvas. It was 1.3, which framed the world
|
||||
while this leaf was running WITHOUT the engine's stylesheet; once mapbox-gl.css
|
||||
reached the shadow root the canvas sized correctly and the same 1.3 cut the visible
|
||||
|
|
@ -2337,14 +2364,16 @@ useShadowStyles(
|
|||
of the 2,107 placed groups sit on a coordinate they share with another group. Where
|
||||
this one does, it names them, because "approximate" on its own hides the part a
|
||||
reader would never otherwise discover — that some dots are literally the same dot.
|
||||
English prose in a dir="ltr" block, per the standing decision on caveats. -->
|
||||
<p class="gm-note" dir="ltr" style="margin:6px 0 0">
|
||||
The dot marks where this people is found, not a town or a boundary.
|
||||
TRANSLATED NOW, in 11 locales, from the shared pins.* area (APPROXPIN). Read through
|
||||
this leaf's own guarded t() rather than by mounting library ApproxPinNote.vue, which
|
||||
calls useI18n() unguarded: this bundle is embeddable in hosts that never called
|
||||
app.use(i18n), where that throws during setup and the shadow boundary swallows it —
|
||||
the failure that blanked a production plugin once already. Same wording either way;
|
||||
it is this map's P5 proposal that became the library's. -->
|
||||
<p class="gm-note" :dir="isEnglish ? 'ltr' : null" style="margin:6px 0 0">
|
||||
{{ t('pins.approximate') }}
|
||||
<template v-if="sharedWith(selectedGroup).length">
|
||||
It sits on the same point as
|
||||
<b>{{ sharedWith(selectedGroup).join(', ') }}</b> — {{ sharedWith(selectedGroup).length + 1 }}
|
||||
groups share this coordinate, so the position tells you the locality and not which
|
||||
group is where.
|
||||
{{ t('pins.sharedPoint', { names: sharedWith(selectedGroup).join(', '), n: sharedWith(selectedGroup).length + 1 }) }}
|
||||
</template>
|
||||
</p>
|
||||
|
||||
|
|
@ -2882,7 +2911,7 @@ useShadowStyles(
|
|||
</div>
|
||||
<div v-if="withResources.length > shown" class="gm-more">
|
||||
Showing {{ shown }} of {{ withResources.length }}.
|
||||
<button type="button" class="gm-back" @click="shown = withResources.length">Show all groups</button>
|
||||
<button type="button" class="gm-back" @click="shown = withResources.length">{{ t('gospel.legend.showAll') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -2903,7 +2932,7 @@ useShadowStyles(
|
|||
</button>
|
||||
<div v-if="withoutResources.length > shown" class="gm-more">
|
||||
Showing {{ shown }} of {{ withoutResources.length }}.
|
||||
<button type="button" class="gm-back" @click="shown = withoutResources.length">Show all groups</button>
|
||||
<button type="button" class="gm-back" @click="shown = withoutResources.length">{{ t('gospel.legend.showAll') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ",
|
||||
"integrity": "sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal",
|
||||
"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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -32,7 +32,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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -32,7 +32,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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -47,7 +47,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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -32,7 +32,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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ" crossorigin="anonymous"></script>
|
||||
<script src="../gospel-resources.js" integrity="sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
// Mapbox token resolution — the A3 ladder, in precedence order:
|
||||
|
|
|
|||
|
|
@ -578,7 +578,7 @@
|
|||
"bundle": "gospel-resources",
|
||||
"scriptUrl": "./gospel-resources/gospel-resources.js",
|
||||
"output": "dx-maps/gospel-resources/gospel-resources.js",
|
||||
"integrity": "sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ",
|
||||
"integrity": "sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal",
|
||||
"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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-X4sMagTlYeIE0b9d5v4Qaq2BLQ9VQJ7hKVsrJsdiTpBzmjjm+ft6/CmSh0bkbypJ\" 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. Keep it only with a real Mapbox token in \"tk\": without one (or with \"provider\":\"maplibre\") the map draws with MapLibre and this line must go -->\n<link rel=\"preload\" as=\"script\" href=\"https://api.mapbox.com/mapbox-gl-js/v3.24.0/mapbox-gl.js\" integrity=\"sha384-tO0clamXONKwbiz7O6xJpUeyJbTSPugC+xM9clvfFvKTH3i8SmCawHGdf5quMWmZ\" crossorigin=\"anonymous\">\n<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./gospel-resources/gospel-resources.js\" integrity=\"sha384-Wx6juT98ZN2xiHbn+OmCtuXGUiRtByJBSPOzN548BynT7F4sizov/cwn7J+HWsal\" 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>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in a new issue