docs(fa): add customization contents

pull/4089/head
Amirhossein Alibakhshi 1 year ago
parent 07a1e14b7a
commit 42bb384f2d

@ -0,0 +1,56 @@
---
outline: deep
---
# اتصال به یک سیستم مدیریت محتوا (CMS)
## گام‌های کلی
اتصال VitePress به یک سیستم مدیریت محتوا به طور عمده بر اساس [مسیریابی پویا](./routing#dynamic-routes) خواهد بود. حتماً قبل از شروع، با روش کار آن آشنا شوید.
از آنجایی که هر سیستم مدیریت محتوا به طریقی متفاوت کار می‌کند، در اینجا تنها می‌توانیم یک جریان کاری عمومی را ارائه دهیم که شما باید آن را برای حالت خاص خودتان سفارشی کنید.
1. اگر سیستم مدیریت محتوا نیاز به احراز هویت دارد، یک فایل `.env` برای ذخیره توکن‌های API خود ایجاد کنید و آن را بارگذاری کنید:
```js
// posts/[id].paths.js
import { loadEnv } from 'vitepress'
const env = loadEnv('', process.cwd())
```
2. داده‌های مورد نیاز را از سیستم مدیریت محتوا بازیابی کرده و به شکل داده‌های مسیر مناسب فرمت کنید:
```js
export default {
async paths() {
// از کتابخانه مشتری مربوط به سیستم مدیریت محتوا استفاده کنید اگر نیاز دارید
const data = await (await fetch('https://my-cms-api', {
headers: {
// توکن در صورت لزوم
}
})).json()
return data.map(entry => {
return {
params: { id: entry.id, /* عنوان، نویسندگان، تاریخ و غیره */ },
content: entry.content
}
})
}
}
```
3. نمایش محتوا در صفحه:
```md
# {{ $params.title }}
- نوشته شده توسط {{ $params.author }} در تاریخ {{ $params.date }}
<!-- @content -->
```
## راهنماهای ادغام
اگر راهنمایی درباره ادغام VitePress با یک سیستم مدیریت محتوا خاص نوشته‌اید، لطفاً از لینک "ویرایش این صفحه" زیر استفاده کنید تا آن را ارسال کنید!

@ -0,0 +1,226 @@
---
outline: deep
---
# استفاده از یک تم سفارشی
## Resolve کردن تم
می‌توانید با ایجاد یک فایل `.vitepress/theme/index.js` یا `.vitepress/theme/index.ts` (فایل ورودی تم) تم سفارشی را فعال کنید:
```
.
├─ docs # ریشه پروژه
│ ├─ .vitepress
│ │ ├─ theme
│ │ │ └─ index.js # ورودی تم
│ │ └─ config.js # فایل پیکربندی
│ └─ index.md
└─ package.json
```
وقتی VitePress حضور یک فایل ورودی تم را شناسایی کند، همواره از تم سفارشی به جای تم پیش‌فرض استفاده می‌کند. با این حال، شما می‌توانید [تم پیش‌فرض را گسترش دهید](./extending-default-theme) تا سفارشی‌سازی‌های پیشرفته‌تری را روی آن اعمال کنید.
## رابط تم
یک تم سفارشی VitePress به عنوان یک شی تعریف می‌شود که شامل رابط زیر است:
```ts
interface Theme {
/**
* کامپوننت لایه‌ی ریشه برای هر صفحه
* @required
*/
Layout: Component
/**
* تقویت نمونه Vue اپلیکیشن
* @optional
*/
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
/**
* گسترش یک تم دیگر، با فراخوانی `enhanceApp` آن پیش از ما
* @optional
*/
extends?: Theme
}
interface EnhanceAppContext {
app: App // نمونه Vue اپلیکیشن
router: Router // نمونه روتر VitePress
siteData: Ref<SiteData> // متادیتاهای سطح سایت
}
```
فایل ورودی تم باید تم را به عنوان export پیش‌فرض خود export کند:
```js
// .vitepress/theme/index.js
// شما می‌توانید فایل‌های Vue را مستقیماً در ورودی تم وارد کنید
// VitePress با @vitejs/plugin-vue پیش‌تنظیم شده است.
import Layout from './Layout.vue'
export default {
Layout,
enhanceApp({ app, router, siteData }) {
// ...
}
}
```
export پیش‌فرض تنها قراردادی برای یک تم سفارشی است و تنها ویژگی `Layout` لازم است. بنابراین، به شیء تم VitePress می‌توان به عنوان یک کامپوننت Vue ساده ترتیب داد.
درون کامپوننت لایه‌ی خود، دقیقاً مانند یک برنامه Vite + Vue 3 عادی عمل می‌کند. با این وجود، توجه داشته باشید که تم همچنین باید [سازگار با SSR](./ssr-compat) باشد.
## ساخت یک لایه
بیشترین لایه‌ی پایه‌ای نیازمند دارای یک کامپوننت `<Content />` است:
```vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<h1>طرح سفارشی!</h1>
<!-- اینجا محتوای markdown نمایش داده می‌شود -->
<Content />
</template>
```
لایه‌ی بالا به سادگی تمام محتوای markdown هر صفحه را به عنوان HTML نمایش می‌دهد. اولین بهبودی که می‌توانیم اعمال کنیم، مدیریت خطاهای 404 است:
```vue{1-4,9-12}
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<template>
<h1>طرح سفارشی!</h1>
<div v-if="page.isNotFound">
صفحه 404 سفارشی!
</div>
<Content v-else />
</template>
```
کمک‌کننده [`useData()`](../reference/runtime-api#usedata) اطلاعات اجرایی مورد نیاز ما را برای رندر شرایطی صفحات مختلف فراهم می‌کند. یکی از دیگر اطلاعاتی که ما می‌توانیم به آن دسترسی داشته باشیم، اطلاعات اولیه صفحه فعلی است. ما می‌توانیم از این اطلاعات برای اجازه دادن به کاربر برای کنترل لایه در هر صفحه استفاده کنیم. به عنوان مثال، کاربر می‌تواند مشخص کند که صفحه باید از یک طرح صفحه خانه خاص استفاده کند با:
```md
---
layout: home
---
```
و ما می‌توانیم تم خود را تنظیم کنیم تا با این موضوع برخورد کند:
```vue{3,12-14}
<script setup>
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>
<template>
<h1>طرح سفارشی!</h1>
<div v-if="page.isNotFound">
صفحه 404 سفارشی!
</div>
<div v-if="frontmatter.layout === 'home'">
صفحه خانه سفارشی!
</div>
<Content v-else />
</template>
```
طبیعتا، شما می‌توانید لایه‌ی خود را به کامپوننت‌های بیشتری تقسیم کنید:
```vue{3-5,12-15}
<script setup>
import { useData } from 'vitepress'
import NotFound from './NotFound.vue'
import Home from './Home.vue'
import Page from './Page.vue'
const { page, frontmatter } = useData()
</script>
<template>
<h1>طرح سفارشی!</h1>
<NotFound v-if="page.isNotFound" />
<Home v-if="frontmatter.layout === 'home'" />
<Page v-else /> <!-- <Page /> با `<Content />` را نمایش می‌دهد -->
</template>
```
برای همه چیزی که در کامپوننت‌های تم موجود است، به [مستندات API اجرایی](../reference/runtime-api) مراجعه کنید. به علاوه، شما می‌توانید از [بارگذاری داده در زمان ساخت](./data-loading) استفاده کنید تا لایه‌های مبتنی بر داده را تولید کنید - به عنوان مثال، یک صفحه که تمام پست‌های وبلاگ در پروژه فعلی را لیست می‌کند.
## توزیع یک تم سفارشی
آسان‌ترین روش برای توزیع یک تم سفارشی ارائه آن به عنوان [قالب مخزن در GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository) است.
اگر می‌خواهید تم را به عنوان یک بسته npm توزیع کنید، مراحل زیر را دنبال کنید:
1. شیء تم را به عنوان export پیش‌فرض در ورودی بسته‌تان export کنید.
2. اگر امکان دارد، تعریف نوع پیکربندی تم خود را به عنوان `ThemeConfig` export کنید.
3. اگر تم شما نیاز به تنظیم پیکربندی VitePress دارد، پیکربندی را تحت یک زیر‌مسیر بسته (مانند `my-theme/config`) export کنید تا کاربر بتواند آن را گسترش دهد.
4. گزینه‌های پیکربندی تم را مستند کنید (هم از طریق فایل پیکربندی و هم از طریق frontmatter).
5. دستورالعمل‌های روشنی برای مصرف تم خود ارائه دهید (مانند زیر).
## مصرف یک تم سفارشی
برای مصرف یک تم خارجی، آن را از ورودی تم سفارشی وارد و دوباره export کنید:
```js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'
export default Theme
```
اگر تم نیاز به گسترش دارد:
```js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'
export default {
extends: Theme,
enhanceApp(ctx) {
// ...
}
}
```
اگر تم نیاز به پیکربندی خاص VitePress دارد، شما همچنین باید آن را در پیکربندی خود گسترش دهید:
```ts
// .vitepress/config.ts
import baseConfig from 'awesome-vitepress-theme/config'
export default {
// گسترش پیکربندی پایه‌ی تم (اگر لازم باشد)
extends: baseConfig
}
```
سرانجام، اگر تم انواع خود را برای پیکربندی تم‌اش ارائه می‌دهد:
```ts
// .vitepress/config.ts
import baseConfig from 'awesome-vitepress-theme/config'
import { defineConfigWithTheme } from 'vitepress'
import type { ThemeConfig } from 'awesome-vitepress-theme'
export default defineConfigWithTheme<ThemeConfig>({
extends: baseConfig,
themeConfig: {
// نوع `ThemeConfig` است
}
})
```

@ -0,0 +1,250 @@
# بارگذاری داده در زمان ساخت
VitePress یک ویژگی به نام **بارگذارهای داده** ارائه می‌دهد که به شما این امکان را می‌دهد که داده‌های دلخواه را بارگیری کنید و آن‌ها را از صفحات یا اجزا وارد کنید. بارگذاری داده فقط **در زمان ساخت** اجرا می‌شود: داده‌های حاصل به صورت JSON در بسته JavaScript نهایی سریالیزه می‌شوند.
بارگذارهای داده می‌توانند برای بارگیری داده‌های از راه دور یا تولید فراداده‌ها بر اساس فایل‌های محلی استفاده شوند. به عنوان مثال، می‌توانید از بارگذارهای داده استفاده کنید تا تمام صفحات API محلی خود را تجزیه کنید و به طور خودکار یک فهرست از تمام ورودی‌های API تولید کنید.
## استفاده ابتدایی
یک فایل بارگذار داده باید با `.data.js` یا `.data.ts` پایان یابد. فایل باید یک صادرات پیش‌فرض از یک شی با متد `load()` داشته باشد:
```js
// example.data.js
export default {
load() {
return {
hello: 'world'
}
}
}
```
ماژول بارگذار فقط در Node.js ارزیابی می‌شود، بنابراین شما می‌توانید APIهای Node و وابستگی‌های npm را به عنوان نیازهای خود وارد کنید.
سپس می‌توانید داده را از این فایل در صفحات `.md` و اجزا `.vue` با استفاده از صادرات نام‌گذاری شده `data` وارد کنید:
```vue
<script setup>
import { data } from './example.data.js'
</script>
<pre>{{ data }}</pre>
```
خروجی:
```json
{
"hello": "world"
}
```
شما متوجه خواهید شد که بارگذار داده خودش داده را صادر نمی‌کند. VitePress پشت صحنه متد `load()` را فراخوانی می‌کند و به طور ضمنی نتیجه را از طریق صادرات نام‌گذاری شده `data` ارائه می‌دهد.
این کار حتی اگر بارگذار async باشد انجام می‌شود:
```js
export default {
async load() {
// دریافت داده از راه دور
return (await fetch('...')).json()
}
}
```
## داده از فایل‌های محلی
وقتی نیاز به تولید داده بر اساس فایل‌های محلی دارید، باید از گزینه `watch` در بارگذار داده استفاده کنید تا تغییرات اعمال شده به این فایل‌ها بتواند به روزرسانی‌های سریع منجر شود.
گزینه `watch` همچنین در آنجا مفید است که می‌توانید از [الگوهای glob](https://github.com/mrmlnc/fast-glob#pattern-syntax) برای تطابق با چندین فایل استفاده کنید. الگوها می‌توانند نسبت به فایل بارگذار خود نسبی باشند و تابع `load()` فایل‌های تطابق یافته را به عنوان مسیرهای مطلق دریافت می‌کند.
مثال زیر نشان می‌دهد که چگونه فایل‌های CSV را بارگذاری کرده و آن‌ها را با استفاده از [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/) به JSON تبدیل می‌کند. این فایل تنها در زمان ساخت اجرا می‌شود، بنابراین شما نیازی به ارسال پارسر CSV به مشتری ندارید!
```js
import fs from 'node:fs'
import { parse } from 'csv-parse/sync'
export default {
watch: ['./data/*.csv'],
load(watchedFiles) {
// watchedFiles یک آرایه از مسیرهای مطلق فایل‌های تطابق یافته خواهد بود.
// تولید یک آرایه از فراداده‌های پست وبلاگ که می‌تواند برای نمایش
// یک لیست در طرح استفاده شود
return watchedFiles.map((file) => {
return parse(fs.readFileSync(file, 'utf-8'), {
columns: true,
skip_empty_lines: true
})
})
}
}
```
## `createContentLoader`
وقتی که در حال ساختن یک سایت متمرکز بر محتوا هستیم، اغلب نیاز به ایجاد یک "بایگانی" یا "فهرست" صفحه داریم: یک صفحه که ما همه ورودی‌های موجود در مجموعه محتوای خود را لیست می‌کنیم، به عنوان مثال پست‌های وبلاگ یا صفحات API. ما می‌توانیم این کار را مستقیماً با API بارگذار داده انجام دهیم، اما از آنجا که این یک حالت استفاده رایج است، VitePress همچنین یک کمک‌کننده به نام `createContentLoader` را فراهم می‌کند تا این فرآیند را ساده‌تر کند:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', /* گزینه‌ها */)
```
کمک‌کننده یک الگوی glob را نسبت به [دایرکتوری منبع](./routing#source-directory) مشخص می‌کند و یک شی `{ watch، load }` را که می‌تواند به عنوان صادرات پیش‌فرض در یک فایل بارگذار داده استفاده شود، برمی‌گرداند. همچنین پیاده‌سازی حافظه پنهانی بر اساس برچسب‌های تغییر مدیریت
می‌کند تا عملکرد توسعه را بهبود بخشد.
لطفاً توجه داشته باشید که بارگذار فقط با فایل‌های Markdown کار می‌کند - فایل‌های غیر-Markdown تطابق یافته حذف می‌شوند.
داده بارگذاری شده یک آرایه با نوع `ContentData[]` خواهد بود:
```ts
interface ContentData {
// آدرس URL برای صفحه. به عنوان مثال /posts/hello.html (شامل پایه نمی‌شود)
// تکرار دستی یا استفاده از `transform` سفارشی برای نرمال کردن مسیرها
url: string
// اطلاعات frontmatter صفحه
frontmatter: Record<string, any>
// موارد زیر فقط وقتی که گزینه‌های مربوط فعال باشند
// ما در زیر آنها را بررسی می‌کنیم
src: string | undefined
html: string | undefined
excerpt: string | undefined
}
```
به طور پیش‌فرض، تنها `url` و `frontmatter` ارائه می‌شوند. این به خاطر این است که داده بارگذاری شده به عنوان JSON در بسته مشتری نهایی درج می‌شود، بنابراین ما باید در مورد اندازه آن محتاط باشیم. در زیر مثالی از استفاده از داده برای ساخت یک صفحه فهرست کمینه وبلاگ آورده شده است:
```vue
<script setup>
import { data as posts } from './posts.data.js'
</script>
<template>
<h1>همه پست‌های وبلاگ</h1>
<ul>
<li v-for="post of posts">
<a :href="post.url">{{ post.frontmatter.title }}</a>
<span>توسط {{ post.frontmatter.author }}</span>
</li>
</ul>
</template>
```
### گزینه‌ها
احتمالاً داده پیش‌فرض به تمام نیازها پاسخ نمی‌دهد - شما می‌توانید با استفاده از گزینه‌ها به تبدیل داده‌ها مشترک شوید:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
includeSrc: true, // آیا منبع اصلی مارک‌داون را اضافه کنیم؟
render: true, // آیا صفحه HTML را نیز شامل کنیم؟
excerpt: true, // آیا خلاصه را نیز شامل کنیم؟
transform(rawData) {
// نقشه‌برداری، مرتب‌سازی یا فیلتر کردن داده‌های اصلی به دلخواه.
// نتیجه نهایی آنچه است که به مشتری ارسال خواهد شد.
return rawData.sort((a, b) => {
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
}).map((page) => {
page.src // منبع اصلی مارک‌داون
page.html // صفحه HTML کامل
page.excerpt // خلاصه HTML (محتوای بالای اولین `---`)
return {/* ... */}
})
}
})
```
بررسی کنید که چگونه در [وبلاگ Vue.js](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts) استفاده شده است.
API `createContentLoader` همچنین می‌تواند در داخل [هوک‌های ساخت](../reference/site-config#build-hooks) استفاده شود:
```js
// .vitepress/config.js
export default {
async buildEnd() {
const posts = await createContentLoader('posts/*.md').load()
// تولید فایل‌های بر اساس فراداده‌های پست‌ها، مثلاً فید RSS
}
}
```
**انواع**
```ts
interface ContentOptions<T = ContentData[]> {
/**
* آیا منبع اصلی را اضافه کنیم؟
* @default false
*/
includeSrc?: boolean
/**
* آیا منبع را به HTML تبدیل کرده و در داده شامل کنیم؟
* @default false
*/
render?: boolean
/**
* اگر `boolean` باشد، آیا باید خلاصه را تجزیه و شامل کنیم؟ (به صورت HTML)
*
* اگر `function` باشد، کنترل نحوه استخراج خلاصه از محتوا.
*
* اگر `string` باشد، تعیین کنید که چگونه جداکننده سفارشی باید برای استخراج خلاصه استفاده شود.
* جداکننده پیش‌فرض `---` است اگر `excerpt` `true` باشد.
*
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator
*
* @default false
*/
excerpt?:
| boolean
| ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void)
| string
/**
* تبدیل داده. توجه داشته باشید که داده به عنوان JSON در بسته مشتری درج خواهد شد
* اگر از اجزا یا فایل‌های مارک‌داون وارد شود.
*/
transform?: (data: ContentData[]) => T | Promise<T>
}
```
## بارگذارهای داده تایپ شده
زمان استفاده از TypeScript، می‌توانید بارگذار و صادرات `data` خود را به این شکل تایپ کنید:
```ts
import { defineLoader } from 'vitepress'
export interface Data {
// نوع داده
}
declare const data: Data
export { data }
export default defineLoader({
// گزینه‌های بارگذاری با تایپ چک شده
watch: ['...'],
async load(): Promise<Data> {
// ...
}
})
```
## پیکربندی
برای دریافت اطلاعات پیکربندی در داخل یک بارگذار، می‌توانید از کدی مانند زیر استفاده کنید:
```ts
import type { SiteConfig } from 'vitepress'
const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG
```

@ -0,0 +1,343 @@
---
outline: deep
---
# گسترش تم پیش‌فرض
تم پیش‌فرض VitePress برای مستندات بهینه‌سازی شده است و قابلیت سفارشی‌سازی دارد. برای دریافت لیست جامع گزینه‌ها، به [نمای کلی از تنظیمات تم پیش‌فرض](../reference/default-theme-config) مراجعه کنید.
با این حال، مواردی وجود دارد که فقط با تنظیمات کافی نخواهد بود. به عنوان مثال:
1. نیاز به تنظیم استایل CSS دارید؛
2. نیاز به اصلاح نمونه برنامه Vue، به عنوان مثال برای ثبت مولفه‌های عمومی؛
3. نیاز به درج محتوای سفارشی در تم از طریق slotهای طرح.
این سفارش‌های پیشرفته نیازمند استفاده از یک تم سفارشی هستند که از تم پیش‌فرض "گسترش" می‌کند.
::: tip
قبل از ادامه، ابتدا [استفاده از یک تم سفارشی](./custom-theme) را بخوانید تا نحوه کار تم‌های سفارشی را درک کنید.
:::
## سفارشی‌سازی CSS
CSS تم پیش‌فرض با نادیده گرفتن متغیرهای CSS سطح ریشه قابل سفارشی‌سازی است:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'
export default DefaultTheme
```
```css
/* .vitepress/theme/custom.css */
:root {
--vp-c-brand-1: #646cff;
--vp-c-brand-2: #747bff;
}
```
لیست متغیرهای CSS [تم پیش‌فرض](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) که می‌توانند سفارشی‌سازی شوند را ببینید.
## استفاده از فونت‌های مختلف
VitePress از [Inter](https://rsms.me/inter/) به عنوان فونت پیش‌فرض استفاده می‌کند و فونت‌ها را در خروجی ساخته‌شده شامل می‌شود. این فونت همچنین در محصولات خودکار پیش‌بارگذاری می‌شود. با این حال، این ممکن است مطلوب نباشد اگر می‌خواهید از یک فونت اصلی مختلف استفاده کنید.
برای جلوگیری از شامل شدن Inter در خروجی ساخته‌شده، تم را به جای `vitepress/theme-without-fonts` وارد کنید:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme-without-fonts'
import './my-fonts.css'
export default DefaultTheme
```
```css
/* .vitepress/theme/custom.css */
:root {
--vp-font-family-base: /* فونت متن عادی */
--vp-font-family-mono: /* فونت کد */
}
```
::: warning
اگر از مولفه‌های اختیاری مانند مولفه‌های [صفحه تیم](../reference/default-theme-team-page) استفاده می‌کنید، اطمینان حاصل کنید که آن‌ها را هم از `vitepress/theme-without-fonts` وارد می‌کنید!
:::
اگر فونت شما یک فایل محلی است که از طریق `@font-face` ارجاع شده است، به عنوان یک دارایی پردازش می‌شود و با نام فایل هشداردار در `.vitepress/dist/assets` شامل می‌شود. برای پیش‌بارگذاری این فایل، از هوک ساخت [transformHead](../reference/site-config#transformhead) استفاده کنید:
```js
// .vitepress/config.js
export default {
transformHead({ assets }) {
// منظور شده برای همسان سازی font خود، regex مورد نیاز را تنظیم کنید
const myFontFile = assets.find(file => /font-name\.\w+\.woff2/)
if (myFontFile) {
return [
[
'link',
{
rel: 'preload',
href: myFontFile,
as: 'font',
type: 'font/woff2',
crossorigin: ''
}
]
]
}
}
}
```
## ثبت مولفه‌های عمومی
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
/** @type {import('vitepress').Theme} */
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// ثبت مولفه‌های عمومی سفارشی‌شده خود را
app.component('MyGlobalComponent' /* ... */)
}
}
```
اگر از TypeScript استفاده می‌کنید:
```ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// ثبت مولفه‌های عمومی سفارشی‌شده خود را
app.component('MyGlobalComponent' /* ... */)
}
} satisfies Theme
```
از آنجا که از Vite استفاده می‌کنیم، می‌توانید از ویژگی [import glob](https://vitejs.dev/guide/features.html#glob-import) در Vite برای خودکار ثبت یک پوشه از مولفه‌ها استفاده کنید.
## slot ‌های طرح
کامپوننت `<Layout/>` تم پیش‌فرض چندین slot دارد که می‌توانید محتوا را در موقعیت‌های مختلف صفحه در آن‌ها درج کنید. در زیر مثالی از درج یک کامپوننت در قبل از طرح داده شده است:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyLayout from './MyLayout.vue'
export default {
extends: DefaultTheme,
// جایگزینی Layout با یک کامپوننت پوشه‌بندی که slotها را درج می‌کند
Layout: MyLayout
}
```
```vue
<!--.vitepress/theme/MyLayout.vue-->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>
<template>
<Layout>
<template #aside-outline-before>
محتوای سفارشی بالای نوار کناری من
</template>
</Layout>
</template>
```
یا می‌توانید از تابع رندر نیز استفاده کنید.
```js
// .vitepress/theme/index.js
import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import MyComponent from './MyComponent.vue'
export default {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
'aside-outline-before': () => h(MyComponent)
})
}
}
```
لیست کاملی از slotهای موجود در طرح پیش‌فرض:
- وقتی `layout: 'doc'` (پیش‌فرض) از طریق frontmatter فعال است:
- `doc-top`
- `doc-bottom`
- `doc-footer-before`
- `doc-before`
- `doc-after`
- `sidebar-nav-before`
- `sidebar-nav-after`
- `aside-top`
- `aside-bottom`
- `aside-outline-before`
- `aside-outline-after`
- `aside-ads-before`
- `aside-ads-after`
- وقتی `layout: 'home'` از طریق frontmatter فعال است:
- `home-hero-before`
- `home-hero-info-before`
- `home-hero-info`
- `home-hero-info-after`
- `home-hero-actions-after`
- `home-hero-image`
- `home-hero-after`
- `home-features-before`
- `home-features-after`
- وقتی `layout: 'page'` از طریق frontmatter فعال است:
- `page-top`
- `page-bottom`
- در صفحه یافت نشد (404):
- `not-found`
- همیشه:
- `layout-top`
- `layout-bottom`
- `nav-bar-title-before`
- `nav-bar-title-after`
- `nav-bar-content-before`
- `nav-bar-content-after`
- `nav-screen-content-before`
- `nav-screen-content-after`
## استفاده از API انتقال نمایش
### در تغییر ظاهر
شما می‌توانید تم پیش‌فرض را گسترش دهید تا هنگام تغییر حالت رنگ، یک انتقال سفارشی را فراهم کند. به عنوان مثال:
```vue
<!-- .vitepress/theme/Layout.vue -->
<script setup lang="ts">
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { nextTick, provide } from 'vue'
const { isDark } = useData()
const enableTransitions = () =>
'startViewTransition' in document &&
window.matchMedia('(prefers-reduced-motion: no-preference)').matches
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
if (!enableTransitions()) {
isDark.value = !isDark.value
return
}
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
)}px at ${x}px ${y}px)`
]
await document.startViewTransition(async () => {
isDark.value = !isDark.value
await nextTick()
}).ready
document.documentElement.animate(
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
{
duration: 300,
easing: 'ease-in',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
})
</script>
<template>
<DefaultTheme.Layout />
</template>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root),
.dark::view-transition-new(root) {
z-index: 1;
}
::view-transition-new(root),
.dark::view-transition-old(root) {
z-index: 9999;
}
.VPSwitchAppearance {
width: 22px !important;
}
.VPSwitchAppearance .check {
transform: none !important;
}
</style>
```
نتیجه (**هشدار!**: رنگ‌های فلاشینگ، حرکات ناگهانی، نورهای شدید):
<details>
<summary>نمایش</summary>
![نمایش انتقال ظاهر تغییر](/appearance-toggle-transition.webp)
</details>
برای جزئیات بیشتر در مورد انتقال‌های نمایش به [اسناد کروم](https://developer.chrome.com/docs/web-platform/view-transitions/) مراجعه کنید.
### در تغییر مسیر
به زودی.
## جایگزینی کامپوننت‌های داخلی
شما می‌توانید با استفاده از [alias های Vite](https://vitejs.dev/config/shared-options.html#resolve-alias)، کامپوننت‌های تم پیش‌فرض را با کامپوننت‌های سفارشی خود جایگزین کنید:
```ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitepress'
export default defineConfig({
vite: {
resolve: {
alias: [
{
find: /^.*\/VPNavBar\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNavBar.vue', import.meta.url)
)
}
]
}
}
})
```
برای دریافت نام دقیق کامپوننت به [کد منبع ما](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components) مراجعه کنید. از آنجا که کامپوننت‌ها داخلی هستند، احتمال آنکه نام آن‌ها بین انتشارات کوچک تغییر کند، وجود دارد.

@ -1,6 +1,6 @@
# افزونه‌های Markdown
VitePress با افزونه‌های مارک‌داون داخلی ارائه شده است.
VitePress با افزونه‌های markdown داخلی ارائه شده است.
## لینک‌های هدر

@ -18,6 +18,6 @@ document.querySelector('h1').addEventListener('click', () => {
# سلام
```
`<script client>` یک ویژگی تنها برای VitePress است، نه یک ویژگی Vue. این در هر دو فایل `.md` و `.vue` کار می‌کند، اما فقط در حالت MPA. اسکریپت‌های کلاینت در تمام اجزای پوسته با هم بسته می‌شوند، در حالی که اسکریپت کلاینت برای یک صفحه خاص، فقط برای آن صفحه تقسیم می‌شود.
`<script client>` یک ویژگی تنها برای VitePress است، نه یک ویژگی Vue. این در هر دو فایل `.md` و `.vue` کار می‌کند، اما فقط در حالت MPA. اسکریپت‌های کلاینت در تمام اجزای تم با هم بسته می‌شوند، در حالی که اسکریپت کلاینت برای یک صفحه خاص، فقط برای آن صفحه تقسیم می‌شود.
توجه داشته باشید که `<script client>` به عنوان **کد مؤلفه مؤلفه Vue** ارزیابی نمی‌شود: به عنوان یک ماژول جاوااسکریپت معمولی پردازش می‌شود. به همین دلیل، حالت MPA فقط باید در صورتی استفاده شود که سایت شما به تعامل کمینه‌ای از جانب کلاینت نیاز دارد.

@ -0,0 +1,136 @@
---
outline: deep
---
# تطابق SSR
VitePress، با استفاده از قابلیت‌های رندرینگ سمت سرور (SSR) ارائه شده توسط Vue، اپلیکیشن را در Node.js در هنگام ساخت تولیدی پیش از رندر می‌کند. این بدان معناست که کلیه کدهای سفارشی در اجزای تم به تطابق SSR وابسته هستند.
[بخش SSR در مستندات رسمی Vue](https://vuejs.org/guide/scaling-up/ssr.html) بیشتر در مورد SSR، ارتباط بین SSR / SSG و نکات متداول در نوشتن کد‌های سازگار با SSR توضیح می‌دهد. قانون عمده این است که فقط در `beforeMount` یا `mounted` هوک‌های اجزای Vue از APIهای مرورگر / DOM استفاده کنید.
## `<ClientOnly>`
اگر از اجزا یا دموهایی استفاده می‌کنید که سازگاری با SSR ندارند (برای مثال حاوی دستورالعمل‌های سفارشی هستند)، می‌توانید آن‌ها را درون کامپوننت داخلی `<ClientOnly>` قرار دهید:
```md
<ClientOnly>
<NonSSRFriendlyComponent />
</ClientOnly>
```
## کتابخانه‌هایی که در هنگام وارد کردن به API مرورگر دسترسی دارند
بعضی از کتابخانه‌ها یا اجزا در هنگام وارد کردن به APIهای مرورگر **دسترسی دارند**. برای استفاده از کدی که فرض می‌کند محیطی مرورگر در هنگام وارد کردن وجود دارد، باید آن‌ها را به صورت پویا وارد کنید.
### وارد کردن در هوک Mounted
```vue
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
import('./lib-that-access-window-on-import').then((module) => {
// استفاده از کد
})
})
</script>
```
### وارد کردن شرطی
می‌توانید همچنین وابستگی را با استفاده از `import.meta.env.SSR` (قسمتی از [متغیرهای env Vite](https://vitejs.dev/guide/env-and-mode.html#env-variables)) به شرط وارد کنید:
```js
if (!import.meta.env.SSR) {
import('./lib-that-access-window-on-import').then((module) => {
// استفاده از کد
})
}
```
از آنجا که `Theme.enhanceApp` می‌تواند async باشد، می‌توانید به صورت شرطی پلاگین‌های Vue را که دسترسی به APIهای مرورگر را هنگام وارد کردن دارند، وارد و ثبت کنید:
```js
// .vitepress/theme/index.js
/** @type {import('vitepress').Theme} */
export default {
// ...
async enhanceApp({ app }) {
if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin.default)
}
}
}
```
اگر از TypeScript استفاده می‌کنید:
```ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
export default {
// ...
async enhanceApp({ app }) {
if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin.default)
}
}
} satisfies Theme
```
### `defineClientComponent`
VitePress یک کمک‌کننده راحتی برای وارد کردن کامپوننت‌های Vue که هنگام وارد کردن به APIهای مرورگر دسترسی دارند فراهم می‌کند.
```vue
<script setup>
import { defineClientComponent } from 'vitepress'
const ClientComp = defineClientComponent(() => {
return import('component-that-access-window-on-import')
})
</script>
<template>
<ClientComp />
</template>
```
همچنین می‌توانید props/children/slots را به کامپوننت مقصد منتقل کنید:
```vue
<script setup>
import { ref } from 'vue'
import { defineClientComponent } from 'vitepress'
const clientCompRef = ref(null)
const ClientComp = defineClientComponent(
() => import('component-that-access-window-on-import'),
// آرگومان‌ها به h() منتقل می‌شوند - https://vuejs.org/api/render-function.html#h
[
{
ref: clientCompRef
},
{
default: () => 'اسلات پیش‌فرض',
foo: () => h('div', 'فو')
bar: () => [h('span', 'یک'), h('span', 'دو')]
}
],
// تابع بازخورد بعد از بارگذاری کامپوننت، می‌تواند async باشد
() => {
console.log(clientCompRef.value)
}
)
</script>
<template>
<ClientComp />
</template>
```
کامپوننت مقصد فقط در هوک Mounted کامپوننت پوشش وارد می‌شود.
Loading…
Cancel
Save