Files
archived-tauri-docs/astro.config.mjs
2025-08-01 20:36:17 +08:00

549 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @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 path from 'path';
import { fileURLToPath } from 'url';
import lunaria from '@lunariajs/starlight';
import { readFileSync } from 'fs';
const authors = {
nothingismagick: {
name: 'Daniel Thompson-Yvetot',
title: 'Tauri Co-Founder',
picture: '/authors/nothingismagick.jpeg',
},
lucasfernog: {
name: 'Lucas Nogueira',
title: 'Tauri Co-Founder',
picture: '/authors/lucasfernog.jpeg',
},
beanow: {
name: 'Robin van Boven',
title: 'Tauri Board Director',
picture: '/authors/Beanow.png',
},
jbolda: {
name: 'Jacob Bolda',
title: 'Tauri Board Director',
picture: '/authors/jbolda.jpeg',
},
lorenzolewis: {
name: 'Lorenzo Lewis',
title: 'Tauri Community Lead',
picture: '/authors/lorenzolewis.png',
},
tweidinger: {
name: 'Tillmann Weidinger',
title: 'Tauri Security',
picture: '/authors/tweidinger.png',
},
amrbashir: {
name: 'Amr Bashir',
title: 'Tauri Development',
picture: '/authors/amrbashir.png',
},
wusyong: {
name: 'Wu Yu Wei',
title: 'Tauri Development Lead',
picture: '/authors/wusyong.png',
},
chip: {
name: 'Chip Reed',
title: 'Tauri Security',
picture: '/authors/chip.png',
},
tony: {
name: 'Tony',
title: 'Tauri Development',
picture: '/authors/tony.jpeg',
},
};
const site = 'https://v2.tauri.app';
// https://astro.build/config
export default defineConfig({
site,
trailingSlash: 'always',
integrations: [
starlight({
plugins: [
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',
'start/project-structure',
// {
// 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',
'develop/icons',
{
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,
exclude: ['/plugin/*/#default-permission', '/plugin/*/#permission-table'],
}),
lunaria({ configPath: './lunaria.config.json', route: '/contribute/translate-status' }),
],
title: 'Tauri',
description: 'The cross-platform app building toolkit',
logo: {
dark: './src/assets/logo.svg',
light: './src/assets/logo_light.svg',
replacesTitle: true,
},
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: 'blueSky', label: 'Bluesky', href: 'https://bsky.app/profile/tauri.app' },
{ 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',
},
head: [
{
tag: 'meta',
attrs: { property: 'og:image', content: site + '/og.png?v=1' },
},
{
tag: 'meta',
attrs: { property: 'twitter:image', content: site + '/og.png?v=1' },
},
{
tag: 'script',
attrs: {
src: '/navigate.js',
},
},
{
tag: 'link',
attrs: {
rel: 'manifest',
href: '/manifest.json',
},
},
{
tag: 'meta',
attrs: { name: 'theme-color', content: '#181818' },
},
],
editLink: {
baseUrl:
process.env.NODE_ENV === 'development'
? `vscode://file/${path.dirname(fileURLToPath(import.meta.url))}`
: 'https://github.com/tauri-apps/tauri-docs/edit/v2',
},
customCss: ['./src/styles/custom.scss'],
expressiveCode: {
styleOverrides: { borderRadius: '0.5rem' },
},
locales,
lastUpdated: true,
}),
astroD2({
skipGeneration: process.env.CONTEXT !== 'd2',
theme: {
default: '105',
},
}),
serviceWorker({
workbox: {
cleanupOutdatedCaches: true,
clientsClaim: true,
inlineWorkboxRuntime: true,
skipWaiting: true,
globIgnores: ['**_redirects**', '**_headers**'],
globPatterns: ['**/*.js', '**/*.css'],
runtimeCaching: [
{
urlPattern: new RegExp('.*'),
handler: 'CacheFirst',
options: {
cacheName: 'tauri-runtime',
expiration: {
maxAgeSeconds: 30 * 60, // 30 minutes
},
},
},
],
},
}),
],
markdown: {
shikiConfig: {
langs: ['powershell', 'ts', 'rust', 'bash', 'json', 'toml', 'html', 'js'],
},
rehypePlugins: [
rehypeHeadingIds,
[
rehypeAutolinkHeadings,
{
behavior: 'wrap',
properties: { ariaHidden: true, tabIndex: -1, class: 'heading-link' },
},
],
],
},
redirects: {
// Old blog url schema redirects
'/blog/2022/06/19/tauri-1-0': '/blog/tauri-1-0',
'/blog/tauri_1_0': '/blog/tauri-1-0',
'/blog/2022/07/12/tauri-programme-turns-1-and-board-elections':
'/blog/tauri-programme-turns-1-and-board-elections',
'/blog/2022/09/15/tauri-1-1': '/blog/tauri-1-1',
'/blog/2022/09/19/tauri-egui-0-1': '/blog/tauri-egui-0-1',
'/blog/2022/11/18/tauri-1-2': '/blog/tauri-1-2',
'/blog/2022/12/09/tauri-mobile-alpha': '/blog/tauri-mobile-alpha',
'/blog/2023/02/03/tauri-2-0-0-alpha-3': '/blog/tauri-2-0-0-alpha-3',
'/blog/2023/02/09/tauri-community-growth-and-feedback':
'/blog/tauri-community-growth-and-feedback',
'/blog/2023/03/01/create-tauri-app-version-3-released':
'/blog/create-tauri-app-version-3-released',
'/blog/2023/03/20/tauri-2-0-0-alpha-4': '/blog/tauri-2-0-0-alpha-4',
'/blog/2023/05/03/tauri-1-3': '/blog/tauri-1-3',
'/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',
// v1 /guides/debugging -> /guides/debug
...i18nRedirect('/v1/guides/debugging/application', '/guides/debug/application'),
...i18nRedirect('/v1/guides/debugging/vs-code', '/guides/debug/vs-code'),
...i18nRedirect('/v1/guides/debugging/rustrover', '/guides/debug/rustrover'),
// v1 /guides/development -> /guides/develop
...i18nRedirect(
'/v1/guides/development/development-cycle',
'/guides/develop/development-cycle'
),
...i18nRedirect(
'/v1/guides/development/updating-dependencies',
'/guides/develop/updating-dependencies'
),
// v1 /guides/distribution -> /guides/distribute
...i18nRedirect('/v1/guides/distribution/publishing', '/guides/distribute/'),
...i18nRedirect('/v1/guides/distribution/updater', '/plugin/updater/'),
// v1 /guides/testing -> /guides/test
...i18nRedirect('/v1/guides/testing/mocking', '/guides/test/mocking'),
...i18nRedirect('/v1/guides/testing/webdriver/ci', '/guides/test/webdriver/ci'),
...i18nRedirect('/v1/guides/testing/webdriver/introduction', '/guides/test/webdriver/'),
...i18nRedirect(
'/v1/guides/testing/webdriver/example/setup',
'/guides/test/webdriver/example/'
),
...i18nRedirect(
'/v1/guides/testing/webdriver/example/selenium',
'/guides/test/webdriver/example/selenium'
),
...i18nRedirect(
'/v1/guides/testing/webdriver/example/webdriverio',
'/test/webdriver/example/webdriverio'
),
// v1 /references
...i18nRedirect('/v1/references', '/concepts'),
...i18nRedirect('/v1/reference/architecture', '/concepts/architecture'),
...i18nRedirect('/v1/reference/architecture/process-model', '/concepts/process-model'),
...i18nRedirect('/v1/reference/architecture/security', '/concepts/tauri-security'),
...i18nRedirect(
'/v1/reference/architecture/inter-process-communication',
'/concepts/inter-process-communication'
),
...i18nRedirect(
'/v1/reference/architecture/inter-process-communication/brownfield',
'/concepts/inter-process-communication/brownfield'
),
...i18nRedirect(
'/v1/reference/architecture/inter-process-communication/isolation',
'/concepts/inter-process-communication/isolation'
),
...i18nRedirect('/v1/reference/security', '/concepts/development-security'),
...i18nRedirect('/v1/reference/configuration-files', '/reference/configuration-files'),
...i18nRedirect('/v1/reference/webview-versions', '/reference/webview-versions'),
// Decommissioned locales -> refer to /public/_redirects file
// '/ko/[...slug]': '/[...slug]',
// '/it/[...slug]': '/[...slug]',
},
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) =>
locale === 'root'
? (routes[from] = to)
: (routes[`/${locale}/${from.replaceAll(/^\/*/g, '')}`] = `/${locale}/${to.replaceAll(
/^\/*/g,
''
)}`)
);
return routes;
}
// Read the HTTP header file in `public/_headers`
function readHeaders() {
const header_file = readFileSync('public/_headers', { encoding: 'utf8' })
.split('\n')
.filter(Boolean);
const headers = {};
for (const line of header_file) {
const [key, val] = line.trim().split(/\s*:\s*(.+)/);
if (key != undefined && val != undefined) {
headers[key] = val.toString();
}
}
return headers;
}