Implement new version switcher

pull/11602/head
Matei-Paul Trandafir 2 years ago
parent 3db5e572c5
commit 96ec08a38b
No known key found for this signature in database
GPG Key ID: BC96CA77836E14F8

@ -1,5 +1,13 @@
import { execFile } from 'node:child_process';
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync } from 'node:fs';
import {
existsSync,
mkdirSync,
readdirSync,
readFileSync,
renameSync,
rmSync,
writeFileSync
} from 'node:fs';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
@ -17,8 +25,11 @@ try {
const version_path = join(docs_dir, version_dir.name);
const {
tags: { regex: tags_regex_raw, filter: tags_filter },
path: repo_path
} = JSON.parse(readFileSync(join(version_path, 'config.json'), 'utf-8'));
path: repo_path,
format
} = /** @type {import('src/lib/docs/types').Config} */ JSON.parse(
readFileSync(join(version_path, 'config.json'), 'utf-8')
);
// Filter list of tags
const tags_regex = new RegExp(tags_regex_raw);
@ -52,7 +63,6 @@ try {
tags = [...map.entries()].map(([major_minor, [tag]]) => [tag, major_minor]);
break;
}
case '':
case undefined:
break;
default:
@ -79,7 +89,7 @@ try {
let skipped = 0;
let i = 0;
for (const [ref, title] of tags) {
const dest_path = join(version_path, `${String(i++).padStart(3, '0')}_${title}`);
let dest_path = join(version_path, `${String(i++).padStart(3, '0')}_${title}`);
if (existsSync(dest_path)) {
if (force) rmRf(dest_path);
else {
@ -87,10 +97,20 @@ try {
continue;
}
}
if (format === 'flat') {
mkdirSync(dest_path);
dest_path = join(dest_path, '01-documentation');
}
rmRf(temp_dir);
mkdirSync(temp_dir);
await run_process(['git', `--work-tree=${temp_dir}`, 'checkout', ref, '--', repo_path]);
await renameSync(join(temp_dir, repo_path), dest_path);
if (format === 'flat') {
writeFileSync(
join(dest_path, 'meta.json'),
JSON.stringify({ title: 'Documentation' }, undefined, 2)
);
}
}
if (skipped) {

@ -1,8 +1,8 @@
{
"title": "Svelte 5 (RC)",
"tags": {
"regex": "^svelte@5\\.0\\.0-(next.\\d+)$"
"regex": "^svelte@(5\\.0\\.0-next.\\d+)$"
},
"path": "documentation/docs",
"path": "sites/svelte-5-preview/src/routes/docs/content",
"format": "sections"
}

@ -5,5 +5,6 @@ export const CONTENT_BASE_PATHS = {
BLOG: `${CONTENT_BASE}/blog`,
TUTORIAL: `${CONTENT_BASE}/tutorial`,
DOCS: `${CONTENT_BASE}/docs`,
PREVIOUS_DOCS: `./scripts/previous-docs`,
EXAMPLES: `${CONTENT_BASE}/examples`
};

@ -0,0 +1,39 @@
export interface Config {
/**
* Version group title
*/
title: string;
/**
* Git tags config
*/
tags: {
/**
* Regex for matching tags. The first numbered capturing group must contain the version name.
*/
regex: string;
/**
* Options to filter/title the git tags:
* - `"minor"` - only take the latest patch version for every minor version.
* Version extracted by the regex must match SemVer. The title is `<major>.<minor>`.
* - `undefined` _(default)_ - take every matching tag.
* The title is the version name.
*/
filter?: 'minor';
};
/**
* Path inside the git repo that docs are found at
*/
path: string;
/**
* Format of the docs files:
* - `flat` - a list of `00_name.md` files
* - `sections` - directories with a `meta.json` and a list of `00_name.md` files
*/
format: 'flat' | 'sections';
}
export interface VersionGroup {
title: string;
id: string;
versions: Record<string, string>;
}

@ -8,7 +8,8 @@ import {
} from '@sveltejs/site-kit/markdown';
import { CONTENT_BASE_PATHS } from '../../../constants.js';
import { render_content } from '../renderer';
import versions from '$lib/docs/versions.js';
import { readdir, readFile } from 'node:fs/promises';
import { join } from 'node:path';
/**
* @param {import('./types').DocsData} docs_data
@ -34,8 +35,15 @@ export async function get_parsed_docs(docs_data, slug) {
* @return {Promise<import('./types').DocsData>}
* */
export async function get_docs_data(version = undefined) {
if (version?.startsWith('v-')) version = version.substring(2);
let base;
if (versions.find((v) => v.version === version)) base = `./scripts/previous-docs/${version}/docs`;
const version_group = (await get_versions()).find((group) => version in group.versions);
if (version_group)
base = join(
CONTENT_BASE_PATHS.PREVIOUS_DOCS,
version_group.id,
version_group.versions[version]
);
else base = CONTENT_BASE_PATHS.DOCS;
const { readdir, readFile } = await import('node:fs/promises');
@ -85,7 +93,7 @@ export async function get_docs_data(version = undefined) {
content: page_content,
category: category_title,
sections: await get_sections(page_content),
path: `${app_base}/docs/${version ? version + '/' : ''}${page_slug}`,
path: `${app_base}/docs/${version ? `v-${version}/` : ''}${page_slug}`,
file: `${category_dir}/${filename}`
});
}
@ -169,3 +177,23 @@ export async function get_sections(markdown) {
return /** @type {import('./types').Section[]} */ (root.sections);
}
/**
* @return {Promise<import('$lib/docs/types').VersionGroup[]>}
*/
export async function get_versions() {
const base = CONTENT_BASE_PATHS.PREVIOUS_DOCS;
return Promise.all(
(await readdir(base)).map(async (dir) => {
const { title } = JSON.parse(await readFile(join(base, dir, 'config.json'), 'utf-8'));
const versions = await readdir(join(base, dir));
versions.splice(versions.indexOf('config.json'), 1);
versions.sort();
return {
title,
id: dir,
versions: Object.fromEntries(versions.map((dir) => [dir.substring(4), dir]))
};
})
);
}

@ -1,4 +1,4 @@
/**
* @type {import('@sveltejs/kit').ParamMatcher}
*/
export const match = (param) => /^v\d/.exec(param) != null;
export const match = (param) => param.startsWith('v-');

@ -3,16 +3,21 @@ export const prerender = true;
/**
* @type {import('./$types').LayoutServerLoad}
*/
export const load = async ({ params, url }) => {
export const load = async ({ params, url, fetch }) => {
const { get_versions } = await import('$lib/server/docs/index.js');
const version_groups = await get_versions();
if (url.pathname === '/docs') {
return {
sections: []
sections: [],
version_groups
};
}
const { get_docs_data, get_docs_list } = await import('$lib/server/docs/index.js');
return {
sections: get_docs_list(await get_docs_data(params.version))
sections: get_docs_list(await get_docs_data(params.version)),
version_groups
};
};

@ -1,7 +1,6 @@
<script>
import { page } from '$app/stores';
import { DocsContents } from '@sveltejs/site-kit/docs';
import versions from '$lib/docs/versions.js';
import { goto } from '$app/navigation';
export let data;
@ -9,6 +8,13 @@
$: version = param_version;
$: if (version !== param_version)
goto(`/docs/${version === 'latest' ? '' : version + '/'}introduction`);
$: version_groups = data.version_groups
.slice()
.reverse()
.map((group) => ({
title: group.title,
versions: Object.keys(group.versions).reverse()
}));
$: pageData = $page.data.page;
@ -21,9 +27,13 @@
<div class="toc-version-picker">
Version:
<select bind:value={version}>
<option value="latest">Latest (Svelte 5)</option>
{#each versions as v}
<option value={v.version}>{v.title}</option>
<option value="latest">Latest</option>
{#each version_groups as group}
<optgroup label={group.title}>
{#each group.versions as version}
<option value={'v-' + version}>{version}</option>
{/each}
</optgroup>
{/each}
</select>
</div>

@ -3,10 +3,8 @@
import { Icon } from '@sveltejs/site-kit/components';
import { copy_code_descendants } from '@sveltejs/site-kit/actions';
import { DocsOnThisPage, setupDocsHovers } from '@sveltejs/site-kit/docs';
import versions from '$lib/docs/versions.js';
export let data;
$: version = versions.find((v) => v.version === $page.params.version);
$: pages = data.sections.flatMap((section) => section.pages);
$: index = pages.findIndex(({ path }) => path === $page.url.pathname);
@ -25,13 +23,14 @@
</svelte:head>
<div class="text" id="docs-content" use:copy_code_descendants>
<a
class="edit"
href="https://github.com/sveltejs/svelte/edit/{version?.branch ??
'main'}/documentation/docs/{data.page.file}"
>
<Icon size={50} name="edit" /> Edit this page on GitHub
</a>
{#if !$page.params.version}
<a
class="edit"
href="https://github.com/sveltejs/svelte/edit/main/documentation/docs/{data.page.file}"
>
<Icon size={50} name="edit" /> Edit this page on GitHub
</a>
{/if}
<DocsOnThisPage details={data.page} />

@ -0,0 +1,8 @@
import { json } from '@sveltejs/kit';
import { get_versions } from '$lib/server/docs/index.js';
export const prerender = true;
export const GET = async () => {
return json(await get_versions());
};
Loading…
Cancel
Save