Update from source 4244c9097
Some checks are pending
Deploy to GitHub Pages / build (push) Waiting to run
Deploy to GitHub Pages / deploy (push) Blocked by required conditions

This commit is contained in:
Doxa Maps 2026-09-28 02:15:02 +00:00
parent e76a2fc7ae
commit 33ba66e297
24 changed files with 1412 additions and 59 deletions

View file

@ -0,0 +1,61 @@
BOUNDARY DATA — SOURCES AND ATTRIBUTION
=======================================
The .geojson files in this folder are third-party boundary data. Every value below is taken
VERBATIM from the upstream metadata (the geoBoundaries API, https://www.geoboundaries.org/api/current/gbOpen/<ISO3>/<LEVEL>/).
Nothing here is our own wording about a licence.
gb-IND-ADM1-full.geojson, gb-IND-ADM1-full-web.geojson
source geoBoundaries gbOpen (www.geoboundaries.org)
boundaryID IND-ADM1-1811400
licence Creative Commons Attribution 2.5 India (CC BY 2.5 IN)
licenceSource github.com/datameet/maps
year 2011
ATTRIBUTION IS REQUIRED for this file: it is Creative Commons Attribution, so a work that
redistributes or displays it must credit the source above.
gb-IND-ADM1.geojson, gb-IND-ADM1-web.geojson
The same India ADM1 boundary as above, curated to the UPG-100 list's partition.
Same source, same boundaryID, same licence, same attribution duty.
gb-CHN-ADM1.geojson
source geoBoundaries gbOpen (www.geoboundaries.org)
boundaryID CHN-ADM1-43563684
licence Public Domain
licenceSource commons.wikimedia.org/wiki/File
year 2019
No attribution duty: upstream records this boundary as Public Domain.
world-adm0.geojson, world-adm0-web.geojson
source geoBoundaries gbOpen (www.geoboundaries.org), assembled per country
features 162 countries
licence MIXED — and now ESTABLISHED per country, not merely acknowledged.
THE PER-COUNTRY TABLE IS THE AUTHORITY, and it lives in ONE place on purpose:
plugin-designs/my-upg-100-list/data/adm0/PROVENANCE.json
It records boundaryLicense, licenseSource and boundaryID for all 162, each value taken
verbatim from https://www.geoboundaries.org/api/current/gbOpen/<ISO3>/<LEVEL>/ (162 queries,
0 failures, one spot-check re-verified against the live API). This file deliberately does NOT
copy that table: one table in two places drifts.
130 OF THE 162 CARRY A DUTY. Only 32 are duty-free (28 Public Domain, 4 CC0). By class:
ATTRIBUTION-ONLY (credit the source)
44 CC BY 4.0 13 CC BY 3.0 IGO 4 CC BY 2.5 2 CC BY 3.0
2 Open Government Licence v3
SHARE-ALIKE CLASS — A STRONGER DUTY: a derivative may have to be licensed alike, which is
the class that actually constrains giving this repository away.
58 Open Data Commons ODbL 1.0
7 Creative Commons ShareAlike 2.0 / 3.0 — AGO GAB GEO GIN MMR NER TUR
ODbL IS LISTED IN THAT CLASS DELIBERATELY. Alongside attribution it requires a Derivative
Database to be offered under ODbL and carries a keep-open provision, so by volume the
share-alike question covers 65 of 162 countries, not 7. This repository has already acted on
that reading once: library/scripts/posters/data/README.md records that Natural Earth's 1:10m
ROADS were requested and deliberately NOT shipped because of an ODbL obligation.
WHETHER 'licensed alike' binds a giveaway of this repository is a legal question, not a
measurement, and it is open. It is recorded here so nobody has to rediscover it.
duty-free: 28 Public Domain, 4 CC0.
See documentation/THIRD-PARTY.md for the whole shipped tree.

View file

@ -162,13 +162,18 @@ The only other thing here is `DX_PB_PORT`, which you set only if the log says po
## One more thing to set ## One more thing to set
The maps need a Mapbox token. It is the one credential you have to ask the team for: Copy `.env.example` to `.env.local`. **Every line in it is optional** — empty means the default, which is
the all-local setup described above. You can start with none of them filled in.
The one you will probably want is a Mapbox token, which is the single credential you have to ask the team
for:
``` ```
VITE_MAPBOX_TOKEN=<ask the team> VITE_MAPBOX_TOKEN=<ask the team>
``` ```
That, plus `DX_SYNC_REMOTE=origin` if you want it, is the whole of `.env.local`. Leave it empty and the Mapbox-backed maps will not draw; you can also work with the keyless MapLibre
provider instead.
--- ---

View file

@ -12,10 +12,11 @@ served folder". The licence travels with the asset; the explanation travels with
| Fonts: bebas-neue, figtree, noto-serif-devanagari, oswald, poppins | Google Fonts / foundry repos | OFL-1.1 | **Yes** — each `LICENSE` is the family's own upstream OFL, verbatim, with its real copyright line | none (closed 2026-09-28) | | Fonts: bebas-neue, figtree, noto-serif-devanagari, oswald, poppins | Google Fonts / foundry repos | OFL-1.1 | **Yes** — each `LICENSE` is the family's own upstream OFL, verbatim, with its real copyright line | none (closed 2026-09-28) |
| `vendor/vue/vue.global.prod.js` | vuejs/core | MIT | **Partly** — the minified banner carries `(c) 2018-present Yuxi (Evan) You` and `@license MIT`, but NOT the permission notice MIT asks to include | closed: upstream `LICENSE` now vendored beside it | | `vendor/vue/vue.global.prod.js` | vuejs/core | MIT | **Partly** — the minified banner carries `(c) 2018-present Yuxi (Evan) You` and `@license MIT`, but NOT the permission notice MIT asks to include | closed: upstream `LICENSE` now vendored beside it |
| `vendor/tabulator/tabulator.min.js` + `.min.css` | olifolkerd/tabulator v6.3.1 | MIT | **No** — the `.js` had only `(c) Oliver Folkerd 2025`; the `.css` had nothing | closed: upstream `LICENSE` now vendored beside it | | `vendor/tabulator/tabulator.min.js` + `.min.css` | olifolkerd/tabulator v6.3.1 | MIT | **No** — the `.js` had only `(c) Oliver Folkerd 2025`; the `.css` had nothing | closed: upstream `LICENSE` now vendored beside it |
| `boundaries/gb-*.geojson` (4 files) | geoBoundaries gbOpen (www.geoboundaries.org) | CC BY — the India ADM1 file records **CC BY 2.5 IN**, sourced from DataMeet/Election Commission of India | **Partly** — provenance sits in ONE sidecar, `gb-IND-ADM1-full.meta.json` (source, boundaryID, licence, fetch URL, processing). The other boundary files have none, and no human-readable attribution ships | **OPEN** — CC BY requires attribution to accompany the work | | `boundaries/gb-IND-ADM1*.geojson` (4 files) | geoBoundaries gbOpen, boundaryID `IND-ADM1-1811400` | **CC BY 2.5 IN**, licenceSource `github.com/datameet/maps`, year 2011 — fetched verbatim from the geoBoundaries API | **Yes** — `boundaries/ATTRIBUTION` now ships beside the data, plus the existing `.meta.json` sidecar | none (closed 2026-09-28) |
| `boundaries/world-adm0*.geojson` | not verified — probably Natural Earth | Natural Earth is public domain | n/a if Natural Earth | **OPEN** — provenance unconfirmed for this file | | `boundaries/gb-CHN-ADM1.geojson` | geoBoundaries gbOpen, boundaryID `CHN-ADM1-43563684` | **Public Domain**, licenceSource `commons.wikimedia.org`, year 2019 | recorded in `boundaries/ATTRIBUTION` | none — upstream records no attribution duty |
| `boundaries/world-adm0*.geojson` (2 files, 162 countries) | **geoBoundaries gbOpen, assembled per country** — corrected: its features carry geoBoundaries' own `iso3`/`shapeGroup`/`shapeName` properties, and the plugin's `data/adm0/PROVENANCE.json` names the source and endpoint. NOT Natural Earth, as this register first guessed | **MIXED — up to 162 different upstream licences.** gbOpen passes each country's own licence through | the principle is stated in `boundaries/ATTRIBUTION`; the per-country licences are **not** | **OPEN** — that PROVENANCE.json's `licences` table is EMPTY, so which of the 162 are CC BY is unestablished. Closing it means one API query per country. upg100-plugin's data; routed to them |
| `people-groups/*` (3 files, 8 MB) | peoplegroups.org | **not established** | no terms ship | **OPEN, judgment** — redistribution terms unknown | | `people-groups/*` (3 files, 8 MB) | peoplegroups.org | **not established** | no terms ship | **OPEN, judgment** — redistribution terms unknown |
| `pplr/*` (6 files, 16 MB) | not resolved from `plugin-designs/pplr-data-maps/scripts/build-data.mjs` | **not established** | nothing ships | **OPEN, judgment** — owner should name the upstream | | `pplr/*` (6 files, 16 MB) | **PPLR ArcGIS Online org** `services2.arcgis.com/S4ydGgujXcif36k3`, aggregating IMB (peoplegroups.org), Joshua Project, the ROP registry, and carrying WCD (World Christian Database) IDs. Built from a local 78 MB extract not present in this repo — evidence from exp-shepherd | **UNRESOLVED.** `aCountry` and `aIMBPeople` publish no `copyrightText`, description or licence (queried `f=json`) | nothing ships | **OPEN, judgment** — redistribution not established. WCD is a proprietary Brill database, so even the IDs need a check |
| `tables/*` (304 files, 36 MB) | derived by `library/scripts/research/fetch-*.mjs` from several upstream APIs | **varies, not established per table** | nothing ships; there is no source or licence doc in `tables/` | **OPEN, judgment** — the largest gap by volume | | `tables/*` (304 files, 36 MB) | derived by `library/scripts/research/fetch-*.mjs` from several upstream APIs | **varies, not established per table** | nothing ships; there is no source or licence doc in `tables/` | **OPEN, judgment** — the largest gap by volume |
| `images/worldmap.svg` | recorded in `images/PROVENANCE` | see that file | the PROVENANCE file ships and explains why no licence file sits beside it | none claimed; reasoning recorded rather than assumed | | `images/worldmap.svg` | recorded in `images/PROVENANCE` | see that file | the PROVENANCE file ships and explains why no licence file sits beside it | none claimed; reasoning recorded rather than assumed |
| `previews/*` (378 files) | our own poster previews | ours | n/a | none | | `previews/*` (378 files) | our own poster previews | ours | n/a | none |
@ -25,6 +26,7 @@ served folder". The licence travels with the asset; the explanation travels with
| Vendored file | Upstream URL | sha256 | | Vendored file | Upstream URL | sha256 |
|---|---|---| |---|---|---|
| `data/boundaries/ATTRIBUTION` | geoBoundaries API, per boundary (values verbatim) | see the file |
| `data/vendor/tabulator/LICENSE` | `https://raw.githubusercontent.com/olifolkerd/tabulator/master/LICENSE` | `191a2ee554684e1064c897b432f0e1bc6dfa714ca045d3f6ea2cf692cbd398b7` | | `data/vendor/tabulator/LICENSE` | `https://raw.githubusercontent.com/olifolkerd/tabulator/master/LICENSE` | `191a2ee554684e1064c897b432f0e1bc6dfa714ca045d3f6ea2cf692cbd398b7` |
| `data/vendor/vue/LICENSE` | `https://raw.githubusercontent.com/vuejs/core/main/LICENSE` | `49190d1f742dd61e47fe816df4963e5186a2a62100d9122f9883a60ea32973ac` | | `data/vendor/vue/LICENSE` | `https://raw.githubusercontent.com/vuejs/core/main/LICENSE` | `49190d1f742dd61e47fe816df4963e5186a2a62100d9122f9883a60ea32973ac` |
| `data/fonts/bebas-neue/LICENSE` | `https://raw.githubusercontent.com/google/fonts/main/ofl/bebasneue/OFL.txt` | see `documentation/vendored-fonts.md` | | `data/fonts/bebas-neue/LICENSE` | `https://raw.githubusercontent.com/google/fonts/main/ofl/bebasneue/OFL.txt` | see `documentation/vendored-fonts.md` |

View file

@ -1551,6 +1551,10 @@ function main() {
// COMPLETE India ADM1 (36 units, geoBoundaries gbOpen, CC BY 2.5 IN; source + licence in its meta), // COMPLETE India ADM1 (36 units, geoBoundaries gbOpen, CC BY 2.5 IN; source + licence in its meta),
// for maps that colour every state. The curated file above is UPG-100's 34-unit partition. // for maps that colour every state. The curated file above is UPG-100's 34-unit partition.
[resolve(__dirname, '..', 'data', 'boundaries', 'gb-IND-ADM1-full.geojson'), 'gb-IND-ADM1-full.geojson'], [resolve(__dirname, '..', 'data', 'boundaries', 'gb-IND-ADM1-full.geojson'), 'gb-IND-ADM1-full.geojson'],
// ★ AND THE ATTRIBUTION, because this pair list is what decides whether it TRAVELS. The India
// ADM1 boundary is Creative Commons Attribution, so the credit has to reach the recipient with
// the data; a file left in data/boundaries would never ship. Same trap as vendor/*/LICENSE.
[resolve(__dirname, '..', 'data', 'boundaries', 'ATTRIBUTION'), 'ATTRIBUTION'],
[resolve(__dirname, '..', 'data', 'boundaries', 'gb-IND-ADM1-full.meta.json'), 'gb-IND-ADM1-full.meta.json'], [resolve(__dirname, '..', 'data', 'boundaries', 'gb-IND-ADM1-full.meta.json'), 'gb-IND-ADM1-full.meta.json'],
// WEB copies (library/scripts/boundaries/build-web-boundaries.mjs): every feature and island kept, about // WEB copies (library/scripts/boundaries/build-web-boundaries.mjs): every feature and island kept, about
// a fifth of the bytes. The interactive maps fetch these; posters, print and build-time point-in-polygon // a fifth of the bytes. The interactive maps fetch these; posters, print and build-time point-in-polygon
@ -1618,6 +1622,11 @@ function main() {
'boundaries/gb-CHN-ADM1.geojson', 'boundaries/gb-CHN-ADM1.geojson',
'boundaries/gb-IND-ADM1-full.geojson', // all 36 states (Cities with Internet's NFHS layer) 'boundaries/gb-IND-ADM1-full.geojson', // all 36 states (Cities with Internet's NFHS layer)
'boundaries/gb-IND-ADM1-full.meta.json', // its source and licence, served beside it 'boundaries/gb-IND-ADM1-full.meta.json', // its source and licence, served beside it
// ★ SECOND STAGE. The pair list above only gathers into the build POOL; THIS list decides what
// reaches the tree. I added ATTRIBUTION to the pair list, ran the build, and it still did not ship
// — a two-stage pipeline needs the entry in both. The India ADM1 boundary is Creative Commons
// Attribution, so the credit must travel with the data.
'boundaries/ATTRIBUTION',
'boundaries/world-adm0-web.geojson', // the web copies the interactive maps fetch 'boundaries/world-adm0-web.geojson', // the web copies the interactive maps fetch
'boundaries/gb-IND-ADM1-web.geojson', 'boundaries/gb-IND-ADM1-web.geojson',
'boundaries/gb-IND-ADM1-full-web.geojson', 'boundaries/gb-IND-ADM1-full-web.geojson',

View file

@ -24,6 +24,7 @@
"props": { "props": {
"profile": "board", "profile": "board",
"view": "province", "view": "province",
"panel": "map",
"urlState": "query" "urlState": "query"
} }
}, },

View file

@ -85,6 +85,16 @@ const back = M.buildQuery({ view: 'zero', filterSet: { band: ['yes', 'partial'],
ok(back.includes('lang=ar') && back.includes('list=700') && back.includes('band=yes%7Cpartial') && back.includes('view=zero'), ok(back.includes('lang=ar') && back.includes('list=700') && back.includes('band=yes%7Cpartial') && back.includes('view=zero'),
`query builds and keeps lang/list: ${back}`) `query builds and keeps lang/list: ${back}`)
ok(M.parseQuery('?view=nonsense').view === 'board', 'an unknown view falls back to board') ok(M.parseQuery('?view=nonsense').view === 'board', 'an unknown view falls back to board')
// the tree is the default panel: a bare URL names no panel, only the map is written, both are read back
ok(M.parseQuery('').panel === '' && M.parseQuery('?panel=map').panel === 'map' && M.parseQuery('?panel=tree').panel === 'tree'
&& M.buildQuery({ panel: 'map' }) === 'panel=map' && M.buildQuery({ panel: 'tree' }) === '', 'the tree is the default panel; ?panel=map restores the map')
// an OLD map link (map state, no ?panel=) still opens the map; a tree link with map state says panel=tree
ok(['?group=abai-sungai', '?groups=abai-sungai,hadrami-arabs', '?country=IND', '?province=IN-BR', '?view=province'].every((s) => M.parseQuery(s).panel === 'map')
&& M.parseQuery('?access=none&band=yes').panel === '' && M.parseQuery('?codes=abf').panel === '' && M.parseQuery('?country=IND&panel=tree').panel === 'tree',
'old links with map state and no panel open the map; a bare or map-free link opens the tree')
const treeBack = M.buildQuery({ panel: 'tree', keep: '?country=IND', filters: false })
ok(M.parseQuery('?' + treeBack).panel === 'tree' && M.parseQuery('?' + M.buildQuery({ panel: 'tree', group: 'abai-sungai' })).panel === 'tree',
'a tree view with map state round-trips to the tree')
// embed-contract parity with Gospel Resources: ?groups= (peoples by slug) and ?codes= / ?code= (languages) // embed-contract parity with Gospel Resources: ?groups= (peoples by slug) and ?codes= / ?code= (languages)
const pg = M.parseQuery('?groups=abai-sungai,hadrami-arabs&codes=abf,ayh') const pg = M.parseQuery('?groups=abai-sungai,hadrami-arabs&codes=abf,ayh')
ok(pg.groups.length === 2 && Array.isArray(pg.filters.language) && pg.filters.language.join('|') === 'abf|ayh', 'parses ?groups= (slugs) and ?codes= (languages), comma-separated as Gospel Resources writes them') ok(pg.groups.length === 2 && Array.isArray(pg.filters.language) && pg.filters.language.join('|') === 'abf|ayh', 'parses ?groups= (slugs) and ?codes= (languages), comma-separated as Gospel Resources writes them')

View file

@ -50,7 +50,7 @@ try {
const res = T('gospel-internet-resources.json') const res = T('gospel-internet-resources.json')
const open = rows.find((r) => r.access_detail === 'none' && r.province) || rows[0] const open = rows.find((r) => r.access_detail === 'none' && r.province) || rows[0]
async function render(lang) { async function render(lang, extra = { legend: 'open' }) {
const app = createSSRApp({ const app = createSSRApp({
setup() { setup() {
const b = useBoard() const b = useBoard()
@ -75,7 +75,7 @@ try {
const appI18n = i18n.createAppI18n() const appI18n = i18n.createAppI18n()
app.use(appI18n) app.use(appI18n)
appI18n.global.locale.value = lang appI18n.global.locale.value = lang
app.provide('profileConfig', ref({ profile: 'board', lang })) app.provide('profileConfig', ref({ profile: 'board', lang, ...extra })) // legends start collapsed; the content checks open them
const errors = [] const errors = []
app.config.errorHandler = (e) => { errors.push(String(e && e.stack || e)) } app.config.errorHandler = (e) => { errors.push(String(e && e.stack || e)) }
app.config.warnHandler = (m) => { if (/Unhandled error|Property .* was accessed during render but is not defined/.test(m)) errors.push(m) } app.config.warnHandler = (m) => { if (/Unhandled error|Property .* was accessed during render but is not defined/.test(m)) errors.push(m) }
@ -84,6 +84,11 @@ try {
} }
const en = await render('en') const en = await render('en')
// the agent's default (2026-09-28): with no knob both legends start collapsed behind their "Legend" button
const shut = await render('en', {})
ok(!/data-tree-legend|class="gim-legend"/.test(shut.html) && /class="gtr-min"/.test(shut.html) && /class="gim-legend-min"/.test(shut.html),
'en: with no knob, the tree and map legends start collapsed')
ok(/data-tree-credit[^>]*>[\s\S]*?Glottolog[\s\S]*?CC BY 4\.0/.test(shut.html), 'en: the Glottolog CC BY credit is on screen with the legend collapsed')
ok(en.errors.length === 0, `en: every panel rendered with no error (${en.errors.length}${en.errors[0] ? ': ' + en.errors[0].slice(0, 160) : ''})`) ok(en.errors.length === 0, `en: every panel rendered with no error (${en.errors.length}${en.errors[0] ? ': ' + en.errors[0].slice(0, 160) : ''})`)
for (const [name, re] of [['GiFacetRail', /data-facet="access"/], ['GiGrid', /data-grid-total/], ['GiCharts', /data-region="charts"/], for (const [name, re] of [['GiFacetRail', /data-facet="access"/], ['GiGrid', /data-grid-total/], ['GiCharts', /data-region="charts"/],
['GiTree', /data-tree-legend[\s\S]*data-tree-poster/], ['GiResources', /data-resources-total/], ['GiMap', /data-region="map"/]]) ok(re.test(en.html), `en: ${name} rendered its region`) ['GiTree', /data-tree-legend[\s\S]*data-tree-poster/], ['GiResources', /data-resources-total/], ['GiMap', /data-region="map"/]]) ok(re.test(en.html), `en: ${name} rendered its region`)

View file

@ -103,9 +103,10 @@ useShadowStyles(
'.gic2{grid-area:combos;display:flex;align-items:center;gap:10px;padding:6px 14px;background:#fff;border-bottom:1px solid #d1d4cd;' + '.gic2{grid-area:combos;display:flex;align-items:center;gap:10px;padding:6px 14px;background:#fff;border-bottom:1px solid #d1d4cd;' +
'min-width:0;font:12.5px/1.3 Roboto,-apple-system,"Segoe UI",sans-serif;color:#3b463d}' + 'min-width:0;font:12.5px/1.3 Roboto,-apple-system,"Segoe UI",sans-serif;color:#3b463d}' +
'.gic2-h{flex:none;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:#6d766e}' + '.gic2-h{flex:none;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:#6d766e}' +
// The selection side is BOUNDED and clips: its nowrap placeholder ran under "Try a combination" at 1280 // The selection side is BOUNDED at 40% (rega r82: the placeholder ran under "Try a combination"), but only
// and 1440 (rega r82). It now ellipsizes; the full text stays in the title tooltip. // its chips and placeholder clip: they scroll or ellipsize. No overflow here and no min-width:0, so the
'.gic2-sel{display:flex;align-items:center;gap:6px;min-width:0;flex:0 1 auto;max-width:40%;overflow:hidden}' + // flex:none label sets the minimum width and is never cut ('YOUR S…' at 390, the zh/ru/hi/ar labels at 1280).
'.gic2-sel{display:flex;align-items:center;gap:6px;flex:0 1 auto;max-width:40%}' +
'.gic2-none{color:#9aa19b;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}' + '.gic2-none{color:#9aa19b;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}' +
'.gic2-try{display:flex;align-items:center;gap:6px;min-width:0;flex:1 1 auto;overflow-x:auto;scrollbar-width:thin}' + '.gic2-try{display:flex;align-items:center;gap:6px;min-width:0;flex:1 1 auto;overflow-x:auto;scrollbar-width:thin}' +
'.gic2-c{flex:none;display:inline-flex;align-items:center;gap:6px;border:1px solid #d1d4cd;background:#f3f3f1;color:#3b463d;border-radius:999px;' + '.gic2-c{flex:none;display:inline-flex;align-items:center;gap:6px;border:1px solid #d1d4cd;background:#f3f3f1;color:#3b463d;border-radius:999px;' +

View file

@ -44,7 +44,8 @@ const ready = ref(false)
// Province shading: 'zero' = groups with nothing found in their own language (from the rows in scope), // Province shading: 'zero' = groups with nothing found in their own language (from the rows in scope),
// 'women' / 'men' = NFHS-5 ever used the internet (India only; China has no verified provincial source). // 'women' / 'men' = NFHS-5 ever used the internet (India only; China has no verified provincial source).
const provinceMode = ref('zero') const provinceMode = ref('zero')
const legendOpen = ref(true) // the agent: legends start collapsed, one tap on "Legend" opens them; the embed knob legend:"open" opens them
const legendOpen = ref(board.profileConfig.value?.legend === 'open')
let unmounted = false let unmounted = false
let adm1Table = null // { [shapeName]: { women, men } } India, NFHS-5 let adm1Table = null // { [shapeName]: { women, men } } India, NFHS-5
const nfhsAttribution = ref('') const nfhsAttribution = ref('')
@ -313,8 +314,6 @@ onMounted(async () => {
// resize the canvas too, or it stretches the old bitmap. // resize the canvas too, or it stretches the old bitmap.
let ro = null let ro = null
onMounted(() => { onMounted(() => {
// A phone opens on the map, not on its legend: at 390px the card covered most of the map (rega r75).
if (mapEl.value && mapEl.value.clientWidth && mapEl.value.clientWidth < 520) legendOpen.value = false
if (mapEl.value && typeof ResizeObserver !== 'undefined') { if (mapEl.value && typeof ResizeObserver !== 'undefined') {
ro = new ResizeObserver(() => { try { mapRef.value && mapRef.value.resize() } catch (_) {} }) ro = new ResizeObserver(() => { try { mapRef.value && mapRef.value.resize() } catch (_) {} })
ro.observe(mapEl.value) ro.observe(mapEl.value)

View file

@ -43,7 +43,8 @@ const mapRef = shallowRef(null)
const err = ref('') const err = ref('')
const ready = ref(false) const ready = ref(false)
const hoverId = ref('') const hoverId = ref('')
const legendOpen = ref(true) // the agent: legends start collapsed, one tap on "Legend" opens them; the embed knob legend:"open" opens them
const legendOpen = ref(board.profileConfig.value?.legend === 'open')
let unmounted = false let unmounted = false
let ro = null let ro = null
@ -242,7 +243,6 @@ async function build() {
} catch (_) {} } catch (_) {}
} }
onMounted(() => { onMounted(() => {
if (el.value && el.value.clientWidth && el.value.clientWidth < 520) legendOpen.value = false // a phone opens on the tree
if (el.value && typeof ResizeObserver !== 'undefined') { if (el.value && typeof ResizeObserver !== 'undefined') {
// the engines only follow WINDOW resizes; a dragged rail or an un-hidden panel must resize the canvas // the engines only follow WINDOW resizes; a dragged rail or an un-hidden panel must resize the canvas
ro = new ResizeObserver(() => { try { mapRef.value && mapRef.value.resize() } catch (_) {} }) ro = new ResizeObserver(() => { try { mapRef.value && mapRef.value.resize() } catch (_) {} })
@ -328,6 +328,10 @@ useShadowStyles(
'.gtr-row .gtr-dot{margin-top:3px}' + '.gtr-row .gtr-dot{margin-top:3px}' +
'.gtr-levels{margin:6px 0 2px;font-size:11.5px}' + '.gtr-levels{margin:6px 0 2px;font-size:11.5px}' +
'.gtr-note{font-size:10.5px;color:#6d766e;margin-top:4px}' + '.gtr-note{font-size:10.5px;color:#6d766e;margin-top:4px}' +
// ALWAYS ON, like a map's attribution control: the CC BY credit never hides behind the collapsed legend
'.gtr-credit{position:absolute;z-index:3;inset-block-end:0;inset-inline-end:0;padding:2px 6px;font:11px/1.45 system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;' +
'background:rgba(255,255,255,.82);color:#3a4048;border-start-start-radius:3px}' +
'.gtr-credit a{color:#2a5d8f;text-decoration:none}' +
'.gtr-poster{display:flex;align-items:center;gap:6px;margin-top:6px;padding-top:6px;border-top:1px solid #e6e8e3;font-weight:600}' + '.gtr-poster{display:flex;align-items:center;gap:6px;margin-top:6px;padding-top:6px;border-top:1px solid #e6e8e3;font-weight:600}' +
'.gtr-poster select,.gtr-poster button{font:inherit;font-weight:400;font-size:12px;border:1px solid #d1d4cd;background:#fff;color:#3b463d;border-radius:6px;min-height:26px;padding:2px 8px;cursor:pointer}' + '.gtr-poster select,.gtr-poster button{font:inherit;font-weight:400;font-size:12px;border:1px solid #d1d4cd;background:#fff;color:#3b463d;border-radius:6px;min-height:26px;padding:2px 8px;cursor:pointer}' +
'.gtr-poster button:focus-visible,.gtr-poster select:focus-visible{outline:2px solid #92b195;outline-offset:1px}' + '.gtr-poster button:focus-visible,.gtr-poster select:focus-visible{outline:2px solid #92b195;outline-offset:1px}' +
@ -385,5 +389,7 @@ useShadowStyles(
<div class="gtr-note">{{ T('gospelInternet.tree.sources', 'Tree: Glottolog (CC BY 4.0). Resources: eBible, Faith Comes By Hearing, Scripture Earth, PNG.Bible, JESUS Film, Global Recordings and others, keyed by ISO 639-3.') }} {{ citation }}</div> <div class="gtr-note">{{ T('gospelInternet.tree.sources', 'Tree: Glottolog (CC BY 4.0). Resources: eBible, Faith Comes By Hearing, Scripture Earth, PNG.Bible, JESUS Film, Global Recordings and others, keyed by ISO 639-3.') }} {{ citation }}</div>
</div> </div>
<button v-else type="button" class="gtr-min" @click="legendOpen = true">{{ T('gospelInternet.legend.show', 'Legend') }}</button> <button v-else type="button" class="gtr-min" @click="legendOpen = true">{{ T('gospelInternet.legend.show', 'Legend') }}</button>
<!-- names and a licence, the same in every language (like the map's own attribution): not catalogue text -->
<div class="gtr-credit" data-tree-credit><a href="https://glottolog.org" target="_blank" rel="noopener noreferrer">Glottolog</a> · <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="noopener noreferrer">CC BY 4.0</a></div>
</div> </div>
</template> </template>

View file

@ -86,6 +86,12 @@ export const VIEWS = ['board', 'zero', 'province', 'platforms']
* The published names are kept so links already shared keep restoring. */ * The published names are kept so links already shared keep restoring. */
export const SHARE_FACETS = Object.fromEntries(Object.entries(URL_KEYS)) export const SHARE_FACETS = Object.fromEntries(Object.entries(URL_KEYS))
// MAP STATE: what a link written while the map was the default carries and only the map shows (an open or
// selected people group's pin, a country or province, the province view). Such a link with no ?panel= opens
// the MAP, so old map links keep working; a bare link opens the tree (dx-shepherd ENDTOKEN-GOINT-ATTR).
const MAP_STATE = ['group', 'groups', 'country', 'province']
export const hasMapState = (q) => MAP_STATE.some((k) => q.get(k)) || q.get('view') === 'province'
/** Parse `?view=&access=…&group=` into { view, filters, group }. Unknown views fall back to board. */ /** Parse `?view=&access=…&group=` into { view, filters, group }. Unknown views fall back to board. */
export function parseQuery(search) { export function parseQuery(search) {
const q = new URLSearchParams(search || '') const q = new URLSearchParams(search || '')
@ -104,7 +110,8 @@ export function parseQuery(search) {
const codes = [...list('codes'), ...list('code')].filter((c) => /^[a-z]{3}$/.test(c)) const codes = [...list('codes'), ...list('code')].filter((c) => /^[a-z]{3}$/.test(c))
if (codes.length && !filters.language) filters.language = codes.length === 1 ? codes[0] : codes if (codes.length && !filters.language) filters.language = codes.length === 1 ? codes[0] : codes
const groups = list('groups').filter((s) => /^[a-z0-9-]+$/.test(s)) const groups = list('groups').filter((s) => /^[a-z0-9-]+$/.test(s))
const panel = q.get('panel') === 'tree' ? 'tree' : 'map' // '' = not in the URL: the board opens on its default (the language tree, the agent 2026-09-28)
const panel = ['tree', 'map'].includes(q.get('panel')) ? q.get('panel') : hasMapState(q) ? 'map' : ''
const tree = /^[a-z0-9-]{3,40}$/.test(q.get('tree') || '') ? q.get('tree') : '' const tree = /^[a-z0-9-]{3,40}$/.test(q.get('tree') || '') ? q.get('tree') : ''
// A tree node narrows by LANGUAGE (its ISO codes); the URL carries the node, not the code list. // A tree node narrows by LANGUAGE (its ISO codes); the URL carries the node, not the code list.
if (tree) delete filters.language if (tree) delete filters.language
@ -118,7 +125,6 @@ export function buildQuery({ view, filterSet, group, keep, panel, tree, filters
// delete nor write them, so the two writers never fight over one address bar // delete nor write them, so the two writers never fight over one address bar
for (const name of [...(filters ? Object.keys(URL_KEYS) : []), 'view', 'group', 'panel', 'tree']) q.delete(name) for (const name of [...(filters ? Object.keys(URL_KEYS) : []), 'view', 'group', 'panel', 'tree']) q.delete(name)
if (view && view !== 'board') q.set('view', view) if (view && view !== 'board') q.set('view', view)
if (panel === 'tree') q.set('panel', 'tree')
if (tree) q.set('tree', tree) if (tree) q.set('tree', tree)
if (filters) for (const [name, key] of Object.entries(URL_KEYS)) { if (filters) for (const [name, key] of Object.entries(URL_KEYS)) {
if (tree && key === 'language') continue if (tree && key === 'language') continue
@ -127,6 +133,8 @@ export function buildQuery({ view, filterSet, group, keep, panel, tree, filters
q.set(name, Array.isArray(v) ? v.join('|') : String(v)) q.set(name, Array.isArray(v) ? v.join('|') : String(v))
} }
if (group) q.set('group', group) if (group) q.set('group', group)
// the tree is the default, so it is written only where map state would otherwise open the map
if (panel === 'map' || (panel === 'tree' && hasMapState(q))) q.set('panel', panel)
return q.toString() return q.toString()
} }

View file

@ -37,7 +37,7 @@ export function useBoard() {
const sort = ref({ key: 'population', dir: -1 }) const sort = ref({ key: 'population', dir: -1 })
const openSlug = ref('') // the group in the detail drawer ('' = closed) const openSlug = ref('') // the group in the detail drawer ('' = closed)
// ── the centre panel: the geographic map or the language tree (loaded on first use) ─────────────── // ── the centre panel: the geographic map or the language tree (loaded on first use) ───────────────
const centre = ref('map') const centre = ref('tree') // the agent: people come for the language tree; the map is one tap away
const tree = shallowRef(null) // indexTree(doc) + { meta } const tree = shallowRef(null) // indexTree(doc) + { meta }
const resources = shallowRef(null) // { meta, rows } — gospel links for the board's languages const resources = shallowRef(null) // { meta, rows } — gospel links for the board's languages
const treeNode = ref('') // the tree node the board is narrowed to ('' = none) const treeNode = ref('') // the tree node the board is narrowed to ('' = none)
@ -180,7 +180,8 @@ export function useBoard() {
if (codes) bus.setFilter('language', codes) if (codes) bus.setFilter('language', codes)
const group = q.group || cfg().group || '' const group = q.group || cfg().group || ''
if (group) pendingGroup = group if (group) pendingGroup = group
const panel = q.panel === 'tree' || cfg().panel === 'tree' ? 'tree' : 'map' // the URL wins, then the embed knob (profile-config panel: 'map'), then the default: the tree
const panel = q.panel || (cfg().panel === 'map' ? 'map' : 'tree')
if (q.tree) pendingTree = q.tree if (q.tree) pendingTree = q.tree
if (q.groups && q.groups.length) pendingSelection = q.groups if (q.groups && q.groups.length) pendingSelection = q.groups
setCentre(panel) setCentre(panel)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,61 @@
BOUNDARY DATA — SOURCES AND ATTRIBUTION
=======================================
The .geojson files in this folder are third-party boundary data. Every value below is taken
VERBATIM from the upstream metadata (the geoBoundaries API, https://www.geoboundaries.org/api/current/gbOpen/<ISO3>/<LEVEL>/).
Nothing here is our own wording about a licence.
gb-IND-ADM1-full.geojson, gb-IND-ADM1-full-web.geojson
source geoBoundaries gbOpen (www.geoboundaries.org)
boundaryID IND-ADM1-1811400
licence Creative Commons Attribution 2.5 India (CC BY 2.5 IN)
licenceSource github.com/datameet/maps
year 2011
ATTRIBUTION IS REQUIRED for this file: it is Creative Commons Attribution, so a work that
redistributes or displays it must credit the source above.
gb-IND-ADM1.geojson, gb-IND-ADM1-web.geojson
The same India ADM1 boundary as above, curated to the UPG-100 list's partition.
Same source, same boundaryID, same licence, same attribution duty.
gb-CHN-ADM1.geojson
source geoBoundaries gbOpen (www.geoboundaries.org)
boundaryID CHN-ADM1-43563684
licence Public Domain
licenceSource commons.wikimedia.org/wiki/File
year 2019
No attribution duty: upstream records this boundary as Public Domain.
world-adm0.geojson, world-adm0-web.geojson
source geoBoundaries gbOpen (www.geoboundaries.org), assembled per country
features 162 countries
licence MIXED — and now ESTABLISHED per country, not merely acknowledged.
THE PER-COUNTRY TABLE IS THE AUTHORITY, and it lives in ONE place on purpose:
plugin-designs/my-upg-100-list/data/adm0/PROVENANCE.json
It records boundaryLicense, licenseSource and boundaryID for all 162, each value taken
verbatim from https://www.geoboundaries.org/api/current/gbOpen/<ISO3>/<LEVEL>/ (162 queries,
0 failures, one spot-check re-verified against the live API). This file deliberately does NOT
copy that table: one table in two places drifts.
130 OF THE 162 CARRY A DUTY. Only 32 are duty-free (28 Public Domain, 4 CC0). By class:
ATTRIBUTION-ONLY (credit the source)
44 CC BY 4.0 13 CC BY 3.0 IGO 4 CC BY 2.5 2 CC BY 3.0
2 Open Government Licence v3
SHARE-ALIKE CLASS — A STRONGER DUTY: a derivative may have to be licensed alike, which is
the class that actually constrains giving this repository away.
58 Open Data Commons ODbL 1.0
7 Creative Commons ShareAlike 2.0 / 3.0 — AGO GAB GEO GIN MMR NER TUR
ODbL IS LISTED IN THAT CLASS DELIBERATELY. Alongside attribution it requires a Derivative
Database to be offered under ODbL and carries a keep-open provision, so by volume the
share-alike question covers 65 of 162 countries, not 7. This repository has already acted on
that reading once: library/scripts/posters/data/README.md records that Natural Earth's 1:10m
ROADS were requested and deliberately NOT shipped because of an ODbL obligation.
WHETHER 'licensed alike' binds a giveaway of this repository is a legal question, not a
measurement, and it is open. It is recorded here so nobody has to rediscover it.
duty-free: 28 Public Domain, 4 CC0.
See documentation/THIRD-PARTY.md for the whole shipped tree.

View file

@ -604,7 +604,7 @@
"bundle": "gospel-internet", "bundle": "gospel-internet",
"scriptUrl": "./gospel-internet/gospel-internet.js", "scriptUrl": "./gospel-internet/gospel-internet.js",
"output": "dx-maps/gospel-internet/gospel-internet.js", "output": "dx-maps/gospel-internet/gospel-internet.js",
"integrity": "sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j", "integrity": "sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U",
"elements": [ "elements": [
"gospel-internet-board" "gospel-internet-board"
], ],
@ -623,7 +623,7 @@
"scriptUrl": "./gospel-internet/gospel-internet.js", "scriptUrl": "./gospel-internet/gospel-internet.js",
"embed": { "embed": {
"iframe": "<iframe src=\"./gospel-internet/board/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>", "iframe": "<iframe src=\"./gospel-internet/board/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-internet/gospel-internet.js\" integrity=\"sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j\" crossorigin=\"anonymous\"></script>\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>" "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-internet/gospel-internet.js\" integrity=\"sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U\" crossorigin=\"anonymous\"></script>\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
}, },
"instances": [ "instances": [
{ {
@ -662,6 +662,7 @@
"props": { "props": {
"profile": "board", "profile": "board",
"view": "province", "view": "province",
"panel": "map",
"urlState": "query" "urlState": "query"
}, },
"element": "gospel-internet-board", "element": "gospel-internet-board",

View file

@ -36,7 +36,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // 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> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // 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> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // Mapbox token resolution — the A3 ladder, in precedence order:
@ -52,7 +52,7 @@
(function () { (function () {
var slot = document.getElementById('slot'); var slot = document.getElementById('slot');
var status = document.getElementById('status'); var status = document.getElementById('status');
var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"board","view":"province","urlState":"query"}; var BASE_CONFIG = {"assetsBase":"../../../assets","profile":"board","view":"province","panel":"map","urlState":"query"};
// MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token: // MapLibre map pages AND shell pages (app-shell / nested-mfe-spa) need NO token:
// the ladder below is skipped entirely and the element mounts immediately. // the ladder below is skipped entirely and the element mounts immediately.
// (A leaf whose engine is MapLibre at RUNTIME joins them — see PROVIDER below.) // (A leaf whose engine is MapLibre at RUNTIME joins them — see PROVIDER below.)

View file

@ -36,7 +36,7 @@
<script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // 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> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // 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> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // 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> <script>window.MAP_APP_API_URL = "https://pray.doxa.life";</script>
<!-- Bundle IIFE — registers the <gospel-internet-board> custom element. --> <!-- Bundle IIFE — registers the <gospel-internet-board> custom element. -->
<script src="../../gospel-internet.js" integrity="sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j" crossorigin="anonymous"></script> <script src="../../gospel-internet.js" integrity="sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U" crossorigin="anonymous"></script>
<script> <script>
// Mapbox token resolution — the A3 ladder, in precedence order: // Mapbox token resolution — the A3 ladder, in precedence order:

File diff suppressed because one or more lines are too long

View file

@ -604,7 +604,7 @@
"bundle": "gospel-internet", "bundle": "gospel-internet",
"scriptUrl": "./gospel-internet/gospel-internet.js", "scriptUrl": "./gospel-internet/gospel-internet.js",
"output": "dx-maps/gospel-internet/gospel-internet.js", "output": "dx-maps/gospel-internet/gospel-internet.js",
"integrity": "sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j", "integrity": "sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U",
"elements": [ "elements": [
"gospel-internet-board" "gospel-internet-board"
], ],
@ -623,7 +623,7 @@
"scriptUrl": "./gospel-internet/gospel-internet.js", "scriptUrl": "./gospel-internet/gospel-internet.js",
"embed": { "embed": {
"iframe": "<iframe src=\"./gospel-internet/board/index.html?utm_source=YOUR_SOURCE\" width=\"100%\" height=\"600\" style=\"border:none;border-radius:12px;\" allowfullscreen></iframe>", "iframe": "<iframe src=\"./gospel-internet/board/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-internet/gospel-internet.js\" integrity=\"sha384-VMy1YepTE3yXPhM0Er8cw6H/THhTAY6BV7KfoZtWyV3IXfAAMJTg7sTT8RuOuh/j\" crossorigin=\"anonymous\"></script>\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>" "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-internet/gospel-internet.js\" integrity=\"sha384-qnCqwfYQGF8v4uMLnMn7+/XdVomUT71pJuy48PzBkuubKegi35eJCSO4hA7oWe8U\" crossorigin=\"anonymous\"></script>\n<gospel-internet-board profile-config='{\"profile\":\"board\",\"tk\":\"YOUR_MAPBOX_TOKEN\",\"utmSource\":\"YOUR_SOURCE\",\"assetsBase\":\"YOUR_TREE_URL/assets\"}'></gospel-internet-board>"
}, },
"instances": [ "instances": [
{ {
@ -662,6 +662,7 @@
"props": { "props": {
"profile": "board", "profile": "board",
"view": "province", "view": "province",
"panel": "map",
"urlState": "query" "urlState": "query"
}, },
"element": "gospel-internet-board", "element": "gospel-internet-board",