From 5c81737581a040bf48a6fb6ca258858e2d9002f3 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Mon, 25 Mar 2024 14:24:32 +0200 Subject: [PATCH] feat: add `/releases` page (#1688) * feat: add `/releases` page * remove solid * generated on build instead * update lockfile * update links * Update index.mdx * Update build.ts * fix slug creations * Add nav links back * update links valitor to 0.6.0 * use link card * wip - generated frontmatter * wip * fix labels name * improve logic * WIP refactor show link to GitHub wip version side navigation improve wording and navigation move releases to references * add entitify * agora vai * Update build.ts * fix: dir name * add (Rust) * fix dirName build * change if order * remove dirName * redo sidenav * place /releases back on header * wip mobile * improve mobile nav * Update ReleaseSidebar.astro * refactor: sidebar nav + dropdown only * fix width and redo button width * revert to show sidebar list + hide toc * fix labels * fix sort * fix split * fix split --------- Signed-off-by: Lorenzo Lewis Co-authored-by: Lorenzo Lewis Co-authored-by: Vitor Ayres Co-authored-by: Lucas Nogueira --- astro.config.mjs | 3 + package.json | 4 +- packages/releases-generator/build.ts | 191 +++++++++++++++ packages/releases-generator/package.json | 15 ++ pnpm-lock.yaml | 9 + pnpm-workspace.yaml | 1 + src/components/list/ReleaseSidebar.astro | 281 +++++++++++++++++++++++ src/components/overrides/Header.astro | 111 +++++++++ src/content/docs/references/index.mdx | 4 + src/content/docs/releases/.gitignore | 2 + 10 files changed, 620 insertions(+), 1 deletion(-) create mode 100644 packages/releases-generator/build.ts create mode 100644 packages/releases-generator/package.json create mode 100644 src/components/list/ReleaseSidebar.astro create mode 100644 src/components/overrides/Header.astro create mode 100644 src/content/docs/releases/.gitignore diff --git a/astro.config.mjs b/astro.config.mjs index 4400fd316..f6c94a567 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -76,6 +76,9 @@ export default defineConfig({ components: { SiteTitle: 'src/components/overrides/SiteTitle.astro', Footer: 'src/components/overrides/Footer.astro', + MarkdownContent: 'starlight-blog/overrides/MarkdownContent.astro', + Sidebar: 'starlight-blog/overrides/Sidebar.astro', + Header: 'src/components/overrides/Header.astro', ThemeSelect: 'src/components/overrides/ThemeSelect.astro', }, head: [ diff --git a/package.json b/package.json index 80423d9c5..647e4206a 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,11 @@ "dev": "astro dev", "format": "prettier -w --cache --plugin prettier-plugin-astro .", "build:references": "pnpm --filter js-api-generator run build", + "build:releases": "pnpm --filter releases-generator run build", "build:config": "pnpm --filter config-generator run build", "build:astro": "astro build", "build:i18n": "pnpm --filter docs-i18n-tracker run build", - "build": "pnpm dev:setup && pnpm build:references && pnpm build:config && pnpm build:astro && pnpm build:i18n", + "build": "pnpm dev:setup && pnpm build:references && pnpm build:config && pnpm build:releases && pnpm build:astro && pnpm build:i18n", "preview": "astro preview" }, "dependencies": { @@ -29,6 +30,7 @@ "prettier": "^3.2.5", "prettier-plugin-astro": "^0.13.0", "rehype-autolink-headings": "^7.1.0", + "semver": "^7.6.0", "sharp": "^0.33.2", "shiki": "^1.1.7", "starlight-blog": "^0.5.0", diff --git a/packages/releases-generator/build.ts b/packages/releases-generator/build.ts new file mode 100644 index 000000000..cba584db3 --- /dev/null +++ b/packages/releases-generator/build.ts @@ -0,0 +1,191 @@ +import { writeFileSync, mkdirSync } from 'node:fs'; +import { join } from 'node:path'; + +const note = + '\n# NOTE: This file is auto-generated in packages/releases-generator/build.ts\n# For corrections please edit it directly'; +const packages = [ + { + name: 'tauri', + url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/core/tauri/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tauri/releases/tag', + }, + { + name: '@tauri-apps/api', + url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/api/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tauri/releases/tag', + }, + { + name: 'tauri-cli', + url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/cli/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tauri/releases/tag', + }, + { + name: '@tauri-apps/cli', + url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/cli/node/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tauri/releases/tag', + }, + { + name: 'tauri-bundler', + url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/tooling/bundler/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tauri/releases/tag', + }, + { + name: 'wry', + url: 'https://raw.githubusercontent.com/tauri-apps/wry/dev/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/wry/releases/tag', + }, + { + name: 'tao', + url: 'https://raw.githubusercontent.com/tauri-apps/tao/dev/CHANGELOG.md', + tag: 'https://github.com/tauri-apps/tao/releases/tag', + }, +]; + +const baseDir = '../../src/content/docs/releases'; + +let latestVersions: { + [key: string]: string; +} = {}; + +async function generator() { + for (const pkg of packages) { + const response = await fetch(pkg.url); + const responseText: string = await response.text(); + const releases = responseText + .split('## \\[') + .filter((item) => !item.includes('# Changelog')) + .map((section) => { + const [version, ...c] = section.split('\n'); + const contents = c.join('\n'); + return { + version: version.replace('\\[', '').replace(']', ''), + notes: contents, + }; + }) + .filter(({ version }) => !version.includes('Not Published')); + + mkdirSync(join(baseDir, pkg.name), { recursive: true }); + // + /* + * Write files for each version + */ + let nextPage = '/releases'; + let nextLabel = pkg.name; + const len = releases.length; + for (let i = 0; i < len; i++) { + /** + * Deal with next-prev labels + */ + const thisVersion = releases[i].version; + let prevLabel, prevPage; + let navFrontmatter; + if (i !== len - 1) { + prevLabel = releases[i + 1].version; + prevPage = `releases/${pkg.name}/v${releases[i + 1].version}`; + } + if (i === 0) { + // latest version + latestVersions[pkg.name] = `v${thisVersion}`; + navFrontmatter = [ + `prev:`, + ` link: '${prevPage}'`, + ` label: '${prevLabel}'`, + `next: false`, + ]; + } else if (i === len - 1) { + // earliest version + navFrontmatter = [ + `prev: false`, + `next:`, + ` link: '${nextPage}'`, + ` label: '${nextLabel}'`, + ]; + } else { + navFrontmatter = [ + `prev:`, + ` link: '${prevPage}'`, + ` label: '${prevLabel}'`, + `next:`, + ` link: '${nextPage}'`, + ` label: '${nextLabel}'`, + ]; + } + + // + const pageFrontmatter = [ + note, + `title: '${pkg.name}@${thisVersion}'`, + `description: '${thisVersion}'`, + `slug: 'releases/${pkg.name}/v${thisVersion}'`, + `tableOfContents: false`, + `editUrl: 'https://github.com/tauri-apps/tauri-docs/packages/releases-generator/build.ts'`, + ]; + + const frontmatter = ['---', ...pageFrontmatter, ...navFrontmatter, '---'].join('\n'); + // + const indexLink = `[Return](/releases)`; + const viewInGitHub = `View on GitHub`; + const linksDiv = `
${indexLink}${viewInGitHub}
`; + // + const sidebar = `\nimport ReleaseSidebar from '@components/list/ReleaseSidebar.astro'; + \n\n\n`; + + writeFileSync( + join(baseDir, pkg.name, `v${thisVersion}.mdx`), + `${frontmatter}\n${sidebar}\n${linksDiv}\n${entitify(releases[i].notes)}` + ); + + // use in next iteration + nextPage = `releases/${pkg.name}/v${thisVersion}`; + nextLabel = `v${thisVersion}`; + } + } + + // Generate index page + const extraNote = + '# To quickly preview changes, you can edit this file, them make sure you copy the changes over the source build.ts script\n'; + const indexPage = [ + '---', + note, + extraNote, + `title: 'Tauri Core Ecosystem Releases'`, + `editUrl: 'https://github.com/tauri-apps/tauri-docs/packages/releases-generator/build.ts'`, + '---', + ].join('\n'); + + const indexPageContent = `import { LinkCard, CardGrid } from '@astrojs/starlight/components';\n + + + + + + + + +`; + + writeFileSync(join(baseDir, 'index.mdx'), `${indexPage}\n${indexPageContent}`); +} + +function entitify(str: string): string { + return str + .replace(/[&<>"']/g, function (entity) { + switch (entity) { + case '&': + return '&'; + case '<': + return '<'; + case '>': + return '>'; + case '"': + return '"'; + case "'": + return '''; + default: + return entity; + } + }) + .replace(/\$\{/g, '$\\{'); +} + +generator(); diff --git a/packages/releases-generator/package.json b/packages/releases-generator/package.json new file mode 100644 index 000000000..da0c11b32 --- /dev/null +++ b/packages/releases-generator/package.json @@ -0,0 +1,15 @@ +{ + "name": "releases-generator", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "tsm ./build.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "tsm": "^2.3.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 193d47db3..22d5ba690 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -40,6 +40,9 @@ importers: rehype-autolink-headings: specifier: ^7.1.0 version: 7.1.0 + semver: + specifier: ^7.6.0 + version: 7.6.0 sharp: specifier: ^0.33.2 version: 0.33.3 @@ -119,6 +122,12 @@ importers: specifier: ^3.1.17 version: 3.1.18(typedoc@0.25.12) + packages/releases-generator: + dependencies: + tsm: + specifier: ^2.3.0 + version: 2.3.0 + packages: /@ampproject/remapping@2.3.0: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d3a35a31d..46e2ae91d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,3 +3,4 @@ packages: - 'packages/js-api-generator' - 'packages/config-generator' - 'packages/tauri-typedoc-theme' + - 'packages/releases-generator' diff --git a/src/components/list/ReleaseSidebar.astro b/src/components/list/ReleaseSidebar.astro new file mode 100644 index 000000000..4437108b9 --- /dev/null +++ b/src/components/list/ReleaseSidebar.astro @@ -0,0 +1,281 @@ +--- +import { stripLeadingAndTrailingSlashes } from 'node_modules/@astrojs/starlight/utils/path'; +import { routes, type Route } from 'node_modules/@astrojs/starlight/utils/routing'; +import { Icon } from '@astrojs/starlight/components'; +import semver from 'semver'; + +interface Props { + /** + * Package name + */ + packageName: string; + /** + * Slug relative to /src - e.g "/zh-cn/features" + * + * Note: leading and trailing slashes are dropped "/features/" === "features" + */ + slug: string; + /** + * Filter out pages by title - case insensitive + */ + filterOutByTitle?: string[]; + /** + * Filter out pages by file name - case insensitive + */ + filterOutByFileName?: string[]; +} + +let { slug } = Astro.props; +const { filterOutByTitle = [], filterOutByFileName = [], packageName } = Astro.props; + +slug = stripLeadingAndTrailingSlashes(slug.toLowerCase()); + +let mainList: Route[] = []; + +routes.forEach((page) => { + // `page.slug` is the slug of the current page being looped, + // `slug` is this component prop + if (page.slug.startsWith(slug + '/')) { + mainList.push(page); + } +}); + +/** + * Filter items if any filter is set + */ + +if (filterOutByTitle.length > 0) { + mainList = mainList.filter( + (page) => !filterOutByTitle.some((val) => page.entry.data.title.includes(val)) + ); +} + +if (filterOutByFileName.length > 0) { + mainList = mainList.filter( + (page) => !filterOutByFileName.some((val) => page.entry.id.includes(val)) + ); +} + +function sortVersions(a: Route, b: Route): number { + const t1 = a.entry.data.title; + const t2 = b.entry.data.title; + const [package1, version1] = t1.split('@').filter(w => w.length > 0); + const [package2, version2] = t2.split('@').filter(w => w.length > 0); + if (package1 === package2) { + return semver.lt(version1, version2); + } else { + return package1.localeCompare(package2); + } +} +mainList.sort((a, b) => sortVersions(b, a)); +--- + +
+
+
+

Changelogs:
{packageName}

+
+
+ { + mainList.map((item) => ( + <> + {item.entry.data.description} + + )) + } +
+
+
+ + + + + + + + diff --git a/src/components/overrides/Header.astro b/src/components/overrides/Header.astro new file mode 100644 index 000000000..86bff3953 --- /dev/null +++ b/src/components/overrides/Header.astro @@ -0,0 +1,111 @@ +--- +import type { Props } from '@astrojs/starlight/props'; +import LanguageSelect from '@astrojs/starlight/components/LanguageSelect.astro'; +import Search from '@astrojs/starlight/components/Search.astro'; +import SiteTitle from './SiteTitle.astro'; +import SocialIcons from '@astrojs/starlight/components/SocialIcons.astro'; +import ThemeSelect from '@astrojs/starlight/components/ThemeSelect.astro'; +--- + +
+
+ +
+
+ +
+
+ + Releases + + +
+
+ + diff --git a/src/content/docs/references/index.mdx b/src/content/docs/references/index.mdx index b8eeca09a..14e83e5b4 100644 --- a/src/content/docs/references/index.mdx +++ b/src/content/docs/references/index.mdx @@ -33,4 +33,8 @@ import { LinkCard, CardGrid } from '@astrojs/starlight/components'; title="Configuration Files" href="/references/configuration-files" /> + diff --git a/src/content/docs/releases/.gitignore b/src/content/docs/releases/.gitignore new file mode 100644 index 000000000..18a2fa3ce --- /dev/null +++ b/src/content/docs/releases/.gitignore @@ -0,0 +1,2 @@ +*.md +*.mdx \ No newline at end of file