diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4d4e59be..b74d5efd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,11 +20,15 @@ concurrency: jobs: test: - runs-on: ubuntu-latest - strategy: matrix: + os: [ubuntu-latest] node_version: [18, 20, 22] + include: + - os: windows-latest + node_version: 22 + + runs-on: ${{ matrix.os }} steps: - name: Checkout diff --git a/README.md b/README.md index 2e70a766..134226a4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![test](https://github.com/vuejs/vitepress/workflows/Test/badge.svg)](https://github.com/vuejs/vitepress/actions) [![npm](https://img.shields.io/npm/v/vitepress)](https://www.npmjs.com/package/vitepress) +[![nightly releases](https://img.shields.io/badge/nightly-releases-orange)](https://nightly.akryum.dev/vuejs/vitepress) [![chat](https://img.shields.io/badge/chat-discord-blue?logo=discord)](https://chat.vuejs.org) --- diff --git a/docs/.postcssrc.json b/docs/.postcssrc.json new file mode 100644 index 00000000..edc6a490 --- /dev/null +++ b/docs/.postcssrc.json @@ -0,0 +1,8 @@ +{ + "plugins": { + "postcss-rtlcss": { + "ltrPrefix": ":where([dir=\"ltr\"])", + "rtlPrefix": ":where([dir=\"rtl\"])" + } + } +} diff --git a/docs/.vitepress/config/es.ts b/docs/.vitepress/config/es.ts index d924c5b8..d30fc89f 100644 --- a/docs/.vitepress/config/es.ts +++ b/docs/.vitepress/config/es.ts @@ -48,7 +48,8 @@ export const es = defineConfig({ sidebarMenuLabel: 'Menu Lateral', darkModeSwitchLabel: 'Tema Oscuro', lightModeSwitchTitle: 'Cambiar a modo claro', - darkModeSwitchTitle: 'Cambiar a modo oscuro' + darkModeSwitchTitle: 'Cambiar a modo oscuro', + skipToContentLabel: 'Saltar al contenido' } }) diff --git a/docs/.vitepress/config/fa.ts b/docs/.vitepress/config/fa.ts new file mode 100644 index 00000000..5c91d0bc --- /dev/null +++ b/docs/.vitepress/config/fa.ts @@ -0,0 +1,223 @@ +import { createRequire } from 'module' +import { defineConfig, type DefaultTheme } from 'vitepress' + +const require = createRequire(import.meta.url) +const pkg = require('vitepress/package.json') + +export const fa = defineConfig({ + title: 'ویت‌پرس', + lang: 'fa-IR', + description: 'Vite & Vue powered static site generator.', + dir: 'rtl', + markdown: { + container: { + tipLabel: 'نکته', + warningLabel: 'هشدار', + dangerLabel: 'خطر', + infoLabel: 'اطلاعات', + detailsLabel: 'جزئیات' + } + }, + themeConfig: { + nav: nav(), + sidebar: { + '/fa/guide/': { base: '/fa/guide/', items: sidebarGuide() }, + '/fa/reference/': { base: '/fa/reference/', items: sidebarReference() } + }, + + editLink: { + pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', + text: 'ویرایش این صفحه در گیت‌هاب' + }, + + footer: { + message: 'انتشار یافته تحت لایسنس MIT', + copyright: 'حق نسخه‌برداری © 2019-کنون Evan You' + }, + + docFooter: { + prev: 'قبلی', + next: 'بعدی' + }, + + outline: { + label: 'در این صفحه' + }, + + lastUpdated: { + text: 'آخرین به‌روزرسانی‌', + formatOptions: { + dateStyle: 'short', + timeStyle: 'medium' + } + }, + + langMenuLabel: 'تغییر زبان', + returnToTopLabel: 'بازگشت به بالا', + sidebarMenuLabel: 'منوی جانبی', + darkModeSwitchLabel: 'تم تاریک', + lightModeSwitchTitle: 'رفتن به حالت روشن', + darkModeSwitchTitle: 'رفتن به حالت تاریک', + notFound: { + linkLabel: 'بازگشت به خانه', + linkText: 'بازگشت به خانه', + title: 'صفحه مورد نظر یافت نشد', + code: '۴۰۴', + quote: + 'اما اگر جهت خود را تغییر ندهید و اگر ادامه دهید به دنبال چیزی که دنبال می‌کنید، ممکن است در نهایت به جایی که در حال رفتن به سمتش هستید، برسید.' + }, + siteTitle: 'ویت‌پرس' + } +}) + +function nav(): DefaultTheme.NavItem[] { + return [ + { + text: 'راهنما', + link: 'fa/guide/what-is-vitepress', + activeMatch: '/guide/' + }, + { + text: 'مرجع', + link: 'fa/reference/site-config', + activeMatch: '/reference/' + }, + { + text: pkg.version, + items: [ + { + text: 'Changelog', + link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' + }, + { + text: 'مشارکت', + link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md' + } + ] + } + ] +} + +function sidebarGuide(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'معرفی', + collapsed: false, + items: [ + { text: 'ویت‌پرس چیست؟', link: 'what-is-vitepress' }, + { text: 'شروع کار', link: 'getting-started' }, + { text: 'مسیریابی', link: 'routing' }, + { text: 'استقرار', link: 'deploy' } + ] + }, + { + text: 'نوشتن', + collapsed: false, + items: [ + { text: 'افزونه‌های Markdown', link: 'markdown' }, + { text: 'مدیریت منابع', link: 'asset-handling' }, + { text: 'Frontmatter', link: 'frontmatter' }, + { text: 'استفاده از Vue در Markdown', link: 'using-vue' }, + { text: 'بین‌المللی سازی', link: 'i18n' } + ] + }, + { + text: 'شخصی‌سازی', + collapsed: false, + items: [ + { text: 'استفاده از تم شخصی', link: 'custom-theme' }, + { + text: 'گسترش تم پیش‌فرض', + link: 'extending-default-theme' + }, + { text: 'بارگیری داده در زمان Build', link: 'data-loading' }, + { text: 'سازگاری SSR', link: 'ssr-compat' }, + { text: 'اتصال به CMS', link: 'cms' } + ] + }, + { + text: 'آزمایشی', + collapsed: false, + items: [ + { text: 'حالت MPA', link: 'mpa-mode' }, + { text: 'جنریت کردن Sitemap', link: 'sitemap-generation' } + ] + }, + { text: 'پیکربندی و مرجع API', base: 'fa/reference/', link: 'site-config' } + ] +} + +function sidebarReference(): DefaultTheme.SidebarItem[] { + return [ + { + text: 'مرجع', + base: 'fa/reference/', + items: [ + { text: 'پیکربندی Site', link: 'site-config' }, + { text: 'پیکربندی Frontmatter', link: 'frontmatter-config' }, + { text: 'Runtime API', link: 'runtime-api' }, + { text: 'CLI', link: 'cli' }, + { + text: 'تم پیش‌فرض', + base: 'fa/reference/default-theme-', + items: [ + { text: 'بررسی اجمالی', link: 'config' }, + { text: 'ناوبری', link: 'nav' }, + { text: 'نوار کنار صفحه', link: 'sidebar' }, + { text: 'صفحه اصلی', link: 'home-page' }, + { text: 'پاورقی', link: 'footer' }, + { text: 'طرح', link: 'layout' }, + { text: 'نشان', link: 'badge' }, + { text: 'صفحه تیم', link: 'team-page' }, + { text: 'لینک‌های قبلی / بعدی', link: 'prev-next-links' }, + { text: 'ویرایش لینک', link: 'edit-link' }, + { text: 'Timestamp آخرین به‌روزرسانی', link: 'last-updated' }, + { text: 'جستجو', link: 'search' }, + { text: 'تبلیغات Carbon', link: 'carbon-ads' } + ] + } + ] + } + ] +} + +export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = { + fa: { + placeholder: 'جستجوی مستندات', + translations: { + button: { + buttonText: 'جستجو', + buttonAriaLabel: 'جستجو' + }, + modal: { + searchBox: { + resetButtonTitle: 'آغاز مجدد جستجو', + resetButtonAriaLabel: 'آغاز مجدد جستجو', + cancelButtonText: 'لغو', + cancelButtonAriaLabel: 'لغو' + }, + startScreen: { + recentSearchesTitle: 'جستجو‌های اخیر', + noRecentSearchesText: 'تاریخچه جستجویی یافت نشد.', + saveRecentSearchButtonTitle: 'ذخیره تاریخچه جستجو', + removeRecentSearchButtonTitle: 'حذف تاریخچه جستجو', + favoriteSearchesTitle: 'موارد دلخواه', + removeFavoriteSearchButtonTitle: 'حذف مورد دلخواه' + }, + errorScreen: { + titleText: 'نتیجه‌ای یافت نشد برای', + helpText: 'اتصال شبکه خود را بررسی کنید' + }, + footer: { + selectText: 'انتخاب', + navigateText: 'رفتن', + closeText: 'بستن', + searchByText: ' جستجو با ' + }, + noResultsScreen: { + noResultsText: 'نتیجه‌ای یافت نشد برای' + } + } + } + } +} diff --git a/docs/.vitepress/config/index.ts b/docs/.vitepress/config/index.ts index 2715ccdc..08a81fb9 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -6,6 +6,7 @@ import { pt } from './pt' import { ru } from './ru' import { es } from './es' import { ko } from './ko' +import { fa } from './fa' export default defineConfig({ ...shared, @@ -15,6 +16,7 @@ export default defineConfig({ pt: { label: 'Português', ...pt }, ru: { label: 'Русский', ...ru }, es: { label: 'Español', ...es }, - ko: { label: '한국어', ...ko } + ko: { label: '한국어', ...ko }, + fa: { label: 'فارسی', ...fa } } }) diff --git a/docs/.vitepress/config/ko.ts b/docs/.vitepress/config/ko.ts index 906669d3..faebabf4 100644 --- a/docs/.vitepress/config/ko.ts +++ b/docs/.vitepress/config/ko.ts @@ -44,7 +44,8 @@ export const ko = defineConfig({ sidebarMenuLabel: '사이드바 메뉴', darkModeSwitchLabel: '다크 모드', lightModeSwitchTitle: '라이트 모드로 변경', - darkModeSwitchTitle: '다크 모드로 변경' + darkModeSwitchTitle: '다크 모드로 변경', + skipToContentLabel: '본문으로 건너뛰기' } }) diff --git a/docs/.vitepress/config/pt.ts b/docs/.vitepress/config/pt.ts index f8ce02a1..12cb52fa 100644 --- a/docs/.vitepress/config/pt.ts +++ b/docs/.vitepress/config/pt.ts @@ -48,7 +48,8 @@ export const pt = defineConfig({ sidebarMenuLabel: 'Menu Lateral', darkModeSwitchLabel: 'Tema Escuro', lightModeSwitchTitle: 'Mudar para Modo Claro', - darkModeSwitchTitle: 'Mudar para Modo Escuro' + darkModeSwitchTitle: 'Mudar para Modo Escuro', + skipToContentLabel: 'Pular para o Conteúdo' } }) diff --git a/docs/.vitepress/config/ru.ts b/docs/.vitepress/config/ru.ts index 6e536347..b75b1b77 100644 --- a/docs/.vitepress/config/ru.ts +++ b/docs/.vitepress/config/ru.ts @@ -42,7 +42,8 @@ export const ru = defineConfig({ darkModeSwitchTitle: 'Переключить на тёмную тему', sidebarMenuLabel: 'Меню', returnToTopLabel: 'Вернуться к началу', - langMenuLabel: 'Изменить язык' + langMenuLabel: 'Изменить язык', + skipToContentLabel: 'Перейти к содержимому' } }) @@ -143,7 +144,7 @@ function sidebarReference(): DefaultTheme.SidebarItem[] { { text: 'Навигация', link: 'nav' }, { text: 'Сайдбар', link: 'sidebar' }, { text: 'Главная страница', link: 'home-page' }, - { text: 'Подвал', link: 'footer' }, + { text: 'Футер', link: 'footer' }, { text: 'Макет', link: 'layout' }, { text: 'Значки', link: 'badge' }, { text: 'Страница команды', link: 'team-page' }, diff --git a/docs/.vitepress/config/shared.ts b/docs/.vitepress/config/shared.ts index b33ee9ae..e7aeb2a4 100644 --- a/docs/.vitepress/config/shared.ts +++ b/docs/.vitepress/config/shared.ts @@ -1,9 +1,15 @@ import { defineConfig } from 'vitepress' -import { search as zhSearch } from './zh' -import { search as ptSearch } from './pt' -import { search as ruSearch } from './ru' import { search as esSearch } from './es' +import { search as faSearch } from './fa' import { search as koSearch } from './ko' +import { search as ptSearch } from './pt' +import { search as ruSearch } from './ru' +import { search as zhSearch } from './zh' +import { + groupIconMdPlugin, + groupIconVitePlugin, + localIconLoader +} from 'vitepress-plugin-group-icons' export const shared = defineConfig({ title: 'VitePress', @@ -25,7 +31,37 @@ export const shared = defineConfig({ return code.replace(/\[\!\!code/g, '[!code') } } - ] + ], + config(md) { + // TODO: remove when https://github.com/vuejs/vitepress/issues/4431 is fixed + const fence = md.renderer.rules.fence! + md.renderer.rules.fence = function (tokens, idx, options, env, self) { + const { localeIndex = 'root' } = env + const codeCopyButtonTitle = (() => { + switch (localeIndex) { + case 'es': + return 'Copiar código' + case 'fa': + return 'کپی کد' + case 'ko': + return '코드 복사' + case 'pt': + return 'Copiar código' + case 'ru': + return 'Скопировать код' + case 'zh': + return '复制代码' + default: + return 'Copy code' + } + })() + return fence(tokens, idx, options, env, self).replace( + '', + `` + ) + } + md.use(groupIconMdPlugin) + } }, sitemap: { @@ -67,11 +103,25 @@ export const shared = defineConfig({ ...ptSearch, ...ruSearch, ...esSearch, - ...koSearch + ...koSearch, + ...faSearch } } }, carbonAds: { code: 'CEBDT27Y', placement: 'vuejsorg' } + }, + vite: { + plugins: [ + groupIconVitePlugin({ + customIcon: { + vitepress: localIconLoader( + import.meta.url, + '../../public/vitepress-logo-mini.svg' + ), + firebase: 'logos:firebase' + } + }) + ] } }) diff --git a/docs/.vitepress/config/zh.ts b/docs/.vitepress/config/zh.ts index b7463980..e9d5fbcd 100644 --- a/docs/.vitepress/config/zh.ts +++ b/docs/.vitepress/config/zh.ts @@ -48,7 +48,8 @@ export const zh = defineConfig({ sidebarMenuLabel: '菜单', darkModeSwitchLabel: '主题', lightModeSwitchTitle: '切换到浅色模式', - darkModeSwitchTitle: '切换到深色模式' + darkModeSwitchTitle: '切换到深色模式', + skipToContentLabel: '跳转到内容' } }) diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 00000000..7208825e --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,4 @@ +import Theme from 'vitepress/theme' +import 'virtual:group-icons.css' + +export default Theme diff --git a/docs/en/guide/custom-theme.md b/docs/en/guide/custom-theme.md index 1d168ce9..96943c9f 100644 --- a/docs/en/guide/custom-theme.md +++ b/docs/en/guide/custom-theme.md @@ -49,8 +49,7 @@ interface EnhanceAppContext { The theme entry file should export the theme as its default export: -```js -// .vitepress/theme/index.js +```js [.vitepress/theme/index.js] // You can directly import Vue files in the theme entry // VitePress is pre-configured with @vitejs/plugin-vue. @@ -72,8 +71,7 @@ Inside your layout component, it works just like a normal Vite + Vue 3 applicati The most basic layout component needs to contain a [``](../reference/runtime-api#content) component: -```vue - +```vue [.vitepress/theme/Layout.vue]