/embed-test embeds every web plugin: production first, then every other; desktop-only plugins skipped by their manifest targets

This commit is contained in:
doxa-maps 2026-09-28 06:12:41 +00:00
parent 50dcf627ad
commit 89ce341c82
2 changed files with 28 additions and 15 deletions

View file

@ -63,11 +63,12 @@ and `/embed-test` load as JavaScript from the maps CDN, as on research-gallery-j
## /embed-test
`/embed-test` embeds **every production plugin**: the list is read at runtime from the tree's
`manifest.json` (each profile with `stage: production`), never typed, and each card loads its bundle's
script and adds the element that bundle defines. A card mounts its map when it scrolls into view and removes
it when it leaves (browsers allow only a few WebGL maps at once). `?only=<bundle>/<profile>` (or a bundle
name, comma-separated) shows just those.
`/embed-test` embeds **every web plugin** in the dx-maps tree, as JavaScript (no iframe). The list is read
at runtime from the tree's `manifest.json`, never typed: section 1 is every profile with `stage: production`,
section 2 every other profile. A profile whose `targets` leave out `web` (a desktop-only plugin, such as
Rudder) is skipped. Each card loads its bundle's script and adds the element that bundle defines. A card
mounts its plugin when it scrolls into view and removes it when it leaves (browsers allow only a few WebGL
maps at once). `?only=<bundle>/<profile>` (or a bundle name, comma-separated) shows just those.
## Updating the maps

View file

@ -1,13 +1,14 @@
<script setup lang="ts">
// /embed-test — proves that EVERY production dx-maps plugin embeds on this site as JavaScript (no
// iframe). The list is read at runtime from the dx-maps tree's manifest.json (every profile whose
// stage is "production"), never typed here, so a plugin promoted or retired changes this page by
// itself. Each card loads its bundle's script from the same tree the rest of the site uses and adds
// /embed-test — proves that EVERY dx-maps plugin built for the web embeds on this site as JavaScript
// (no iframe). The list is read at runtime from the dx-maps tree's manifest.json, never typed here:
// section 1 is every profile whose stage is "production", section 2 every other profile. A profile whose
// manifest `targets` leaves out "web" (a desktop-only plugin) is skipped. So a plugin promoted, added or
// retired changes this page by itself. Each card loads its bundle's script from the same tree the rest of the site uses and adds
// the element the bundle defines, the way the manifest's embed.script snippet does.
//
// A map owns a WebGL context and a browser allows only a handful at once, so a card MOUNTS its
// element when it scrolls into view and REMOVES it when it scrolls far away. ?only=<bundle>/<profile>
// (comma-separated) shows just those cards, for a single-plugin check.
// (comma-separated, or a bundle name) shows just those cards, for a single-plugin check.
useHead({ title: 'Embed test', meta: [{ name: 'robots', content: 'noindex' }] })
@ -19,6 +20,7 @@ interface Card {
script: string
integrity: string
description: string
production: boolean
state: 'idle' | 'loading' | 'mounted' | 'error'
error: string
}
@ -68,6 +70,8 @@ async function mount(card: Card) {
// with a Mapbox token the maps use it; without one they use the keyless MapLibre engine
...(token ? { tk: token } : { provider: 'maplibre' })
}))
// shells (the Research Gallery, Plugin Studio) find their child maps through the tree's manifest
el.setAttribute('tree-base', treeBase())
host.replaceChildren(el)
card.state = 'mounted'
} catch (e) {
@ -100,17 +104,21 @@ onMounted(async () => {
for (const b of manifest.bundles || []) {
const defined: string[] = b.elements || []
for (const p of b.profiles || []) {
if ((p.stage || b.stage) !== 'production') continue
// desktop-only (or any non-web) plugins are not embeddable in a web page
const targets: string[] | undefined = p.targets || b.targets
if (Array.isArray(targets) && !targets.includes('web')) continue
const key = `${b.bundle}/${p.profile}`
if (only.length && !only.includes(key) && !only.includes(b.bundle)) continue
// the tag the bundle actually defines (a profile's own element name can name one it does not)
const tag = p.element && (!defined.length || defined.includes(p.element)) ? p.element : defined[0] || p.element
out.push({ key, bundle: b.bundle, profile: p.profile, tag, script: resolveUrl(base, b.scriptUrl || `${b.bundle}/${b.bundle}.js`),
integrity: b.integrity || '', description: p.description || '', state: 'idle', error: '' })
integrity: b.integrity || '', description: p.description || '', production: (p.stage || b.stage) === 'production',
state: 'idle', error: '' })
}
}
cards.value = out
status.value = `${out.length} production plugin${out.length === 1 ? '' : 's'} from ${base}/manifest.json, each embedded as JavaScript.`
cards.value = [...out.filter((c) => c.production), ...out.filter((c) => !c.production)]
const prod = out.filter((c) => c.production).length
status.value = `${out.length} web plugins from ${base}/manifest.json (${prod} production, ${out.length - prod} other), each embedded as JavaScript.`
await nextTick()
observer = new IntersectionObserver((entries) => {
for (const en of entries) {
@ -135,7 +143,10 @@ const setHost = (key: string) => (el: unknown) => { if (el) hosts.set(key, el as
<div class="container page-content embed-test stack stack--lg">
<h1>Embed test</h1>
<p data-embed-status>{{ status }}</p>
<section v-for="c in cards" :key="c.key" class="embed-card" :data-card="c.key" :data-state="c.state">
<template v-for="(c, i) in cards" :key="c.key">
<h2 v-if="i === 0 && c.production" data-embed-section="production">1. Production</h2>
<h2 v-if="!c.production && (i === 0 || cards[i - 1].production)" data-embed-section="other">2. Every other web plugin</h2>
<section class="embed-card" :data-card="c.key" :data-state="c.state" :data-production="c.production">
<header class="embed-card__head">
<strong>{{ c.bundle }} / {{ c.profile }}</strong>
<code>&lt;{{ c.tag }}&gt;</code>
@ -145,6 +156,7 @@ const setHost = (key: string) => (el: unknown) => { if (el) hosts.set(key, el as
<p v-if="c.error" class="embed-card__error" role="alert">{{ c.error }}</p>
<div :ref="setHost(c.key)" class="embed-card__host" />
</section>
</template>
</div>
</template>