feat(export): single-file offline keepsake viewer + guest download
Rebuild the guest "keepsake" (offline HTML gallery) so it renders when the extracted index.html is opened over file://. Browsers block external ES-module scripts and fetch() at origin null, so a normal multi-file SvelteKit build shows a blank window. Build the viewer as one self-contained index.html (inlined JS/CSS via vite-plugin-singlefile, standalone non-SvelteKit entry) and inject the data as window.__EXPORT_DATA__; the backend embeds the built viewer via include_dir! and writes the data global into index.html when zipping. Also surface the guest-facing download: a feed banner and the BottomNav Export tab, both shown once the host releases the export. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -99,9 +99,18 @@
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
const res = await fetch('./data.json');
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
data = await res.json();
|
||||
// The keepsake is opened by double-clicking index.html (file://), where a
|
||||
// cross-origin `fetch()` is blocked. The export injects the data as a global
|
||||
// so it's available without any network request; fall back to fetching
|
||||
// data.json only when the viewer is actually served over http(s).
|
||||
const injected = (globalThis as { __EXPORT_DATA__?: ViewerData }).__EXPORT_DATA__;
|
||||
if (injected) {
|
||||
data = injected;
|
||||
} else {
|
||||
const res = await fetch('./data.json');
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
data = await res.json();
|
||||
}
|
||||
} catch {
|
||||
error =
|
||||
'Daten konnten nicht geladen werden. Stelle sicher, dass data.json im selben Ordner liegt.';
|
||||
|
||||
8
frontend/export-viewer/src/standalone.ts
Normal file
8
frontend/export-viewer/src/standalone.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
// Standalone (non-SvelteKit) entry for the offline keepsake. Mounts the plain
|
||||
// Svelte viewer component into a single, self-contained index.html so it works
|
||||
// when opened by double-clicking from an extracted ZIP (file://).
|
||||
import './app.css';
|
||||
import { mount } from 'svelte';
|
||||
import App from './routes/+page.svelte';
|
||||
|
||||
mount(App, { target: document.getElementById('app')! });
|
||||
Reference in New Issue
Block a user