diff --git a/packages/create-rstack/README.md b/packages/create-rstack/README.md index 9a453522..a3b245b2 100644 --- a/packages/create-rstack/README.md +++ b/packages/create-rstack/README.md @@ -38,6 +38,7 @@ npx create-rstack -d my-project -t app-vanilla-ts - `lib-solid-js` - JavaScript Solid library - `lib-solid-ts` - TypeScript Solid library - `doc-basic` - Basic documentation site +- `doc-i18n` - Multilingual documentation site ## Documentation diff --git a/packages/create-rstack/src/index.ts b/packages/create-rstack/src/index.ts index 428c6e41..d57d370a 100644 --- a/packages/create-rstack/src/index.ts +++ b/packages/create-rstack/src/index.ts @@ -44,7 +44,26 @@ const getTemplateName = async ({ template }: Argv): Promise => { ); if (projectType === 'doc') { - return 'doc-basic'; + const documentationType = checkCancel( + await select({ + message: 'Choose documentation language setup', + initialValue: 'basic', + options: [ + { + value: 'basic', + label: 'Single language', + hint: 'docs', + }, + { + value: 'i18n', + label: 'Multilingual', + hint: 'docs/en, docs/zh', + }, + ], + }), + ); + + return `doc-${documentationType}`; } const templateType = checkCancel( @@ -101,6 +120,7 @@ await create({ 'lib-solid-js', 'lib-solid-ts', 'doc-basic', + 'doc-i18n', ], builtinTools: [], getTemplateName, diff --git a/packages/create-rstack/template-doc-i18n/AGENTS.md b/packages/create-rstack/template-doc-i18n/AGENTS.md new file mode 100644 index 00000000..456cacda --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/AGENTS.md @@ -0,0 +1,13 @@ +# AGENTS.md + +## Commands + +- `{{ packageManager }} run dev` - Start the documentation development server +- `{{ packageManager }} run build` - Build the documentation site for production +- `{{ packageManager }} run preview` - Preview the production build locally + +## Docs + +- Rstack: https://rstack.rs/llms.txt +- Rspress: https://rspress.rs/llms.txt +- Rsbuild: https://rsbuild.rs/llms.txt diff --git a/packages/create-rstack/template-doc-i18n/README.md b/packages/create-rstack/template-doc-i18n/README.md new file mode 100644 index 00000000..d7963525 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/README.md @@ -0,0 +1,34 @@ +# Rstack multilingual documentation site + +## Setup + +Install the dependencies: + +```bash +{{ packageManager }} install +``` + +## Get started + +Start the development server: + +```bash +{{ packageManager }} run dev +``` + +Build the website for production: + +```bash +{{ packageManager }} run build +``` + +Preview the production build locally: + +```bash +{{ packageManager }} run preview +``` + +## Learn more + +- [Rstack documentation](https://rstack.rs) +- [Rspress documentation](https://rspress.rs) diff --git a/packages/create-rstack/template-doc-i18n/docs/en/_nav.json b/packages/create-rstack/template-doc-i18n/docs/en/_nav.json new file mode 100644 index 00000000..1c47924a --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/_nav.json @@ -0,0 +1,16 @@ +[ + { + "text": "Guide", + "link": "/guide/start/introduction", + "activeMatch": "/guide/" + }, + { + "text": "API", + "link": "/api/", + "activeMatch": "/api/" + }, + { + "text": "Rspress", + "link": "https://rspress.rs/" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/en/api/_meta.json b/packages/create-rstack/template-doc-i18n/docs/en/api/_meta.json new file mode 100644 index 00000000..f0ff0de6 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/api/_meta.json @@ -0,0 +1 @@ +["index", "commands"] diff --git a/packages/create-rstack/template-doc-i18n/docs/en/api/commands.mdx b/packages/create-rstack/template-doc-i18n/docs/en/api/commands.mdx new file mode 100644 index 00000000..6e7494c5 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/api/commands.mdx @@ -0,0 +1,25 @@ +# Commands + +## dev + +Start the local development server: + +```bash +rs doc +``` + +## build + +Build the documentation site for production: + +```bash +rs doc build +``` + +## preview + +Preview the production build locally: + +```bash +rs doc preview +``` diff --git a/packages/create-rstack/template-doc-i18n/docs/en/api/index.mdx b/packages/create-rstack/template-doc-i18n/docs/en/api/index.mdx new file mode 100644 index 00000000..939b2956 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/api/index.mdx @@ -0,0 +1,6 @@ +--- +title: API Overview +overview: true +--- + +This is an API Overview page which outlines all the available APIs. diff --git a/packages/create-rstack/template-doc-i18n/docs/en/guide/_meta.json b/packages/create-rstack/template-doc-i18n/docs/en/guide/_meta.json new file mode 100644 index 00000000..2dc352c6 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/guide/_meta.json @@ -0,0 +1,7 @@ +[ + { + "type": "dir-section-header", + "name": "start", + "label": "Getting Started" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/en/guide/start/_meta.json b/packages/create-rstack/template-doc-i18n/docs/en/guide/start/_meta.json new file mode 100644 index 00000000..f818265c --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/guide/start/_meta.json @@ -0,0 +1 @@ +["introduction"] diff --git a/packages/create-rstack/template-doc-i18n/docs/en/guide/start/introduction.md b/packages/create-rstack/template-doc-i18n/docs/en/guide/start/introduction.md new file mode 100644 index 00000000..0bf0ab47 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/guide/start/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +Rspress is a fast static site generator based on [Rsbuild](https://rsbuild.rs/). It supports Markdown and MDX and includes a default documentation theme. + +Learn more in the [Rspress documentation](https://rspress.rs/). diff --git a/packages/create-rstack/template-doc-i18n/docs/en/index.md b/packages/create-rstack/template-doc-i18n/docs/en/index.md new file mode 100644 index 00000000..d47c03f4 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/en/index.md @@ -0,0 +1,39 @@ +--- +pageType: home + +hero: + name: My Site + text: A cool website! + tagline: This is the tagline + actions: + - theme: brand + text: Quick Start + link: /guide/start/introduction + - theme: alt + text: GitHub + link: https://github.com/rstackjs/rstack-cli + image: + src: https://assets.rspack.rs/rspress/rspress-logo.svg + alt: Logo +features: + - title: Blazing fast build speed + details: The core compilation module is based on the Rust front-end toolchain, providing a more ultimate development experience. + icon: 🏃🏻‍♀️ + link: /guide/start/introduction + - title: Built-in full-text search + details: Automatically generates a full-text search index for you during construction, providing out-of-the-box full-text search capabilities. + icon: 🎨 + link: https://rspress.rs/guide/advanced/custom-search + - title: AI-friendly + details: Generate llms.txt and Markdown files compliant with the llms.txt specification through SSG-MD, making it easier for large language models to understand and use your documentation. + icon: 🤖 + link: https://rspress.rs/guide/basic/ssg-md + - title: Static site generation + details: In production, it automatically builds into static HTML files, which can be easily deployed anywhere. + icon: 🌈 + link: https://rspress.rs/guide/basic/ssg + - title: Providing multiple custom capabilities + details: Through its extension mechanism, you can easily extend theme UI and build process. + icon: 🔥 + link: https://rspress.rs/guide/basic/custom-theme +--- diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/_nav.json b/packages/create-rstack/template-doc-i18n/docs/zh/_nav.json new file mode 100644 index 00000000..fd08ce7c --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/_nav.json @@ -0,0 +1,16 @@ +[ + { + "text": "指南", + "link": "/guide/start/introduction", + "activeMatch": "/guide/" + }, + { + "text": "API", + "link": "/api/", + "activeMatch": "/api/" + }, + { + "text": "Rspress", + "link": "https://rspress.rs/zh/" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/api/_meta.json b/packages/create-rstack/template-doc-i18n/docs/zh/api/_meta.json new file mode 100644 index 00000000..ceb13efc --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/api/_meta.json @@ -0,0 +1,12 @@ +[ + { + "type": "file", + "name": "index", + "label": "API 概览" + }, + { + "type": "file", + "name": "commands", + "label": "命令" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/api/commands.mdx b/packages/create-rstack/template-doc-i18n/docs/zh/api/commands.mdx new file mode 100644 index 00000000..142a6ec4 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/api/commands.mdx @@ -0,0 +1,25 @@ +# 命令 + +## dev + +启动本地开发服务器: + +```bash +rs doc +``` + +## build + +构建用于生产环境的文档站点: + +```bash +rs doc build +``` + +## preview + +在本地预览生产构建: + +```bash +rs doc preview +``` diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/api/index.mdx b/packages/create-rstack/template-doc-i18n/docs/zh/api/index.mdx new file mode 100644 index 00000000..0aa87d8c --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/api/index.mdx @@ -0,0 +1,6 @@ +--- +title: API 概览 +overview: true +--- + +这是一个 API 概览页面,用于列出所有可用 API。 diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/guide/_meta.json b/packages/create-rstack/template-doc-i18n/docs/zh/guide/_meta.json new file mode 100644 index 00000000..d200fa82 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/guide/_meta.json @@ -0,0 +1,7 @@ +[ + { + "type": "dir-section-header", + "name": "start", + "label": "快速开始" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/_meta.json b/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/_meta.json new file mode 100644 index 00000000..9993e602 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/_meta.json @@ -0,0 +1,7 @@ +[ + { + "type": "file", + "name": "introduction", + "label": "介绍" + } +] diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/introduction.md b/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/introduction.md new file mode 100644 index 00000000..16f39008 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/guide/start/introduction.md @@ -0,0 +1,5 @@ +# 介绍 + +Rspress 是一个基于 [Rsbuild](https://rsbuild.rs/) 的快速静态站点生成器。它支持 Markdown 和 MDX,并内置默认文档主题。 + +前往 [Rspress 文档](https://rspress.rs/zh/)了解更多。 diff --git a/packages/create-rstack/template-doc-i18n/docs/zh/index.md b/packages/create-rstack/template-doc-i18n/docs/zh/index.md new file mode 100644 index 00000000..b7066f95 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/docs/zh/index.md @@ -0,0 +1,39 @@ +--- +pageType: home + +hero: + name: 我的站点 + text: 一个很酷的网站! + tagline: 这是网站的副标题 + actions: + - theme: brand + text: 快速开始 + link: /zh/guide/start/introduction + - theme: alt + text: GitHub + link: https://github.com/rstackjs/rstack-cli + image: + src: https://assets.rspack.rs/rspress/rspress-logo.svg + alt: Logo +features: + - title: 极速构建 + details: 核心编译模块基于 Rust 前端工具链,提供更极致的开发体验。 + icon: 🏃🏻‍♀️ + link: /zh/guide/start/introduction + - title: 内置全文搜索 + details: 构建时自动生成全文搜索索引,提供开箱即用的全文搜索能力。 + icon: 🎨 + link: https://rspress.rs/zh/guide/advanced/custom-search + - title: AI 友好 + details: 通过 SSG-MD 生成符合 llms.txt 规范的 llms.txt 和 Markdown 文件,让大语言模型更容易理解和使用你的文档。 + icon: 🤖 + link: https://rspress.rs/zh/guide/basic/ssg-md + - title: 静态站点生成 + details: 在生产环境中自动构建为静态 HTML 文件,可以轻松部署到任意位置。 + icon: 🌈 + link: https://rspress.rs/zh/guide/basic/ssg + - title: 提供多种自定义能力 + details: 通过扩展机制,你可以轻松扩展主题 UI 和构建流程。 + icon: 🔥 + link: https://rspress.rs/zh/guide/basic/custom-theme +--- diff --git a/packages/create-rstack/template-doc-i18n/gitignore b/packages/create-rstack/template-doc-i18n/gitignore new file mode 100644 index 00000000..23a4bc92 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/gitignore @@ -0,0 +1,14 @@ +# Local +.DS_Store +*.local +*.log* + +# Dist +node_modules +dist/ +doc_build/ + +# IDE +.vscode/* +!.vscode/extensions.json +.idea diff --git a/packages/create-rstack/template-doc-i18n/package.json b/packages/create-rstack/template-doc-i18n/package.json new file mode 100644 index 00000000..9f368fb2 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/package.json @@ -0,0 +1,23 @@ +{ + "name": "rstack-doc-i18n", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "rs doc build", + "dev": "rs doc", + "format": "rs fmt", + "lint": "rs lint", + "preview": "rs doc preview" + }, + "devDependencies": { + "@rspress/core": "^2.0.19", + "@types/node": "^24.13.3", + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.4", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "rstack": "^0.3.5", + "typescript": "^7.0.2" + } +} diff --git a/packages/create-rstack/template-doc-i18n/rstack.config.ts b/packages/create-rstack/template-doc-i18n/rstack.config.ts new file mode 100644 index 00000000..e599efda --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/rstack.config.ts @@ -0,0 +1,35 @@ +// Rstack configuration guide: https://rstack.rs/config +import path from 'node:path'; +import { define } from 'rstack'; + +define.doc({ + root: path.join(import.meta.dirname, 'docs'), + title: 'My Site', + description: 'A multilingual Rspress documentation site.', + lang: 'en', + locales: [ + { + lang: 'en', + label: 'English', + title: 'My Site', + description: 'A multilingual Rspress documentation site.', + }, + { + lang: 'zh', + label: '简体中文', + title: '我的站点', + description: '一个多语言 Rspress 文档站点。', + }, + ], +}); + +define.lint(async () => { + const { js, ts, reactPlugin, reactHooksPlugin } = await import('rstack/lint'); + + return [ + js.configs.recommended, + ts.configs.recommended, + reactPlugin.configs.recommended, + reactHooksPlugin.configs.recommended, + ]; +}); diff --git a/packages/create-rstack/template-doc-i18n/tsconfig.json b/packages/create-rstack/template-doc-i18n/tsconfig.json new file mode 100644 index 00000000..559f2a04 --- /dev/null +++ b/packages/create-rstack/template-doc-i18n/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "lib": ["DOM", "ES2020"], + "jsx": "react-jsx", + "target": "ES2020", + "noEmit": true, + "skipLibCheck": true, + "types": ["rstack/types", "node"], + "useDefineForClassFields": true, + + /* modules */ + "moduleDetection": "force", + "moduleResolution": "bundler", + "verbatimModuleSyntax": true, + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + + /* type checking */ + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["docs", "rstack.config.ts"], + "mdx": { + "checkMdx": true + } +} diff --git a/packages/create-rstack/tests/create.test.ts b/packages/create-rstack/tests/create.test.ts index 5e7bcda5..5396e7b0 100644 --- a/packages/create-rstack/tests/create.test.ts +++ b/packages/create-rstack/tests/create.test.ts @@ -136,6 +136,23 @@ test('creates the doc-basic template', async () => { ).resolves.toBeUndefined(); }); +test('creates the doc-i18n template', async () => { + const projectDirectory = await createProject('doc-i18n'); + const packageJson = JSON.parse( + await readFile(path.join(projectDirectory, 'package.json'), 'utf8'), + ); + + expect(packageJson.name).toBe('my-app'); + + await expect(access(path.join(projectDirectory, 'rstack.config.ts'))).resolves.toBeUndefined(); + await expect( + access(path.join(projectDirectory, 'docs', 'en', 'index.md')), + ).resolves.toBeUndefined(); + await expect( + access(path.join(projectDirectory, 'docs', 'zh', 'index.md')), + ).resolves.toBeUndefined(); +}); + test.each([ { template: 'lib-node-js',