update starlight and astro ecosystem pkgs (#3196)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jacob Bolda <me@jacobbolda.com>
This commit is contained in:
Vitor Ayres
2025-07-10 14:19:11 -03:00
committed by GitHub
parent 1bdf01b795
commit 89bf4cb684
36 changed files with 1430 additions and 1702 deletions

View File

@@ -1,16 +1,18 @@
// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import { rehypeHeadingIds } from '@astrojs/markdown-remark';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import locales from './locales.json';
import starlightLinksValidator from 'starlight-links-validator';
import starlightSidebarTopics from 'starlight-sidebar-topics';
import starlightBlog from 'starlight-blog';
import serviceWorker from 'astrojs-service-worker';
import astroD2 from 'astro-d2';
import starlightUtils from '@lorenzo_lewis/starlight-utils';
import path from 'path';
import { fileURLToPath } from 'url';
import lunaria from '@lunariajs/starlight';
import { readFileSync } from 'fs';
const authors = {
nothingismagick: {
@@ -74,12 +76,247 @@ export default defineConfig({
integrations: [
starlight({
plugins: [
starlightUtils({
multiSidebar: {
switcherStyle: 'horizontalList',
},
}),
starlightBlog({ authors }),
starlightSidebarTopics(
[
{
label: {
en: 'Guides',
'zh-CN': '指引',
es: 'Guías',
},
id: 'guides',
link: '/start/',
icon: 'open-book',
items: [
{
label: 'Quick Start',
translations: {
'zh-CN': '快速开始',
es: 'Guía rápida',
},
collapsed: true,
items: [
'start',
'start/prerequisites',
'start/create-project',
// {
// label: 'What is Tauri?',
// // translations: {
// // 'zh-CN': '什么是 Tauri',
// // es: '¿Qué es Tauri?',
// // },
// link: '/start/',
// },
// {
// label: 'Prerequisites',
// // translations: {
// // 'zh-CN': '前置条件',
// // es: 'Requisitos previos',
// // },
// link: '/start/prerequisites/',
// },
// {
// label: 'Create a Project',
// // translations: {
// // 'zh-CN': '创建项目',
// // es: 'Crea un proyecto',
// // },
// link: '/start/create-project/',
// },
{
label: 'Frontend Configuration',
translations: {
'zh-CN': '前端配置',
es: 'Configuración del frontend',
},
collapsed: true,
autogenerate: { directory: 'start/frontend' },
},
{
label: 'Upgrade & Migrate',
translations: {
'zh-CN': '升级和迁移',
es: 'Actualizar y migrar',
},
collapsed: true,
autogenerate: { directory: 'start/migrate' },
},
],
},
{
label: 'Core Concepts',
translations: {
'zh-CN': '核心概念',
es: 'Conceptos básicos',
},
collapsed: true,
autogenerate: { directory: 'concept' },
},
{
label: 'Security',
translations: {
'zh-CN': '安全',
es: 'Seguridad',
},
collapsed: true,
autogenerate: { directory: 'security' },
},
{
label: 'Develop',
translations: {
'zh-CN': '开发',
es: 'Desarrollo',
},
collapsed: true,
items: [
'develop',
'develop/configuration-files',
'develop/calling-rust',
'develop/calling-frontend',
'develop/resources',
'develop/sidecar',
'develop/state-management',
'develop/updating-dependencies',
{
label: 'Debug',
collapsed: true,
autogenerate: { directory: 'develop/Debug' },
},
{
label: 'Plugins',
collapsed: true,
autogenerate: { directory: 'develop/Plugins' },
},
{
label: 'Tests',
collapsed: true,
autogenerate: { directory: 'develop/Tests' },
},
],
},
{
label: 'Distribute',
translations: {
'zh-CN': '分发',
es: 'Distribuir',
},
collapsed: true,
autogenerate: { directory: 'distribute' },
},
{
label: 'Learn',
translations: {
'zh-CN': '学习',
es: 'Aprende',
},
collapsed: true,
autogenerate: { directory: 'learn' },
},
{
label: 'Plugins',
translations: {
'zh-CN': '插件',
es: 'Plugins',
},
collapsed: true,
autogenerate: { directory: 'plugin' },
},
{
label: 'About',
translations: {
'zh-CN': '关于',
es: 'Acerca de',
},
collapsed: true,
autogenerate: { directory: 'about' },
},
],
},
{
label: { en: 'References', 'zh-CN': '参考', es: 'Referencias' },
id: 'references',
link: '/reference/cli',
icon: 'document',
items: [
{
label: 'Command Line Interface',
translations: {
'zh-CN': '命令行接口CLI',
es: 'Interfaz de línea de comandos',
},
link: '/reference/cli/',
},
{
label: 'Security',
translations: {
'zh-CN': '安全',
es: 'Seguridad',
},
collapsed: true,
autogenerate: { directory: 'reference/acl' },
},
{
label: 'Configuration',
translations: {
'zh-CN': '配置',
es: 'Configuración',
},
link: '/reference/config/',
},
{
label: 'Environment Variables',
translations: {
'zh-CN': '环境变量',
es: 'Variables de entorno',
},
link: '/reference/environment-variables/',
},
{
label: 'Webview Versions',
translations: {
'zh-CN': 'Webview 版本',
es: 'Versiones de Webview',
},
link: '/reference/webview-versions/',
},
{
label: 'Releases',
translations: {
'zh-CN': '发行版',
es: 'Lanzamientos',
},
collapsed: true,
autogenerate: { directory: 'release' },
},
{
label: 'JavaScript',
collapsed: true,
autogenerate: { directory: 'reference/javascript' },
},
{
label: 'Rust (docs.rs)',
link: 'https://docs.rs/tauri/~2/',
},
],
},
{
label: 'Blog',
id: 'blog',
link: '/blog/',
icon: 'pen',
// Empty item to instruct it that is is local files, not an external link
// this is actually filled in through the topics dir for `blog` below
items: [],
},
],
{
exclude: ['**/_*/**'],
topics: {
blog: ['/blog', '/blog/*', '/blog/**/*', '**/blog', '**/blog/*', '**/blog/**/*'],
},
}
),
starlightLinksValidator({
errorOnFallbackPages: false,
errorOnRelativeLinks: false,
@@ -94,19 +331,17 @@ export default defineConfig({
light: './src/assets/logo_light.svg',
replacesTitle: true,
},
social: {
github: 'https://github.com/tauri-apps/tauri',
discord: 'https://discord.com/invite/tauri',
twitter: 'https://twitter.com/TauriApps',
mastodon: 'https://fosstodon.org/@TauriApps',
rss: `${site}/rss/`,
},
social: [
{ icon: 'github', label: 'GitHub', href: 'https://github.com/tauri-apps/tauri' },
{ icon: 'discord', label: 'Discord', href: 'https://discord.com/invite/tauri' },
{ icon: 'twitter', label: 'Twitter', href: 'https://twitter.com/TauriApps' },
{ icon: 'mastodon', label: 'Mastodon', href: 'https://fosstodon.org/@TauriApps' },
{ icon: 'rss', label: 'RSS', href: `${site}/rss` },
],
components: {
Header: './src/components/overrides/Header.astro',
Footer: 'src/components/overrides/Footer.astro',
ThemeSelect: 'src/components/overrides/ThemeSelect.astro',
PageFrame: 'src/components/overrides/PageFrame.astro',
TableOfContents: 'src/components/overrides/TableOfContents.astro',
},
head: [
{
@@ -145,249 +380,6 @@ export default defineConfig({
expressiveCode: {
styleOverrides: { borderRadius: '0.5rem' },
},
sidebar: [
{
label: 'Guides',
translations: {
'zh-CN': '指引',
es: 'Guías',
},
collapsed: true,
items: [
{
label: 'Quick Start',
translations: {
'zh-CN': '快速开始',
es: 'Guía rápida',
},
collapsed: true,
items: [
{
label: 'What is Tauri?',
translations: {
'zh-CN': '什么是 Tauri',
es: '¿Qué es Tauri?',
},
link: '/start/',
},
{
label: 'Prerequisites',
translations: {
'zh-CN': '前置条件',
es: 'Requisitos previos',
},
link: '/start/prerequisites/',
},
{
label: 'Create a Project',
translations: {
'zh-CN': '创建项目',
es: 'Crea un proyecto',
},
link: '/start/create-project/',
},
{
label: 'Frontend Configuration',
translations: {
'zh-CN': '前端配置',
es: 'Configuración del frontend',
},
collapsed: true,
autogenerate: { directory: 'start/frontend' },
},
{
label: 'Upgrade & Migrate',
translations: {
'zh-CN': '升级和迁移',
es: 'Actualizar y migrar',
},
collapsed: true,
autogenerate: { directory: 'start/migrate' },
},
],
},
{
label: 'Core Concepts',
translations: {
'zh-CN': '核心概念',
es: 'Conceptos básicos',
},
collapsed: true,
autogenerate: { directory: 'concept' },
},
{
label: 'Security',
translations: {
'zh-CN': '安全',
es: 'Seguridad',
},
collapsed: true,
autogenerate: { directory: 'security' },
},
{
label: 'Develop',
translations: {
'zh-CN': '开发',
es: 'Desarrollo',
},
collapsed: true,
items: [
'develop',
'develop/configuration-files',
'develop/calling-rust',
'develop/calling-frontend',
'develop/resources',
'develop/sidecar',
'develop/state-management',
'develop/updating-dependencies',
{
label: 'Debug',
collapsed: true,
autogenerate: { directory: 'develop/Debug' },
},
{
label: 'Plugins',
collapsed: true,
autogenerate: { directory: 'develop/Plugins' },
},
{
label: 'Tests',
collapsed: true,
autogenerate: { directory: 'develop/Tests' },
},
],
},
{
label: 'Distribute',
translations: {
'zh-CN': '分发',
es: 'Distribuir',
},
collapsed: true,
autogenerate: { directory: 'distribute' },
},
{
label: 'Learn',
translations: {
'zh-CN': '学习',
es: 'Aprende',
},
collapsed: true,
autogenerate: { directory: 'learn' },
},
{
label: 'Plugins',
translations: {
'zh-CN': '插件',
es: 'Plugins',
},
collapsed: true,
autogenerate: { directory: 'plugin' },
},
{
label: 'Contribute',
link: '/contribute/',
},
{
label: 'About',
translations: {
'zh-CN': '关于',
es: 'Acerca de',
},
collapsed: true,
autogenerate: { directory: 'about' },
},
],
},
{
label: 'References',
translations: {
'zh-CN': '参考',
es: 'Referencias',
},
collapsed: true,
items: [
{
label: 'Security',
translations: {
'zh-CN': '安全',
es: 'Seguridad',
},
collapsed: true,
autogenerate: { directory: 'reference/acl' },
},
{
label: 'Command Line Interface',
translations: {
'zh-CN': '命令行接口CLI',
es: 'Interfaz de línea de comandos',
},
link: '/reference/cli/',
},
{
label: 'Configuration',
translations: {
'zh-CN': '配置',
es: 'Configuración',
},
link: '/reference/config/',
},
{
label: 'Environment Variables',
translations: {
'zh-CN': '环境变量',
es: 'Variables de entorno',
},
link: '/reference/environment-variables/',
},
{
label: 'Webview Versions',
translations: {
'zh-CN': 'Webview 版本',
es: 'Versiones de Webview',
},
link: '/reference/webview-versions/',
},
{
label: 'Releases',
translations: {
'zh-CN': '发行版',
es: 'Lanzamientos',
},
collapsed: true,
autogenerate: { directory: 'release' },
},
{
label: 'JavaScript',
collapsed: true,
autogenerate: { directory: 'reference/javascript' },
},
{
label: 'Rust (docs.rs)',
link: 'https://docs.rs/tauri/~2/',
},
],
},
{
label: 'Blog',
translations: {
'zh-CN': '博客',
es: 'Blog',
},
collapsed: true,
items: [
{
label: 'All posts',
link: '/blog/',
},
{
label: 'Recent posts',
collapsed: false,
autogenerate: { directory: 'blog', sort: 'date', order: 'descending' },
},
],
},
],
locales,
lastUpdated: true,
}),
@@ -455,7 +447,7 @@ export default defineConfig({
'/blog/2023/06/14/tauri-1-4': '/blog/tauri-1-4',
'/blog/2023/06/15/tauri-board-elections-and-governance-updates':
'/blog/tauri-board-elections-and-governance-updates',
'about/intro': 'about/philosophy',
'/about/intro': '/about/philosophy',
// v1 /guides/debugging -> /guides/debug
...i18nRedirect('/v1/guides/debugging/application', '/guides/debug/application'),
...i18nRedirect('/v1/guides/debugging/vs-code', '/guides/debug/vs-code'),
@@ -517,10 +509,13 @@ export default defineConfig({
server: {
headers: readHeaders(),
},
//
});
// Generates a redirect for each locale.
/**
* @param {string} from
* @param {string} to
*/
function i18nRedirect(from, to) {
const routes = {};
Object.keys(locales).map((locale) =>
@@ -536,8 +531,7 @@ function i18nRedirect(from, to) {
// Read the HTTP header file in `public/_headers`
function readHeaders() {
const header_file = fs
.readFileSync('public/_headers', { encoding: 'utf8' })
const header_file = readFileSync('public/_headers', { encoding: 'utf8' })
.split('\n')
.filter(Boolean);
const headers = {};

View File

@@ -22,34 +22,29 @@
"preview": "astro preview"
},
"dependencies": {
"@astrojs/markdown-remark": "^5.2.0",
"@astrojs/rss": "^4.0.7",
"@astrojs/starlight": "0.29.2",
"@lorenzo_lewis/starlight-utils": "^0.2.0",
"@astrojs/markdown-remark": "^6.3.2",
"@astrojs/rss": "^4.0.12",
"@astrojs/starlight": "0.34.4",
"@lunariajs/core": "^0.1.1",
"@lunariajs/starlight": "^0.1.1",
"@types/json-schema": "^7.0.15",
"astro": "^4.16.18",
"astro-d2": "^0.6.0",
"astro": "^5.11.0",
"astro-d2": "^0.8.0",
"astro-feelback": "^0.3.4",
"astrojs-service-worker": "^2.0.0",
"jsdom": "^26.1.0",
"prettier": "^3.2.5",
"prettier-plugin-astro": "^0.14.0",
"prettier-plugin-astro": "^0.14.1",
"rehype-autolink-headings": "^7.1.0",
"sass": "^1.89.0",
"sharp": "^0.33.5",
"shiki": "^3.0.0",
"starlight-blog": "^0.15.0",
"starlight-links-validator": "^0.13.0"
"starlight-blog": "^0.24.0",
"starlight-sidebar-topics": "^0.6.0",
"starlight-links-validator": "^0.17.0"
},
"packageManager": "pnpm@10.12.4",
"engines": {
"pnpm": "^10.0.0"
},
"pnpm": {
"patchedDependencies": {
"@astrojs/starlight@0.29.2": "patches/@astrojs__starlight@0.29.2.patch"
}
}
}

View File

@@ -13,8 +13,8 @@
"dependencies": {
"github-slugger": "^2.0.0",
"tsm": "^2.3.0",
"typedoc": "^0.26.6",
"typedoc-plugin-markdown": "^4.2.6",
"typedoc-plugin-mdn-links": "^3.2.11"
"typedoc": "0.26.6",
"typedoc-plugin-markdown": "4.2.6",
"typedoc-plugin-mdn-links": "3.2.11"
}
}

View File

@@ -1,50 +0,0 @@
diff --git a/schemas/sidebar.ts b/schemas/sidebar.ts
index 2c4cc1d588f27b0106a82135ca3772cba86c5309..59a46a986a3fac739043c71f8a97801fa50e3e64 100644
--- a/schemas/sidebar.ts
+++ b/schemas/sidebar.ts
@@ -49,6 +49,8 @@ const AutoSidebarGroupSchema = SidebarGroupSchema.extend({
// TODO: not supported by Docusaurus but would be good to have
/** How many directories deep to include from this directory in the sidebar. Default: `Infinity`. */
// depth: z.number().optional(),
+ sort: z.enum(['date']).optional(),
+ order: z.enum(['ascending','descending']).optional()
}),
}).strict();
export type AutoSidebarGroup = z.infer<typeof AutoSidebarGroupSchema>;
diff --git a/utils/navigation.ts b/utils/navigation.ts
index 2ae0fa092fa53574c2287a1f3e0b818b5bb66aad..8bf0f9ce5a1f904e883cc6b4cef22cd53e7712dd 100644
--- a/utils/navigation.ts
+++ b/utils/navigation.ts
@@ -99,7 +99,7 @@ function groupFromAutogenerateConfig(
routes: Route[],
currentPathname: string
): Group {
- const { collapsed: subgroupCollapsed, directory } = item.autogenerate;
+ const { collapsed: subgroupCollapsed, directory , sort, order } = item.autogenerate;
const localeDir = locale ? locale + '/' + directory : directory;
const dirDocs = routes.filter(
(doc) =>
@@ -108,7 +108,8 @@ function groupFromAutogenerateConfig(
// Match against `foo/anything/else.md`.
doc.id.startsWith(localeDir + '/')
);
- const tree = treeify(dirDocs, localeDir);
+ const sorted = !sort ? dirDocs : dirDocs.sort(sortHandler(sort, order)).map((doc, i) => {doc.entry.data.sidebar.order = i; return doc});
+ const tree = treeify(sorted, localeDir);
const label = pickLang(item.translations, localeToLang(locale)) || item.label;
return {
type: 'group',
@@ -119,6 +120,13 @@ function groupFromAutogenerateConfig(
};
}
+const sortHandler = (kind: 'date', order: 'ascending' | 'descending') => {
+ if (kind === 'date') {
+ if (order === 'ascending') return (docA: Route, docB: Route) => docA.entry.data.date! > docB.entry.data.date! ? 1 : -1
+ return (docA: Route, docB: Route) => docA.entry.data.date! < docB.entry.data.date! ? 1 : -1
+ }
+}
+
/** Check if a string starts with one of `http://` or `https://`. */
const isAbsolute = (link: string) => /^https?:\/\//.test(link);

1956
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,13 @@
},
"packageRules": [
{
"matchPackageNames": ["/.*astro.*/i", "/.*starlight.*/i", "/.*typedoc.*/i"],
"matchPackageNames": ["/.*astro.*/i", "/.*starlight.*/i"],
"groupName": "astro & starlight packages",
"separateMajorMinor": false
},
{
"matchPackageNames": ["typedoc", "typedoc-plugin-markdown", "typedoc-plugin-mdn-links"],
"enabled": false
}
]
}

View File

@@ -18,42 +18,42 @@ const { npm, yarn, pnpm, bun, cargo, deno } = Astro.props;
{
npm && (
<TabItem label="npm">
<Code code={npm} lang="sh" theme="css-variables" frame="none" />
<Code code={npm} lang="sh" frame="none" />
</TabItem>
)
}
{
yarn && (
<TabItem label="yarn">
<Code code={yarn} lang="sh" theme="css-variables" frame="none" />
<Code code={yarn} lang="sh" frame="none" />
</TabItem>
)
}
{
pnpm && (
<TabItem label="pnpm">
<Code code={pnpm} lang="sh" theme="css-variables" frame="none" />
<Code code={pnpm} lang="sh" frame="none" />
</TabItem>
)
}
{
deno && (
<TabItem label="deno">
<Code code={deno} lang="sh" theme="css-variables" frame="none" />
<Code code={deno} lang="sh" frame="none" />
</TabItem>
)
}
{
bun && (
<TabItem label="bun">
<Code code={bun} lang="sh" theme="css-variables" frame="none" />
<Code code={bun} lang="sh" frame="none" />
</TabItem>
)
}
{
cargo && (
<TabItem label="cargo">
<Code code={cargo} lang="sh" theme="css-variables" frame="none" />
<Code code={cargo} lang="sh" frame="none" />
</TabItem>
)
}

View File

@@ -7,7 +7,7 @@ interface Props extends HTMLAttributes<'a'> {}
---
<div>
<a class="not-content" {...Astro.props}>Tauri 1.0 Upgrade Guide <Icon name="rocket" /></a>
<a class="not-content">Tauri 1.0 Upgrade Guide <Icon name="rocket" /></a>
</div>
<style>

View File

@@ -5,10 +5,11 @@ import {
ensureTrailingSlash,
} from 'node_modules/@astrojs/starlight/utils/path';
import { CardGrid } from '@astrojs/starlight/components';
import { routes, type Route } from 'node_modules/@astrojs/starlight/utils/routing';
import { routes } from 'node_modules/@astrojs/starlight/utils/routing';
// custom component copied from starlight/components/LinkCard
import CustomLinkCard from '@components/plugins/CustomLinkCard.astro';
import type { Route } from 'node_modules/@astrojs/starlight/utils/routing/types';
interface Props {
/**
@@ -47,10 +48,13 @@ function alphaSort(a: Route, b: Route): number {
}
function compareOrder(a: Route, b: Route): boolean {
return a.entry.data.sidebar.order > b.entry.data.sidebar.order;
const orderA = a.entry.data.sidebar?.order ?? 0;
const orderB = b.entry.data.sidebar?.order ?? 0;
return orderA > orderB;
}
let { slug } = Astro.props;
let { slug }: Props = Astro.props;
const {
filterOutByTitle = [],
filterOutByFileName = [],
@@ -84,11 +88,11 @@ let fallbackList: Route[] = [];
let mainList: Route[] = [];
routes.forEach((page) => {
// `page.slug` is the slug of the current page being looped, `slug` is a prop
if (page.slug.startsWith(slug)) {
// `page.id` is the slug of the current page being looped, `slug` is component prop
if (page.id.startsWith(slug)) {
if (page.isFallback) {
fallbackList.push(page);
} else if (page.slug !== slug) {
} else if (page.id !== slug) {
mainList.push(page);
}
}
@@ -154,9 +158,9 @@ if (!sortAlphabetically) {
return (
<CustomLinkCard
title={item.entry.data.title}
href={`/${item.slug}/`}
href={`/${item.id}/`}
description={item.entry.data.description}
footer={callback instanceof Function && callback(item.slug)}
footer={callback instanceof Function && callback(item.id)}
/>
);
})
@@ -167,9 +171,9 @@ if (!sortAlphabetically) {
<CustomLinkCard
class="fallback-badge"
title={item.entry.data.title}
href={`/${item.slug}/`}
href={`/${item.id}/`}
description={item.entry.data.description}
footer={callback instanceof Function && callback(item.slug)}
footer={callback instanceof Function && callback(item.id)}
/>
))
}

View File

@@ -1,10 +1,9 @@
---
import type { Props } from '@astrojs/starlight/props';
import Default from '@astrojs/starlight/components/Footer.astro';
const year = new Date().getFullYear();
---
<Default {...Astro.props}><slot /></Default>
<Default><slot /></Default>
<hr />

View File

@@ -1,13 +1,12 @@
---
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 './ThemeSelect.astro';
const curLocale = Astro.props.locale;
const curLocale = Astro.locals.starlightRoute.locale;
const slug = Astro.locals.starlightRoute.entry.slug;
type Link = {
title: string;
@@ -41,10 +40,10 @@ const links: Link[] = [
<div class="header sl-flex">
<div class="full-width sl-flex">
<SiteTitle {...Astro.props} />
<SiteTitle />
</div>
<div class="sl-flex">
<Search {...Astro.props} />
<Search />
</div>
<div class="sl-hidden md:sl-flex right-group">
<div class="desktop">
@@ -57,10 +56,10 @@ const links: Link[] = [
}
</div>
<div class="sl-flex social-icons">
<SocialIcons {...Astro.props} />
<SocialIcons />
</div>
<LanguageSelect {...Astro.props} />
<ThemeSelect {...Astro.props} />
<LanguageSelect />
<ThemeSelect />
</div>
</div>
@@ -136,7 +135,7 @@ body[data-mobile-menu-expanded] header {
</style>
{
Astro.props.entry.slug === '' || Astro.props.locale === Astro.props.entry.slug ?
slug === '' || slug === curLocale ?
<style>
.header {
background-color: transparent;

View File

@@ -1,101 +0,0 @@
---
import MobileMenuToggle from 'virtual:starlight/components/MobileMenuToggle';
import type { Props } from '@astrojs/starlight/props';
import Sidebar from '@lorenzo_lewis/starlight-utils/components/Sidebar.astro';
const { t } = Astro.locals;
---
<div class="page sl-flex">
<header class="header"><slot name="header" /></header>
<nav class="sidebar" aria-label={t('sidebarNav.accessibleLabel')}>
<MobileMenuToggle {...Astro.props} />
<div
id="starlight__sidebar"
class={Astro.props.entry.slug === '' || Astro.props.locale === Astro.props.entry.slug
? 'sidebar-pane lp-hide'
: 'sidebar-pane'}
>
<div class="sidebar-content sl-flex">
<Sidebar {...Astro.props} />
</div>
</div>
</nav>
<div class="main-frame"><slot /></div>
</div>
<style>
.page {
flex-direction: column;
min-height: 100vh;
}
@media (min-width: 50rem) {
.lp-hide {
display: none;
}
}
.header {
z-index: var(--sl-z-index-navbar);
position: fixed;
inset-inline-start: 0;
inset-block-start: 0;
width: 100%;
height: var(--sl-nav-height);
border-bottom: 1px solid var(--sl-color-hairline-shade);
padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x);
padding-inline-end: var(--sl-nav-pad-x);
background-color: var(--sl-color-bg-nav);
}
:global([data-has-sidebar]) .header {
padding-inline-end: calc(var(--sl-nav-gap) + var(--sl-nav-pad-x) + var(--sl-menu-button-size));
}
.sidebar-pane {
visibility: var(--sl-sidebar-visibility, hidden);
position: fixed;
z-index: var(--sl-z-index-menu);
inset-block: var(--sl-nav-height) 0;
inset-inline-start: 0;
width: 100%;
background-color: var(--sl-color-black);
overflow-y: auto;
}
:global([aria-expanded='true']) ~ .sidebar-pane {
--sl-sidebar-visibility: visible;
}
.sidebar-content {
height: 100%;
min-height: max-content;
padding: 1rem var(--sl-sidebar-pad-x) 0;
flex-direction: column;
gap: 1rem;
}
@media (min-width: 50rem) {
.sidebar-content::after {
content: '';
padding-bottom: 1px;
}
}
.main-frame {
padding-top: calc(var(--sl-nav-height) + var(--sl-mobile-toc-height));
padding-inline-start: var(--sl-content-inline-start);
}
@media (min-width: 50rem) {
:global([data-has-sidebar]) .header {
padding-inline-end: var(--sl-nav-pad-x);
}
.sidebar-pane {
--sl-sidebar-visibility: visible;
width: var(--sl-sidebar-width);
background-color: var(--sl-color-bg-sidebar);
border-inline-end: 1px solid var(--sl-color-hairline-shade);
}
}
</style>

View File

@@ -3,7 +3,6 @@
// https://github.com/withastro/starlight/blob/main/packages/starlight/components/Select.astro
// https://github.com/withastro/starlight/blob/main/packages/starlight/components/LanguageSelect.astro
import type { Props } from '@astrojs/starlight/props';
import Default from '@astrojs/starlight/components/SiteTitle.astro';
import { Icon } from '@astrojs/starlight/components';
@@ -40,7 +39,7 @@ const links: Link[] = [
---
<>
<Default {...Astro.props}><slot /></Default>
<Default><slot /></Default>
<starlight-select class="mobile">
<label>

View File

@@ -1,26 +0,0 @@
---
import TableOfContentsList from './TableOfContents/TableOfContentsList.astro';
import type { Props as BaseProps } from '@astrojs/starlight/props';
type Props = BaseProps & {
toc: BaseProps['toc'] & {
collapseLevel?: number;
};
};
const { toc } = Astro.props;
const { t } = Astro.locals;
---
{
toc && (
<tauri-starlight-toc data-min-h={toc.minHeadingLevel} data-max-h={toc.maxHeadingLevel}>
<nav aria-labelledby="starlight__on-this-page">
<h2 id="starlight__on-this-page">{t('tableOfContents.onThisPage')}</h2>
<TableOfContentsList toc={toc.items} collapseLevel={toc.collapseLevel} />
</nav>
</tauri-starlight-toc>
)
}
<script src="./TableOfContents/starlight-toc"></script>

View File

@@ -1,144 +0,0 @@
---
import type { TocItem } from 'node_modules/@astrojs/starlight/utils/generateToC';
interface Props {
toc: TocItem[];
depth?: number;
collapseLevel?: number;
isMobile?: boolean;
}
const { toc, isMobile = false, depth = 0, collapseLevel = 1 } = Astro.props;
---
<ul class:list={{ isMobile }}>
{
toc.map((heading) => (
<li>
{heading.children.length === 0 && (
<>
<a href={'#' + heading.slug}>
<span>{heading.text}</span>
</a>
{heading.children.length > 0 && (
<Astro.self toc={heading.children} depth={depth + 1} isMobile={isMobile} />
)}
</>
)}
{heading.children.length > 0 && (
<details open={depth < collapseLevel}>
<summary>
<a href={'#' + heading.slug}>
<span>{heading.text}</span>
</a>
</summary>
{heading.children.length > 0 && (
<Astro.self toc={heading.children} depth={depth + 1} isMobile={isMobile} />
)}
</details>
)}
</li>
))
}
</ul>
<style define:vars={{ depth }}>
ul {
padding: 0;
list-style: none;
}
a {
--pad-inline: 0.5rem;
display: block;
border-radius: 0.25rem;
padding-block: 0.25rem;
padding-inline: calc(1rem * var(--depth) + var(--pad-inline)) var(--pad-inline);
line-height: 1.25;
}
a[aria-current='true'] {
color: var(--sl-color-text-accent);
}
details > summary {
list-style: none;
display: flex;
justify-content: flex-start;
align-items: center;
cursor: pointer;
}
details > summary::-webkit-details-marker {
display: none;
}
details > summary::after {
content: '▶';
color: transparent;
width: 16px;
height: 16px;
transition: 0.2s;
/* Chevron SVG icon (Black) */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='%23000000'%3E%3Cpath d='m14.83 11.29-4.24-4.24a1 1 0 1 0-1.42 1.41L12.71 12l-3.54 3.54a1 1 0 0 0 0 1.41 1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.24-4.24a1.002 1.002 0 0 0 0-1.42Z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center right;
background-size: 16px 16px;
opacity: 0.5;
}
details > summary:hover::after {
opacity: 1;
}
:root[data-theme='dark'] {
details > summary::after {
/* Chevron SVG icon (White) */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='%23ffffff'%3E%3Cpath d='m14.83 11.29-4.24-4.24a1 1 0 1 0-1.42 1.41L12.71 12l-3.54 3.54a1 1 0 0 0 0 1.41 1 1 0 0 0 .71.29 1 1 0 0 0 .71-.29l4.24-4.24a1.002 1.002 0 0 0 0-1.42Z'/%3E%3C/svg%3E");
}
}
details[open] > summary::after {
transform: rotate(90deg);
}
.isMobile a {
--pad-inline: 1rem;
display: flex;
justify-content: space-between;
gap: var(--pad-inline);
border-top: 1px solid var(--sl-color-gray-6);
border-radius: 0;
padding-block: 0.5rem;
color: var(--sl-color-text);
font-size: var(--sl-text-sm);
text-decoration: none;
outline-offset: var(--sl-outline-offset-inside);
}
.isMobile:first-child > li:first-child > a {
border-top: 0;
}
.isMobile a[aria-current='true'],
.isMobile a[aria-current='true']:hover,
.isMobile a[aria-current='true']:focus {
color: var(--sl-color-white);
background-color: unset;
}
.isMobile a[aria-current='true']::after {
content: '';
width: 1rem;
background-color: var(--sl-color-text-accent);
/* Check mark SVG icon */
-webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg==');
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxNCAxNCc+PHBhdGggZD0nTTEwLjkxNCA0LjIwNmEuNTgzLjU4MyAwIDAgMC0uODI4IDBMNS43NCA4LjU1NyAzLjkxNCA2LjcyNmEuNTk2LjU5NiAwIDAgMC0uODI4Ljg1N2wyLjI0IDIuMjRhLjU4My41ODMgMCAwIDAgLjgyOCAwbDQuNzYtNC43NmEuNTgzLjU4MyAwIDAgMCAwLS44NTdaJy8+PC9zdmc+Cg==');
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
flex-shrink: 0;
}
</style>

View File

@@ -1,110 +0,0 @@
import { PAGE_TITLE_ID } from 'node_modules/@astrojs/starlight/constants';
export class StarlightTOC extends HTMLElement {
private _current = this.querySelector<HTMLAnchorElement>('a[aria-current="true"]');
private minH = parseInt(this.dataset.minH || '2', 10);
private maxH = parseInt(this.dataset.maxH || '3', 10);
protected set current(link: HTMLAnchorElement) {
if (link === this._current) return;
if (this._current) this._current.removeAttribute('aria-current');
link.setAttribute('aria-current', 'true');
this._current = link;
}
private onIdle = (cb: IdleRequestCallback) =>
(window.requestIdleCallback || ((cb) => setTimeout(cb, 1)))(cb);
constructor() {
super();
this.onIdle(() => this.init());
}
private init = (): void => {
/** All the links in the table of contents. */
const links = [...this.querySelectorAll('a')];
/** Test if an element is a table-of-contents heading. */
const isHeading = (el: Element): el is HTMLHeadingElement => {
if (el instanceof HTMLHeadingElement) {
// Special case for page title h1
if (el.id === PAGE_TITLE_ID) return true;
// Check the heading level is within the user-configured limits for the ToC
const level = el.tagName[1];
if (level) {
const int = parseInt(level, 10);
if (int >= this.minH && int <= this.maxH) return true;
}
}
return false;
};
/** Walk up the DOM to find the nearest heading. */
const getElementHeading = (el: Element | null): HTMLHeadingElement | null => {
if (!el) return null;
const origin = el;
while (el) {
if (isHeading(el)) return el;
// Assign the previous siblings last, most deeply nested child to el.
el = el.previousElementSibling;
while (el?.lastElementChild) {
el = el.lastElementChild;
}
// Look for headings amongst siblings.
const h = getElementHeading(el);
if (h) return h;
}
// Walk back up the parent.
return getElementHeading(origin.parentElement);
};
/** Handle intersections and set the current link to the heading for the current intersection. */
const setCurrent: IntersectionObserverCallback = (entries) => {
for (const { isIntersecting, target } of entries) {
if (!isIntersecting) continue;
const heading = getElementHeading(target);
if (!heading) continue;
const link = links.find((link) => link.hash === '#' + encodeURIComponent(heading.id));
if (link) {
this.current = link;
break;
}
}
};
// Observe elements with an `id` (most likely headings) and their siblings.
// Also observe direct children of `.content` to include elements before
// the first heading.
const toObserve = document.querySelectorAll('main [id], main [id] ~ *, main .content > *');
let observer: IntersectionObserver | undefined;
const observe = () => {
if (observer) return;
observer = new IntersectionObserver(setCurrent, { rootMargin: this.getRootMargin() });
toObserve.forEach((h) => observer!.observe(h));
};
observe();
let timeout: NodeJS.Timeout;
window.addEventListener('resize', () => {
// Disable intersection observer while window is resizing.
if (observer) observer.disconnect();
clearTimeout(timeout);
timeout = setTimeout(() => this.onIdle(observe), 200);
});
};
private getRootMargin(): `-${number}px 0% ${number}px` {
const navBarHeight = document.querySelector('header')?.getBoundingClientRect().height || 0;
// `<summary>` only exists in mobile ToC, so will fall back to 0 in large viewport component.
const mobileTocHeight = this.querySelector('summary')?.getBoundingClientRect().height || 0;
/** Start intersections at nav height + 2rem padding. */
const top = navBarHeight + mobileTocHeight + 32;
/** End intersections `53px` later. This is slightly more than the maximum `margin-top` in Markdown content. */
const bottom = top + 53;
const height = document.documentElement.clientHeight;
return `-${top}px 0% ${bottom - height}px`;
}
}
customElements.define('tauri-starlight-toc', StarlightTOC);

View File

@@ -1,5 +1,4 @@
---
import type { Props } from '@astrojs/starlight/props';
import { Icon } from '@astrojs/starlight/components';
---

15
src/content.config.ts Normal file
View File

@@ -0,0 +1,15 @@
import { defineCollection } from 'astro:content';
import { i18nSchema, docsSchema } from '@astrojs/starlight/schema';
import { docsLoader, i18nLoader } from '@astrojs/starlight/loaders';
import { topicSchema } from 'starlight-sidebar-topics/schema';
import { blogSchema } from 'starlight-blog/schema';
export const collections = {
docs: defineCollection({
loader: docsLoader(),
schema: docsSchema({
extend: (context) => blogSchema(context).merge(topicSchema),
}),
}),
i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }),
};

View File

@@ -1,10 +0,0 @@
import { defineCollection } from 'astro:content';
import { i18nSchema } from '@astrojs/starlight/schema';
import { docsSchema } from 'src/schemas/docsSchema';
export const collections = {
docs: defineCollection({
schema: docsSchema,
}),
i18n: defineCollection({ type: 'data', schema: i18nSchema() }),
};

View File

@@ -1,5 +1,6 @@
---
title: '404'
topic: guides # this sidebar is active when viewing this page
template: doc
editUrl: false
tableOfContents: false

View File

@@ -1,3 +1,7 @@
---
title: 'Create Tauri app'
---
import { Tabs, TabItem } from '@astrojs/starlight/components';
<Tabs syncKey="cmd">

View File

@@ -1,5 +1,6 @@
---
title: Contribute
topic: guides # this sidebar is active when viewing this page
description: Guide for Tauri contributors
sidebar:
order: 0

View File

@@ -1,36 +0,0 @@
---
title: Development Cycle
---
import CommandTabs from '@components/CommandTabs.astro';
### 1. Démarrez votre serveur de développement
Maintenant que tout est configuré, vous devez démarrer votre serveur de développement d'applications fourni par votre framework ou bundler d'interface utilisateur (en supposant que vous en utilisiez un, bien sûr).
:::note
Chaque framework possède ses propres outils de développement. Il n'entre pas dans le cadre de ce document de les couvrir tous ou de rester à jour.
:::
### 2. Démarrer la fenêtre de développement de Tauri
<CommandTabs
npm="npm run tauri dev"
yarn="yarn tauri dev"
pnpm="pnpm tauri dev"
deno="deno tauri dev"
bun="bun tauri dev"
cargo="cargo tauri dev"
/>
La première fois que vous exécutez cette commande, le gestionnaire de packages Rust prend plusieurs minutes pour télécharger et créer tous les packages requis. Comme ils sont mis en cache, les builds suivants sont beaucoup plus rapides, car seul votre code a besoin d'être reconstruit.
Une fois que Rust a terminé la construction, la vue Web s'ouvre et affiche votre application Web. Vous pouvez apporter des modifications à votre application Web, et si vos outils le permettent, la vue Web devrait se mettre à jour automatiquement, tout comme un navigateur. Lorsque vous apportez des modifications à vos fichiers Rust, ils sont reconstruits automatiquement et votre application redémarre automatiquement.
:::caution[À propos de Cargo.toml et du contrôle de code source]
Dans votre référentiel de projet, vous **DEVEZ** valider le `src-tauri/Cargo.lock` avec le `src-tauri/Cargo.toml` sur git car Cargo utilise le fichier de verrouillage pour fournir des versions déterministes. Par conséquent, il est recommandé que toutes les applications enregistrent leur `Cargo.lock`. Vous **NE DEVEZ PAS** valider le dossier `src-tauri/target` ou l'un de ses contenus.
:::

View File

@@ -1,5 +1,6 @@
---
title: '404'
topic: guides # this sidebar is active when viewing this page
template: doc
editUrl: false
tableOfContents: false

View File

@@ -1,5 +1,6 @@
---
title: Tauri Doc 日本語版 改訂記録メモ | Memorundom on Doc-JP Rev Control
topic: guides # this sidebar is active when viewing this page
---
- Rev Status Control of Japanese Translation Documents <br /> 日本語訳文書の改訂履歴メモ

View File

@@ -1,6 +1,7 @@
---
title: Tauri RSS フィード
i18nReady: true
topic: guides # this sidebar is active when viewing this page
---
import { LinkCard } from '@astrojs/starlight/components';

View File

@@ -1,5 +1,6 @@
---
title: Tauri RSS Feeds
topic: guides # this sidebar is active when viewing this page
i18nReady: true
---

View File

@@ -1,5 +1,6 @@
---
title: 访问控制列表
topic: guides # this sidebar is active when viewing this page
---
每个 Tauri [命令](/zh-cn/develop/calling-rust/)都向 JavaScript 层公开一个 Rust 函数,该函数可以使用操作系统 API 执行任意操作,默认情况下,该层使用 Web 标准进行沙箱化。

View File

@@ -1,6 +1,7 @@
---
title: Tauri RSS 订阅
i18nReady: true
topic: guides # this sidebar is active when viewing this page
---
import { LinkCard } from '@astrojs/starlight/components';

View File

@@ -19,12 +19,12 @@ export function groupDocsByPrefix(
prefixes.forEach((prefix) => {
grouped.set(
prefix,
docs.filter((doc) => doc.slug.startsWith(prefix))
docs.filter((doc) => doc.id.startsWith(prefix))
);
});
// sort each group by slug
for (const [prefix, items] of grouped) {
items.sort((a, b) => a.slug.localeCompare(b.slug));
items.sort((a, b) => a.id.localeCompare(b.id));
}
return grouped;
@@ -38,7 +38,7 @@ export const GET: APIRoute = async ({ params, request }) => {
const { llm_slug } = params;
const slug = llm_slug?.replace(/\/llms\.txt$/, '');
const docs = await getCollection('docs');
const doc = docs.find((doc) => doc.slug === slug);
const doc = docs.find((doc) => doc.id === slug);
if (!doc) {
return new Response('Not Found', { status: 404 });
}
@@ -54,7 +54,7 @@ export async function getStaticPaths() {
const docs = await getCollection('docs');
const docsBySection = groupDocsByPrefix(llmsTxtSections, docs);
const paths = Array.from(docsBySection.values())
.map((docs) => docs.map((doc) => doc.slug))
.map((docs) => docs.map((doc) => doc.id))
.flat()
.map((slug) => ({ params: { llm_slug: toLlmsTxtPath(slug) } }));

View File

@@ -34,7 +34,7 @@ export async function GET(context: APIContext) {
title: post.data.title,
pubDate: post.id.startsWith('blog') ? post.data.date : getTimestamp(post.id),
description: post.id.startsWith('blog') ? post.data.excerpt : post.data.description,
link: `/${post.slug}/`,
link: `/${post.id}/`,
})),
});
}

View File

@@ -11,7 +11,7 @@ function groupDocsByPrefix(docs: Awaited<ReturnType<typeof getCollection<'docs'>
prefixes.forEach((prefix) => {
grouped.set(
prefix,
docs.filter((doc) => doc.slug.startsWith(prefix))
docs.filter((doc) => doc.id.startsWith(prefix))
);
});
@@ -42,9 +42,9 @@ export const GET: APIRoute = async ({ params, request }) => {
if (items.length > 0) {
content += `\n## ${prefix.charAt(0).toUpperCase() + prefix.slice(1)}\n`;
items.forEach((doc) => {
const level = getHeaderLevel(doc.slug);
const level = getHeaderLevel(doc.id);
const indent = ' '.repeat(level - 2);
content += `${indent}- [${doc.data.title}](https://tauri.app/${doc.slug}/)\n`;
content += `${indent}- [${doc.data.title}](https://tauri.app/${doc.id}/)\n`;
});
}
}

View File

@@ -18,9 +18,9 @@ export const GET: APIRoute = async ({ params, request }) => {
if (items.length > 0) {
content += `\n${n++}. ${prefix.charAt(0).toUpperCase() + prefix.slice(1)}\n`;
items.forEach((doc) => {
const level = getHeaderLevel(doc.slug);
const level = getHeaderLevel(doc.id);
const indent = ' '.repeat(level - 2);
content += `${indent}- [${doc.data.title}](#${doc.slug})\n`;
content += `${indent}- [${doc.data.title}](#${doc.id})\n`;
});
}
}

View File

@@ -34,7 +34,7 @@ export async function GET(context: APIContext) {
items: posts.map((post) => ({
pubDate: getTimestamp(post.id),
...post.data,
link: `/${post.slug}/`,
link: `/${post.id}/`,
})),
});
}

View File

@@ -1,12 +1,16 @@
:root {
--sl-hue-orange: 42;
--tauri-transition-speed: 200ms;
}
:root[data-theme='dark'] {
--sl-hue-orange: 35;
--sl-color-orange-low: hsl(var(--sl-hue-orange), 100%, 15%);
--sl-color-orange: hsl(var(--sl-hue-orange), 100%, 60%);
--sl-color-orange: #ffc131;
--sl-color-orange-high: hsl(var(--sl-hue-orange), 100%, 90%);
--sl-hue-blue: 186;
--sl-color-blue-low: hsl(var(--sl-hue-blue), 72%, 15%);
--sl-color-blue: hsl(var(--sl-hue-blue), 72%, 50%);
--sl-color-blue-high: hsl(var(--sl-hue-blue), 72%, 90%);
--sl-hue-blue: 187;
--sl-color-blue-low: hsl(var(--sl-hue-blue), 71%, 15%);
--sl-color-blue: #24c8db;
--sl-color-blue-high: hsl(var(--sl-hue-blue), 71%, 90%);
--sl-hue-accent: var(--sl-hue-blue);
--sl-color-accent-low: var(--sl-color-blue-low);
--sl-color-accent: var(--sl-color-blue);
@@ -20,7 +24,16 @@
--sl-color-gray-5: #383838;
--sl-color-gray-6: #272727;
--sl-color-black: #181818;
/* Custom */
--tauri-transition-speed: 200ms;
}
:root[data-theme='light'] {
--sl-color-white: #070707;
--sl-color-gray-1: #2f2f2f;
--sl-color-gray-2: #353841;
--sl-color-gray-3: #545861;
--sl-color-gray-4: #888b96;
--sl-color-gray-5: #c0c2c7;
--sl-color-gray-6: #eceef2;
--sl-color-gray-7: #f6f6f6;
--sl-color-black: #ffffff;
}

View File

@@ -7,5 +7,7 @@
"@assets/*": ["src/assets/*"],
"@fragments/*": ["src/content/docs/_fragments/*"]
}
}
},
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}