diff --git a/apps/svelte.dev/src/lib/server/content.ts b/apps/svelte.dev/src/lib/server/content.ts index 718731afe0..08d6554d9e 100644 --- a/apps/svelte.dev/src/lib/server/content.ts +++ b/apps/svelte.dev/src/lib/server/content.ts @@ -112,4 +112,49 @@ function create_docs() { export const docs = create_docs(); -export const examples = index.examples.children; +export const examples_promise: ReturnType = new Promise(async (fulfil) => + fulfil(await load_examples()) +); + +async function load_examples() { + const sections = []; + + for (const section of index.examples.children) { + const examples = []; + + for (const document of section.children) { + // TODO 'components' is a misnomer, this can include other files + const components = []; + + for (const [file, source] of Object.entries(document.assets!)) { + const dot = file.lastIndexOf('.'); + let name = file.slice(0, dot); + let type = file.slice(dot + 1); + + components.push({ name, type, source: await read(source).text() }); + } + + components.sort((a, b) => { + if (a.name === 'App' && a.type === 'svelte') return -1; + if (b.name === 'App' && b.type === 'svelte') return 1; + + if (a.type !== b.type) return a.type === 'svelte' ? -1 : 1; + + return a.name < b.name ? -1 : 1; + }); + + examples.push({ + title: document.metadata.title, + slug: document.slug.split('/').pop()!, + components + }); + } + + sections.push({ + title: section.metadata.title, + examples + }); + } + + return sections; +} diff --git a/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.server.ts b/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.server.ts index 0373bbc781..1636e0f62d 100644 --- a/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.server.ts +++ b/apps/svelte.dev/src/routes/(authed)/playground/[id]/+page.server.ts @@ -1,18 +1,21 @@ import { error } from '@sveltejs/kit'; -import type { Examples } from '../api/examples/all.json/+server.js'; +import { examples_promise } from '$lib/server/content.js'; + +const examples = await examples_promise; export async function load({ fetch, params, url }) { - const examples_res = fetch('/playground/api/examples/all.json').then((r) => r.json()); + // TODO skip the .json indirection const res = await fetch(`/playground/api/${params.id}.json`); if (!res.ok) { error(res.status); } - const [gist, examples] = await Promise.all([res.json(), examples_res as Promise]); + const gist = await res.json(); return { gist, + // TODO do this work in layout instead examples: examples .filter((section) => !section.title.includes('Embeds')) .map((section) => ({ diff --git a/apps/svelte.dev/src/routes/(authed)/playground/api/[id].json/+server.ts b/apps/svelte.dev/src/routes/(authed)/playground/api/[id].json/+server.ts index 4693680f03..f22b4147af 100644 --- a/apps/svelte.dev/src/routes/(authed)/playground/api/[id].json/+server.ts +++ b/apps/svelte.dev/src/routes/(authed)/playground/api/[id].json/+server.ts @@ -1,16 +1,16 @@ import { dev } from '$app/environment'; import { client } from '$lib/db/client.js'; import * as gist from '$lib/db/gist.js'; -import { examples } from '$lib/server/content'; +import { index, examples_promise } from '$lib/server/content'; import { error, json } from '@sveltejs/kit'; -import type { Examples } from '../examples/all.json/+server.js'; export const prerender = 'auto'; const UUID_REGEX = /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/; +const examples = await examples_promise; + export async function GET({ fetch, params }) { - const examples: Examples = await fetch('/playground/api/examples/all.json').then((r) => r.json()); const example = examples .flatMap((section) => section.examples) .find((example) => example.slug.split('/').pop() === params.id); @@ -25,21 +25,6 @@ export async function GET({ fetch, params }) { }); } - if (dev && !client) { - // in dev with no local Supabase configured, proxy to production - // this lets us at least load saved REPLs - const res = await fetch(`https://svelte.dev/playground/api/${params.id}.json`); - - // returning the response directly results in a bizarre - // content encoding error, so we create a new one - return new Response(await res.text(), { - status: res.status, - headers: { - 'content-type': 'application/json' - } - }); - } - if (!UUID_REGEX.test(params.id)) { error(404); } @@ -62,7 +47,7 @@ export async function GET({ fetch, params }) { } export async function entries() { - return examples + return index.examples.children .flatMap((section) => section.children) .map((example) => ({ id: example.slug.split('/').pop()! })); } diff --git a/apps/svelte.dev/src/routes/(authed)/playground/api/examples/all.json/+server.ts b/apps/svelte.dev/src/routes/(authed)/playground/api/examples/all.json/+server.ts deleted file mode 100644 index 8e202001d8..0000000000 --- a/apps/svelte.dev/src/routes/(authed)/playground/api/examples/all.json/+server.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { read } from '$app/server'; -import { examples } from '$lib/server/content'; -import { json } from '@sveltejs/kit'; - -export type Examples = Array<{ - title: string; - examples: Array<{ - title: string; - slug: string; - components: Array<{ name: string; type: string; source: string }>; - }>; -}>; - -export const prerender = true; - -async function munge(files: Record) { - const result = []; - - for (const [file, source] of Object.entries(files)) { - const dot = file.lastIndexOf('.'); - let name = file.slice(0, dot); - let type = file.slice(dot + 1); - - result.push({ name, type, source: await read(source).text() }); - } - - result.sort((a, b) => { - if (a.name === 'App' && a.type === 'svelte') return -1; - if (b.name === 'App' && b.type === 'svelte') return 1; - - if (a.type !== b.type) return a.type === 'svelte' ? -1 : 1; - - return a.name < b.name ? -1 : 1; - }); - - return result; -} - -// TODO move this into examples.json once we have fixed this SvelteKit bug: -// [id].json/+server.ts contained a fetch to examples.json, but it did not turn up here and instead recursed to itself. - -// Examples are prerendered to avoid making FS requests at runtime, -// things needing the examples data will need to go through this endpoint -export async function GET() { - return json( - (await Promise.all( - examples.map(async (section) => ({ - title: section.metadata.title, - examples: await Promise.all( - section.children.map(async (example) => ({ - title: example.metadata.title, - slug: example.slug.split('/').pop()!, - components: await munge(example.assets!) - })) - ) - })) - )) as Examples - ); -} diff --git a/apps/svelte.dev/src/routes/content.json/+server.ts b/apps/svelte.dev/src/routes/content.json/+server.ts index 2343b047bf..7175243166 100644 --- a/apps/svelte.dev/src/routes/content.json/+server.ts +++ b/apps/svelte.dev/src/routes/content.json/+server.ts @@ -1,4 +1,4 @@ -import { index, docs as _docs, examples } from '$lib/server/content'; +import { index, docs as _docs } from '$lib/server/content'; import { json } from '@sveltejs/kit'; import { transform, slugify, clean } from '@sveltejs/site-kit/markdown'; import type { Block } from '@sveltejs/site-kit/search'; @@ -82,7 +82,7 @@ async function content() { } } - for (const section of examples) { + for (const section of index.examples.children) { for (const example of section.children) { blocks.push({ breadcrumbs: ['Examples', section.metadata.title, example.metadata.title],