diff --git a/apps/svelte.dev/src/lib/server/content.ts b/apps/svelte.dev/src/lib/server/content.ts index 0a38d4304d..4136e7b295 100644 --- a/apps/svelte.dev/src/lib/server/content.ts +++ b/apps/svelte.dev/src/lib/server/content.ts @@ -1,4 +1,5 @@ import { read } from '$app/server'; +import type { Document } from '@sveltejs/site-kit'; import { create_index } from '@sveltejs/site-kit/server/content'; const documents = import.meta.glob('../../../content/**/*.md', { @@ -51,3 +52,64 @@ export const blog_posts = index.blog.children }; }) .sort((a, b) => (a.date < b.date ? 1 : -1)); + +/** + * Create docs index, which is basically the same structure as the original index + * but with adjusted slugs (the section part is omitted for cleaner URLs), separated + * topics/pages and next/prev adjusted so that they don't point to different topics. + */ +function create_docs() { + function remove_section(slug: string) { + return slug.replace(/\/[^/]+(\/[^/]+)$/g, '$1'); + } + + function remove_docs(slugs: string) { + return slugs.replace(/^docs\//, ''); + } + + let docs: { + /** The top level entries/packages: svelte/kit/etc. Key is the topic */ + topics: Record; + /** The docs pages themselves. Key is the topic + page */ + pages: Record; + } = { topics: {}, pages: {} }; + + for (const topic of index.docs.children) { + const pkg = topic.slug.split('/')[1]; + const sections = topic.children; + const transformed_topic: Document = (docs.topics[remove_docs(topic.slug)] = { + ...topic, + children: [] + }); + + for (const section of sections) { + const pages = section.children; + const transformed_section: Document = { + ...section, + children: [] + }; + + transformed_topic.children.push(transformed_section); + + for (const page of pages) { + const slug = remove_section(page.slug); + const transformed_page: Document = (docs.pages[remove_docs(slug)] = { + ...page, + slug, + next: page.next?.slug.startsWith(`docs/${pkg}/`) + ? { slug: remove_section(page.next.slug), title: page.next.title } + : null, + prev: page.prev?.slug.startsWith(`docs/${pkg}/`) + ? { slug: remove_section(page.prev.slug), title: page.prev.title } + : null + }); + + transformed_section.children.push(transformed_page); + } + } + } + + return docs; +} + +export const docs = create_docs(); diff --git a/apps/svelte.dev/src/routes/content.json/+server.ts b/apps/svelte.dev/src/routes/content.json/+server.ts index bc43de6446..65e5efbf18 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 } from '$lib/server/content'; +import { index, docs as _docs } from '$lib/server/content'; import { json } from '@sveltejs/kit'; import { markedTransform, normalizeSlugify, removeMarkdown } from '@sveltejs/site-kit/markdown'; import type { Block } from '@sveltejs/site-kit/search'; @@ -18,11 +18,7 @@ function get_href(parts: string[]) { async function content() { const blocks: Block[] = []; const breadcrumbs: string[] = []; - // We want the actual contents: docs -> docs/svelte etc -> docs/svelte/overview etc -> docs/svelte/overview/introduction etc - let docs = index.docs.children.flatMap((topic) => - topic.children.flatMap((section) => section.children) - ); - docs = docs.concat( + const docs = Object.values(_docs.pages).concat( index.tutorial.children.flatMap((topic) => topic.children.flatMap((section) => section.children.map((entry) => ({ diff --git a/apps/svelte.dev/src/routes/docs/[...path]/+layout.server.ts b/apps/svelte.dev/src/routes/docs/[...path]/+layout.server.ts index 5f6e4c30e2..56b4c3cb09 100644 --- a/apps/svelte.dev/src/routes/docs/[...path]/+layout.server.ts +++ b/apps/svelte.dev/src/routes/docs/[...path]/+layout.server.ts @@ -1,10 +1,10 @@ -import { index } from '$lib/server/content'; +import { docs } from '$lib/server/content'; import { error } from '@sveltejs/kit'; export const prerender = true; export async function load({ params }) { - const page = index[`docs/${params.path.split('/')[0]}`]; + const page = docs.topics[params.path.split('/')[0]]; if (!page) { error(404, 'Not found'); diff --git a/apps/svelte.dev/src/routes/docs/[...path]/+page.server.js b/apps/svelte.dev/src/routes/docs/[...path]/+page.server.js index b14a2fa09d..6f224b0712 100644 --- a/apps/svelte.dev/src/routes/docs/[...path]/+page.server.js +++ b/apps/svelte.dev/src/routes/docs/[...path]/+page.server.js @@ -1,36 +1,22 @@ -import { index } from '$lib/server/content'; +import { docs } from '$lib/server/content'; import { render_content } from '$lib/server/renderer'; import { error, redirect } from '@sveltejs/kit'; export async function load({ params }) { - const document = index[`docs/${params.path}`]; + const document = docs.pages[params.path]; if (!document) { - error(404); - } - - if (!document.body) { - let child = document; - - while (child.children[0]) { - child = child.children[0]; + const topic = docs.topics[params.path]; + if (topic) { + redirect(307, `/${topic.children[0].children[0].slug}`); } - - if (child === document) { - error(404); - } - - redirect(307, `/${child.slug}`); + error(404); } - const pkg = params.path.split('/')[0]; - return { document: { ...document, - body: await render_content(document.file, document.body), - prev: document.prev?.slug.startsWith(`docs/${pkg}/`) ? document.prev : null, - next: document.next?.slug.startsWith(`docs/${pkg}/`) ? document.next : null + body: await render_content(document.file, document.body) } }; } diff --git a/apps/svelte.dev/src/routes/nav.json/+server.ts b/apps/svelte.dev/src/routes/nav.json/+server.ts index e71856e111..5bf3d179e7 100644 --- a/apps/svelte.dev/src/routes/nav.json/+server.ts +++ b/apps/svelte.dev/src/routes/nav.json/+server.ts @@ -1,5 +1,5 @@ import { json } from '@sveltejs/kit'; -import { blog_posts, index } from '$lib/server/content'; +import { blog_posts, docs as _docs, index } from '$lib/server/content'; import type { NavigationLink } from '@sveltejs/site-kit'; export const prerender = true; @@ -9,7 +9,7 @@ export const GET = async () => { }; async function get_nav_list(): Promise { - const docs = index.docs.children.map((topic) => ({ + const docs = Object.values(_docs.topics).map((topic) => ({ title: topic.metadata.title, sections: topic.children.map((section) => ({ title: section.metadata.title,