Merge APPROXPIN and rebuild against the library it moved
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions

studio's APPROXPIN (dee9f9c9) moved library/ — legends, PinHint, useMapInstance,
i18n — so the rebuild was certain rather than conditional this time. Checked, as
always, with `git diff --name-only <base> <main> | grep '^library/'` rather than
assumed: that test was EMPTY on one earlier merge and NON-EMPTY on the next two,
and it is the only thing that decides whether the bundle must follow.

All conflicts were DERIVED artifacts again — my two leaf HTMLs and the manifests,
zero source conflicts. Resolved to main's fresh build, then regenerated from the
merged source, because picking a side of a generated file is meaningless.

VERIFIED BY HASHING, the step whose absence shipped a blank page: fix:sri rewrote
the two manifests, and I then recomputed sha384 over the actual bundle —
upg-100-list, upg-100-mfe and poster-wall all MATCH, whole-tree sweep 57 integrity
attributes with 0 mismatches. fix:sri, not tree: studio had already regenerated the
pages and the gate itself warns that tree re-reads .vue source on a shared branch.
This commit is contained in:
Doxa Maps 2026-09-26 13:20:45 +00:00
commit 85a4172644
137 changed files with 2042 additions and 1057 deletions

View file

@ -0,0 +1,58 @@
#!/usr/bin/env node
/**
* check-approx-pin-note — people-group pins say what they are, in one shared wording (APPROXPIN). Headless.
*
* ASSERTS (1) library/utils/colocation.js: groups on the same coordinate find each other (pairs, triples),
* a lone point shares with nobody, rows without a position are ignored, and both roster rows and GeoJSON
* features are read; (2) ApproxPinNote renders the first sentence always, the named second sentence only
* for a shared point, never a raw coordinate, and in Arabic from the Arabic catalogue.
* EXIT 0 pass · 1 fail
*/
import { readFileSync } from 'node:fs'
import { join, resolve, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { buildColocationIndex, colocatedWith } from '../library/utils/colocation.js'
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..')
let bad = 0
const check = (name, ok, got) => { if (!ok) bad++; console.log(` ${ok ? 'ok ' : 'FAIL'} ${name}${ok ? '' : ' — ' + JSON.stringify(got)}`) }
const rows = [
{ name: 'Godda', latitude: 12.843781, longitude: 75.247906 },
{ name: 'Koraga', latitude: '12.843781', longitude: '75.247906' },
{ type: 'Feature', properties: { name: 'Maila' }, geometry: { type: 'Point', coordinates: [75.247906, 12.843781] } },
{ name: 'Alone', latitude: 10, longitude: 10 },
{ name: 'NoPos', latitude: '', longitude: '' },
]
const idx = buildColocationIndex(rows)
check('three groups on one point find each other', colocatedWith(idx, rows[0]).sort().join() === 'Koraga,Maila', colocatedWith(idx, rows[0]))
check('a GeoJSON feature is matched to rows on the same point', colocatedWith(idx, rows[2]).sort().join() === 'Godda,Koraga', colocatedWith(idx, rows[2]))
check('a lone point shares with nobody', colocatedWith(idx, rows[3]).length === 0, colocatedWith(idx, rows[3]))
check('a row without a position is ignored', colocatedWith(idx, rows[4]).length === 0, colocatedWith(idx, rows[4]))
const { createServer } = await import('vite')
const { default: vue } = await import('@vitejs/plugin-vue')
const server = await createServer({ root: ROOT, configFile: false, logLevel: 'error', appType: 'custom',
server: { middlewareMode: true, hmr: false, ws: false, watch: null }, plugins: [vue()], resolve: { alias: { '@map': join(ROOT, 'library') } } })
try {
globalThis.__INTLIFY_JIT_COMPILATION__ = true
const Note = (await server.ssrLoadModule('/library/components/legends/ApproxPinNote.vue')).default
const { createSSRApp, h } = await import('vue')
const { createI18n } = await import('vue-i18n')
const { renderToString } = await import('vue/server-renderer')
const render = async (lc, props) => {
const pins = JSON.parse(readFileSync(join(ROOT, 'library/i18n/locales', lc, 'pins.json'), 'utf8'))
const app = createSSRApp({ render: () => h(Note, props) })
app.use(createI18n({ legacy: false, locale: lc, messages: { [lc]: { pins } } }))
return (await renderToString(app)).replace(/<[^>]+>/g, '').replace(/<!--.*?-->/g, '').trim()
}
const one = await render('en', {})
check('first sentence always', /not a town or a boundary/.test(one) && !/same point/.test(one), one)
const two = await render('en', { shared: ['Koraga', 'Maila'] })
check('shared point names the others and counts all', /Koraga, Maila/.test(two) && /3 groups share/.test(two), two)
check('never prints a raw coordinate', !/\d+\.\d{3,}/.test(one + two), one + two)
const ar = await render('ar', { shared: ['Koraga'] })
check('Arabic renders from the Arabic catalogue', /[؀-ۿ]/.test(ar) && /Koraga/.test(ar), ar)
} finally { await server.close() }
if (bad) { console.log(`APPROX-PIN-NOTE: FAIL — ${bad} case(s).`); process.exit(1) }
console.log('APPROX-PIN-NOTE: PASS — pins say they are localities, and name the groups that share a point.')

View file

@ -114,11 +114,20 @@ function readFacetRail(src) {
if (end < 0) throw new Error('facetRail array is unterminated')
const body = src.slice(open, end + 1)
const sections = []
// one entry per `{ … }` object at the top level of that array
const objRe = /\{[^{}]*\}/g
let m
while ((m = objRe.exec(body))) {
const obj = m[0]
// One entry per object at the TOP level of that array, found by brace depth. A `{[^{}]*}` regex
// matched only objects with no braces inside, and 53e2c662 gave every section a getter title
// (`get title() { return tStatic(…) || 'People' }`): the four drill sections stopped parsing, the
// bus was built with no hierarchy, and this gate reported 21 "orphans" in a dashboard that cascades
// correctly. Braces inside quoted strings are skipped, for the same reason.
const objs = []
for (let i = 1, d = 0, st = -1, q = null; i < body.length - 1; i++) {
const c = body[i]
if (q) { if (c === '\\') i++; else if (c === q) q = null; continue }
if (c === "'" || c === '"' || c === '`') { q = c; continue }
if (c === '{') { if (d === 0) st = i; d++ }
else if (c === '}') { d--; if (d === 0 && st >= 0) { objs.push(body.slice(st, i + 1)); st = -1 } }
}
for (const obj of objs) {
const id = /id:\s*'([^']+)'/.exec(obj)?.[1]
const drillRaw = /drill:\s*\[([^\]]*)\]/.exec(obj)?.[1]
const drill = drillRaw ? [...drillRaw.matchAll(/'([^']+)'/g)].map((x) => x[1]) : undefined
@ -126,6 +135,10 @@ function readFacetRail(src) {
sections.push({ id, drill, facet })
}
if (!sections.length) throw new Error('no facetRail sections parsed')
// A section with neither a drill nor a facet is one this parser could not read: fail loudly
// rather than test a hierarchy that is not the dashboard's.
const unread = sections.filter((x) => !x.id || (!x.drill && !x.facet))
if (unread.length) throw new Error(`facetRail: ${unread.length} section(s) could not be read (${unread.map((x) => x.id || '?').join(', ')})`)
return sections
}

View file

@ -66,6 +66,7 @@ const POLICY = {
'my-upg-100-list': 'header', // upg-100-mfe.vue header owns it
'research-map-plus-grid': 'composite', // overrides child shareUrl to share itself
'key-cities': 'none', // not published
'template-bundle': 'none', // the STARTER, not published: a copy adds ShareButton when it becomes a real map
'all-people-groups': 'own-button', // was debt-no-share; ShareButton added 2026-09-24
// ⚠ prayer-walk-planner took a SECOND LOOK before this flipped, and the reason is worth
// keeping: it builds a PERSONAL WALKING ROUTE from polygons the reader draws, so a share

View file

@ -125,7 +125,11 @@ function isBrowserGate(name) {
// playwright and would have been graded static, while three of the gates it spawns
// (posters, app-tables, map-paint) render pages. It already marks those `browser: true`
// for its own reasons, so that declaration is honoured here rather than duplicated.
return /from 'playwright'|require\('playwright'\)|chromium/.test(src) || /browser:\s*true/.test(src)
// …but a runner only drives chrome when ASKED to: verify-all runs its browser guards only with --full,
// so plain `verify` is a static step (it printed "ALL GUARDS PASS (browser guards skipped)" and was
// still routed through the browser slot, where a headless seat could only fail or skip it).
if (/from 'playwright'|require\('playwright'\)|chromium/.test(src)) return true
return /browser:\s*true/.test(src) && /--full\b/.test(String(scripts[name]))
} catch { return false }
}
@ -196,7 +200,15 @@ function buildSteps() {
.map((name) => ({ name, cmd: 'bun', args: ['x', 'vite', 'build'], env: { BUNDLE: name } }))
}
// ★ ONLY A SEAT THAT MAY RUN A BROWSER RUNS BROWSER GATES (2026-09-26, project rule: browsers are one
// agent's; every other agent works headless). Elsewhere a browser gate is NOT MEASURED — never run, never
// counted as a failure, never counted as a pass. DOXA_BROWSER=1 marks the browser seat.
const BROWSER_SEAT = process.env.DOXA_BROWSER === '1'
async function runStep(step) {
if (step.browser && !BROWSER_SEAT) {
return { ...step, ms: 0, code: LOCK_BUSY_CODE, out: ` (browser gate on a headless seat: set DOXA_BROWSER=1 on the browser seat to measure it)` }
}
if (step.browser && existsSync('/proc/loadavg')) await waitForQuiet((m) => console.log(m))
return new Promise((done) => {
const started = Date.now()
@ -244,21 +256,23 @@ async function main() {
// could see it, because the wave reported it green. An always-taken SKIP is
// indistinguishable from an unwired gate unless the runner says so.
// A gate that never ran because the browser lock stayed busy is UNMEASURED, not failed.
const lockBusy = r.browser && r.code === LOCK_BUSY_CODE
const skipped = lockBusy || /(^|\n)\s*[A-Z][A-Z0-9-]*:\s*SKIP\b/.test(r.out)
if (lockBusy) r.out = (r.out || '') + `\n (could not take the browser lock within ${LOCK_WAIT_S}s — not a product finding)`
// THREE OUTCOMES, never two. Exit 75 (EX_TEMPFAIL) from ANY step is NOT MEASURED: the gate could not
// look (no browser seat, no slot, no built tree), which is neither a pass nor a failure. A gate that
// exits 0 while announcing SKIP is also NOT MEASURED. Only any other non-zero exit is a FAIL.
const unmeasured = r.code === LOCK_BUSY_CODE || (r.code === 0 && /(^|\n)\s*[A-Z][A-Z0-9-]*:\s*(SKIP|NOT MEASURED)\b/.test(r.out))
r.bucket = unmeasured ? 'NOT MEASURED' : r.code === 0 ? 'PASS' : 'FAIL'
console.log(
` ${skipped ? '⊘' : r.code !== 0 ? '✗' : '✓'} ${r.name.padEnd(26)} ${String(r.ms).padStart(7)}ms` +
(r.code === 0 ? '' : ` exit ${r.code}`)
` ${unmeasured ? '⊘' : r.code !== 0 ? '✗' : '✓'} ${r.name.padEnd(26)} ${String(r.ms).padStart(7)}ms` +
(r.code === 0 || unmeasured ? '' : ` exit ${r.code}`)
)
r.skipped = skipped
r.skipped = unmeasured
}
}
await Promise.all(Array.from({ length: Math.min(CONCURRENCY, steps.length) }, worker))
const wall = Date.now() - t0
const serial = results.reduce((a, r) => a + r.ms, 0)
const failed = results.filter((r) => r.code !== 0 && !(r.browser && r.code === LOCK_BUSY_CODE))
const failed = results.filter((r) => r.bucket === 'FAIL')
if (VERBOSE) for (const r of results) if (r.out.trim()) console.log(`\n───── ${r.name} ─────\n${r.out}`)
// A failure must be readable in full: these gates explain themselves in their output, and
@ -268,16 +282,16 @@ async function main() {
// COUNT THE SKIPS IN THE SUMMARY, because the summary is the line a reader quotes and
// the one that lands in a report. "35/35 passed" was true of a wave where a third of the
// gates declined to look at anything.
const skips = results.filter((r) => r.skipped)
const skips = results.filter((r) => r.bucket === 'NOT MEASURED')
const passed = results.filter((r) => r.bucket === 'PASS')
console.log(
`\n▶ ${LABEL}: ${results.length - failed.length - skips.length}/${results.length} passed` +
(skips.length ? `, ${skips.length} SKIPPED` : '') +
`\n▶ ${LABEL}: PASS ${passed.length} · FAIL ${failed.length} · NOT MEASURED ${skips.length} (of ${results.length})` +
` in ${(wall / 1000).toFixed(1)}s wall ` +
`(${(serial / 1000).toFixed(1)}s of work — ${(serial / Math.max(wall, 1)).toFixed(1)}x)`
)
if (skips.length) {
console.log(` ⊘ evaluated nothing: ${skips.map((s) => s.name).join(', ')}`)
console.log(' Each declined on a precondition it names in its own output (run it alone to see).')
console.log(` ⊘ NOT MEASURED: ${skips.map((s) => s.name).join(', ')}`)
console.log(' Each could not look (no browser seat, no slot, or a missing precondition it names); not a pass, not a failure.')
}
if (failed.length) {
console.error(`✗ ${LABEL}: ${failed.length} step(s) FAILED — ${failed.map((f) => f.name).join(', ')}`)

View file

@ -0,0 +1,29 @@
<!--
ApproxPinNote.vue — the ONE wording every map with people-group pins uses (APPROXPIN, 2026-09-26).
The first sentence always: a dot is where a people is found, not a town or a boundary. The second only
when the pin's point is SHARED, naming the other groups (from library/utils/colocation.js, built from the
roster the map draws), because "approximate" alone hides that some dots are the same dot.
Never shows the raw coordinate: six decimal places beside a caveat that says "approximate" reads as a
contradiction. Wording: gospel-plugin's measured proposal (P5), in library/i18n/locales/<lc>/pins.json.
-->
<script setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const props = defineProps({
/** Names of the OTHER groups on this pin's coordinate; empty = not shared. */
shared: { type: Array, default: () => [] },
dark: { type: Boolean, default: false },
})
const { t } = useI18n()
const second = computed(() => props.shared.length
? t('pins.sharedPoint', { names: props.shared.join(', '), n: props.shared.length + 1 })
: '')
</script>
<template>
<p class="approx-pin-note" :style="{ margin: '6px 10px 4px', font: '400 11px/1.4 system-ui, -apple-system, Segoe UI, Roboto, sans-serif', color: dark ? 'rgba(243,243,241,0.7)' : '#5b6470' }">
{{ t('pins.approximate') }}<template v-if="second"> {{ second }}</template>
</p>
</template>

View file

@ -12,6 +12,8 @@ import { useLegendData } from '../../composables/legends/useLegendData.js'
import { retryableAsyncComponent } from '../../composables/retryableAsyncComponent.js'
import LegendRows from './LegendRows.vue'
import PeopleGroupDetail from '../PeopleGroupDetail.vue'
import ApproxPinNote from './ApproxPinNote.vue'
import { buildColocationIndex, colocatedWith } from '../../utils/colocation.js'
// Async-import the heavier branches so the boot bundle stays lean.
const LegendMobile = retryableAsyncComponent(() => import('./LegendMobile.vue'))
// Language-family tab is now handled by <SemanticTreeLegend> mounted directly
@ -253,6 +255,9 @@ const isMobile = computed(() => uiStore.isMobile)
// Legend mode (prayer progress ↔ people group detail)
const legendMode = computed(() => uiStore.legendMode)
const selectedPeopleGroup = computed(() => uiStore.selectedPeopleGroup)
// APPROXPIN: the other groups on the selected pin's coordinate, from the roster THIS map draws.
const colocation = computed(() => buildColocationIndex(peopleGroupsForFamilyTree.value))
const selectedShared = computed(() => (selectedPeopleGroup.value ? colocatedWith(colocation.value, selectedPeopleGroup.value) : []))
// Reactive data
const isCollapsed = ref(props.initiallyCollapsed)
@ -398,13 +403,15 @@ onBeforeUnmount(() => {
</button>
<div class="legend-content" :class="{ 'no-padding': legendColumns.length > 0 }">
<PeopleGroupDetail
v-if="legendMode === 'detail' && selectedPeopleGroup"
:peopleGroup="selectedPeopleGroup"
:hideHeader="true"
:dark="isDark"
:action="popupAction"
/>
<template v-if="legendMode === 'detail' && selectedPeopleGroup">
<PeopleGroupDetail
:peopleGroup="selectedPeopleGroup"
:hideHeader="true"
:dark="isDark"
:action="popupAction"
/>
<ApproxPinNote :shared="selectedShared" :dark="isDark" />
</template>
<template v-else-if="legendType === 'language-family'"></template>
<LegendRows
v-else
@ -432,6 +439,7 @@ onBeforeUnmount(() => {
</button>
</template>
</LegendRows>
<ApproxPinNote v-if="legendMode !== 'detail'" :dark="isDark" />
</div>
</div>

View file

@ -10,6 +10,8 @@ import { useLanguageFamilyLegendData } from '../../composables/legends/useLangua
import { useAffinityBlockLegendData } from '../../composables/legends/useAffinityBlockLegendData.js'
import { useWagfRegionsLegendData } from '../../composables/legends/useWagfRegionsLegendData.js'
import PeopleGroupDetail from '../PeopleGroupDetail.vue'
import ApproxPinNote from './ApproxPinNote.vue'
import { buildColocationIndex, colocatedWith } from '../../utils/colocation.js'
const { t } = useI18n()
@ -521,6 +523,13 @@ const caretRotation = computed(() => uiStore.caretRotation)
const showPullTab = computed(() => uiStore.showPullTab)
const legendMode = computed(() => uiStore.legendMode)
const selectedPeopleGroup = computed(() => uiStore.selectedPeopleGroup)
// APPROXPIN: the other groups on the selected pin's coordinate, from the roster THIS map draws.
const colocation = computed(() => {
const rows = []
for (const id in (dataStore?.sources || {})) { const src = dataStore.sources[id]; if (src?.features?.length) rows.push(...src.features) }
return buildColocationIndex(rows)
})
const selectedShared = computed(() => (selectedPeopleGroup.value ? colocatedWith(colocation.value, selectedPeopleGroup.value) : []))
// Legend title — swaps based on legend state and selection
const legendTitle = computed(() => {
@ -804,6 +813,7 @@ onBeforeUnmount(() => {
:dark="isDark"
:action="popupAction"
/>
<ApproxPinNote v-if="legendState !== 'collapsed'" :shared="selectedShared" :dark="isDark" />
</template>
<!-- Semantic-tree tabs (Languages, People Groups, WAGF Regions):
@ -865,6 +875,7 @@ onBeforeUnmount(() => {
</button>
</template>
</LegendRows>
<ApproxPinNote v-if="legendMode !== 'detail' && legendState !== 'collapsed'" :dark="isDark" />
</div>
</div>
</div><!-- /.legend-sheet-root -->

View file

@ -14,6 +14,11 @@
* { id, label, color?, count?, pop?, filter?, info?, children?: TreeNode[] }
*/
import { ref, computed, watch, nextTick, inject, unref } from 'vue'
import { tStatic } from '@map/i18n/index.js'
// This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
// custom elements that install no i18n plugin, and an unguarded useI18n() throws on the way in.
const T = (key, en) => tStatic(key) || en
import { useI18n } from 'vue-i18n'
import { useShadowStyles } from '../../composables/useShadowStyles.js'
import { useInstance } from '../../composables/usePplrInstance.js'
@ -1305,14 +1310,15 @@ useShadowStyles(`
<div v-if="tabLoading && !visibleRows.length" class="stl-empty stl-loading">
<span class="stl-spinner"></span>
<span>Loading {{ tabList[activeTab]?.label || 'rows' }}…</span>
<span>{{ T('legend.loadingRows', 'Loading {label}…').replace('{label}', tabList[activeTab]?.label || 'rows') }}</span>
</div>
<div v-else-if="!visibleRows.length && nodes.length === 0" class="stl-empty">Loading data…</div>
<div v-else-if="!visibleRows.length && nodes.length === 0" class="stl-empty">{{ T('legend.loadingData', 'Loading data…') }}</div>
<div v-else-if="!visibleRows.length" class="stl-empty">{{ t('legend.noDataAtThisLevel') }}</div>
<div v-if="topNodesOverflow > 0" class="stl-overflow">
Showing top {{ tabList[activeTab].topLimit.toLocaleString() }} of
{{ topNodesAll.length.toLocaleString() }} —
<span class="stl-overflow-hint">use the geocoder above to find the rest</span>
{{ T('legend.showingTop', 'Showing top {n} of {m}')
.replace('{n}', tabList[activeTab].topLimit.toLocaleString())
.replace('{m}', topNodesAll.length.toLocaleString()) }} —
<span class="stl-overflow-hint">{{ T('legend.useGeocoderHint', 'use the geocoder above to find the rest') }}</span>
</div>
</div>
</div>

View file

@ -17,10 +17,10 @@
class="poster-preview__map"
:src="snapshot"
:style="boxStyle(layout.map)"
alt="map preview"
:alt="T('poster.map_preview', 'map preview')"
/>
<div v-else class="poster-preview__map placeholder" :style="boxStyle(layout.map)">
Loading map snapshot…
{{ T('poster.loading_snapshot', 'Loading map snapshot…') }}
</div>
<TitleSlot
@ -68,6 +68,11 @@
<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
import { tStatic } from '../../i18n/index.js'
// This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
// custom elements that install no i18n plugin, and an unguarded useI18n() throws on the way in.
const T = (key, en) => tStatic(key) || en
import TitleSlot from './slots/TitleSlot.vue';
import LegendSlot from './slots/LegendSlot.vue';
import ScaleBarSlot from './slots/ScaleBarSlot.vue';

View file

@ -40,6 +40,11 @@
* CustomEvent scoped by instanceId, so several embeds on one page never cross-talk.
*/
import { computed, ref, watch, onBeforeUnmount } from 'vue'
import { tStatic } from '../../i18n/index.js'
// This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
// custom elements that install no i18n plugin, and an unguarded useI18n() throws on the way in.
const T = (key, en) => tStatic(key) || en
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { usePosterPrints } from '@map/composables/usePosterPrints.js'
import { useI18n } from 'vue-i18n'
@ -959,7 +964,7 @@ useShadowStyles(
<span v-if="collapsible" class="sec-caret" :class="{ 'is-open': !isCollapsed(sec.name) }">▶</span>
<h3 class="sec-name">{{ sec.name }}</h3>
<span class="sec-count">
{{ sec.total.toLocaleString() }} people groups ·
{{ sec.total.toLocaleString() }} {{ T('gospel.list.peopleGroups', 'people groups') }} ·
{{ sec.items.length }} {{ sec.items.length === 1 ? itemNoun : plural }}
</span>
</component>
@ -1021,7 +1026,7 @@ useShadowStyles(
poster that is sitting on disk is how the Driver came to report this.
i18n DEBT: this literal predates t() here and is still untranslated, like
the two beside it. -->
<div class="ph-note">preview unavailable</div>
<div class="ph-note">{{ T('poster.preview_unavailable', 'preview unavailable') }}</div>
</div>
<!-- ★ THE PRINT ROW LIVES INSIDE .main, NOT BESIDE IT (Driver 2026-09-25).

View file

@ -41,7 +41,9 @@ const ENGINES = {
// THE ENGINE'S OWN CONTROL LABELS ("Zoom in", "Toggle attribution", the gesture hints…) in the reader's
// language. Both engines take a `locale` map of their UI strings at construction; without one they stay
// English under ar/es (rega's row 30). Strings live in library/i18n/locales/<lc>/mapui.json. The keys are
// the engines' own; an engine ignores the ones it does not use.
// the engines' own; an engine ignores the ones it does not use. EXPORTED for the maps built RAW
// (new gl.Map outside this composable, e.g. gospel-resources, cities-internet): pass
// `locale: engineUiLocale(lang, provider)` to their constructor, or their controls stay English.
const ENGINE_UI_KEYS = {
'Map.Title': 'map', 'Marker.Title': 'marker', 'Popup.Close': 'closePopup',
'NavigationControl.ZoomIn': 'zoomIn', 'NavigationControl.ZoomOut': 'zoomOut', 'NavigationControl.ResetBearing': 'resetBearing',
@ -54,12 +56,15 @@ const ENGINE_UI_KEYS = {
// Mapbox's names for the same gesture hints
'ScrollZoomBlocker.CtrlMessage': 'ctrlScroll', 'ScrollZoomBlocker.CmdMessage': 'cmdScroll', 'TouchPanBlocker.Message': 'twoFingers',
}
export function engineUiLocale(lang) {
export function engineUiLocale(lang, provider) {
const out = {}
for (const [engineKey, ours] of Object.entries(ENGINE_UI_KEYS)) {
const v = tStatic(`mapui.${ours}`, lang)
if (v) out[engineKey] = v
}
// The logo's label names its own engine ("Mapbox homepage" / "MapLibre logo"): one key, two meanings.
const logo = tStatic(provider === 'maplibre' ? 'mapui.maplibreLogo' : 'mapui.mapboxHomepage', lang)
if (logo) out['LogoControl.Title'] = logo
return out
}
@ -541,7 +546,7 @@ export function useMapInstance({
// day/night decision, not a guess made here. (Computed above the branch: the Mapbox
// branch's own `initialConfig` is scoped to that branch and is NOT visible here.)
style: maplibreStyle(effectiveStyle, _bootPreset),
locale: engineUiLocale(readerLang()),
locale: engineUiLocale(readerLang(), 'maplibre'),
center,
zoom,
minZoom: initialMinZoom,
@ -568,7 +573,7 @@ export function useMapInstance({
accessToken: token, // BP #1 from W1A — per-instance token; avoids last-writer-wins on multi-embed pages
container: containerRef.value, // real DOM element — never a string ID in shadow DOM
style: effectiveStyle,
locale: engineUiLocale(readerLang()),
locale: engineUiLocale(readerLang(), 'mapbox'),
// Pins a Standard basemap's lightPreset/theme BEFORE its first frame; without it the
// schema default 'day' paints one LIGHT frame before any setConfigProperty can run.
...(initialConfig ? { config: initialConfig } : {}),

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "لا توجد بيانات في هذا المستوى",
"exportButton": "تصدير",
"exportSelection": "تصدير التحديد"
"exportSelection": "تصدير التحديد",
"loadingRows": "جارٍ تحميل {label}…",
"loadingData": "جارٍ تحميل البيانات…",
"showingTop": "عرض أعلى {n} من {m}",
"useGeocoderHint": "استخدم أداة البحث أعلاه للعثور على البقية"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "إيقاف الكرة الأرضية",
"ctrlScroll": "استخدم Ctrl مع التمرير لتكبير الخريطة",
"cmdScroll": "استخدم ⌘ مع التمرير لتكبير الخريطة",
"twoFingers": "استخدم إصبعين لتحريك الخريطة"
"twoFingers": "استخدم إصبعين لتحريك الخريطة",
"mapboxHomepage": "الصفحة الرئيسية لـ Mapbox",
"maplibreLogo": "شعار MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "قائمتي UPG 100 — قوائم الصلاة والملصقات",
"upg100WallTag": "تعبئة للصلاة",
"upg100WallIntro": "وزّع مهمة الصلاة في مجموعات من خمسين ومئة — كما أطعم يسوع الخمسة آلاف (لوقا ٩:١٤). كل ملصق هو قائمة من 100 يمكنك أن تصلي بها وتطبعها وتعلّقها على الحائط — مصلّيًا لأجلهم <strong>باسم شعبهم</strong>."
"upg100WallIntro": "وزّع مهمة الصلاة في مجموعات من خمسين ومئة — كما أطعم يسوع الخمسة آلاف (لوقا ٩:١٤). كل ملصق هو قائمة من 100 يمكنك أن تصلي بها وتطبعها وتعلّقها على الحائط — مصلّيًا لأجلهم <strong>باسم شعبهم</strong>.",
"loadingNamed": "جارٍ تحميل {name}…",
"couldNotLoadNamed": "تعذّر تحميل {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "تشير النقطة إلى المكان الذي يوجد فيه هذا الشعب، وليست بلدة أو حدودًا.",
"sharedPoint": "تقع في النقطة نفسها مع {names} — {n} مجموعات تتشارك هذا الإحداثي، لذا يدل الموقع على المنطقة لا على مكان كل مجموعة."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "شريط المقياس",
"north_arrow": "سهم الشمال",
"footer_attribution": "التذييل (الإسناد مطلوب)",
"cancel": "إلغاء"
"cancel": "إلغاء",
"map_preview": "معاينة الخريطة",
"loading_snapshot": "جارٍ تحميل لقطة الخريطة…",
"preview_unavailable": "المعاينة غير متاحة"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "Keine Daten auf dieser Ebene",
"exportButton": "Exportieren",
"exportSelection": "Auswahl exportieren"
"exportSelection": "Auswahl exportieren",
"loadingRows": "{label} werden geladen…",
"loadingData": "Daten werden geladen…",
"showingTop": "Top {n} von {m} werden angezeigt",
"useGeocoderHint": "verwenden Sie die Suche oben, um die übrigen zu finden"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Globus ausschalten",
"ctrlScroll": "Strg + Scrollen zum Zoomen der Karte",
"cmdScroll": "⌘ + Scrollen zum Zoomen der Karte",
"twoFingers": "Mit zwei Fingern die Karte bewegen"
"twoFingers": "Mit zwei Fingern die Karte bewegen",
"mapboxHomepage": "Mapbox-Startseite",
"maplibreLogo": "MapLibre-Logo"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "Meine UPG-100-Liste — Gebetslisten und Poster",
"upg100WallTag": "Gebetsmobilisierung",
"upg100WallIntro": "Teilen Sie die Gebetsaufgabe in Gruppen zu fünfzig und hundert auf — so wie Jesus die 5.000 speiste (Lukas 9,14). Jedes Poster ist eine 100er-Liste, die Sie beten, drucken und an die Wand hängen können — und für sie <strong>mit dem Namen ihrer Volksgruppe</strong> beten."
"upg100WallIntro": "Teilen Sie die Gebetsaufgabe in Gruppen zu fünfzig und hundert auf — so wie Jesus die 5.000 speiste (Lukas 9,14). Jedes Poster ist eine 100er-Liste, die Sie beten, drucken und an die Wand hängen können — und für sie <strong>mit dem Namen ihrer Volksgruppe</strong> beten.",
"loadingNamed": "{name} wird geladen…",
"couldNotLoadNamed": "{name} konnte nicht geladen werden."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "Der Punkt zeigt, wo dieses Volk lebt – nicht eine Stadt oder eine Grenze.",
"sharedPoint": "Er liegt auf demselben Punkt wie {names} — {n} Gruppen teilen sich diese Koordinate; die Position nennt also die Gegend, nicht wo welche Gruppe lebt."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Maßstabsleiste",
"north_arrow": "Nordpfeil",
"footer_attribution": "Fußzeile (Quellenangabe erforderlich)",
"cancel": "Abbrechen"
"cancel": "Abbrechen",
"map_preview": "Kartenvorschau",
"loading_snapshot": "Kartenaufnahme wird geladen…",
"preview_unavailable": "Vorschau nicht verfügbar"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "No data at this level",
"exportButton": "Export",
"exportSelection": "Export selection"
"exportSelection": "Export selection",
"loadingRows": "Loading {label}…",
"loadingData": "Loading data…",
"showingTop": "Showing top {n} of {m}",
"useGeocoderHint": "use the geocoder above to find the rest"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Disable globe",
"ctrlScroll": "Use Ctrl + scroll to zoom the map",
"cmdScroll": "Use ⌘ + scroll to zoom the map",
"twoFingers": "Use two fingers to move the map"
"twoFingers": "Use two fingers to move the map",
"mapboxHomepage": "Mapbox homepage",
"maplibreLogo": "MapLibre logo"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "My UPG 100 List — Prayer Lists & Posters",
"upg100WallTag": "Prayer Mobilization",
"upg100WallIntro": "Hand away the prayer task in clusters of fifties and hundreds — the way Jesus fed the 5,000 (Luke 9:14). Each poster is a 100-list you can pray, print, and put on a wall — praying for them <strong>by their people group name</strong>."
"upg100WallIntro": "Hand away the prayer task in clusters of fifties and hundreds — the way Jesus fed the 5,000 (Luke 9:14). Each poster is a 100-list you can pray, print, and put on a wall — praying for them <strong>by their people group name</strong>.",
"loadingNamed": "Loading {name}…",
"couldNotLoadNamed": "Could not load {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "The dot marks where this people is found, not a town or a boundary.",
"sharedPoint": "It sits on the same point as {names} — {n} groups share this coordinate, so the position tells you the locality and not which group is where."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Scale bar",
"north_arrow": "North arrow",
"footer_attribution": "Footer (attribution required)",
"cancel": "Cancel"
"cancel": "Cancel",
"map_preview": "map preview",
"loading_snapshot": "Loading map snapshot…",
"preview_unavailable": "preview unavailable"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "No hay datos en este nivel",
"exportButton": "Exportar",
"exportSelection": "Exportar la selección"
"exportSelection": "Exportar la selección",
"loadingRows": "Cargando {label}…",
"loadingData": "Cargando datos…",
"showingTop": "Mostrando los {n} principales de {m}",
"useGeocoderHint": "usa el buscador de arriba para encontrar el resto"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Desactivar globo",
"ctrlScroll": "Usa Ctrl + desplazamiento para hacer zoom en el mapa",
"cmdScroll": "Usa ⌘ + desplazamiento para hacer zoom en el mapa",
"twoFingers": "Usa dos dedos para mover el mapa"
"twoFingers": "Usa dos dedos para mover el mapa",
"mapboxHomepage": "Página de inicio de Mapbox",
"maplibreLogo": "Logotipo de MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "Mi lista UPG 100 — Listas de oración y carteles",
"upg100WallTag": "Movilización de oración",
"upg100WallIntro": "Reparte la tarea de la oración en grupos de cincuenta y de cien, como Jesús alimentó a los 5.000 (Lucas 9:14). Cada cartel es una lista de 100 que puedes orar, imprimir y poner en la pared — orando por ellos <strong>por el nombre de su pueblo</strong>."
"upg100WallIntro": "Reparte la tarea de la oración en grupos de cincuenta y de cien, como Jesús alimentó a los 5.000 (Lucas 9:14). Cada cartel es una lista de 100 que puedes orar, imprimir y poner en la pared — orando por ellos <strong>por el nombre de su pueblo</strong>.",
"loadingNamed": "Cargando {name}…",
"couldNotLoadNamed": "No se pudo cargar {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "El punto indica dónde se encuentra este pueblo, no una ciudad ni una frontera.",
"sharedPoint": "Está en el mismo punto que {names}: {n} grupos comparten esta coordenada, así que la posición indica la zona y no dónde está cada grupo."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Barra de escala",
"north_arrow": "Flecha norte",
"footer_attribution": "Pie de página (atribución obligatoria)",
"cancel": "Cancelar"
"cancel": "Cancelar",
"map_preview": "vista previa del mapa",
"loading_snapshot": "Cargando la captura del mapa…",
"preview_unavailable": "vista previa no disponible"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "Aucune donnée à ce niveau",
"exportButton": "Exporter",
"exportSelection": "Exporter la sélection"
"exportSelection": "Exporter la sélection",
"loadingRows": "Chargement de {label}…",
"loadingData": "Chargement des données…",
"showingTop": "Affichage des {n} premiers sur {m}",
"useGeocoderHint": "utilisez la recherche ci-dessus pour trouver les autres"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Désactiver le globe",
"ctrlScroll": "Utilisez Ctrl + molette pour zoomer sur la carte",
"cmdScroll": "Utilisez ⌘ + molette pour zoomer sur la carte",
"twoFingers": "Utilisez deux doigts pour déplacer la carte"
"twoFingers": "Utilisez deux doigts pour déplacer la carte",
"mapboxHomepage": "Page d'accueil de Mapbox",
"maplibreLogo": "Logo MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "Ma liste UPG 100 — Listes de prière et affiches",
"upg100WallTag": "Mobilisation pour la prière",
"upg100WallIntro": "Répartissez la tâche de la prière par groupes de cinquante et de cent — comme Jésus a nourri les 5 000 (Luc 9:14). Chaque affiche est une liste de 100 que vous pouvez prier, imprimer et afficher au mur — en priant pour eux <strong>par le nom de leur peuple</strong>."
"upg100WallIntro": "Répartissez la tâche de la prière par groupes de cinquante et de cent — comme Jésus a nourri les 5 000 (Luc 9:14). Chaque affiche est une liste de 100 que vous pouvez prier, imprimer et afficher au mur — en priant pour eux <strong>par le nom de leur peuple</strong>.",
"loadingNamed": "Chargement de {name}…",
"couldNotLoadNamed": "Impossible de charger {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "Le point indique où vit ce peuple, pas une ville ni une frontière.",
"sharedPoint": "Il se trouve au même point que {names} — {n} groupes partagent cette coordonnée : la position indique la région, pas où se trouve chaque groupe."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Échelle",
"north_arrow": "Flèche du nord",
"footer_attribution": "Pied de page (attribution requise)",
"cancel": "Annuler"
"cancel": "Annuler",
"map_preview": "aperçu de la carte",
"loading_snapshot": "Chargement de l'instantané de la carte…",
"preview_unavailable": "aperçu indisponible"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "इस स्तर पर कोई डेटा नहीं",
"exportButton": "निर्यात",
"exportSelection": "चयन निर्यात करें"
"exportSelection": "चयन निर्यात करें",
"loadingRows": "{label} लोड हो रहे हैं…",
"loadingData": "डेटा लोड हो रहा है…",
"showingTop": "{m} में से शीर्ष {n} दिखाए जा रहे हैं",
"useGeocoderHint": "बाकी खोजने के लिए ऊपर दिए गए खोज बॉक्स का उपयोग करें"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "ग्लोब बंद करें",
"ctrlScroll": "मानचित्र ज़ूम करने के लिए Ctrl + स्क्रॉल करें",
"cmdScroll": "मानचित्र ज़ूम करने के लिए ⌘ + स्क्रॉल करें",
"twoFingers": "मानचित्र हिलाने के लिए दो उँगलियों का उपयोग करें"
"twoFingers": "मानचित्र हिलाने के लिए दो उँगलियों का उपयोग करें",
"mapboxHomepage": "Mapbox मुखपृष्ठ",
"maplibreLogo": "MapLibre लोगो"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "मेरी UPG 100 सूची — प्रार्थना सूचियाँ और पोस्टर",
"upg100WallTag": "प्रार्थना लामबंदी",
"upg100WallIntro": "प्रार्थना के काम को पचास-पचास और सौ-सौ के समूहों में बाँटें — जैसे यीशु ने 5,000 लोगों को खिलाया (लूका 9:14)। हर पोस्टर 100 की एक सूची है जिसके लिए आप प्रार्थना कर सकते हैं, छाप सकते हैं और दीवार पर लगा सकते हैं — उनके लिए <strong>उनके जनसमूह के नाम से</strong> प्रार्थना करते हुए।"
"upg100WallIntro": "प्रार्थना के काम को पचास-पचास और सौ-सौ के समूहों में बाँटें — जैसे यीशु ने 5,000 लोगों को खिलाया (लूका 9:14)। हर पोस्टर 100 की एक सूची है जिसके लिए आप प्रार्थना कर सकते हैं, छाप सकते हैं और दीवार पर लगा सकते हैं — उनके लिए <strong>उनके जनसमूह के नाम से</strong> प्रार्थना करते हुए।",
"loadingNamed": "{name} लोड हो रहा है…",
"couldNotLoadNamed": "{name} लोड नहीं हो सका।"
}

View file

@ -0,0 +1,4 @@
{
"approximate": "बिंदु दिखाता है कि यह लोग कहाँ पाए जाते हैं, कोई शहर या सीमा नहीं।",
"sharedPoint": "यह {names} के साथ एक ही बिंदु पर है — {n} समूह यह निर्देशांक साझा करते हैं, इसलिए स्थान क्षेत्र बताता है, यह नहीं कि कौन-सा समूह कहाँ है।"
}

View file

@ -15,5 +15,8 @@
"scale_bar": "स्केल बार",
"north_arrow": "उत्तर तीर",
"footer_attribution": "फ़ुटर (एट्रिब्यूशन आवश्यक)",
"cancel": "रद्द करें"
"cancel": "रद्द करें",
"map_preview": "मानचित्र पूर्वावलोकन",
"loading_snapshot": "मानचित्र स्नैपशॉट लोड हो रहा है…",
"preview_unavailable": "पूर्वावलोकन उपलब्ध नहीं"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "Nessun dato a questo livello",
"exportButton": "Esporta",
"exportSelection": "Esporta la selezione"
"exportSelection": "Esporta la selezione",
"loadingRows": "Caricamento di {label}…",
"loadingData": "Caricamento dati…",
"showingTop": "Mostrati i primi {n} di {m}",
"useGeocoderHint": "usa la ricerca qui sopra per trovare gli altri"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Disattiva globo",
"ctrlScroll": "Usa Ctrl + scorrimento per ingrandire la mappa",
"cmdScroll": "Usa ⌘ + scorrimento per ingrandire la mappa",
"twoFingers": "Usa due dita per spostare la mappa"
"twoFingers": "Usa due dita per spostare la mappa",
"mapboxHomepage": "Home page di Mapbox",
"maplibreLogo": "Logo di MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "La mia lista UPG 100 — Liste di preghiera e poster",
"upg100WallTag": "Mobilitazione alla preghiera",
"upg100WallIntro": "Distribuisci il compito della preghiera in gruppi di cinquanta e di cento — come Gesù sfamò i 5.000 (Luca 9:14). Ogni poster è una lista di 100 che puoi pregare, stampare e appendere al muro — pregando per loro <strong>con il nome del loro popolo</strong>."
"upg100WallIntro": "Distribuisci il compito della preghiera in gruppi di cinquanta e di cento — come Gesù sfamò i 5.000 (Luca 9:14). Ogni poster è una lista di 100 che puoi pregare, stampare e appendere al muro — pregando per loro <strong>con il nome del loro popolo</strong>.",
"loadingNamed": "Caricamento di {name}…",
"couldNotLoadNamed": "Impossibile caricare {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "Il punto indica dove si trova questo popolo, non una città né un confine.",
"sharedPoint": "Si trova nello stesso punto di {names} — {n} gruppi condividono questa coordinata, quindi la posizione indica la zona e non dove si trova ciascun gruppo."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Barra della scala",
"north_arrow": "Freccia nord",
"footer_attribution": "Piè di pagina (attribuzione obbligatoria)",
"cancel": "Annulla"
"cancel": "Annulla",
"map_preview": "anteprima della mappa",
"loading_snapshot": "Caricamento dell'istantanea della mappa…",
"preview_unavailable": "anteprima non disponibile"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "Sem dados neste nível",
"exportButton": "Exportar",
"exportSelection": "Exportar a seleção"
"exportSelection": "Exportar a seleção",
"loadingRows": "Carregando {label}…",
"loadingData": "Carregando dados…",
"showingTop": "Mostrando os {n} principais de {m}",
"useGeocoderHint": "use a busca acima para encontrar os restantes"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Desativar globo",
"ctrlScroll": "Use Ctrl + rolagem para ampliar o mapa",
"cmdScroll": "Use ⌘ + rolagem para ampliar o mapa",
"twoFingers": "Use dois dedos para mover o mapa"
"twoFingers": "Use dois dedos para mover o mapa",
"mapboxHomepage": "Página inicial do Mapbox",
"maplibreLogo": "Logótipo do MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "A minha lista UPG 100 — Listas de oração e cartazes",
"upg100WallTag": "Mobilização de oração",
"upg100WallIntro": "Reparta a tarefa da oração em grupos de cinquenta e de cem — como Jesus alimentou os 5.000 (Lucas 9:14). Cada cartaz é uma lista de 100 que pode orar, imprimir e pôr na parede — orando por eles <strong>pelo nome do seu povo</strong>."
"upg100WallIntro": "Reparta a tarefa da oração em grupos de cinquenta e de cem — como Jesus alimentou os 5.000 (Lucas 9:14). Cada cartaz é uma lista de 100 que pode orar, imprimir e pôr na parede — orando por eles <strong>pelo nome do seu povo</strong>.",
"loadingNamed": "Carregando {name}…",
"couldNotLoadNamed": "Não foi possível carregar {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "O ponto indica onde este povo se encontra, não uma cidade nem uma fronteira.",
"sharedPoint": "Está no mesmo ponto que {names} — {n} grupos partilham esta coordenada, por isso a posição indica a região e não onde está cada grupo."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Barra de escala",
"north_arrow": "Seta norte",
"footer_attribution": "Rodapé (atribuição obrigatória)",
"cancel": "Cancelar"
"cancel": "Cancelar",
"map_preview": "pré-visualização do mapa",
"loading_snapshot": "Carregando o instantâneo do mapa…",
"preview_unavailable": "pré-visualização indisponível"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "Nu există date la acest nivel",
"exportButton": "Exportă",
"exportSelection": "Exportă selecția"
"exportSelection": "Exportă selecția",
"loadingRows": "Se încarcă {label}…",
"loadingData": "Se încarcă datele…",
"showingTop": "Se afișează primele {n} din {m}",
"useGeocoderHint": "folosește căutarea de mai sus pentru a le găsi pe celelalte"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Dezactivează globul",
"ctrlScroll": "Folosește Ctrl + derulare pentru a mări harta",
"cmdScroll": "Folosește ⌘ + derulare pentru a mări harta",
"twoFingers": "Folosește două degete pentru a muta harta"
"twoFingers": "Folosește două degete pentru a muta harta",
"mapboxHomepage": "Pagina principală Mapbox",
"maplibreLogo": "Sigla MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "Lista mea UPG 100 — Liste de rugăciune și afișe",
"upg100WallTag": "Mobilizare pentru rugăciune",
"upg100WallIntro": "Împarte sarcina rugăciunii în grupuri de câte cincizeci și o sută — așa cum Isus a hrănit cei 5.000 (Luca 9:14). Fiecare afiș este o listă de 100 pe care o poți ruga, tipări și pune pe perete — rugându-te pentru ei <strong>pe numele poporului lor</strong>."
"upg100WallIntro": "Împarte sarcina rugăciunii în grupuri de câte cincizeci și o sută — așa cum Isus a hrănit cei 5.000 (Luca 9:14). Fiecare afiș este o listă de 100 pe care o poți ruga, tipări și pune pe perete — rugându-te pentru ei <strong>pe numele poporului lor</strong>.",
"loadingNamed": "Se încarcă {name}…",
"couldNotLoadNamed": "Nu s-a putut încărca {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "Punctul arată unde se află acest popor, nu un oraș sau o graniță.",
"sharedPoint": "Se află în același punct cu {names} — {n} grupuri împart această coordonată, deci poziția arată zona, nu unde se află fiecare grup."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Bară de scară",
"north_arrow": "Săgeata nord",
"footer_attribution": "Subsol (atribuire obligatorie)",
"cancel": "Anulează"
"cancel": "Anulează",
"map_preview": "previzualizare hartă",
"loading_snapshot": "Se încarcă instantaneul hărții…",
"preview_unavailable": "previzualizare indisponibilă"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "На этом уровне нет данных",
"exportButton": "Экспорт",
"exportSelection": "Экспортировать выбранное"
"exportSelection": "Экспортировать выбранное",
"loadingRows": "Загрузка {label}…",
"loadingData": "Загрузка данных…",
"showingTop": "Показаны первые {n} из {m}",
"useGeocoderHint": "используйте поиск выше, чтобы найти остальные"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "Выключить глобус",
"ctrlScroll": "Используйте Ctrl + прокрутку для масштабирования карты",
"cmdScroll": "Используйте ⌘ + прокрутку для масштабирования карты",
"twoFingers": "Используйте два пальца, чтобы перемещать карту"
"twoFingers": "Используйте два пальца, чтобы перемещать карту",
"mapboxHomepage": "Главная страница Mapbox",
"maplibreLogo": "Логотип MapLibre"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "Мой список UPG 100 — молитвенные списки и плакаты",
"upg100WallTag": "Молитвенная мобилизация",
"upg100WallIntro": "Разделите молитвенный труд на группы по пятьдесят и по сто — так Иисус накормил 5000 (Луки 9:14). Каждый плакат — это список из 100, о котором можно молиться, распечатать и повесить на стену, молясь о них <strong>по имени их народа</strong>."
"upg100WallIntro": "Разделите молитвенный труд на группы по пятьдесят и по сто — так Иисус накормил 5000 (Луки 9:14). Каждый плакат — это список из 100, о котором можно молиться, распечатать и повесить на стену, молясь о них <strong>по имени их народа</strong>.",
"loadingNamed": "Загрузка {name}…",
"couldNotLoadNamed": "Не удалось загрузить {name}."
}

View file

@ -0,0 +1,4 @@
{
"approximate": "Точка показывает, где живёт этот народ, а не город и не границу.",
"sharedPoint": "Она совпадает с точкой {names} — {n} групп делят эту координату, поэтому положение указывает местность, а не где какая группа."
}

View file

@ -15,5 +15,8 @@
"scale_bar": "Масштабная линейка",
"north_arrow": "Указатель севера",
"footer_attribution": "Нижний колонтитул (указание источника обязательно)",
"cancel": "Отмена"
"cancel": "Отмена",
"map_preview": "предпросмотр карты",
"loading_snapshot": "Загрузка снимка карты…",
"preview_unavailable": "предпросмотр недоступен"
}

View file

@ -72,5 +72,9 @@
},
"noDataAtThisLevel": "此层级没有数据",
"exportButton": "导出",
"exportSelection": "导出所选内容"
"exportSelection": "导出所选内容",
"loadingRows": "正在加载{label}…",
"loadingData": "正在加载数据…",
"showingTop": "显示 {m} 个中的前 {n} 个",
"useGeocoderHint": "使用上方的搜索框查找其余内容"
}

View file

@ -15,5 +15,7 @@
"disableGlobe": "停用地球仪",
"ctrlScroll": "使用 Ctrl + 滚轮缩放地图",
"cmdScroll": "使用 ⌘ + 滚轮缩放地图",
"twoFingers": "使用两根手指移动地图"
"twoFingers": "使用两根手指移动地图",
"mapboxHomepage": "Mapbox 主页",
"maplibreLogo": "MapLibre 标志"
}

View file

@ -5,5 +5,7 @@
},
"upg100WallHeading": "我的 UPG 100 名單 — 禱告名單與海報",
"upg100WallTag": "禱告動員",
"upg100WallIntro": "將禱告的工作分成五十人、一百人一組 — 就像耶穌餵飽五千人那樣(路加福音 9:14)。每一張海報都是一份 100 人名單,你可以為他們禱告、列印出來、貼在牆上 — <strong>按著他們族群的名字</strong>為他們禱告。"
"upg100WallIntro": "將禱告的工作分成五十人、一百人一組 — 就像耶穌餵飽五千人那樣(路加福音 9:14)。每一張海報都是一份 100 人名單,你可以為他們禱告、列印出來、貼在牆上 — <strong>按著他們族群的名字</strong>為他們禱告。",
"loadingNamed": "正在加载{name}…",
"couldNotLoadNamed": "无法加载{name}。"
}

View file

@ -0,0 +1,4 @@
{
"approximate": "此点标示该民族所在的地区,而非某个城镇或边界。",
"sharedPoint": "它与 {names} 位于同一点 — {n} 个群体共用此坐标,因此位置只表示所在地区,而非各群体的具体位置。"
}

View file

@ -15,5 +15,8 @@
"scale_bar": "比例尺",
"north_arrow": "指北针",
"footer_attribution": "页脚(必须署名)",
"cancel": "取消"
"cancel": "取消",
"map_preview": "地图预览",
"loading_snapshot": "正在加载地图快照…",
"preview_unavailable": "预览不可用"
}

View file

@ -222,9 +222,9 @@
v-for="row in mountedElementRows" :key="row.key"
class="vtl-host" v-show="row.key === active" :hidden="row.key !== active">
<div class="vtl-host-slot" :ref="el => setHostSlot(row.key, el)"></div>
<div v-if="hostState[row.key] === 'loading'" class="vtl-host-hint">Loading {{ row.label }}…</div>
<div v-if="hostState[row.key] === 'loading'" class="vtl-host-hint">{{ T('messages.loadingNamed', 'Loading {name}…').replace('{name}', row.label) }}</div>
<div v-else-if="hostState[row.key] === 'error'" class="vtl-host-hint err">
Could not load {{ row.label }}.<br><small>{{ hostError[row.key] }}</small>
{{ T('messages.couldNotLoadNamed', 'Could not load {name}.').replace('{name}', row.label) }}<br><small>{{ hostError[row.key] }}</small>
</div>
</section>
<!-- Host-owned panes (the SPA/studio render their own here). Always available. -->
@ -237,6 +237,13 @@
<script>
import { defineComponent } from 'vue'
import { tStatic } from '../i18n/index.js'
// This layout's chrome, read out of the catalogue. tStatic and not useI18n: it is the root of a
// custom element, where useI18n() cannot resolve its injection and throws. Exposed from setup()
// rather than kept at module scope, because an options-API template can only see what the component
// returns — a module-level const would compile and then render nothing.
const tr = (key, en) => tStatic(key) || en
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { icon as localIcon } from '@map/layouts/app-wrapper-material/icons.js'
@ -555,6 +562,7 @@ export default defineComponent({
emits: ['update:active'],
setup() {
useShadowStyles(VTL_SHADOW_CSS, 'vertical-tabs-layout')
return { T: tr }
},
data() {
// _folderOverride: user toggles keyed by group key (true=open, false=closed). When a folder

View file

@ -0,0 +1,42 @@
/**
* colocation.js — which people groups share ONE coordinate on a map (APPROXPIN, 2026-09-26).
*
* A people-group pin is a representative point, not an address, and some pins ARE THE SAME POINT:
* measured on the Doxa roster (gospel-plugin): 2,107 groups on 2,048 distinct coordinates, 108 groups on
* a point shared with another (41 pairs, 6 triples, 2 quadruples). Saying "approximate" hides that; naming
* the co-located groups is the only version a reader can check. The index is built from THE ROSTER THE MAP
* DRAWS (every map's roster differs), never hardcoded.
*/
const KEY = (lat, lng) => `${Number(lat).toFixed(6)},${Number(lng).toFixed(6)}`
/** Read [lat, lng] from a roster row or a GeoJSON feature; null when it has no usable position. */
export function pointOf(r) {
if (!r) return null
const c = r.geometry && r.geometry.coordinates
const p = r.properties || r
const lat = c ? c[1] : (p.latitude ?? p.lat), lng = c ? c[0] : (p.longitude ?? p.lng ?? p.lon)
return Number.isFinite(Number(lat)) && Number.isFinite(Number(lng)) && lat !== '' && lng !== '' ? [Number(lat), Number(lng)] : null
}
const nameOf = (r) => { const p = (r && (r.properties || r)) || {}; return p.name || p.peopleName || p.PeopNameInCountry || '' }
/** Build once per roster: Map<coordinate key, names[]>. */
export function buildColocationIndex(rows) {
const idx = new Map()
for (const r of rows || []) {
const pt = pointOf(r); const n = nameOf(r)
if (!pt || !n) continue
const k = KEY(pt[0], pt[1])
if (!idx.has(k)) idx.set(k, [])
idx.get(k).push(n)
}
return idx
}
/** The OTHER groups on this row's point ([] when the point is not shared). */
export function colocatedWith(idx, row) {
const pt = pointOf(row); if (!idx || !pt) return []
const me = nameOf(row)
const all = idx.get(KEY(pt[0], pt[1])) || []
const others = all.filter((n) => n !== me)
return all.length > 1 ? [...new Set(others)] : []
}

View file

@ -19,6 +19,7 @@
"capability-exemplars": "node internal/generate-capability-exemplars.mjs",
"check:a11y-button-names": "node internal/check-a11y-button-names.mjs",
"check:app-start-page": "node internal/set-app-start-page.mjs --check",
"check:approx-pin-note": "node internal/check-approx-pin-note.mjs",
"check:auto-engine": "node internal/check-auto-engine.mjs",
"check:backlog-refs": "node internal/check-backlog-refs.mjs",
"check:backlog-status": "node internal/check-backlog-status-enum.mjs",
@ -207,7 +208,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 check:dashboard-geocoder-provider check:leaf-engine-per-provider check:map-props-unit check:composites-mount check:composite-interop check:no-free-identifiers check:map-fly-reduced-motion check:mst-clustering check:list-prop-unit check:profiles-mount check:cdn-pins check:no-eval check:popup-escaping check:i18n-treeshake check:pinned-umd check:one-palette:self-test check:no-cross-plugin-imports check:no-cross-plugin-imports:self-test check:map-attribution check:studio-rail",
"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 check:map-props-unit check:composites-mount check:composite-interop check:no-free-identifiers check:map-fly-reduced-motion check:mst-clustering check:list-prop-unit check:profiles-mount check:cdn-pins check:no-eval check:popup-escaping check:i18n-treeshake check:pinned-umd check:one-palette:self-test check:no-cross-plugin-imports check:no-cross-plugin-imports:self-test check:map-attribution check:studio-rail check:approx-pin-note",
"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",
"internet:adm1": "node plugin-designs/cities-internet/scripts/build-adm1-internet.mjs",
"library-index": "node internal/generate-library-index.mjs",
@ -259,6 +260,7 @@
"cap:sync": "NOT `bunx` — bunx is not on PATH in this environment (command not found, exit 127), which broke cap:sync -> apk:debug -> phone at step one. The CLI IS installed locally (@capacitor/cli 7.6.9); invoke the local bin directly. The rest of package.json already uses the spaced `bun x` form.",
"capability-exemplars": "regenerate documentation/reference-capability-exemplars.md — the DERIVED answer to \"which bundle is the capability-N example?\", a question answered WRONGLY in three separate artifacts (a gate, the README, the /plugin-designer skill).",
"check:a11y-button-names": "every VISIBLE button must have an accessible name (aria-label / aria-labelledby / visible text — a `title` is a TOOLTIP and does NOT count). Measures the RENDERED DOM through shadow roots: a source grep cannot answer this (132 `<button>` hits, most with visible text). Needs a browser, so NOT in build:unlocked and NOT in CI. ALL=1 sweeps every profile.",
"check:approx-pin-note": "people-group pins say they are localities, not towns or boundaries, in ONE shared wording (library/components/legends/ApproxPinNote.vue): the colocation index finds groups sharing a coordinate, the note names them only for a shared point, never prints a raw coordinate, and renders from each locale's catalogue. Headless.",
"check:auto-engine": "BROWSER. The default engine is auto: on one map leaf, no token draws with MapLibre and makes zero api.mapbox.com requests, a token draws with Mapbox, and an explicit provider wins. Under the fleet browser policy it is a rega run, not part of gates:post.",
"check:backlog-refs": "a card may not depend on a card that does not exist. A dangling depends_on can never be done, so the card can never become ready and nothing says so — it reads as ordinary blocked work forever. FAILS only for depends_on on an OPEN card; a dangling parent or a stale link on a done card is REPORTED, because failing on filing debt teaches people to delete the reference rather than restore the card. Reads all three phase backlogs — references legitimately cross phases. SKIPs when _qa-cycle is absent.",
"check:basemap-labels": "the BASEMAP's place names follow the reader's language on BOTH engines (library/maps/localize-labels.js): reads the RENDERED country labels at ?lang=en and ?lang=ru — Mapbox via the Standard basemap's place-labels featureset, MapLibre via each symbol's evaluated text — and requires them to flip. Serves this checkout on an OS-assigned port; --dir <tree> for a negative control. Negative-tested: a bundle built before 319064a1 FAILS on both engines.",

View file

@ -49,7 +49,7 @@ 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 { ensureEngineScript, engineGlobal, ensureEngineCSS, engineStylesheetUrl } from '@map/composables/useMapInstance.js'
import { ensureEngineScript, engineGlobal, ensureEngineCSS, engineStylesheetUrl, engineUiLocale } from '@map/composables/useMapInstance.js'
import { resolveNamedStyle } from '@map/styles/registry.js'
import { installRtlTextPlugin } from '@map/maps/rtl-text.js'
// People-group dots open the SAME detail panel as Prayer Progress (doxa-simple-map): the
@ -92,6 +92,16 @@ const selectedAdm1 = ref(null)
const PG_DOT = '#e11d48'
const uiStore = inject('uiStore', null)
const _lang = (() => { const v = inject('lang', null)?.value; return (v && v !== 'en') ? v : null })()
// The reader's language for the ENGINE'S OWN labels (the canvas's "Map" name, "Zoom in", attribution…).
// This map is built raw, not through useMapInstance, so it must hand the engine that locale itself;
// without it they stayed English under ar on both engines (rega, row 34). Same ladder as
// useMapInstance's readerLang: ProfileLoader's lang, then profile-config, then ?lang=, then <html lang>.
const readerLang = () => {
if (_lang) return _lang
const pc = profileConfig.value
if (pc && (pc.locale || pc.lang)) return String(pc.locale || pc.lang)
try { const q = new URLSearchParams(location.search); return q.get('lang') || q.get('locale') || document.documentElement.lang || 'en' } catch { return 'en' }
}
const dsm = new DataSourceManager({ locale: _lang, profileConfig })
const groups = shallowRef([])
const dotCount = ref(0)
@ -383,6 +393,7 @@ onMounted(async () => {
style: resolveNamedStyle(isDark.value ? 'ink' : 'paper', ciProvider).style
|| (isDark.value ? 'mapbox://styles/mapbox/dark-v11' : 'mapbox://styles/mapbox/light-v11'),
accessToken: mapboxToken.value,
locale: engineUiLocale(readerLang(), ciProvider),
center: [42, 18], zoom: 1.3, projection: 'mercator', attributionControl: false,
})
mapRef.value = markRaw(map)

View file

@ -76,6 +76,7 @@ import { applyPeopleGroupList } from '@map/lists/peopleGroupList.js'
import { EN_MESSAGES } from '@map/i18n/index.js'
import { useShadowStyles } from '@map/composables/useShadowStyles.js'
import { addMapAttribution } from '@map/composables/useMapAttribution'
import { engineUiLocale } from '@map/composables/useMapInstance.js'
// Map toolbar — canonical modular control rail (MapToolbar slot-wrapper + button
// children). ThemeToggleButton is omitted: this profile's isDark is a read-only
@ -732,6 +733,16 @@ try {
const isEnglish = (() => {
try { return String(useI18n().locale.value || 'en').split('-')[0] === 'en' } catch { return true }
})()
/* The reader's language as a bare tag, for the ENGINE's own control labels. Read the same way
isEnglish is, so the engine's chrome and ours can never disagree about who is reading. */
const readerLang = () => {
try { return String(useI18n().locale.value || 'en') } catch { return 'en' }
}
/* A TRANSLATION WHERE ONE EXISTS, TODAY'S ENGLISH WHERE IT DOES NOT — never the key name.
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 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(', ')
@ -1443,6 +1454,12 @@ onMounted(async () => {
style: resolveNamedStyle(isDark.value ? 'ink' : 'paper', grProvider).style
|| (isDark.value ? 'mapbox://styles/mapbox/dark-v11' : 'mapbox://styles/mapbox/light-v11'),
accessToken: mapboxToken.value,
/* THE ENGINE'S OWN STRINGS, IN THE READER'S LANGUAGE (rega row 34). This leaf calls
`new gl.Map` directly instead of going through useMapInstance, so it did not inherit
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()),
/* 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
@ -1973,7 +1990,7 @@ useShadowStyles(
<button type="button" class="gm-key gm-kbtn wide" :class="{ on: pinFilter === 'hnr' }"
@click="setPinFilter(pinFilter === 'hnr' ? 'all' : 'hnr')"
:aria-pressed="pinFilter === 'hnr'"
title="Groups with recorded audio, the JESUS Film, a Bible video or Words of Life, but no text Scripture found in the pools checked. Not a claim that none exists.">
:title="tOr('gospel.legend.hnrTip', 'Groups with recorded audio, the JESUS Film, a Bible video or Words of Life, but no text Scripture found in the pools checked. Not a claim that none exists.')">
{{ t('gospel.legend.hnr') }}
<b>{{ fmt(pinTally.hnr) }}</b>
</button>

View file

@ -0,0 +1,165 @@
#!/usr/bin/env node
/**
* check-ui-strings-have-keys.mjs — user-visible text must come from the catalogue, and the ground
* we have won must not be given back.
*
* ★ WHY THIS EXISTS, AND WHY NO EXISTING CHECK COULD SEE IT.
* check:composite-locale-leaks asks "does the catalogue translate this string, and is the page
* showing English anyway?" — a LOOKUP, and a good one. But its criterion is that the catalogue
* already HOLDS the string, so a string nobody ever added is invisible to it by construction. And
* it runs in a browser, so it only ever sees what happens to be rendered on one screen.
*
* That blind spot was measured, not guessed: after both composites passed the leak gate with 0
* findings, a source audit of the same two trees found 31 more user-visible strings — 24 with no
* catalogue entry at all and 7 that HAD a translation in eleven languages and were still typed into
* the template. Most were aria-labels, titles and tooltips: text only a screen-reader user or a
* hovering mouse ever meets. Our localization verification had been "what can I see", and the blind
* spot was exactly the readers who most need the words.
*
* TWO CLASSES, because they are different defects with different fixes:
* NO KEY wording must be written and translated — a decision, sometimes the Driver's.
* HAS A KEY the translation already ships in eleven locales and the reader is shown English
* anyway. The cheapest defect in the catalogue: the work was done and wasted.
*
* ★ WARN-ONLY AGAINST A BASELINE, ON PURPOSE. Failing on the whole backlog would make this
* unlandable and it would be switched off within a day. It fails on what is NEW — a string added
* today with no key, or a newly hardcoded one — so the count can only fall. When a batch lands,
* refresh the baseline with --update and the gate holds the new line.
*
* QaCorner is excluded by name: it is an opt-in DEVELOPER widget, not reader-facing, and studio is
* making it host-neutral or removing it. Eleven locales for a corner only we open is not worth the
* translations, and that is a judgement worth writing down rather than leaving as a silent gap.
*
* USAGE node .../check-ui-strings-have-keys.mjs check against the baseline
* node .../check-ui-strings-have-keys.mjs --update rewrite the baseline from today's tree
* Exit: 0 clean or only improvements · 1 a NEW uncatalogued or newly hardcoded string.
*/
import { readFileSync, writeFileSync, readdirSync, statSync, existsSync } from 'node:fs'
import { resolve, dirname, join, relative } from 'node:path'
import { fileURLToPath } from 'node:url'
import { parse as parseSFC } from '@vue/compiler-sfc'
const TAG = 'UI-STRINGS-HAVE-KEYS'
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..', '..')
const BASELINE = join(ROOT, 'plugin-designs', 'research-map-plus-grid', 'scripts', 'ui-strings-baseline.json')
const ROOTS = ['plugin-designs', 'library']
// Not reader-facing: an opt-in developer widget, being made host-neutral or removed.
const EXCLUDE = [/\/qa\/QaCorner\.vue$/]
// ── the catalogue: English value -> the key(s) that hold it ─────────────────────────────────────
const flat = (o, p, out) => {
for (const [k, v] of Object.entries(o || {})) {
const K = p ? `${p}.${k}` : k
if (v && typeof v === 'object') flat(v, K, out); else out[K] = v
}
return out
}
const en = {}
const enDir = join(ROOT, 'library/i18n/locales/en')
for (const f of readdirSync(enDir).filter((f) => f.endsWith('.json'))) {
flat(JSON.parse(readFileSync(join(enDir, f), 'utf8')), f.replace(/\.json$/, ''), en)
}
const known = new Map()
for (const [k, v] of Object.entries(en)) {
const t = String(v).trim()
if (!t) continue
if (!known.has(t)) known.set(t, [])
known.get(t).push(k)
}
const vues = (d, out = []) => {
let es; try { es = readdirSync(d) } catch { return out }
for (const e of es) {
if (e === 'node_modules' || e.startsWith('.')) continue
const p = join(d, e)
if (statSync(p).isDirectory()) vues(p, out); else if (e.endsWith('.vue')) out.push(p)
}
return out
}
const VISIBLE_ATTRS = new Set(['placeholder', 'title', 'aria-label', 'alt', 'label', 'aria-placeholder', 'aria-description'])
/** Worth translating? Real words, not a glyph, a number, a class name or a CSS value. */
const worthIt = (t) => {
const s = String(t || '').trim()
if (s.length < 3 || s.length > 120) return false
if (!/[A-Za-z]{2}/.test(s)) return false
if (!/[A-Za-z]/.test(s[0])) return false
if (/^[a-z][a-z0-9-]*$/.test(s)) return false
if (/[{}<>;]|:\s*\d|px$|rem$|%$/.test(s)) return false
if (/^(true|false|null|undefined)$/i.test(s)) return false
return true
}
function walk(node, hit) {
if (!node) return
if (node.type === 2 && node.content) hit(node.content)
if (node.type === 1) {
for (const p of node.props || []) {
if (p.type === 6 && VISIBLE_ATTRS.has(p.name) && p.value && p.value.content) hit(p.value.content)
}
}
for (const c of node.children || []) walk(c, hit)
if (node.branches) for (const b of node.branches) walk(b, hit)
}
const findings = { noKey: {}, hasKey: {} }
let scanned = 0
for (const r of ROOTS) {
for (const file of vues(join(ROOT, r))) {
const rel = relative(ROOT, file)
if (EXCLUDE.some((re) => re.test(rel))) continue
let d
try { ({ descriptor: d } = parseSFC(readFileSync(file, 'utf8'), { filename: file })) } catch { continue }
if (!d.template || !d.template.ast) continue
scanned++
const seen = new Set()
walk(d.template.ast, (text) => {
const t = String(text).replace(/\s+/g, ' ').trim()
if (!worthIt(t) || seen.has(t)) return
seen.add(t)
const bucket = known.has(t) ? findings.hasKey : findings.noKey
;(bucket[rel] ||= []).push(t)
})
}
}
for (const b of [findings.noKey, findings.hasKey]) for (const k of Object.keys(b)) b[k].sort()
if (process.argv.includes('--update')) {
writeFileSync(BASELINE, JSON.stringify(findings, null, 2) + '\n')
const n = (b) => Object.values(b).reduce((a, l) => a + l.length, 0)
console.log(`${TAG}: baseline rewritten — ${n(findings.noKey)} without a key, ${n(findings.hasKey)} hardcoded-with-a-key, across ${scanned} components.`)
process.exit(0)
}
if (!existsSync(BASELINE)) {
console.log(`${TAG}: FAIL — no baseline at ${relative(ROOT, BASELINE)}. Create it with --update, and read it before you do.`)
process.exit(1)
}
const base = JSON.parse(readFileSync(BASELINE, 'utf8'))
const inBase = (cls, file, text) => (base[cls]?.[file] || []).includes(text)
const fresh = { noKey: [], hasKey: [] }
const fixed = { noKey: [], hasKey: [] }
for (const cls of ['noKey', 'hasKey']) {
for (const [file, list] of Object.entries(findings[cls])) {
for (const t of list) if (!inBase(cls, file, t)) fresh[cls].push([file, t])
}
for (const [file, list] of Object.entries(base[cls] || {})) {
for (const t of list) if (!(findings[cls][file] || []).includes(t)) fixed[cls].push([file, t])
}
}
const count = (b) => Object.values(b).reduce((a, l) => a + l.length, 0)
console.log(`${TAG}: ${scanned} component(s); ${count(findings.noKey)} string(s) with no catalogue entry, ${count(findings.hasKey)} with a key but hardcoded.`)
if (fixed.noKey.length || fixed.hasKey.length) {
console.log(` ✓ ${fixed.noKey.length + fixed.hasKey.length} baseline string(s) fixed since it was set — refresh with --update to hold the new line.`)
}
if (fresh.noKey.length || fresh.hasKey.length) {
console.log(`\n${TAG}: FAIL — ${fresh.noKey.length + fresh.hasKey.length} NEW string(s) since the baseline:`)
for (const [f, t] of fresh.noKey) console.log(` ✗ no key ${f} ${JSON.stringify(t)}`)
for (const [f, t] of fresh.hasKey) console.log(` ✗ has a key ${f} ${JSON.stringify(t)} — the translation already ships; read it instead of typing it`)
console.log('\n A string with NO key needs wording and eleven translations, which is sometimes the')
console.log(' Driver\'s call. A string that HAS a key needs one edit: the work is already done.')
process.exit(1)
}
console.log(`${TAG}: PASS — no new English has appeared in a template since the baseline.`)

View file

@ -0,0 +1,420 @@
{
"noKey": {
"plugin-designs/country-posters/countries-map.vue": [
"Research map loading…"
],
"plugin-designs/doxa-simple-map/doxa-simple-map.vue": [
"pray.doxa.life"
],
"plugin-designs/golden-path-check/golden-path-check.vue": [
"Could not read",
"Golden path — live self-test",
"Reading the catalog manifest…",
"This element was authored in",
"beside this page.",
"bun run build",
"manifest.json",
"plugin-designs/"
],
"plugin-designs/gospel-resources/charts.vue": [
"Counted BY LANGUAGE, so",
"Scripture found:",
"languages have",
"languages present here have nothing found in the pools checked.",
"no scripture and no film found in the pools checked",
"people groups collapse to",
"people in",
"people — cannot appear here. The \"Where Nothing Was Found\" table is keyed per people group and does include them.",
"people.",
"with no ISO 639-3 code in the source —"
],
"plugin-designs/gospel-resources/data-tables.vue": [
"Loading",
"deaths per day.",
"people groups are",
"people, an estimated",
"with no scripture and no film found in the pools checked —"
],
"plugin-designs/gospel-resources/resources-list.vue": [
"The largest are",
"This page lists",
"What “no text” means.",
"Which unengaged people groups have scripture",
"eBible.org",
"in their own language",
"languages — no text Scripture found in the pools checked",
"people groups across",
"published resource availability only",
"translations across"
],
"plugin-designs/gospel-resources/resources-map.vue": [
"A bridge, not a translation",
"A second language is a way in, not a translation — the gap in their own language is unchanged.",
"A “found” colour is equally bounded: it counts what these pools list, not everything that exists.",
"About SUN ↗",
"Bible video ·",
"Bridge strength:",
"DOOR International",
"Deaf Bible Society",
"Deaths/day applies a national crude death rate to a sub-population — order of magnitude, not a count.",
"Every one of those",
"Every resource used in",
"Gospel presentation ·",
"Gospel resources found (",
"How these numbers are made",
"It sits on the same point as",
"Largest with nothing:",
"Link states:",
"Matched on ISO 639-3",
"No resource found (",
"Not ranked and not recommended",
"Not their language — but spoken around them.",
"Nothing found for any group here in the pools checked.",
"Nothing in",
"Nothing was found in",
"Possibly a way in — worth checking locally.",
"SUN",
"SUN is already being taught in",
"Scripture and the JESUS Film",
"Scripture was translated by",
"Scripture,",
"See the 40 largest →",
"Show all",
"Showing 12 of",
"Showing 8 of",
"Showing only",
"So is",
"That is a statement about how the standard groups these codes,",
"That is a statement about the pools searched,",
"The",
"The groups with nothing found in any pool checked AND nobody praying —",
"The largest language among the people groups mapped here that does have Scripture and the JESUS Film is",
"The open catalogues are",
"There is one signed language with Scripture in it.",
"This is a sign language.",
"Training",
"Translated by",
"Way in:",
"What that number is made of.",
"Zume Training publishes its discipleship course in this language — free, no account needed to read it.",
"Zume Training publishes its discipleship course in this language.",
"a different set of groups",
"already praying",
"and is an official language",
"and official",
"both a film and a text Scripture.",
"different situations share it, and only the first is a translation problem:",
"filmed in this sign language",
"finished for every group in the gap",
"from the curated country analysis, over",
"groups (",
"groups doxa.life publishes a page for can appear here at all.",
"groups have nothing ·",
"groups share this coordinate, so the position tells you the locality and not which group is where.",
"groups sharing this language.",
"groups with nothing ·",
"groups ·",
"has a possible way in",
"has resources",
"have a possible way in",
"is never evidence that a link works or fails.",
"is spoken by",
"matches — keep typing to narrow.",
"no text Scripture found in the pools checked",
"nothing found, and nobody praying — open their prayer page ↗",
"of its",
"of them also carry a code no pool can index, so they are doubly stuck.",
"of them. That is a count of THIS MAP's groups, not of the country — no published figure for the country was available.",
"of these",
"of those",
"people groups and does have",
"people groups can already hear the gospel — a recording, the JESUS Film, a Bible video or Words of Life — but have",
"people groups have no Scripture, audio, film, Bible video or Door43 resource in the pools checked —",
"people ·",
"people) — every pool this build can reach was checked and found nothing. This is the real gap.",
"people,",
"people.",
"related:",
"shown, largest first. Tapping one opens their prayer page on doxa.life.",
"sign languages on this map, covering",
"the JESUS Film",
"together with",
"way in:"
],
"plugin-designs/key-cities/cities-list.vue": [
"A cluster of people-group centroids within ~25km —",
"Internet figures are NATIONAL",
"Nominatim/OpenStreetMap",
"This page carries people-group locations and connectivity only — no church, believer or meeting-point data, by design.",
"What a row is.",
"multi-group centres were resolved by"
],
"plugin-designs/my-upg-100-list/upg-100-list.vue": [
"Batch Select",
"Map unavailable",
"Tap territories on the map or legend rows to add · tap again to remove",
"UUPG"
],
"plugin-designs/plugin-studio/plugin-studio.vue": [
"https://doxa.life/api/maps/token",
"pk.eyJ…"
],
"plugin-designs/plugin-studio/src/StudioTree.vue": [
"CAP"
],
"plugin-designs/pplr-data-maps/pplr-data-maps.vue": [
"PPLR data maps"
],
"plugin-designs/pplr-data-maps/src/components/DataSourcesDropdown.vue": [
"Data sources"
],
"plugin-designs/pplr-data-maps/src/components/FlatLegend.vue": [
"Clear selection (Esc)",
"Open legend"
],
"plugin-designs/pplr-data-maps/src/components/LoadingGlobe.vue": [
"Retry"
],
"plugin-designs/pplr-data-maps/src/components/PinDetailCard.vue": [
"Close (Esc)",
"Fly to pin",
"Name in 17 locales"
],
"plugin-designs/pplr-data-maps/src/components/SemanticTreeLegend.vue": [
"Loading",
"Pop",
"Showing top",
"Sort by UPGs",
"UPGs"
],
"plugin-designs/pplr-data-maps/src/views/pplr-coverage.vue": [
"Avg locales / 17",
"Translation coverage · choropleth = avg locales filled per country · click PG pin or country"
],
"plugin-designs/pplr-data-maps/src/views/pplr-d3-tree.vue": [
"Data sources",
"Loading ROP hierarchy",
"ROP Hierarchy · Affinity Bloc → People Cluster · scroll to zoom"
],
"plugin-designs/pplr-data-maps/src/views/pplr-index.vue": [
"Click a tile, or use the topbar tabs above to switch displays. Click",
"Many small displays — each answers one validation question about the PPLR people-group data. Source:",
"PPLR ArcGIS FeatureServer",
"PPLR data validation",
"top-right to see every slot at once."
],
"plugin-designs/pplr-data-maps/src/views/pplr-language-families.vue": [
"Base map",
"Data sources",
"Ethnolinguistic families (PPLR) · click pin for detail",
"Search by people, place, language, religion…"
],
"plugin-designs/pplr-data-maps/src/views/pplr-pins.vue": [
"All PG-in-country pins · click for cross-system IDs",
"Data sources"
],
"plugin-designs/pplr-data-maps/src/views/pplr-religion.vue": [
"Base map",
"Data sources",
"Primary Religion",
"Religion distribution · click pin for detail",
"Search by people, place, language, religion…"
],
"plugin-designs/pplr-data-maps/src/views/pplr-rop-tree.vue": [
"Base map",
"Data sources",
"ROP Hierarchy",
"ROP Hierarchy · Affinity Bloc → Cluster → People Group → PGIC",
"Search by people, place, language, religion…"
],
"plugin-designs/pplr-data-maps/src/views/pplr-rosetta-cards.vue": [
"Cross-system ID Rosetta · color = which IDs exist · ★ = sample row",
"ID coverage"
],
"plugin-designs/pplr-data-maps/src/views/pplr-semantic-trees.vue": [
"API field names per external system",
"Engagement status tiers?",
"Migration corridors?",
"Religious sub-streams?",
"Semantic tree reference",
"Translation lineage?",
"What other semantic trees",
"are hiding in the data?",
"denomination → tradition → school",
"origin → diaspora pathways",
"source language → script → orthography",
"unreached → unengaged → unevangelized"
],
"plugin-designs/pplr-data-maps/src/views/pplr-translations.vue": [
"Data sources",
"PG name · 17 locales · click any pin"
],
"plugin-designs/stack-demo/stack-demo.vue": [
"Stacked view",
"scroll ↓"
],
"plugin-designs/template-bundle/template-map-b.vue": [
"Profile B",
"Served from",
"bundle.",
"in the",
"note:",
"template-map-b.vue"
],
"plugin-designs/upg-neighbor/src/bloom-cockpit.vue": [
"FLOWER",
"LIVE",
"Loading the harvest field…",
"MAP",
"Map or flower view",
"SEND (solid=same-lang · dashed=cluster · dotted=in-country)",
"clusters ·",
"senders →",
"unreached target",
"unreached · baked senders"
],
"plugin-designs/upg-neighbor/src/cockpit/FlowerCell.vue": [
"Pick a red target on the map —",
"its reached neighbors bloom here as a flower.",
"navy = SEND ·",
"same-country ·",
"unreached ·"
],
"plugin-designs/upg-neighbor/src/cockpit/FlowerClusters.vue": [
"Flower-clusters",
"reached petals · by",
"red cores (clustered) → granular green reached petals (same language)",
"taxonomy = research-map semantic tree (family→language→dialect)",
"unreached = LIVE pray.doxa.life · reached = baked PPLR"
],
"plugin-designs/upg-neighbor/src/cockpit/ListCell.vue": [
"Adjacency",
"Bridge",
"Build send list",
"Code",
"Details",
"No senders match the current filters",
"Pick a red target",
"Tap a red bubble on the map to build its send list.",
"This target has no reached neighbors in the baked set yet",
"reached senders nearby",
"senders available",
"senders hidden — clear a facet to see them",
"unreached clusters ·"
],
"plugin-designs/upg-neighbor/src/flower-mesh.vue": [
"Flower-Mesh",
"center = doxa-2000 (pray.doxa.life)",
"km)",
"neighbors = baked",
"province N/A in source — finest grain = country (see RE)",
"reached neighbor → unreached center"
],
"plugin-designs/upg-neighbor/src/lang-cluster.vue": [
"Bounded sets",
"IN/CN province = real ADM1 (my-upg-100-list point-in-polygon)",
"Language clusters",
"reached = baked reached-neighbors",
"red unreached · green reached-by-language",
"unreached = LIVE pray.doxa.life ("
],
"plugin-designs/upg-neighbor/src/send-map.vue": [
"Adjacency",
"Language pair",
"Lower persecution",
"No qualifying reached senders with a known country centroid for this target.",
"SEND",
"UPGs ·",
"chain: UPG-100 → FPG base → My UPG Neighbor",
"km)",
"reached neighbor → unreached target",
"reached senders",
"senders = baked",
"target = LIVE (JP UnreachedPeoplesByCountry)"
],
"plugin-designs/wall-of-people-groups/src/components/PeopleGroupCard.vue": [
"View prayers and comments",
"prayed that they would receive God's love and the love of a missionary"
],
"plugin-designs/wall-of-people-groups/src/components/SourceSelector.vue": [
"CSV includes ~1,439 groups with images from Joshua Project",
"Current:",
"Live prayer data — people praying, committed workers, adoption, images",
"Source URL:",
"WordPress API — descriptions & photos, no prayer data"
],
"plugin-designs/wall-of-people-groups/wall-of-people-groups.vue": [
"The wall could not load its drawing library:"
],
"library/ProfileLoader.vue": [
"Example:",
"not found.",
"prop."
],
"library/components/legends/LegendRows.vue": [
"Toggle children"
]
},
"hasKey": {
"plugin-designs/country-posters/countries-map.vue": [
"The map could not be loaded."
],
"plugin-designs/country-posters/country-posters-mfe.vue": [
"Views"
],
"plugin-designs/demo-map/demo-map.vue": [
"Loading map…",
"The map could not be loaded."
],
"plugin-designs/doxa-maps-spa/doxa-maps-spa.vue": [
"Change language"
],
"plugin-designs/gospel-resources/charts.vue": [
"people group"
],
"plugin-designs/gospel-resources/resources-map.vue": [
"Audio",
"Bible video",
"Find a people group, language or ISO code",
"Loading resources…",
"Scripture",
"Show all groups",
"Showing",
"The dot marks where this people is found, not a town or a boundary.",
"link checked"
],
"plugin-designs/pplr-data-maps/pplr-data-maps.vue": [
"Choose a view"
],
"plugin-designs/pplr-data-maps/src/components/FlatLegend.vue": [
"Legend"
],
"plugin-designs/pplr-data-maps/src/components/PinDetailCard.vue": [
"Close",
"People Group"
],
"plugin-designs/pplr-data-maps/src/components/SemanticTreeLegend.vue": [
"Loading data…",
"No data at this level",
"Sort by Population",
"use the geocoder above to find the rest"
],
"plugin-designs/pplr-data-maps/src/views/pplr-index.vue": [
"Overview"
],
"plugin-designs/pplr-data-maps/src/views/pplr-language-families.vue": [
"Language Families"
],
"plugin-designs/upg-neighbor/src/cockpit/ListCell.vue": [
"Country",
"Export",
"Language",
"People group",
"Population",
"Religion"
],
"library/components/poster/PosterWall.vue": [
"people groups"
]
}
}

File diff suppressed because one or more lines are too long

View file

@ -36,7 +36,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-8rqwLEQ0MCPH6srSqGcrf0r9Ca2UxpnHyrLiF0lKZJlXPHdnhMc0Dl6nY6cCeBmN" crossorigin="anonymous"></script>
<script src="../all-people-groups.js" integrity="sha384-Nbxk0XCRXF7Hk+SRFe1ELYRpi17umTAnmHvxyFK2zZgb6FdbE/rKlStPeKI1mHf5" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -32,7 +32,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-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -36,7 +36,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-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -32,7 +32,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-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9" crossorigin="anonymous"></script>
<script src="../cities-internet.js" integrity="sha384-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -36,7 +36,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-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -32,7 +32,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-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -47,7 +47,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-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI" crossorigin="anonymous"></script>
<script src="../country-posters.js" integrity="sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -47,7 +47,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-5Yvna6wDcKVmPHD5Gc+ed3n+AAxx4a2hM4IwHIb08bus3WNjC5Eq9mC4lxH+T2VM" crossorigin="anonymous"></script>
<script src="../../dashboard-plus-grid.js" integrity="sha384-MEKfB+l81kMnJzhvslh4YCXoA4AIdi00sgFqe87KNAUGp68dKmwO1/05TTMrkoBO" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -47,7 +47,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-5Yvna6wDcKVmPHD5Gc+ed3n+AAxx4a2hM4IwHIb08bus3WNjC5Eq9mC4lxH+T2VM" crossorigin="anonymous"></script>
<script src="../dashboard-plus-grid.js" integrity="sha384-MEKfB+l81kMnJzhvslh4YCXoA4AIdi00sgFqe87KNAUGp68dKmwO1/05TTMrkoBO" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -36,7 +36,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-VwwqaqWnh7Eu2Z109JkgeZKUqoZvOQUFKbM75tfyJSBoe9TNMI7yDjzo2YVvFmvx" crossorigin="anonymous"></script>
<script src="../demo-map.js" integrity="sha384-VurWSvaAQ4GLea5h7qCLYDPRkGJFbnziOc4sMuKrAY3ow+Po8bcHKvVhDD5iIEg9" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -33,7 +33,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-VwwqaqWnh7Eu2Z109JkgeZKUqoZvOQUFKbM75tfyJSBoe9TNMI7yDjzo2YVvFmvx" crossorigin="anonymous"></script>
<script src="../../demo-map.js" integrity="sha384-VurWSvaAQ4GLea5h7qCLYDPRkGJFbnziOc4sMuKrAY3ow+Po8bcHKvVhDD5iIEg9" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -32,7 +32,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
<script src="../../doxa-maps-spa.js" integrity="sha384-3oieM9DBAZT405/cnEiwdILeKEl61JlrjNW00BS0xGcfESTGbEPe5cqKFCPLuJv6" crossorigin="anonymous"></script>
<script src="../../doxa-maps-spa.js" integrity="sha384-ZdZNtw5tcs6hvlrye+/KEPQ+S4AcPtLTnwcpMbQPAYAweYo6C61qNea8oNTSxY06" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -32,7 +32,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <doxa-maps-spa> custom element. -->
<script src="../doxa-maps-spa.js" integrity="sha384-3oieM9DBAZT405/cnEiwdILeKEl61JlrjNW00BS0xGcfESTGbEPe5cqKFCPLuJv6" crossorigin="anonymous"></script>
<script src="../doxa-maps-spa.js" integrity="sha384-ZdZNtw5tcs6hvlrye+/KEPQ+S4AcPtLTnwcpMbQPAYAweYo6C61qNea8oNTSxY06" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -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-8rqwLEQ0MCPH6srSqGcrf0r9Ca2UxpnHyrLiF0lKZJlXPHdnhMc0Dl6nY6cCeBmN",
"integrity": "sha384-Nbxk0XCRXF7Hk+SRFe1ELYRpi17umTAnmHvxyFK2zZgb6FdbE/rKlStPeKI1mHf5",
"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. 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=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-8rqwLEQ0MCPH6srSqGcrf0r9Ca2UxpnHyrLiF0lKZJlXPHdnhMc0Dl6nY6cCeBmN\" 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. 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=\"./all-people-groups/all-people-groups.js\" integrity=\"sha384-Nbxk0XCRXF7Hk+SRFe1ELYRpi17umTAnmHvxyFK2zZgb6FdbE/rKlStPeKI1mHf5\" 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"
}
@ -104,7 +104,7 @@
"bundle": "cities-internet",
"scriptUrl": "./cities-internet/cities-internet.js",
"output": "dx-maps/cities-internet/cities-internet.js",
"integrity": "sha384-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9",
"integrity": "sha384-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp",
"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-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9\" 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-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp\" 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. 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=\"./cities-internet/cities-internet.js\" integrity=\"sha384-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9\" 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. 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=\"./cities-internet/cities-internet.js\" integrity=\"sha384-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp\" 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-fn/XqzAvikU3wkpcVg0TllWNs4sP9V5ahWKYodEhmXO+eFTWfUkR+Qx+5Sz2moN9\" 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-3WSedZ9tfPG02UIuZx9J7szxNHaGB/gaWW5cJ4gkJ83gRWCtrPSmlT/l7HVR+yzp\" 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-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI",
"integrity": "sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo",
"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. 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=\"./country-posters/country-posters.js\" integrity=\"sha384-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI\" 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. 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=\"./country-posters/country-posters.js\" integrity=\"sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo\" 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-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI\" 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-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo\" 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. 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=\"./country-posters/country-posters.js\" integrity=\"sha384-pSEjrRVgGp3ArV0+sMjER5pDVl/MZIQntQAc/DfrK7ENXykRDug54abbm3wcjOoI\" 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. 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=\"./country-posters/country-posters.js\" integrity=\"sha384-GSjFaBfN5YTxQrtqJMI5DAEDtUQ88fP9xTVVNQ+UGhzCWzvKuu10xSiHkynYPtXo\" 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-5Yvna6wDcKVmPHD5Gc+ed3n+AAxx4a2hM4IwHIb08bus3WNjC5Eq9mC4lxH+T2VM",
"integrity": "sha384-MEKfB+l81kMnJzhvslh4YCXoA4AIdi00sgFqe87KNAUGp68dKmwO1/05TTMrkoBO",
"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. 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=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-5Yvna6wDcKVmPHD5Gc+ed3n+AAxx4a2hM4IwHIb08bus3WNjC5Eq9mC4lxH+T2VM\" 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. 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=\"./dashboard-plus-grid/dashboard-plus-grid.js\" integrity=\"sha384-MEKfB+l81kMnJzhvslh4YCXoA4AIdi00sgFqe87KNAUGp68dKmwO1/05TTMrkoBO\" 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-VwwqaqWnh7Eu2Z109JkgeZKUqoZvOQUFKbM75tfyJSBoe9TNMI7yDjzo2YVvFmvx",
"integrity": "sha384-VurWSvaAQ4GLea5h7qCLYDPRkGJFbnziOc4sMuKrAY3ow+Po8bcHKvVhDD5iIEg9",
"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. 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=\"./demo-map/demo-map.js\" integrity=\"sha384-VwwqaqWnh7Eu2Z109JkgeZKUqoZvOQUFKbM75tfyJSBoe9TNMI7yDjzo2YVvFmvx\" 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. 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=\"./demo-map/demo-map.js\" integrity=\"sha384-VurWSvaAQ4GLea5h7qCLYDPRkGJFbnziOc4sMuKrAY3ow+Po8bcHKvVhDD5iIEg9\" 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": [
{
@ -301,7 +301,7 @@
"bundle": "doxa-maps-spa",
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"output": "dx-maps/doxa-maps-spa/doxa-maps-spa.js",
"integrity": "sha384-3oieM9DBAZT405/cnEiwdILeKEl61JlrjNW00BS0xGcfESTGbEPe5cqKFCPLuJv6",
"integrity": "sha384-ZdZNtw5tcs6hvlrye+/KEPQ+S4AcPtLTnwcpMbQPAYAweYo6C61qNea8oNTSxY06",
"elements": [
"doxa-maps-spa"
],
@ -326,7 +326,7 @@
"scriptUrl": "./doxa-maps-spa/doxa-maps-spa.js",
"embed": {
"iframe": "<iframe src=\"./doxa-maps-spa/doxa-maps-spa/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=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-3oieM9DBAZT405/cnEiwdILeKEl61JlrjNW00BS0xGcfESTGbEPe5cqKFCPLuJv6\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./doxa-maps-spa/doxa-maps-spa.js\" integrity=\"sha384-ZdZNtw5tcs6hvlrye+/KEPQ+S4AcPtLTnwcpMbQPAYAweYo6C61qNea8oNTSxY06\" crossorigin=\"anonymous\"></script>\n<doxa-maps-spa profile-config='{\"profile\":\"doxa-maps-spa\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></doxa-maps-spa>"
},
"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-/CrEOS84aq6H2h49BU5qh/UyhN024nEtPoVbBXQbqGjZN3NaFhxVtl5i3nw9LnDt",
"integrity": "sha384-//BWiBJKnO5FZj7OXyG5ARk5GoRTu6AxITWq5hQNfNMw6CJH/hHA6oaxAhO163zH",
"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. 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=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-/CrEOS84aq6H2h49BU5qh/UyhN024nEtPoVbBXQbqGjZN3NaFhxVtl5i3nw9LnDt\" 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. 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=\"./doxa-research-map/doxa-research-map.js\" integrity=\"sha384-//BWiBJKnO5FZj7OXyG5ARk5GoRTu6AxITWq5hQNfNMw6CJH/hHA6oaxAhO163zH\" 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-IzP+TYwOcLqEGl+vLlFnN2o810DYxWQbrmPfcSbL/GQgdQDPM7JK4cQrGf4LV2jQ",
"integrity": "sha384-0jGwjrxPWnf55BStWaZ1KLTPoWoJ2BVTZfXpl9LQUcX7nle2ZeFTuMg04r9q1686",
"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. 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=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-IzP+TYwOcLqEGl+vLlFnN2o810DYxWQbrmPfcSbL/GQgdQDPM7JK4cQrGf4LV2jQ\" 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. 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=\"./doxa-simple-map/doxa-simple-map.js\" integrity=\"sha384-0jGwjrxPWnf55BStWaZ1KLTPoWoJ2BVTZfXpl9LQUcX7nle2ZeFTuMg04r9q1686\" 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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX",
"integrity": "sha384-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD",
"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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX\" 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-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD\" 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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX\" 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-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD\" 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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX\" 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-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD\" 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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX\" 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-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD\" 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-0RXI6YQmfeqjYqe0XQbPDR0Ftki055fH7BKpfHisu2qqyzY2jSf48vYfhQ8qYbzX\" 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-p263yTKAy2jJeJe43nwf9HwtYzizSAfpRw3amZkiqSp9ov0dl1O1Igjdzu6rPmAD\" 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-WfLw90ABBRt200wUJDZ4AuepgEAf15b3OeprbdcU41QhpNXE/fYVK/SetuFQKJdH",
"integrity": "sha384-eUIpcAwx1aA/m27z1RXdT1GqUfpKOJOBU/GIpTKbYBGXXeCl7aZzPkeSrMMiUkMx",
"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-WfLw90ABBRt200wUJDZ4AuepgEAf15b3OeprbdcU41QhpNXE/fYVK/SetuFQKJdH\" 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-eUIpcAwx1aA/m27z1RXdT1GqUfpKOJOBU/GIpTKbYBGXXeCl7aZzPkeSrMMiUkMx\" 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. 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=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-WfLw90ABBRt200wUJDZ4AuepgEAf15b3OeprbdcU41QhpNXE/fYVK/SetuFQKJdH\" 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. 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=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-eUIpcAwx1aA/m27z1RXdT1GqUfpKOJOBU/GIpTKbYBGXXeCl7aZzPkeSrMMiUkMx\" 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. 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=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-WfLw90ABBRt200wUJDZ4AuepgEAf15b3OeprbdcU41QhpNXE/fYVK/SetuFQKJdH\" 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. 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=\"./my-upg-100-list/my-upg-100-list.js\" integrity=\"sha384-eUIpcAwx1aA/m27z1RXdT1GqUfpKOJOBU/GIpTKbYBGXXeCl7aZzPkeSrMMiUkMx\" 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>"
}
}
]
@ -781,7 +781,7 @@
"bundle": "plugin-studio",
"scriptUrl": "./plugin-studio/plugin-studio.js",
"output": "dx-maps/plugin-studio/plugin-studio.js",
"integrity": "sha384-SRHKnE5CmMXYbfq62EJxnMzbdjxIWOJC2Tyj0D9Z3JgwPKq8TjRfH8gVm1KugwN0",
"integrity": "sha384-Hm8H3zmSG4Z6QE3U5KOK4yQITwoHb6Pl6EIj3bSWUuuMs2YGcrqCLeLM8Y6EHE1o",
"elements": [
"plugin-studio"
],
@ -809,7 +809,7 @@
"scriptUrl": "./plugin-studio/plugin-studio.js",
"embed": {
"iframe": "<iframe src=\"./plugin-studio/plugin-studio/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=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-SRHKnE5CmMXYbfq62EJxnMzbdjxIWOJC2Tyj0D9Z3JgwPKq8TjRfH8gVm1KugwN0\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
"script": "<script>window.MAP_APP_API_URL=\"https://pray.doxa.life\";</script>\n<script src=\"./plugin-studio/plugin-studio.js\" integrity=\"sha384-Hm8H3zmSG4Z6QE3U5KOK4yQITwoHb6Pl6EIj3bSWUuuMs2YGcrqCLeLM8Y6EHE1o\" crossorigin=\"anonymous\"></script>\n<plugin-studio profile-config='{\"profile\":\"plugin-studio\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></plugin-studio>"
},
"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-zl/7rCcl87TEwtnYDVPuNb1vEZ5R0JLfN811T2ppUACgqxCYW1pidhreNUKGe/12",
"integrity": "sha384-5vzwRjw77x1BLJlLIb7RTmxc2hphP9GEMa75GDiBtRkN6jGdLEF7My4tKT/SjbsK",
"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. 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=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-zl/7rCcl87TEwtnYDVPuNb1vEZ5R0JLfN811T2ppUACgqxCYW1pidhreNUKGe/12\" 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. 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=\"./pplr-data-maps/pplr-data-maps.js\" integrity=\"sha384-5vzwRjw77x1BLJlLIb7RTmxc2hphP9GEMa75GDiBtRkN6jGdLEF7My4tKT/SjbsK\" 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-8A4fz8QD1mfQqomQ7WuDzFWXQojs6WapA5sz9MFjuOYt3evO0uyOt4k8+9gAI8S7",
"integrity": "sha384-YGKO2e+BZTuNjfZzlWY9BdwMADy3kJrlKKjbSVYV11Gup/JjVrWyz80yUL0MdxOO",
"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. 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=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-8A4fz8QD1mfQqomQ7WuDzFWXQojs6WapA5sz9MFjuOYt3evO0uyOt4k8+9gAI8S7\" 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. 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=\"./prayer-walk-planner/prayer-walk-planner.js\" integrity=\"sha384-YGKO2e+BZTuNjfZzlWY9BdwMADy3kJrlKKjbSVYV11Gup/JjVrWyz80yUL0MdxOO\" 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-szmbfFfvaS0M/DAcKz5JaD/g0rbp4q5u8epiJNz23VZskl3jHQ4YrJK0Ptg+SfUq",
"integrity": "sha384-nqfxMTXkGhiAaqxHCTAvzDOcKh7kO4NBaDv9lEskjq/ZiFQ0hYlEfbO+CFXwzaFn",
"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. 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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-szmbfFfvaS0M/DAcKz5JaD/g0rbp4q5u8epiJNz23VZskl3jHQ4YrJK0Ptg+SfUq\" 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. 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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-nqfxMTXkGhiAaqxHCTAvzDOcKh7kO4NBaDv9lEskjq/ZiFQ0hYlEfbO+CFXwzaFn\" 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-szmbfFfvaS0M/DAcKz5JaD/g0rbp4q5u8epiJNz23VZskl3jHQ4YrJK0Ptg+SfUq\" 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-nqfxMTXkGhiAaqxHCTAvzDOcKh7kO4NBaDv9lEskjq/ZiFQ0hYlEfbO+CFXwzaFn\" 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. 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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-szmbfFfvaS0M/DAcKz5JaD/g0rbp4q5u8epiJNz23VZskl3jHQ4YrJK0Ptg+SfUq\" 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. 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=\"./regions-dashboard/regions-dashboard.js\" integrity=\"sha384-nqfxMTXkGhiAaqxHCTAvzDOcKh7kO4NBaDv9lEskjq/ZiFQ0hYlEfbO+CFXwzaFn\" 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-40xjIv1DesZgQORPeB88ouk4P0u16BjSFJA8AC6eTpHobWUXbbbzNSMJWkYoAQSA",
"integrity": "sha384-UVgH/Gz7zLEaYk588PEssO9IQLroK16w1zqRU/DF210FrMRvVoGFnuWMCeDh4odB",
"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. 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=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-40xjIv1DesZgQORPeB88ouk4P0u16BjSFJA8AC6eTpHobWUXbbbzNSMJWkYoAQSA\" 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. 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=\"./research-dashboard/research-dashboard.js\" integrity=\"sha384-UVgH/Gz7zLEaYk588PEssO9IQLroK16w1zqRU/DF210FrMRvVoGFnuWMCeDh4odB\" 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"
}
@ -1058,7 +1058,7 @@
"bundle": "upg-neighbor",
"scriptUrl": "./upg-neighbor/upg-neighbor.js",
"output": "dx-maps/upg-neighbor/upg-neighbor.js",
"integrity": "sha384-Tva3pof7Llydfn2sFUmvWWPyeVNPJ+SHYCtQJwNQd0Etq2lusUoIFOuT100QJlBB",
"integrity": "sha384-0Lvr21zGpq8gs2h3e4MRdDyNFf5lMH9197LDerKVvdnSkAkIxU4dBD1XQbIEowhH",
"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. 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=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-Tva3pof7Llydfn2sFUmvWWPyeVNPJ+SHYCtQJwNQd0Etq2lusUoIFOuT100QJlBB\" 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. 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=\"./upg-neighbor/upg-neighbor.js\" integrity=\"sha384-0Lvr21zGpq8gs2h3e4MRdDyNFf5lMH9197LDerKVvdnSkAkIxU4dBD1XQbIEowhH\" 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": [
{
@ -1157,7 +1157,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-knrQigyHlLQRSTw+xROhwusY2CkjmzvdDjWLlfiXpwsTFWlZhzxxDhs8SoO/qxkm",
"integrity": "sha384-wljGjbV7gbuaJz4ixErUnJKMvhsgcpS41wV/L6Rnog741NUWI7XABssq67Lk4026",
"elements": [
"wall-of-people-groups"
],
@ -1173,7 +1173,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-knrQigyHlLQRSTw+xROhwusY2CkjmzvdDjWLlfiXpwsTFWlZhzxxDhs8SoO/qxkm\" 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-wljGjbV7gbuaJz4ixErUnJKMvhsgcpS41wV/L6Rnog741NUWI7XABssq67Lk4026\" 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"
}

File diff suppressed because one or more lines are too long

View file

@ -36,7 +36,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-/CrEOS84aq6H2h49BU5qh/UyhN024nEtPoVbBXQbqGjZN3NaFhxVtl5i3nw9LnDt" crossorigin="anonymous"></script>
<script src="../doxa-research-map.js" integrity="sha384-//BWiBJKnO5FZj7OXyG5ARk5GoRTu6AxITWq5hQNfNMw6CJH/hHA6oaxAhO163zH" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -33,7 +33,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-/CrEOS84aq6H2h49BU5qh/UyhN024nEtPoVbBXQbqGjZN3NaFhxVtl5i3nw9LnDt" crossorigin="anonymous"></script>
<script src="../../doxa-research-map.js" integrity="sha384-//BWiBJKnO5FZj7OXyG5ARk5GoRTu6AxITWq5hQNfNMw6CJH/hHA6oaxAhO163zH" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -36,7 +36,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-IzP+TYwOcLqEGl+vLlFnN2o810DYxWQbrmPfcSbL/GQgdQDPM7JK4cQrGf4LV2jQ" crossorigin="anonymous"></script>
<script src="../../doxa-simple-map.js" integrity="sha384-0jGwjrxPWnf55BStWaZ1KLTPoWoJ2BVTZfXpl9LQUcX7nle2ZeFTuMg04r9q1686" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -36,7 +36,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-IzP+TYwOcLqEGl+vLlFnN2o810DYxWQbrmPfcSbL/GQgdQDPM7JK4cQrGf4LV2jQ" crossorigin="anonymous"></script>
<script src="../../doxa-simple-map.js" integrity="sha384-0jGwjrxPWnf55BStWaZ1KLTPoWoJ2BVTZfXpl9LQUcX7nle2ZeFTuMg04r9q1686" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

View file

@ -36,7 +36,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-IzP+TYwOcLqEGl+vLlFnN2o810DYxWQbrmPfcSbL/GQgdQDPM7JK4cQrGf4LV2jQ" crossorigin="anonymous"></script>
<script src="../doxa-simple-map.js" integrity="sha384-0jGwjrxPWnf55BStWaZ1KLTPoWoJ2BVTZfXpl9LQUcX7nle2ZeFTuMg04r9q1686" crossorigin="anonymous"></script>
<script>
// Mapbox token resolution — the A3 ladder, in precedence order:

Some files were not shown because too many files have changed in this diff Show more