diff --git a/library/components/poster/PosterWall.vue b/library/components/poster/PosterWall.vue index 8bf843e3b..2cb22b51c 100644 --- a/library/components/poster/PosterWall.vue +++ b/library/components/poster/PosterWall.vue @@ -46,6 +46,7 @@ import { tStatic } from '../../i18n/index.js' // 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 { fetchPosterRaster, fetchPosterSource } from '@map/packet/poster-fetch.js' import { usePosterPrints } from '@map/composables/usePosterPrints.js' import { useOptionalI18n, useOptionalT } from '@map/composables/useOptionalT.js' // Export-modal geometry. A fixed;inset:0 scrim covers only the CONTENT PANE in the cap-5 shell @@ -387,10 +388,10 @@ async function exportPoster(item) { // which aborts every .webp at the network layer to force the default-drop // condition, went from PASS on the old wall to FAIL here with 0 .html requests. // The wall this component was extracted from already guarded it; the extraction - // did not carry the guard across. - let res = null - try { res = await fetch(`${base.value}/posters/${item.id}.webp`) } catch { /* treated as a miss */ } - if (!res || !res.ok) { + // did not carry the guard across. The guard now lives in poster-fetch.js, which also + // takes a host's 200 fallback page (text/html for a missing .webp) as a miss. + const raster = await fetchPosterRaster(`${base.value}/posters/${item.id}.webp`) + if (!raster) { // ★ NO PRE-RENDERED IMAGE? GENERATE IT. The 378 .webp posters were 41 MB in // every clone, shipped to every reader whether or not they opened one — and a // publish was already rejected once at a 74 MB asset tree. The poster HTML is @@ -400,10 +401,10 @@ async function exportPoster(item) { // ship nothing. A 404 used to end here as "poster not found". exportState.value = { ...exportState.value, phase: 'render', message: 'generating the poster', pct: 45 } - const htmlRes = await fetch(`${base.value}/posters/${item.id}.html`) - if (!htmlRes.ok) throw new Error(`poster not found (${htmlRes.status})`) + const source = await fetchPosterSource(`${base.value}/posters/${item.id}.html`) + if (!source.html) throw new Error(`poster not found (${source.status})`) const { rasterPoster, looksRendered } = await import('@map/packet/poster-raster.js') - const blob = await rasterPoster(await htmlRes.text(), { scale: 2 }) + const blob = await rasterPoster(source.html, { scale: 2 }) // Fail LOUDLY rather than hand over a black rectangle: an SVG in an is // an isolated document, so a missing stylesheet makes every fill fall back to // black with no error at all. @@ -411,7 +412,7 @@ async function exportPoster(item) { await deliverPoster(blob, item) return } - await deliverPoster(await res.blob(), item) + await deliverPoster(raster, item) } catch (e) { exportState.value = { label: item.label, kind: 'Poster', phase: 'error', message: String(e?.message || e).slice(0, 140), pct: 0 }