Merge branch 'main' into main

pull/4066/head
Divyansh Singh 11 months ago committed by GitHub
commit 9b49890105
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -13,7 +13,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions-ecosystem/action-add-labels@v1 - run: gh issue edit ${{ github.event.issue.number }} --add-label cr-tracked --repo ${{ github.repository }}
with: env:
labels: cr-tracked GITHUB_TOKEN: ${{ secrets.CR_PAT }}
github_token: ${{ secrets.CR_PAT }}

@ -16,6 +16,10 @@ on:
permissions: {} permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}
cancel-in-progress: true
jobs: jobs:
release: release:
if: ${{ !github.event.pull_request.draft && contains(github.event.pull_request.labels.*.name, 'cr-tracked') && !contains(github.event.pull_request.labels.*.name, 'spam') && !contains(github.event.pull_request.labels.*.name, 'invalid') }} if: ${{ !github.event.pull_request.draft && contains(github.event.pull_request.labels.*.name, 'cr-tracked') && !contains(github.event.pull_request.labels.*.name, 'spam') && !contains(github.event.pull_request.labels.*.name, 'invalid') }}

@ -1,3 +1,41 @@
# [1.4.0](https://github.com/vuejs/vitepress/compare/v1.3.4...v1.4.0) (2024-10-07)
### Bug Fixes
- `vueRE` conflicting with `lineNoRE` ([#4247](https://github.com/vuejs/vitepress/issues/4247)) ([2ac64b8](https://github.com/vuejs/vitepress/commit/2ac64b8d4180f2a7c54fda57df7f3a0a52488d62))
- hmr not updating page data in rewritten paths and file path is wrong in mdit for dynamic routes ([c46e4b7](https://github.com/vuejs/vitepress/commit/c46e4b784ddb9ce3bd1cfcc3de1d1d676535cb5b)), closes [#4172](https://github.com/vuejs/vitepress/issues/4172)
- remove font synthesis in webfont mode, google fonts now support italic axis in inter ([1628918](https://github.com/vuejs/vitepress/commit/1628918f30b5602b83c51a2a8f4ec5e773cf7445))
- **theme:** change the order of CSS rules of `VPFlyout` ([#4225](https://github.com/vuejs/vitepress/issues/4225)) ([68150a6](https://github.com/vuejs/vitepress/commit/68150a6f3349c1741ed5683e3010d9ecea02f3a8)), closes [#4224](https://github.com/vuejs/vitepress/issues/4224)
- **theme:** respect custom tag prop in VPButton component ([#4185](https://github.com/vuejs/vitepress/issues/4185)) ([9c5d348](https://github.com/vuejs/vitepress/commit/9c5d348c034eb6773562c93cad699d287051aa7b))
### Features
- add `data-title` attribute for code group label tag ([#4152](https://github.com/vuejs/vitepress/issues/4152)) ([bc7271d](https://github.com/vuejs/vitepress/commit/bc7271d258047feb8a39c97ebc5e2a16bf899bb5))
- allow ignoring certain headers and their subtrees completely in outline ([3e11b6a](https://github.com/vuejs/vitepress/commit/3e11b6abf5fbe80c2bc733f590ab57c7b2cc06f2)), closes [#4171](https://github.com/vuejs/vitepress/issues/4171)
- **client:** add `onAfterPageLoad` hook in router ([#4126](https://github.com/vuejs/vitepress/issues/4126)) ([315c220](https://github.com/vuejs/vitepress/commit/315c22004993f6f1cbdbb59178e46745d8e505a6))
- support adding extra attributes to snippet imports (useful for twoslash) ([#4100](https://github.com/vuejs/vitepress/issues/4100)) ([e8f7dd1](https://github.com/vuejs/vitepress/commit/e8f7dd16f6139fdfd129b86caff4b6613dd1e887))
- **theme:** expose theme default VPLink & VPSocialLink(s) component ([#4178](https://github.com/vuejs/vitepress/issues/4178)) ([615e33b](https://github.com/vuejs/vitepress/commit/615e33bb24d5005574af971ffcf1f41d751a855c))
- trigger `onContentUpdated` on frontmatter-only changes too ([0db269a](https://github.com/vuejs/vitepress/commit/0db269a4c5d90ecf69f0219982cdf8f335e787ce))
## [1.3.4](https://github.com/vuejs/vitepress/compare/v1.3.3...v1.3.4) (2024-08-24)
### Bug Fixes
- check if `_importGlobMap` (vite internal) exists before using it ([612d66f](https://github.com/vuejs/vitepress/commit/612d66fbb5162d9905cfb10919ca1761ce8c4680))
## [1.3.3](https://github.com/vuejs/vitepress/compare/v1.3.2...v1.3.3) (2024-08-17)
### Miscellaneous
- bump deps ([a20db24](https://github.com/vuejs/vitepress/commit/a20db247822438ac4e0e76bc4a2b4ee2f5d94940))
## [1.3.2](https://github.com/vuejs/vitepress/compare/v1.3.1...v1.3.2) (2024-08-05)
### Bug Fixes
- multiple cache busting imports causing useData to fail ([2b3e486](https://github.com/vuejs/vitepress/commit/2b3e486ab913ff77707410b9cee3ba6d256ccc95)), closes [#3820](https://github.com/vuejs/vitepress/issues/3820), reverts [#3398](https://github.com/vuejs/vitepress/issues/3398), reopens [#3363](https://github.com/vuejs/vitepress/issues/3363)
- **theme:** excerpt style in LocalSearchBox ([#4050](https://github.com/vuejs/vitepress/issues/4050)) ([2bc0d39](https://github.com/vuejs/vitepress/commit/2bc0d39d5089841986f0988fc9cfe15533d3a0c6))
## [1.3.1](https://github.com/vuejs/vitepress/compare/v1.3.0...v1.3.1) (2024-07-14) ## [1.3.1](https://github.com/vuejs/vitepress/compare/v1.3.0...v1.3.1) (2024-07-14)
### Bug Fixes ### Bug Fixes

@ -7,14 +7,10 @@ export declare const data: Data
export default defineLoader({ export default defineLoader({
watch: ['./data/*'], watch: ['./data/*'],
async load(files: string[]): Promise<Data> { async load(files: string[]): Promise<Data> {
const foo = fs.readFileSync( const data: Data = []
files.find((f) => f.endsWith('foo.json'))!, for (const file of files.sort().filter((file) => file.endsWith('.json'))) {
'utf-8' data.push(JSON.parse(fs.readFileSync(file, 'utf-8')))
) }
const bar = fs.readFileSync( return data
files.find((f) => f.endsWith('bar.json'))!,
'utf-8'
)
return [JSON.parse(foo), JSON.parse(bar)]
} }
}) })

@ -1,3 +1,6 @@
import fs from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
describe('static data file support in vite 3', () => { describe('static data file support in vite 3', () => {
beforeAll(async () => { beforeAll(async () => {
await goto('/data-loading/data') await goto('/data-loading/data')
@ -7,10 +10,10 @@ describe('static data file support in vite 3', () => {
expect(await page.textContent('pre#basic')).toMatchInlineSnapshot(` expect(await page.textContent('pre#basic')).toMatchInlineSnapshot(`
"[ "[
{ {
"foo": true "a": true
}, },
{ {
"bar": true "b": true
} }
]" ]"
`) `)
@ -39,4 +42,68 @@ describe('static data file support in vite 3', () => {
]" ]"
`) `)
}) })
// TODO: make it `.runIf(!process.env.VITE_TEST_BUILD)` -- it currently works, but is skipped to avoid vite's ecosystem-ci from failing (https://github.com/vitejs/vite/pull/16471#issuecomment-2308437187)
test.skip('hmr works', async () => {
const a = fileURLToPath(new URL('./data/a.json', import.meta.url))
const b = fileURLToPath(new URL('./data/b.json', import.meta.url))
try {
await fs.writeFile(a, JSON.stringify({ a: false }, null, 2) + '\n')
await page.waitForFunction(
() =>
document.querySelector('pre#basic')?.textContent ===
JSON.stringify([{ a: false }, { b: true }], null, 2),
undefined,
{ timeout: 3000 }
)
} finally {
await fs.writeFile(a, JSON.stringify({ a: true }, null, 2) + '\n')
}
let err = true
try {
await fs.unlink(b)
await page.waitForFunction(
() =>
document.querySelector('pre#basic')?.textContent ===
JSON.stringify([{ a: true }], null, 2),
undefined,
{ timeout: 3000 }
)
err = false
} finally {
if (err) {
await fs.writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n')
}
}
try {
await fs.writeFile(b, JSON.stringify({ b: false }, null, 2) + '\n')
await page.waitForFunction(
() =>
document.querySelector('pre#basic')?.textContent ===
JSON.stringify([{ a: true }, { b: false }], null, 2),
undefined,
{ timeout: 3000 }
)
} finally {
await fs.writeFile(b, JSON.stringify({ b: true }, null, 2) + '\n')
}
})
/*
MODIFY a.json with { a: false }
this should trigger a hmr update and the content should be updated to [{ a: false }, { b: true }]
reset a.json
DELETE b.json
this should trigger a hmr update and the content should be updated to [{ a: true }]
reset b.json if failed
CREATE b.json with { b: false }
this should trigger a hmr update and the content should be updated to [{ a: true }, { b: false }]
reset b.json
*/
}) })

@ -1,5 +1,11 @@
import { resolveHeaders } from 'client/theme-default/composables/outline' import { resolveHeaders } from 'client/theme-default/composables/outline'
const element = {
classList: {
contains: () => false
}
} as unknown as HTMLHeadElement
describe('client/theme-default/composables/outline', () => { describe('client/theme-default/composables/outline', () => {
describe('resolveHeader', () => { describe('resolveHeader', () => {
test('levels range', () => { test('levels range', () => {
@ -9,12 +15,14 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 2, level: 2,
title: 'h2 - 1', title: 'h2 - 1',
link: '#h2-1' link: '#h2-1',
element
}, },
{ {
level: 3, level: 3,
title: 'h3 - 1', title: 'h3 - 1',
link: '#h3-1' link: '#h3-1',
element
} }
], ],
[2, 3] [2, 3]
@ -28,9 +36,12 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 3, level: 3,
title: 'h3 - 1', title: 'h3 - 1',
link: '#h3-1' link: '#h3-1',
children: [],
element
} }
] ],
element
} }
]) ])
}) })
@ -42,12 +53,14 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 2, level: 2,
title: 'h2 - 1', title: 'h2 - 1',
link: '#h2-1' link: '#h2-1',
element
}, },
{ {
level: 3, level: 3,
title: 'h3 - 1', title: 'h3 - 1',
link: '#h3-1' link: '#h3-1',
element
} }
], ],
2 2
@ -56,7 +69,9 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 2, level: 2,
title: 'h2 - 1', title: 'h2 - 1',
link: '#h2-1' link: '#h2-1',
children: [],
element
} }
]) ])
}) })
@ -68,42 +83,50 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 2, level: 2,
title: 'h2 - 1', title: 'h2 - 1',
link: '#h2-1' link: '#h2-1',
element
}, },
{ {
level: 3, level: 3,
title: 'h3 - 1', title: 'h3 - 1',
link: '#h3-1' link: '#h3-1',
element
}, },
{ {
level: 4, level: 4,
title: 'h4 - 1', title: 'h4 - 1',
link: '#h4-1' link: '#h4-1',
element
}, },
{ {
level: 3, level: 3,
title: 'h3 - 2', title: 'h3 - 2',
link: '#h3-2' link: '#h3-2',
element
}, },
{ {
level: 4, level: 4,
title: 'h4 - 2', title: 'h4 - 2',
link: '#h4-2' link: '#h4-2',
element
}, },
{ {
level: 2, level: 2,
title: 'h2 - 2', title: 'h2 - 2',
link: '#h2-2' link: '#h2-2',
element
}, },
{ {
level: 3, level: 3,
title: 'h3 - 3', title: 'h3 - 3',
link: '#h3-3' link: '#h3-3',
element
}, },
{ {
level: 4, level: 4,
title: 'h4 - 3', title: 'h4 - 3',
link: '#h4-3' link: '#h4-3',
element
} }
], ],
'deep' 'deep'
@ -122,9 +145,12 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 4, level: 4,
title: 'h4 - 1', title: 'h4 - 1',
link: '#h4-1' link: '#h4-1',
children: [],
element
} }
] ],
element
}, },
{ {
level: 3, level: 3,
@ -134,11 +160,15 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 4, level: 4,
title: 'h4 - 2', title: 'h4 - 2',
link: '#h4-2' link: '#h4-2',
children: [],
element
} }
] ],
element
} }
] ],
element
}, },
{ {
level: 2, level: 2,
@ -153,11 +183,15 @@ describe('client/theme-default/composables/outline', () => {
{ {
level: 4, level: 4,
title: 'h4 - 3', title: 'h4 - 3',
link: '#h4-3' link: '#h4-3',
children: [],
element
} }
] ],
element
} }
] ],
element
} }
]) ])
}) })

@ -18,7 +18,7 @@ export const ko = defineConfig({
editLink: { editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'GitHub에서 이 페이지를 편집하세요' text: '이 페이지 편집 제안하기'
}, },
footer: { footer: {
@ -32,7 +32,7 @@ export const ko = defineConfig({
}, },
outline: { outline: {
label: '이 페이지에서' label: '이 페이지 목차'
}, },
lastUpdated: { lastUpdated: {
@ -105,7 +105,7 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
collapsed: false, collapsed: false,
items: [ items: [
{ {
text: '마크다운 확장', text: '마크다운 확장 기능',
link: 'markdown' link: 'markdown'
}, },
{ {
@ -113,33 +113,33 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
link: 'asset-handling' link: 'asset-handling'
}, },
{ {
text: '프론트마터', text: '전문(Front-matter)',
link: 'frontmatter' link: 'frontmatter'
}, },
{ {
text: '마크다운에서 Vue 사용', text: '마크다운에서 Vue 사용하기',
link: 'using-vue' link: 'using-vue'
}, },
{ {
text: '국제화', text: 'i18n',
link: 'i18n' link: 'i18n'
} }
] ]
}, },
{ {
text: '사용자 정의', text: '커스텀',
collapsed: false, collapsed: false,
items: [ items: [
{ {
text: '맞춤 테마 사용', text: '커스텀 테마 사용하기',
link: 'custom-theme' link: 'custom-theme'
}, },
{ {
text: '기본 테마 확장', text: '기본 테마 확장하기',
link: 'extending-default-theme' link: 'extending-default-theme'
}, },
{ {
text: '빌드할 때 데이터 로딩', text: '빌드할 때 데이터 로딩하기',
link: 'data-loading' link: 'data-loading'
}, },
{ {
@ -147,7 +147,7 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
link: 'ssr-compat' link: 'ssr-compat'
}, },
{ {
text: 'CMS 연결', text: 'CMS 연결하기',
link: 'cms' link: 'cms'
} }
] ]
@ -167,7 +167,7 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] {
] ]
}, },
{ {
text: '설정 & API 참조', text: '구성 & API 레퍼런스',
base: '/ko/reference/', base: '/ko/reference/',
link: 'site-config' link: 'site-config'
} }
@ -180,7 +180,7 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
text: '레퍼런스', text: '레퍼런스',
items: [ items: [
{ text: '사이트 구성', link: 'site-config' }, { text: '사이트 구성', link: 'site-config' },
{ text: '머리말 구성', link: 'frontmatter-config' }, { text: '전문(front-matter) 구성', link: 'frontmatter-config' },
{ text: '런타임 API', link: 'runtime-api' }, { text: '런타임 API', link: 'runtime-api' },
{ text: 'CLI', link: 'cli' }, { text: 'CLI', link: 'cli' },
{ {
@ -188,16 +188,16 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
base: '/ko/reference/default-theme-', base: '/ko/reference/default-theme-',
items: [ items: [
{ text: '개요', link: 'config' }, { text: '개요', link: 'config' },
{ text: '네비게이션', link: 'nav' }, { text: '네비게이션', link: 'nav' },
{ text: '사이드바', link: 'sidebar' }, { text: '사이드바', link: 'sidebar' },
{ text: '홈 페이지', link: 'home-page' }, { text: '홈 페이지', link: 'home-page' },
{ text: '푸터', link: 'footer' }, { text: '푸터', link: 'footer' },
{ text: '레이아웃', link: 'layout' }, { text: '레이아웃', link: 'layout' },
{ text: '배지', link: 'badge' }, { text: '배지(badge)', link: 'badge' },
{ text: '팀 페이지', link: 'team-page' }, { text: '팀 페이지', link: 'team-page' },
{ text: '이전 / 다음 링크', link: 'prev-next-links' }, { text: '이전/다음 링크', link: 'prev-next-links' },
{ text: '편집 링크', link: 'edit-link' }, { text: '편집 링크', link: 'edit-link' },
{ text: '마지막 업데이트 시간', link: 'last-updated' }, { text: '마지막 업데이트 날짜', link: 'last-updated' },
{ text: '검색', link: 'search' }, { text: '검색', link: 'search' },
{ text: '카본 광고', link: 'carbon-ads' } { text: '카본 광고', link: 'carbon-ads' }
] ]

@ -60,7 +60,7 @@ export const shared = defineConfig({
provider: 'algolia', provider: 'algolia',
options: { options: {
appId: '8J64VVRP8K', appId: '8J64VVRP8K',
apiKey: 'a18e2f4cc5665f6602c5631fd868adfd', apiKey: '52f578a92b88ad6abde815aae2b0ad7c',
indexName: 'vitepress', indexName: 'vitepress',
locales: { locales: {
...zhSearch, ...zhSearch,

@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* normal text font */ --vp-font-family-base: /* normal text font */
--vp-font-family-mono: /* code font */ --vp-font-family-mono: /* code font */

@ -255,7 +255,7 @@ Wraps in a <div class="vp-raw">
} }
``` ```
It uses [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config) under the hood. You can pass its options like this: It uses [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector) under the hood. You can pass its options like this:
```js ```js
postcssIsolateStyles({ postcssIsolateStyles({

@ -296,7 +296,7 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: 'Documentation' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',

@ -161,6 +161,12 @@ aside: false
The levels of header in the outline to display for the page. It's same as [config.themeConfig.outline.level](./default-theme-config#outline), and it overrides the value set in site-level config. The levels of header in the outline to display for the page. It's same as [config.themeConfig.outline.level](./default-theme-config#outline), and it overrides the value set in site-level config.
```yaml
---
outline: [2, 4]
---
```
### lastUpdated ### lastUpdated
- Type: `boolean | Date` - Type: `boolean | Date`

@ -103,10 +103,14 @@ interface Router {
*/ */
onBeforeRouteChange?: (to: string) => Awaitable<void | boolean> onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>
/** /**
* Called before the page component is loaded (after the history state is * Called before the page component is loaded (after the history state is updated).
* updated). Return `false` to cancel the navigation. * Return `false` to cancel the navigation.
*/ */
onBeforePageLoad?: (to: string) => Awaitable<void | boolean> onBeforePageLoad?: (to: string) => Awaitable<void | boolean>
/**
* Called after the page component is loaded (before the page component is updated).
*/
onAfterPageLoad?: (to: string) => Awaitable<void>
/** /**
* Called after the route changes. * Called after the route changes.
*/ */

@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* fuente de texto normal */ --vp-font-family-base: /* fuente de texto normal */
--vp-font-family-mono: /* fuente de código */ --vp-font-family-mono: /* fuente de código */

@ -289,7 +289,7 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: 'Documentation' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',

@ -1,54 +1,54 @@
# 자산 처리 {#asset-handling} # 에셋 핸들링 {#asset-handling}
## 정적 자산 참조하기 {#referencing-static-assets} ## 정적 에셋 참조하기 {#referencing-static-assets}
모든 Markdown 파일은 Vue 컴포넌트로 컴파일되며 [Vite](https://vitejs.dev/ko/guide/assets.html)에 의해 처리됩니다. 상대 URL을 사용하여 어떠한 자산도 참조할 수 **있으며 해야 합니다**: 모든 마크다운 파일은 Vue 컴포넌트로 컴파일되어 [Vite](https://vitejs.dev/guide/assets.html)에 의해 처리됩니다. 모든 에셋은 상대 URL을 사용하여 참조할 수 있으며, **참조해야 합니다**:
```md ```md
![이미지](./image.png) ![이미지](./image.png)
``` ```
Markdown 파일, 테마`*.vue` 컴포넌트, 스타일 및 일반 `.css` 파일에서 정적 자산참조할 수 있으며, 절대 공개 경로(프로젝트 루트를 기준으로) 또는 상대 경로(파일 시스템을 기준으로)를 사용할 수 있습니다. 후자는 Vite, Vue CLI 또는 webpack의 `file-loader`를 사용해 본 적이 있다면 익숙한 동작 방식과 유사합니다. 마크다운 파일에서 정적 에셋을 참조할 수 있으며, 테마 내`*.vue` 컴포넌트, 스타일 및 일반 `.css` 파일을 절대 경로(프로젝트 루트를 기준으로) 또는 상대 경로(파일 시스템을 기준으로)를 사용하여 참조할 수 있습니다. 후자는 Vite, Vue CLI 또는 webpack의 `file-loader` 동작과 유사합니다.
일반적인 이미지, 미디어, 폰트 파일 유형은 자동으로 자산으로 감지되어 포함됩니다. 일반적인 이미지, 미디어 및 글꼴 파일 형식은 자동으로 에셋으로 감지되어 포함됩니다.
::: tip 링크된 파일은 자산으로 취급되지 않음 ::: tip 링크를 통해 참조된 파일은 에셋으로 처리되지 않습니다
Markdown 파일 내의 링크로 참조된 PDF 또는 기타 문서는 자동으로 자산으로 취급되지 않습니다. 링크된 파일을 접근 가능하게 만들기 위해서는 수동으로 해당 파일을 프로젝트의 [`public`](#the-public-directory) 디렉토리에 배치해야 합니다. 마크다운 파일 내에서 링크로 참조된 PDF 또는 기타 문서는 자동으로 에셋으로 처리되지 않습니다. 링크된 파일을 접근 가능하게 하려면 프로젝트의 [`public`](#the-public-directory) 디렉토리에 수동으로 배치해야 합니다.
::: :::
절대 경로를 포함한 모든 참조된 자산은 생산 빌드에서 해시된 파일 이름으로 출력 디렉토리에 복사됩니다. 참조되지 않은 자산은 복사되지 않습니다. 4kb보다 작은 이미지 자산은 base64 인라인으로 처리됩니다 - 이는 [`vite`](../reference/site-config#vite) 구성 옵션을 통해 설정할 수 있습니다. 절대 경로를 사용하는 에셋을 포함하여 모든 참조된 에셋은 프로덕션 빌드에서 해시된 파일 이름으로 출력 디렉토리에 복사됩니다. 참조되지 않은 에셋은 복사되지 않습니다. 4kb보다 작은 이미지 에셋은 base64로 인라인됩니다. 이는 [`vite`](../reference/site-config#vite) 구성 옵션을 통해 구성할 수 있습니다.
모든 **정적** 경로 참조, 절대 경로를 포함하여, 작업 디렉토리 구조를 기반으로 해야 합니다. 모든 **정적** 경로 참조는 절대 경로를 포함하여 작업 디렉토리 구조를 기반으로 해야 합니다.
## Public 디렉리 {#the-public-directory} ## Public 디렉리 {#the-public-directory}
Markdown이나 테마 컴포넌트에서 직접 참조되지 않은 정적 자산을 제공할 필요가 있거나, 특정 파일을 원본 파일명으로 제공하고 싶은 경우가 있을 수 있습니다. 이러한 파일의 예로는 `robots.txt`, 파비콘, PWA 아이콘이 있습니다. 때때로 마크다운이나 테마 컴포넌트에서 직접 참조되지 않는 정적 에셋을 제공해야 하거나 특정 파일을 원래 파일 이름으로 제공하고 싶을 때가 있습니다. 이러한 파일의 예로는 `robots.txt`, 파비콘, PWA 아이콘이 있습니다.
이 파일들은 [소스 디렉토리](./routing#source-directory) 아래의 `public` 디렉토리에 배치할 수 있습니다. 예를 들어, 프로젝트 루트가 `./docs`이고 기본 소스 디렉토리 위치를 사용한다면, public 디렉토리는 `./docs/public`이 됩니다. 이 파일들은 [소스 디렉토리](./routing#source-directory) 아래의 `public` 디렉토리에 놓을 수 있습니다. 예를 들어 프로젝트 루트가 `./docs`이고 기본 소스 디렉토리 위치를 사용 중인 경우, `public` 디렉토리는 `./docs/public`이 됩니다.
`public`에 배치된 자산은 그대로 출력 디렉토리의 루트로 복사됩니다. `public`에 배치된 에셋은 출력 디렉토리의 루트로 그대로 복사됩니다.
`public`에 배치된 파일을 참조할 때는 루트 절대 경로를 사용해야 한다는 점에 유의하세요 - 예를 들어, `public/icon.png`는 소스 코드에서 항상 `/icon.png`로 참조되어야 합니다. `public`에 배치된 파일은 루트 절대 경로를 사용하여 참조해야 한다는 점에 유의하세요. 예를 들어, `public/icon.png`는 소스 코드에서 항상 `/icon.png`로 참조되어야 합니다.
## 기본 URL {#base-url} ## Base URL {#base-url}
사이트가 루트 URL이 아닌 곳에 배포되는 경우, `.vitepress/config.js`에서 `base` 옵션을 설정해야 합니다. 예를 들어, 사이트를 `https://foo.github.io/bar/`에 배포할 계획이라면, `base``'/bar/'`(항상 슬래시로 시작하고 끝나야 함)로 설정해야 합니다. 사이트가 루트 URL이 아닌 곳에 배포 경우, `.vitepress/config.js`에서 `base` 옵션을 설정해야 합니다. 예를 들어, 사이트를 `https://foo.github.io/bar/`에 배포하려는 경우 `base``'/bar/'`로 설정해야 합니다(항상 슬래시로 시작하고 끝나야 합니다).
모든 정적 자산 경로는 다양한 `base` 구성 값에 맞게 자동으로 처리됩니다. 예를 들어, 마크다운에서 `public` 아래에 있는 자산에 대한 절대 참조가 있는 경우: 모든 정적 에셋 경로는 다른 `base` 구성 값에 맞게 자동으로 처리됩니다. 예를 들어, 마크다운에서 `public` 하위의 에셋에 대한 절대 참조가 있는 경우:
```md ```md
![이미지](/image-inside-public.png) ![이미지](/image-inside-public.png)
``` ```
이 경우 `base` 구성 값을 변경하더라도 업데이트할 필요가 **없습니다**. 이 경우 `base` 구성 값을 변경할 때 **업데이트할 필요가 없습니다**.
그러나 자산을 동적으로 연결하는 테마 컴포넌트를 작성하는 경우, 예를 들어 테마 구성 값에 기반한 이미지의 `src`가 있는 경우: 그러나 테마 구성 값을 기반으로 `src`가 설정된 이미지와 같이 동적으로 에셋에 링크하는 테마 컴포넌트를 작성하는 경우:
```vue ```vue
<img :src="theme.logoPath" /> <img :src="theme.logoPath" />
``` ```
이 경우 VitePress에 제공되는 [`withBase` 헬퍼](../reference/runtime-api#withbase)로 경로를 래핑하는 것이 권장됩니다: 이 경우 VitePress에서 제공하는 [`withBase` 헬퍼](../reference/runtime-api#withbase)로 경로를 감싸는 것이 좋습니다:
```vue ```vue
<script setup> <script setup>

@ -4,13 +4,13 @@ outline: deep
# CMS에 연결하기 {#connecting-to-a-cms} # CMS에 연결하기 {#connecting-to-a-cms}
## 일반 워크플로우 {#general-workflow} ## 일반적인 워크플로우 {#general-workflow}
VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dynamic-routes)를 중심으로 진행될 것입니다. 진행하기 전에 이것이 어떻게 작동하는지 이해하는 것이 중요합니다. VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dynamic-routes)를 중심으로 이루어질 것입니다. 진행하기 전에 작동 방식을 이해해야 합니다.
각 CMS는 다르게 작동하기 때문에, 여기서는 특정 상황에 맞게 조정해야 할 일반적인 워크플로우만 제공할 수 있습니다. 각 CMS가 다르게 작동하므로, 여기서는 특정 상황에 맞게 조정해야 하는 일반적인 워크플로우만 제공할 수 있습니다.
1. CMS에서 인증이 필요한 경우, API 토큰을 저장할 `.env` 파일을 만들고 다음과 같이 로드하세요: 1. CMS가 인증을 요구하는 경우, `.env` 파일을 생성하여 API 토큰을 저장하고 다음과 같이 로드하세요:
```js ```js
// posts/[id].paths.js // posts/[id].paths.js
@ -19,15 +19,15 @@ VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dyna
const env = loadEnv('', process.cwd()) const env = loadEnv('', process.cwd())
``` ```
2. CMS에서 필요한 데이터를 가져와 적절한 경로 데이터로 포맷하세요: 2. CMS에서 필요한 데이터를 가져와 적절한 경로 데이터로 형식을 지정하세요:
```js ```js
export default { export default {
async paths() { async paths() {
// 필요시 각 CMS 클라이언트 라이브러리 사용 // 필요한 경우 해당 CMS 클라이언트 라이브러리 사용
const data = await (await fetch('https://my-cms-api', { const data = await (await fetch('https://my-cms-api', {
headers: { headers: {
// 필요한 경우 토큰 // 필요한 경우 토큰을 사용
} }
})).json() })).json()
@ -41,16 +41,16 @@ VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dyna
} }
``` ```
3. 페이지에서 콘텐츠를 렌더링하세요: 3. 페이지의 컨텐츠를 렌더링하세요:
```md ```md
# {{ $params.title }} # {{ $params.title }}
- {{ $params.author }}에 의해 {{ $params.date }}에 - 작성자: {{ $params.author }}, 작성일: {{ $params.date }}
<!-- @content --> <!-- @content -->
``` ```
## 통합 가이드 {#integration-guides} ## 통합 가이드 {#integration-guides}
VitePress와 특정 CMS의 통합에 대한 가이드를 작성한 경우, 아래 "이 페이지 편집" 링크를 사용하여 여기에 제출하세요! VitePress를 특정 CMS와 통합하는 방법에 대한 가이드를 작성한 경우 아래의 "이 페이지 편집 제안하기" 링크를 클릭하여 여기에 제출하세요!

@ -1,8 +1,8 @@
# 사용자 정의 테마 사용하기 {#using-a-custom-theme} # 커스텀 테마 사용하기 {#using-a-custom-theme}
## 테마 해결 {#theme-resolving} ## 테마 사용법 {#theme-resolving}
`.vitepress/theme/index.js` 또는 `.vitepress/theme/index.ts` 파일(“테마 엔트리 파일”)을 생성하여 사용자 정의 테마를 활성화할 수 있습니다: `.vitepress/theme/index.js` 또는 `.vitepress/theme/index.ts` 파일("테마 엔트리 파일")을 생성하여 커스텀 테마를 활성화할 수 있습니다:
``` ```
. .
@ -10,50 +10,50 @@
│ ├─ .vitepress │ ├─ .vitepress
│ │ ├─ theme │ │ ├─ theme
│ │ │ └─ index.js # 테마 엔트리 │ │ │ └─ index.js # 테마 엔트리
│ │ └─ config.js # 설정 파일 │ │ └─ config.js # 구성 파일
│ └─ index.md │ └─ index.md
└─ package.json └─ package.json
``` ```
VitePress는 테마 엔트리 파일의 존재를 감지하면 기본 테마 대신 항상 사용자 정의 테마를 사용합니다. 하지만 [기본 테마를 확장하여](./extending-default-theme) 그 위에 고급 사용자 정의를 수행할 수 있습니다. VitePress는 테마 엔트리 파일이 존재를 감지하면 기본 테마 대신 커스텀 테마를 사용합니다. 아니면 [기본 테마 확장하기](./extending-default-theme)를 통해 이를 기반으로 고급 커스터마이징을 수행할 수 있습니다.
## 테마 인터페이스 {#theme-interface} ## 테마 인터페이스 {#theme-interface}
VitePress 사용자 정의 테마는 다음 인터페이스를 가진 객체로 정의됩니다: VitePress 커스텀 테마는 아래와 같은 인터페이스 객체로 정의됩니다:
```ts ```ts
interface Theme { interface Theme {
/** /**
* 모든 페이지의 루트 레이아웃 컴포넌트 * 모든 페이지의 루트 레이아웃 컴포넌트
* @필수 * @required
*/ */
Layout: Component Layout: Component
/** /**
* Vue 앱 인스턴스 개선 * Vue 애플리케이션 인스턴스 추가조작 (의역: "enhance → 추가조작")
* @선택적 * @optional
*/ */
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void> enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
/** /**
* 다른 테마 확장, 우리의 `enhanceApp` 전에 호출 * 현재 `enhanceApp`를 호출하기 전, 다른 테마를 먼저 확장
* @선택적 * @optional
*/ */
extends?: Theme extends?: Theme
} }
interface EnhanceAppContext { interface EnhanceAppContext {
app: App // Vue 인스턴스 app: App // Vue 애플리케이션 인스턴스
router: Router // VitePress 라우터 인스턴스 router: Router // VitePress 라우터 인스턴스
siteData: Ref<SiteData> // 사이트 수준 메타데이터 siteData: Ref<SiteData> // 사이트 수준 메타데이터
} }
``` ```
테마 엔트리 파일은 테마를 기본으로 내보내야 합니다: 테마 엔트리 파일은 테마(Theme 객체)를 "export default" 해야 합니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
// 테마 엔트리에서 Vue 파일을 직접 가져올 수 있습니다 // 테마 엔트리에서 Vue 파일을 직접 "import" 할 수 있습니다.
// VitePress는 @vitejs/plugin-vue로 미리 설정되어 있습니다. // VitePress는 @vitejs/plugin-vue가 사전 구성되어 있습니다.
import Layout from './Layout.vue' import Layout from './Layout.vue'
export default { export default {
@ -64,25 +64,25 @@ export default {
} }
``` ```
기본 내보내기는 사용자 정의 테마에 대한 유일한 계약이며, `Layout` 속성만 필수입니다. 기술적으로, VitePress 테마는 단일 Vue 컴포넌트만큼 간단할 수 있습니다. "export default"는 커스텀 테마를 설정하는 유일한 방법이며, `Layout` 프로퍼티만 필수입니다. 따라서 기술적으로 VitePress 테마는 단일 Vue 컴포넌트처럼 간단할 수 있습니다.
레이아웃 컴포넌트 내부에서는 평소처럼 Vite + Vue 3 애플리케이션처럼 작동합니다. 테마도 [SSR-호환성이](./ssr-compat) 있어야 합니다. 레이아웃 컴포넌트 내부에서는 일반적인 Vite + Vue 3 애플리케이션처럼 동작합니다. 또한 테마가 [SSR 호환](./ssr-compat)이 되어야 합니다.
## 레이아웃 만들기 {#building-a-layout} ## 레이아웃 만들기 {#building-a-layout}
가장 기본적인 레이아웃 컴포넌트는 [`<Content />`](../reference/runtime-api#content) 컴포넌트를 포함해야 합니다: 가장 기본적인 레이아웃 컴포넌트는 [`<Content />`](../reference/runtime-api#content) 컴포넌트가 포함되어야 합니다:
```vue ```vue
<!-- .vitepress/theme/Layout.vue --> <!-- .vitepress/theme/Layout.vue -->
<template> <template>
<h1>사용자 정의 레이아웃!</h1> <h1>Custom Layout!</h1>
<!-- 마크다운 내용 여기에 렌더링됩니다 --> <!-- 마크다운 내용 여기에 렌더링됩니다 -->
<Content /> <Content />
</template> </template>
``` ```
위의 레이아웃은 각 페이지의 마크다운을 HTML로 단순히 렌더링합니다. 우리가 추가할 수 있는 첫 번째 개선 사항은 404 오류를 처리하는 것입니다: 위의 레이아웃은 각 페이지의 마크다운을 HTML로 렌더링합니다. 첫 번째로 개선 사항은 404 에러를 처리하는 것입니다:
```vue{1-4,9-12} ```vue{1-4,9-12}
<script setup> <script setup>
@ -91,16 +91,16 @@ const { page } = useData()
</script> </script>
<template> <template>
<h1>사용자 정의 레이아웃!</h1> <h1>Custom Layout!</h1>
<div v-if="page.isNotFound"> <div v-if="page.isNotFound">
사용자 정의 404 페이지! Custom 404 page!
</div> </div>
<Content v-else /> <Content v-else />
</template> </template>
``` ```
[`useData()`](../reference/runtime-api#usedata) 헬퍼는 우리가 필요로 하는 모든 런타임 데이터를 제공하여, 다른 레이아웃을 조건부로 렌더링할 수 있습니다. 우리가 접근할 수 있는 또 다른 데이터는 현재 페이지의 프론트매터입니다. 이를 활용하여 사용자가 각 페이지의 레이아웃을 제어할 수 있도록 합니다. 예를 들어, 사용자는 특별한 홈페이지 레이아웃을 사용해야 한다고 지정할 수 있습니다: [`useData()`](../reference/runtime-api#usedata) 헬퍼는 다양한 레이아웃을 조건부로 렌더링하는 데 필요한 모든 런타임 데이터를 제공합니다. 접근할 수 있는 다른 데이터 중 하나는 현재 페이지의 전문(front-matter)입니다. 이를 활용하여 각 페이지에 맞게 레이아웃을 제어할 수 있습니다. 예를 들어 특정 페이지에서 홈 페이지 레이아웃을 사용하도록 지정할 수 있습니다:
```md ```md
--- ---
@ -108,7 +108,7 @@ layout: home
--- ---
``` ```
그리고 우리는 이를 처리하기 위해 테마를 조정할 수 있습니다: 그리고 이를 처리하도록 테마를 조정할 수 있습니다:
```vue{3,12-14} ```vue{3,12-14}
<script setup> <script setup>
@ -117,19 +117,19 @@ const { page, frontmatter } = useData()
</script> </script>
<template> <template>
<h1>사용자 정의 레이아웃!</h1> <h1>Custom Layout!</h1>
<div v-if="page.isNotFound"> <div v-if="page.isNotFound">
사용자 정의 404 페이지! Custom 404 page!
</div> </div>
<div v-if="frontmatter.layout === 'home'"> <div v-if="frontmatter.layout === 'home'">
사용자 정의 홈 페이지! Custom home page!
</div> </div>
<Content v-else /> <Content v-else />
</template> </template>
``` ```
물론, 레이아웃을 더 많은 컴포넌트로 나눌 수 있습니다: 물론 레이아웃을 더 많은 컴포넌트로 나눌 수 있습니다:
```vue{3-5,12-15} ```vue{3-5,12-15}
<script setup> <script setup>
@ -142,35 +142,35 @@ const { page, frontmatter } = useData()
</script> </script>
<template> <template>
<h1>사용자 정의 레이아웃!</h1> <h1>Custom Layout!</h1>
<NotFound v-if="page.isNotFound" /> <NotFound v-if="page.isNotFound" />
<Home v-if="frontmatter.layout === 'home'" /> <Home v-if="frontmatter.layout === 'home'" />
<Page v-else /> <!-- <Page />는 <Content />를 렌더링합니다 --> <Page v-else /> <!-- <Page /> 는 <Content /> 를 렌더링합니다 -->
</template> </template>
``` ```
테마 컴포넌트에서 사용할 수 있는 모든 것에 대한 [런타임 API 참조](../reference/runtime-api)를 참조하세요. 또한, [빌드할 때 데이터 로딩](./data-loading)을 활용하여 데이터 기반 레이아웃을 생성할 수 있습니다 - 예를 들어, 현재 프로젝트 내 모든 블로그 포스트를 나열하는 페이지 등. 테마 컴포넌트에서 사용할 수 있는 모든 항목에 대해서는 [런타임 API 레퍼런스](../reference/runtime-api)를 참고하세요. 또한 [빌드할 때 데이터 로딩하기](./data-loading)를 활용하여 데이터 기반의 레이아웃을 생성할 수 있습니다. 예를 들어 현재 프로젝트의 모든 블로그 게시물을 나열하는 페이지를 만들 수 있습니다.
## 사용자 정의 테마 배포하기 {#distributing-a-custom-theme} ## 사용자 정의 테마 배포하기 {#distributing-a-custom-theme}
사용자 정의 테마를 배포하는 가장 쉬운 방법은 [GitHub에서 템플릿 저장소로 제공하는 것입니다](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository). 커스텀 테마를 배포하는 가장 쉬운 방법은 [GitHub 템플릿 리포지토리](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository)로 제공하는 것입니다.
npm 패키지로 테마를 배포하려면 다음 단계를 따르세요: 테마를 npm 패키지로 배포하려면 다음 단계를 따라야 합니다:
1. 패키지 엔트리에서 테마 객체를 기본 내보내기로 내보냅니다. 1. 패키지 엔트리에서 테마 객체를 "export default" 합니다.
2. 적용된다면, 테마 설정 타입 정의를 `ThemeConfig`로 내보냅니다. 2. 해당되는 경우, 테마 구성 타입 정의를 `ThemeConfig`로 "export" 합니다.
3. 테마가 VitePress 설정을 조정해야 하는 경우, 사용자가 확장할 수 있도록 패키지 하위 경로(예: `my-theme/config`)에 해당 설정을 내보냅니다. 3. 테마에서 VitePress 구성을 조정해야 하는 경우, 사용자가 확장할 수 있도록 패키지 하위 경로(예: `my-theme/config`)에 해당 구성을 "export" 합니다.
4. 설정 파일 및 프론트매터를 통한 테마 설정 옵션을 문서화합니다. 4. 테마 구성 옵션을 문서화합니다 (구성 파일과 전문 둘 다).
5. 테마를 소비하는 방법에 대한 명확한 지침을 제공합니다(아래 참조). 5. 테마를 사용하는 방법에 대한 명확한 지침을 제공합니다 (아래 참조).
## 사용자 정의 테마 소비하기 {#consuming-a-custom-theme} ## 커스텀 테마 사용하기 {#consuming-a-custom-theme}
외부 테마를 소비하려면 사용자 정의 테마 엔트리에서 가져와서 다시 내보냅니다: 외부 테마를 사용하려면, 커스텀 테마 엔트리에서 테마를 "import" 후 다시 "export"합니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -193,19 +193,19 @@ export default {
} }
``` ```
테마가 특별한 VitePress 설정을 요구하는 경우, 자신의 설정에서도 그 설정을 확장해야 합니다: 테마가 특별한 VitePress 구성을 요구하는 경우, 해당 구성을 (외부 커스텀 테마를 사용하는 자신의) 구성 파일에서도 확장해야 합니다:
```ts ```ts
// .vitepress/config.ts // .vitepress/config.ts
import baseConfig from 'awesome-vitepress-theme/config' import baseConfig from 'awesome-vitepress-theme/config'
export default { export default {
// 필요한 경우 테마 기본 설정 확장 // 필요한 경우 테마 기본 구성 확장
extends: baseConfig extends: baseConfig
} }
``` ```
마지막으로, 테마가 테마 설정에 대한 타입을 제공하는 경우: 마지막으로 테마가 테마 구성에 대한 타입을 제공하는 경우:
```ts ```ts
// .vitepress/config.ts // .vitepress/config.ts

@ -1,12 +1,12 @@
# 빌드할 때 데이터 로딩 {#build-time-data-loading} # 빌드할 때 데이터 로딩하기 {#build-time-data-loading}
VitePress는 **데이터 로더**라고 불리는 기능을 제공하여 임의의 데이터를 로드하고 페이지나 컴포넌트에서 가져올 수 있습니다. 데이터 로딩은 **빌드 시간에만 실행**됩니다: 결과적으로 생성된 데이터는 최종 자바스크립트 번들에 JSON으로 직렬화됩니다. VitePress는 페이지나 컴포넌트에서 임의의 데이터를 로드하고 이를 가져올 수 있는 **데이터 로더** 기능을 제공합니다. 데이터 로딩은 **빌드할 때에만** 실행되며, 결과적으로 생성된 데이터는 최종 JavaScript 번들에 JSON으로 직렬화됩니다.
데이터 로더는 원격 데이터를 가져오거나 로컬 파일을 기반으로 메타데이터를 생성하는 데 사용할 수 있습니다. 예를 들어, 모든 로컬 API 페이지를 파싱하고 모든 API 항목의 색인을 자동으로 생성하기 위해 데이터 로더를 사용할 수 있습니다. 데이터 로더는 원격 데이터를 가져오거나 로컬 파일을 기반으로 메타데이터를 생성하는 데 사용할 수 있습니다. 예를 들어, 데이터 로더를 사용하여 모든 로컬 API 페이지를 파싱하고 모든 API 항목의 색인을 자동으로 생성할 수 있습니다.
## 기본 사용법 {#basic-usage} ## 기본 사용법 {#basic-usage}
데이터 로더 파일은 `.data.js` 또는 `.data.ts`로 끝나야 합니다. 이 파일은 `load()` 메서드를 가진 객체를 기본 내보내기해야 합니다: 데이터 로더 파일은 반드시 `.data.js` 또는 `.data.ts`로 끝나야 합니다. 이 파일은 `load()` 메서드를 가진 객체를 "export default" 해야 합니다:
```js ```js
// example.data.js // example.data.js
@ -19,9 +19,9 @@ export default {
} }
``` ```
로더 모듈은 Node.js에서만 평가되므로, 필요에 따라 Node API와 npm 종속성을 가져올 수 있습니다. 로더 모듈은 Node.js에서만 평가되므로, 필요한 경우 Node API와 npm 종속성을 "import" 할 수 있습니다.
이 파일에서 데이터를 `.md` 페이지와 `.vue` 컴포넌트에서 `data`라는 이름으로 내보낼 수 있습니다: 그런 다음 `.md` 페이지와 `.vue` 컴포넌트에서 `data`라는 이름으로 "export" 한 데이터를 이 파일에서 "import" 할 수 있습니다:
```vue ```vue
<script setup> <script setup>
@ -39,9 +39,9 @@ import { data } from './example.data.js'
} }
``` ```
데이터 로더 자체가 `data`내보내지 않는 것을 알 수 있습니다. 이는 VitePress가 내부에서 `load()` 메서드를 호출하고 `data`라는 이름으로 결과를 암시적으로 노출한다는 것을 의미합니다. 데이터 로더 자체가 `data`"export" 하지 않는다는 점에 주목하십시오. VitePress가 백그라운드에서 `load()` 메서드를 호출하고 결과를 암묵적으로 `data`라는 이름으로 "export" 하기 때문입니다.
로더가 비동기인 경우에도 작동합니다: 이 방법은 로더가 비동기적이어도 작동합니다:
```js ```js
export default { export default {
@ -54,11 +54,11 @@ export default {
## 로컬 파일에서 데이터 가져오기 {#data-from-local-files} ## 로컬 파일에서 데이터 가져오기 {#data-from-local-files}
로컬 파일을 기반으로 데이터를 생성해야 할 때는 데이터 로더에서 `watch` 옵션을 사용해야 합니다. 그래야 해당 파일에 변경 사항이 발생했을 때 핫 업데이트를 트리거할 수 있습니다. 로컬 파일을 기반으로 데이터를 생성해야 할 때는 데이터 로더에서 `watch` 옵션을 사용해야 합니다. 이 옵션을 사용하면 이러한 파일에 변경이 있을 때 핫 업데이트를 트리거할 수 있습니다.
`watch` 옵션은 또한 여러 파일을 일치시키기 위해 [글로브 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)을 사용할 수 있어 편리합니다. 패턴은 로더 파일 자체에 상대적이며, `load()` 함수는 일치한 파일을 절대 경로로 받습니다. `watch` 옵션은 또한 여러 파일을 매칭하는 [glob 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)을 사용할 수 있어 편리합니다. 패턴은 로더 파일 자체에 상대적일 수 있으며, `load()` 함수는 매칭된 파일을 절대 경로로 받게 됩니다.
다음 예제는 [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/)를 사용하여 CSV 파일을 불러오고 JSON으로 변환하는 방법을 보여줍니다. 이 파일은 빌드 시간에만 실행되므로, CSV 파서를 클라이언트에 전송하지 않을 것입니다! 다음 예제는 CSV 파일을 로드하고 이를 [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/)를 사용하여 JSON으로 변환하는 방법을 보여줍니다. 이 파일은 빌드할 때에만 실행되므로 CSV 파서를 클라이언트로 전송하지 않습니다!
```js ```js
import fs from 'node:fs' import fs from 'node:fs'
@ -67,9 +67,9 @@ import { parse } from 'csv-parse/sync'
export default { export default {
watch: ['./data/*.csv'], watch: ['./data/*.csv'],
load(watchedFiles) { load(watchedFiles) {
// watchedFiles는 일치하는 파일의 절대 경로 배열이 될 것입니다. // watchedFiles는 매칭된 파일의 절대 경로 배열 입니다.
// 블로그 포스트 메타데이터의 배열을 생성하여 // 테마 레이아웃에서 목록을 렌더링하는 데 사용할 수 있는
// 테마 레이아웃에서 목록을 렌더링하는 데 사용할 수 있습니다 // 블로그 포스트 메타데이터 배열을 생성합니다.
return watchedFiles.map((file) => { return watchedFiles.map((file) => {
return parse(fs.readFileSync(file, 'utf-8'), { return parse(fs.readFileSync(file, 'utf-8'), {
columns: true, columns: true,
@ -82,38 +82,38 @@ export default {
## `createContentLoader` ## `createContentLoader`
콘텐츠 중심 사이트를 구축할 때, 우리는 종종 "아카이브" 또는 "인덱스" 페이지를 만들 필요가 있습니다: 우리 콘텐츠 컬렉션에서 사용 가능한 모든 항목을 나열하는 페이지, 예를 들어 블로그 게시물이나 API 페이지의 경우입니다. 데이터 로더 API를 직접 사용하여 이를 구현할 **수 있지만**, 이는 흔한 사용 사례이므로 VitePress는 이를 단순화하기 위해 `createContentLoader` 헬퍼를 제공합니다: 콘텐츠가 많은 사이트를 구축할 때, 종종 "아카이브" 또는 "인덱스" 페이지를 만들어야 합니다. 이 페이지는 콘텐츠 모음에 있는 모든 항목(예: 블로그 게시물, API 페이지)을 나열하는 페이지입니다. 데이터 로더 API를 직접 사용하여 이를 구현할 수 있지만, VitePress는 이러한 일반적인 사용 사례를 간소화하기 위해 `createContentLoader` 헬퍼를 제공합니다:
```js ```js
// posts.data.js // posts.data.js
import { createContentLoader } from 'vitepress' import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', /* 옵션 */) export default createContentLoader('posts/*.md', /* options */)
``` ```
헬퍼는 [소스 디렉토리](./routing#source-directory)에 상대적인 글로브 패턴을 취하며, 기본 내보내기로 사용할 수 있는 `{ watch, load }` 데이터 로더 객체를 반환합니다. 이는 또한 파일 수정 타임스탬프를 기반으로 캐싱을 구현하여 개발 성능을 향상시킵니다. 이 헬퍼는 [소스 디렉터리](./routing#source-directory)를 기준으로 glob 패턴을 허용하고 데이터 로드 파일에서 "default export"로 사용할 수 있는 `{ watch, load }` 데이터 로더 객체를 반환합니다. 또한 파일 수정 타임스탬프를 기반으로 캐싱을 구현하여 개발 성능을 향상시킵니다.
로더는 마크다운 파일과만 작동합니다 - 마크다운이 아닌 일치하는 파일은 건너뜁니다. 참고로 로더는 마크다운 파일에서만 작동하며, 매칭되는 마크다운이 아닌 파일은 건너뜁니다.
로드된 데이터는 `ContentData[]` 타입의 배열일 것입니다: 로드된 데이터는 `ContentData[]` 타입의 배열입니다:
```ts ```ts
interface ContentData { interface ContentData {
// 페이지 매핑된 URL입니다. 예: /posts/hello.html (base는 포함하지 않음) // 페이지 매핑된 URL입니다. 예: /posts/hello.html (base는 포함하지 않음)
// 수동으로 반복하거나 사용자 정의 `transform`을 사용하여 경로를 정규화하세요 // 수동으로 반복하거나 커스텀 `transform`을 사용하여 경로를 정규화.
url: string url: string
// 페이지의 프론트매터 데이터 // 페이지의 전문(front-matter) 데이터
frontmatter: Record<string, any> frontmatter: Record<string, any>
// 다음은 관련 옵션이 활성화되어 있을 때만 존재합니다 // 다음은 관련 옵션이 활성화된 경우에만 나타납니다.
// 아래에서 이에 대해 논의할 것입니다 // 아래에서 이에 대해 논의할 것입니다.
src: string | undefined src: string | undefined
html: string | undefined html: string | undefined
excerpt: string | undefined excerpt: string | undefined
} }
``` ```
기본적으로 `url``frontmatter`만 제공됩니다. 로드된 데이터는 클라이언트 번들에 JSON으로 인라인되기 때문에 크기에 대해 신중해야 합니다. 다음은 데이터를 사용하여 최소한의 블로그 인덱스 페이지를 구축하는 예입니다: 기본적으로 `url``frontmatter`만 제공됩니다. 이는 로드된 데이터가 클라이언트 번들에 JSON으로 인라인되기 때문에 크기에 주의해야 합니다. 다음은 데이터를 사용하여 최소한의 블로그 인덱스 페이지를 구축하는 예입니다:
```vue ```vue
<script setup> <script setup>
@ -121,7 +121,7 @@ import { data as posts } from './posts.data.js'
</script> </script>
<template> <template>
<h1>모든 블로그 게시물</h1> <h1>All Blog Posts</h1>
<ul> <ul>
<li v-for="post of posts"> <li v-for="post of posts">
<a :href="post.url">{{ post.frontmatter.title }}</a> <a :href="post.url">{{ post.frontmatter.title }}</a>
@ -133,34 +133,34 @@ import { data as posts } from './posts.data.js'
### 옵션 {#options} ### 옵션 {#options}
기본 데이터가 모든 요구 사항에 맞지 않을 수 있습니다 - 옵션을 사용하여 데이터를 변환할 수 있습니다: 기본 데이터가 모든 요구 사항에 충족하지 않을 수 있습니다. 옵션을 사용하여 데이터를 변환할 수 있습니다:
```js ```js
// posts.data.js // posts.data.js
import { createContentLoader } from 'vitepress' import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', { export default createContentLoader('posts/*.md', {
includeSrc: true, // 원시 마크다운 소스를 포함시킬까요? includeSrc: true, // 원시 마크다운 소스를 포함까요?
render: true, // 완성된 전체 페이지 HTML을 렌더링하여 포함시킬까요? render: true, // 렌더링된 전체 페이지 HTML을 포함할까요?
excerpt: true, // 발췌문을 포함시킬까요? excerpt: true, // 발췌문을 포함까요?
transform(rawData) { transform(rawData) {
// 원하는 대로 원시 데이터를 매핑, 정렬 또는 필터링하세요. // 필요에 따라 원시 데이터를 매핑, 정렬 또는 필터링.
// 최종 결과가 클라이언트에 전송될 것입니다. // 최종 결과를 클라이언트에 전달.
return rawData.sort((a, b) => { return rawData.sort((a, b) => {
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date) return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
}).map((page) => { }).map((page) => {
page.src // 원시 마크다운 소스 page.src // 원시 마크다운 소스
page.html // 렌더링된 전체 페이지 HTML page.html // 렌더링된 전체 페이지 HTML
page.excerpt // 렌더링된 발췌문 HTML (`---` 위의 내용) page.excerpt // 렌더링된 발췌문 HTML (첫 번째 `---` 위에 있는 내용)
return {/* ... */} return {/* ... */}
}) })
} }
}) })
``` ```
[Vue.js 블로그](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)에서 사용되는 방법을 확인하세요. [Vue.js 블로그](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)에서 어떻게 사용되었는지 확인해보세요.
`createContentLoader` API는 [빌드 후크](../reference/site-config#build-hooks) 내에서도 사용될 수 있습니다: `createContentLoader` API는 [빌드 훅](../reference/site-config#build-hooks) 내에서도 사용할 수 있습니다:
```js ```js
// .vitepress/config.js // .vitepress/config.js
@ -168,6 +168,7 @@ export default {
async buildEnd() { async buildEnd() {
const posts = await createContentLoader('posts/*.md').load() const posts = await createContentLoader('posts/*.md').load()
// 포스트 메타데이터를 기반으로 파일 생성하기, 예: RSS 피드 // 포스트 메타데이터를 기반으로 파일 생성하기, 예: RSS 피드
// 게시물 메타데이터를 기반으로 파일 생성, 예: RSS 피드
} }
} }
``` ```
@ -177,23 +178,23 @@ export default {
```ts ```ts
interface ContentOptions<T = ContentData[]> { interface ContentOptions<T = ContentData[]> {
/** /**
* src를 포함시킬까요? * src를 포함까요?
* @default false * @default false
*/ */
includeSrc?: boolean includeSrc?: boolean
/** /**
* src를 HTML로 렌더링하고 데이터에 포함시킬까요? * src를 HTML로 렌더링하고 데이터에 포함까요?
* @default false * @default false
*/ */
render?: boolean render?: boolean
/** /**
* `boolean`인 경우, 발췌문을 구문 분석하고 포함할지 여부입니다. (HTML로 렌더링됨) * `boolean` 타입인 경우, 발췌문을 파싱하고 포함할지 여부를 나타냅니다. (HTML로 렌더링됨)
* *
* `function`인 경우, 콘텐츠에서 발췌문이 추출되는 방식을 제어합니다. * `function` 타입인 경우, 콘텐츠에서 발췌문을 추출하는 방법을 제어합니다.
* *
* `string`인 경우, 발췌문을 추출하는 데 사용되는 사용자 정의 구분자를 정의합니다. * `string` 타입인 경우, 발췌문을 추출하는 데 사용할 커스텀 구분자를 정의합니다.
* `excerpt``true`인 경우 기본 구분자는 `---`입니다. * `excerpt``true`인 경우 기본 구분자는 `---`입니다.
* *
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt * @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt
@ -207,16 +208,16 @@ interface ContentOptions<T = ContentData[]> {
| string | string
/** /**
* 데이터를 변환하십시오. 컴포넌트나 마크다운 파일에서 가져올 경우, * 데이터를 변환합니다. 데이터는 컴포넌트나 마크다운 파일에서 가져올 경우,
* 데이터는 클라이언트 번들에 JSON으로 인라인될 것입니다. * 클라이언트 번들에 JSON으로 포함됩니다.
*/ */
transform?: (data: ContentData[]) => T | Promise<T> transform?: (data: ContentData[]) => T | Promise<T>
} }
``` ```
## 타입된 데이터 로더 {#typed-data-loaders} ## 데이터 로더의 "export" 타입 {#typed-data-loaders}
TypeScript를 사용할 때, 다음과 같이 로더와 `data` 내보내기를 타입할 수 있습니다: TypeScript를 사용할 때, 로더와 `data` "export"를 다음과 같이 타입 지정할 수 있습니다:
```ts ```ts
import { defineLoader } from 'vitepress' import { defineLoader } from 'vitepress'
@ -229,7 +230,7 @@ declare const data: Data
export { data } export { data }
export default defineLoader({ export default defineLoader({
// 타입 검사된 로더 옵션 // type checked loader options
watch: ['...'], watch: ['...'],
async load(): Promise<Data> { async load(): Promise<Data> {
// ... // ...
@ -239,7 +240,7 @@ export default defineLoader({
## 구성 {#configuration} ## 구성 {#configuration}
로더 내부에서 구성 정보를 가져오려면 다음과 같은 코드를 사용할 수 있습니다: 로더 내부에서 구성 정보를 가져오려면 다음과 같이 코드를 사용해야 합니다:
```ts ```ts
import type { SiteConfig } from 'vitepress' import type { SiteConfig } from 'vitepress'

@ -4,11 +4,11 @@ outline: deep
# VitePress 사이트 배포하기 {#deploy-your-vitepress-site} # VitePress 사이트 배포하기 {#deploy-your-vitepress-site}
다음 가이드는 몇 가지 공유된 가정을 바탕으로 합니다: 다음 가이드는 몇 가지 공통된 가정을 기반으로 합니다:
- VitePress 사이트는 프로젝트의 `docs` 디렉토리 안에 있습니다. - VitePress 사이트는 프로젝트의 `docs` 디렉토리 안에 있다.
- 기본 빌드 출력 디렉토리(`.vitepress/dist`)를 사용하고 있습니다. - 기본 빌드 출력 디렉토리(`.vitepress/dist`)를 사용하고 있다.
- VitePress를 프로젝트의 로컬 의존성으로 설치했으며, `package.json`에 다음 스크립트를 설정했습니다: - VitePress는 프로젝트의 로컬 종속성으로 설치되어 있으며, `package.json`에 다음 스크립트가 설정되어 있다:
```json ```json
{ {
@ -33,9 +33,9 @@ outline: deep
$ npm run docs:preview $ npm run docs:preview
``` ```
`preview` 명령어는 `.vitepress/dist` 출력 디렉토리를 `http://localhost:4173`에서 제공하는 로컬 정적 웹 서버를 부팅합니다. 이를 사용하여 프로덕션에 푸시하기 전에 모든 것이 잘 보이는지 확인할 수 있습니다. `preview` 명령은 출력 디렉토리 `.vitepress/dist``http://localhost:4173`에서 제공할 것입니다. 이를 사용하여 프로덕션에 푸시하기 전에 모든 것이 잘 보이는지 확인할 수 있습니다.
3. `--port`를 전달하여 서버의 포트를 구성할 수 있습니다. 3. `--port`를 전달하여 서버의 포트를 구성할 수 있습니다.
```json ```json
{ {
@ -45,21 +45,21 @@ outline: deep
} }
``` ```
이제 `docs:preview`드가 `http://localhost:8080`에서 서버를 시작합니다. 이제 `docs:preview`드가 `http://localhost:8080`에서 서버를 시작합니다.
## public 기본 경로 설정하기 {#setting-a-public-base-path} ## public 기본 경로 설정하기 {#setting-a-public-base-path}
기본적으로, 사이트가 도메인의 루트 경로(`/`)에서 배포될 것으로 가정합니다. 사이트가 하위 경로, 예를 들어 `https://mywebsite.com/blog/`에서 제공되는 경우, VitePress 구성에서 [`base`](../reference/site-config#base) 옵션을 `'/blog/'`로 설정해야 합니다. 기본적으로 사이트가 도메인의 루트 경로(`/`)에 배포된다고 가정합니다. 예를 들어 사이트가 `https://mywebsite.com/blog/` 와 같은 서브 경로에서 제공될 경우, VitePress 구성에서 [`base`](../reference/site-config#base) 옵션을 `'/blog/'`로 설정해야 합니다.
**예:** GitHub(또는 GitLab) 페이지를 사용하여 `user.github.io/repo/` 배포하는 경우, `base``/repo/`로 설정하세요. **예**: Github(또는 GitLab) Pages를 사용하여 `user.github.io/repo/` 배포하는 경우, `base``/repo/`로 설정하세요.
## HTTP 캐시 헤더 {#http-cache-headers} ## HTTP 캐시 헤더 {#http-cache-headers}
프로덕션 서버에서 HTTP 헤더를 제어할 수 있다면, 반복 방문 시 성능을 향상시키기 위해 `cache-control` 헤더를 구성할 수 있습니다. 프로덕션 서버에서 HTTP 헤더를 제어할 수 있다면, 반복 방문 시 더 나은 성능을 위해 `cache-control` 헤더를 구성할 수 있습니다.
프로덕션 빌드는 정적 자산(JavaScript, CSS, `public`에 있지 않은 다른 가져온 자산)을 위해 해시된 파일 이름을 사용합니다. 브라우저 개발 도구의 네트워크 탭을 사용하여 프로덕션 미리보기를 검사하면, `app.4f283b18.js`와 같은 파일을 볼 수 있습니다. 프로덕션 빌드는 정적 자산(JavaScript, CSS, `public`가 아닌 곳에서 가져온 에셋)에 대해 해시된 파일 이름을 사용합니다. 브라우저 개발 도구의 네트워크 탭을 사용하여 프로덕션 미리보기를 검사하면 `app.4f283b18.js`와 같은 파일을 볼 수 있습니다.
`4f283b18` 해시는 이 파일의 내용에서 생성됩니다. 같은 해시된 URL은 항상 동일한 파일 내용을 제공하도록 보장됩니다 - 내용이 변경되면 URL도 변경됩니다. 이는 이러한 파일에 대해 가장 강력한 캐시 헤더를 안전하게 사용할 수 있음을 의미합니다. 이러한 모든 파일이 출력 디렉토리의 `assets/` 아래에 배치되므로, 그들을 위해 다음 헤더를 구성할 수 있습니다: `4f283b18` 해시는 파일의 내용에서 생성됩니다. 동일한 해시된 URL은 동일한 파일 내용을 제공할 것이 보장되며, 내용이 변경되면 URL도 변경됩니다. 이는 이러한 파일에 대해 가장 강력한 캐시 헤더를 안전하게 사용할 수 있음을 의미합니다. 모든 이러한 파일은 출력 디렉토리의 `assets/` 아래에 배치되므로, 다음 헤더를 구성할 수 있습니다:
``` ```
Cache-Control: max-age=31536000,immutable Cache-Control: max-age=31536000,immutable
@ -73,13 +73,13 @@ Cache-Control: max-age=31536000,immutable
cache-control: immutable cache-control: immutable
``` ```
참고: `_headers` 파일은 [public 디렉토리](./asset-handling#the-public-directory)에 배치해야 합니다 - 우리의 경우, `docs/public/_headers` - 출력 디렉토리에 그대로 복사되도록 하기 위해서입니다. 참고: `_headers` 파일은 [public 디렉토리](./asset-handling#the-public-directory)에 배치해야 합니다. 이 경우 `docs/public/_headers`에 위치하여 출력 디렉토리에 그대로 복사됩니다.
[Netlify 사용자 정의 헤더 문서](https://docs.netlify.com/routing/headers/) [Netlify 커스텀 헤더 문서](https://docs.netlify.com/routing/headers/)
::: :::
::: details `vercel.json` 내의 Vercel 설정 예시 ::: details Vercel 내의 `vercel.json` 구성 예시
```json ```json
{ {
@ -97,9 +97,9 @@ Cache-Control: max-age=31536000,immutable
} }
``` ```
참고: `vercel.json` 파일은 **리포지토리**의 루트에 치해야 합니다. 참고: `vercel.json` 파일은 **리포지토리**의 루트에 치해야 합니다.
[Vercel 헤더 설정에 대한 문서](https://vercel.com/docs/concepts/projects/project-configuration#headers) [Vercel 헤더 구성에 대한 문서](https://vercel.com/docs/concepts/projects/project-configuration#headers)
::: :::
@ -107,42 +107,41 @@ Cache-Control: max-age=31536000,immutable
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render ### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
새 프로젝트를 설정하고 대시보드를 사용하여 설정을 변경하세요: 새 프로젝트를 설정하고 대시보드를 사용하여 다음 설정을 변경하세요:
- **빌드 명령어:** `npm run docs:build` - **빌드 명령어:** `npm run docs:build`
- **출력 디렉토리:** `docs/.vitepress/dist` - **출력 디렉토리:** `docs/.vitepress/dist`
- **노드 버전:** `18` (또는 그 이상) - **노드 버전:** `18` (또는 그 이상)
::: warning ::: warning
HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세요. Vue에 의미를 가진 주석이 제거될 수 있습니다. 제거되면 수화 불일치 오류가 발생할 수 있습니다. HTML 코드에 대해 _Auto Minify_ 옵션을 활성화하지 마세요. 이는 Vue에 의미가 있는 주석을 출력에서 제거할 것입니다. 제거되면 하이드레이션 불일치 오류가 발생할 수 있습니다.
::: :::
### GitHub Pages ### GitHub Pages
1. 프로젝트의 `.github/workflows` 디렉토리 안에 `deploy.yml`이라는 파일을 생성하고 다음과 같은 내용을 넣으세요: 1. 프로젝트의 `.github/workflows` 디렉토리 안에 `deploy.yml`이라는 파일을 만들고 다음과 같은 내용을 추가하세요:
```yaml ```yaml
# GitHub Pages에 VitePress 사이트를 빌드하고 배포하기 위한 샘플 워크플로우 # VitePress 사이트를 GitHub Pages에 빌드하고 배포하는 샘플 워크플로우
# #
name: Deploy VitePress site to Pages name: VitePress 사이트를 Pages에 배포
on: on:
# `main` 브랜치를 대상으로 하는 푸시에 대해 실행합니다. 기본 브랜치로 `master` # `main` 브랜치를 대상으로 하는 푸시에서 실행됩니다. 기본 브랜치로 `master`를 사용하는 경우 여기를 `master`로 변경하세요.
# 사용하는 경우, 이를 `master`로 변경하세요.
push: push:
branches: [main] branches: [main]
# Actions 탭에서 이 워크플로우를 수동으로 실행할 수 있도록 허용합니다. # Actions 탭에서 이 워크플로우를 수동으로 실행할 수 있합니다.
workflow_dispatch: workflow_dispatch:
# GitHub Pages에 배포를 허용하기 위해 GITHUB_TOKEN의 권한을 설정합니다. # GitHub Pages에 배포할 수 있도록 GITHUB_TOKEN의 권한을 설정합니다.
permissions: permissions:
contents: read contents: read
pages: write pages: write
id-token: write id-token: write
# 동시에 하나의 배포만 허용하며, 진행 중인 실행과 최신 대기열 사이에 대기열에 있는 실행을 건너뛰기. # 진행 중인 실행과 마지막으로 대기 중인 실행 사이에 대기 중인 실행을 건너뛰어 하나의 동시 배포만 허용합니다.
# 그러나, 이러한 프로덕션 배포를 완료하도록 진행 중인 실행을 취소하지는 마세요. # 그러나 이러한 프로덕션 배포가 완료되도록 진행 중인 실행은 취소하지 않습니다.
concurrency: concurrency:
group: pages group: pages
cancel-in-progress: false cancel-in-progress: false
@ -155,9 +154,9 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0 # lastUpdated가 활성화되어 있지 않다면 필요 없습니다 fetch-depth: 0 # lastUpdated가 활성화되지 않은 경우 필요하지 않음
# - uses: pnpm/action-setup@v3 # pnpm을 사용하는 경우 이것을 주석 해제하세요 # - uses: pnpm/action-setup@v3 # pnpm을 사용하는 경우 주석 해제
# - uses: oven-sh/setup-bun@v1 # Bun을 사용하는 경우 이것을 주석 해제하세요 # - uses: oven-sh/setup-bun@v1 # Bun을 사용하는 경우 주석 해제
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
@ -189,16 +188,16 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
``` ```
::: warning ::: warning
VitePress의 `base` 옵션이 제대로 구성되어 있는지 확인하세요. 자세한 내용은 [public 기본 경로 설정하기](#setting-a-public-base-path)를 참하세요. VitePress의 `base` 옵션이 제대로 구성되어 있는지 확인하세요. 자세한 내용은 [public 기본 경로 설정하기](#setting-a-public-base-path)를 참하세요.
::: :::
2. 저장소 설정에서 "Pages" 메뉴 항목 아래 "빌드 및 배포 > 출처"에서 "GitHub Actions"를 선택하세요. 2. 리포지토리 설정의 "Pages" 메뉴 항목에서 "Build and deployment > Source"에서 "GitHub Actions"를 선택하세요.
3. `main` 브랜치에 변경 사항을 푸시하고 GitHub Actions 워크플로우가 완료되기를 기다리세요. 설정에 따라 사이트가 `https://<username>.github.io/[repository]/` 또는 `https://<custom-domain>/`에 배포된 것을 볼 수 있습니다. `main` 브랜치에 푸시할 때마다 사이트가 자동으로 배포됩니다. 3. 변경 사항을 `main` 브랜치에 푸시하고 GitHub Actions 워크플로우가 완료될 때까지 기다립니다. 설정에 따라 사이트가 `https://<username>.github.io/[repository]/` 또는 `https://<custom-domain>/`에 배포된 것을 볼 수 있습니다. 사이트는 `main` 브랜치에 푸시할 때마다 자동으로 배포됩니다.
### GitLab Pages ### GitLab Pages
1. VitePress 구성에서 `outDir``../public`으로 설정합니다. `https://<username>.gitlab.io/<repository>/`에 배포하려면 `base` 옵션을 `'/<repository>/'`로 구성하세요. 1. VitePress 구성에서 `outDir``../public`으로 설정하세요. `https://<username>.gitlab.io/<repository>/`에 배포하려면 `base` 옵션을 `'/<repository>/'`로 구성하세요. 커스텀 도메인, 유저 또는 그룹 페이지에 배포하거나 GitLab에서 "Use unique domain" 설정이 활성화된 경우에는 `base`가 필요하지 않습니다.
2. 변경 사항을 적용할 때마다 사이트를 빌드하고 배포하도록 하기 위해 프로젝트의 루트에 다음 내용을 가진 `.gitlab-ci.yml` 파일을 생성하세요: 2. 변경 사항을 적용할 때마다 사이트를 빌드하고 배포하도록 하기 위해 프로젝트의 루트에 다음 내용을 가진 `.gitlab-ci.yml` 파일을 생성하세요:
@ -209,7 +208,7 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
paths: paths:
- node_modules/ - node_modules/
script: script:
# - apk add git # lastUpdated가 활성화되어 있고 alpine과 같은 작은 도커 이미지를 사용하는 경우 이것을 주석 해제하세요 # - apk add git # alpine 과 같은 작은 도커 이미지를 사용하고 있고 lastUpdated 가 활성화된 경우 주석 처리를 제거하세요.
- npm install - npm install
- npm run docs:build - npm run docs:build
artifacts: artifacts:
@ -223,7 +222,7 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
1. [공식 문서](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)를 따르세요. 1. [공식 문서](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)를 따르세요.
2. 구성 파일에 값을 설정하세요(필요하지 않은 값들, 예를 들어 `api_location` 같은 것은 제거하세요): 2. 구성 파일에 다음 값을 설정하세요(필요하지 않은 값들, 예를 들어 `api_location` 같은 것은 제거하세요):
- **`app_location`**: `/` - **`app_location`**: `/`
- **`output_location`**: `docs/.vitepress/dist` - **`output_location`**: `docs/.vitepress/dist`
@ -231,7 +230,7 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
### Firebase {#firebase} ### Firebase {#firebase}
1. 프로젝트 루트에 `firebase.json``.firebaserc`를 생성하세요: 1. 프로젝트 루트에 `firebase.json``.firebaserc`를 생성하세요:
`firebase.json`: `firebase.json`:
@ -270,9 +269,9 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
### Heroku ### Heroku
1. [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static)에 주어진 문서 및 가이드를 따르세요. 1. [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static)에 제공된 문서와 가이드를 따르세요.
2. 프로젝트의 루트에 아래 내용을 가진 `static.json` 파일을 생성하세요: 2. 프로젝트 루트에 아래 내용을 포함한 `static.json` 파일을 생성하세요:
```json ```json
{ {
@ -282,19 +281,19 @@ HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세
### Edgio ### Edgio
[Edgio에 VitePress 앱 생성 및 배포하기](https://docs.edg.io/guides/vitepress)를 참하세요. [Edgio에 VitePress 앱 생성 및 배포하기](https://docs.edg.io/guides/vitepress)를 참하세요.
### Kinsta 정적 사이트 호스팅 {#kinsta-static-site-hosting} ### Kinsta 정적 사이트 호스팅 {#kinsta-static-site-hosting}
[Kinsta](https://kinsta.com/static-site-hosting/)에서 VitePress 웹사이트를 배포하는 방법은 [지침](https://kinsta.com/docs/vitepress-static-site-example/)을 따르세요. [VitePress](https://kinsta.com/static-site-hosting/) 웹사이트를 [Kinsta](https://kinsta.com/static-site-hosting/)에 배포하려면 이 [지침](https://kinsta.com/docs/vitepress-static-site-example/)을 따르세요.
### 스톰킷 ### Stormkit
VitePress 프로젝트를 [Stormkit](https://www.stormkit.io)에 배포하려면 이 [지침](https://stormkit.io/blog/how-to-deploy-vitepress)을 따르세요. [VitePress](https://stormkit.io) 프로젝트를 [Stormkit](https://www.stormkit.io)에 배포하려면 이 [지침](https://stormkit.io/blog/how-to-deploy-vitepress)을 따르세요.
### Nginx ### Nginx
다음은 Nginx 서버 블록 구성의 예입니다. 이 설정에는 일반적인 텍스트 기반 자산에 대한 gzip 압축, 적절한 캐싱 헤더로 VitePress 사이트의 정적 파일을 제공하는 규칙, `cleanUrls: true`를 처리하는 규칙이 포함되어 있습니다. 다음은 Nginx 서버 블록 구성의 예입니다. 이 설정은 일반적인 텍스트 기반 에셋에 대한 gzip 압축, VitePress 사이트의 정적 파일을 적절한 캐싱 헤더와 함께 제공하는 규칙 및 `cleanUrls: true`를 처리하는 규칙을 포함합니다.
```nginx ```nginx
server { server {
@ -306,20 +305,20 @@ server {
index index.html; index index.html;
location / { location / {
# 내용 위치 # 콘텐츠 위치
root /app; root /app;
# 정확한 일치 -> 깨끗한 URL로 처리 -> 폴더 -> 찾을 수 없음 # 정확히 일치하는 파일 -> 정제된 URL로 역방향 매핑 -> 폴더 -> 파일 없음
try_files $uri $uri.html $uri/ =404; try_files $uri $uri.html $uri/ =404;
# 존재하지 않는 페이지 # 존재하지 않는 페이지
error_page 404 /404.html; error_page 404 /404.html;
# index.html이 없는 폴더는 이 설정에서 403 발생시킴 # index.html이 없는 폴더는 이 설정에서 403 오류를 발생시킴
error_page 403 /404.html; error_page 403 /404.html;
# 캐싱 헤더 조정 # 캐싱 헤더 조정
# assets 폴더의 파일은 해시 파일 이름을 가짐 # assets 폴더의 파일들은 해시된 파일명 사용
location ~* ^/assets/ { location ~* ^/assets/ {
expires 1y; expires 1y;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
@ -328,10 +327,10 @@ server {
} }
``` ```
이 구성은 빌드된 VitePress 사이트가 서버`/app` 디렉토리에 위치한다고 가정합니다. 사이트 파일이 다른 곳에 위치한 경우 `root` 지시문을 그에 맞게 조정하세요. 이 구성은 빌드된 VitePress 사이트가 서버의 `/app` 디렉토리에 위치한다고 가정합니다. 사이트 파일이 다른 곳에 위치한 경우 `root` 지시문을 적절하게 조정하세요.
::: warning index.html을 기본값으로 설정하지 마세요. ::: warning index.html을 기본값으로 설정하지 마세요.
try_files 해결은 다른 Vue 애플리케이션처럼 index.html로 기본 설정되어서는 안 됩니다. 이것은 유효하지 않은 페이지 상태로 이어질 것입니다. try_files는 다른 Vue 애플리케이션처럼 index.html을 기본값으로 할 수 없습니다. 이는 페이지 상태가 유효하지 않게 만듭니다.
::: :::
추가 정보는 [공식 nginx 문서](https://nginx.org/en/docs/), 이슈 [#2837](https://github.com/vuejs/vitepress/discussions/2837), [#3235](https://github.com/vuejs/vitepress/issues/3235) 그리고 Mehdi Merah의 [블로그 포스트](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings)에서 찾을 수 있습니다. 추가 정보는 [공식 nginx 문서](https://nginx.org/en/docs/), 이슈 [#2837](https://github.com/vuejs/vitepress/discussions/2837), [#3235](https://github.com/vuejs/vitepress/issues/3235) Mehdi Merah의 [블로그 포스트](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings)에서 확인할 수 있습니다.

@ -4,23 +4,23 @@ outline: deep
# 기본 테마 확장하기 {#extending-the-default-theme} # 기본 테마 확장하기 {#extending-the-default-theme}
VitePress의 기본 테마는 문서화에 최적화되어 있으며, 커스터마이징이 가능합니다. [기본 테마 구성 개요](../reference/default-theme-config)를 참조하여 가능한 옵션의 전체 목록을 확인하세요. VitePress의 기본 테마는 문서화에 최적화되어 있으며, 커스텀할 수 있습니다. 포괄적인 옵션 목록은 [기본 테마 구성](../reference/default-theme-config)을 참고하세요.
그러나 설정만으로는 충분하지 않은 경우가 여러 번 있을 수 있습니다. 예를 들면: 그러나 구성만으로는 충분하지 않을 수 있습니다. 예를 들어:
1. CSS 스타일링을 조정해야 할 때; 1. CSS 스타일링을 조정해야 하는 경우.
2. 전역 컴포넌트 등록과 같이 Vue 앱 인스턴스를 수정해야 할 때; 2. 전역 컴포넌트를 등록하기 위해 Vue 애플리케이션 인스턴스를 수정해야 하는 경우.
3. 레이아웃 슬롯을 통해 테마에 사용자 정의 컨텐츠를 삽입해야 할 때. 3. 레이아웃 슬롯을 통해 테마에 커스텀 컨텐츠를 삽입해야 하는 경우.
이러한 고급 커스터마이징은 기본 테마를 "확장하는" 사용자 지정 테마를 사용해야 합니다. 이러한 고급 커스터마이징은 기본 테마를 "확장"하는 커스텀 테마 사용이 필요 합니다.
::: tip ::: tip
진행하기 전에, 사용자 지정 테마가 어떻게 작동하는지 이해하기 위해 [사용자 지정 테마 사용하기](./custom-theme)를 먼저 읽어보세요. 진행하기 전에, 커스텀 테마가 어떻게 작동하는지 이해하려면 먼저 [커스텀 테마 사용하기](./custom-theme)를 읽어보세요.
::: :::
## CSS 커스터마이징하기 {#customizing-css} ## CSS 커스터마이징하기 {#customizing-css}
기본 테마의 CSS는 루트 레벨 CSS 변수를 오버라이딩하여 커스터마이즈 할 수 있습니다: 기본 테마의 CSS는 루트 레벨의 CSS 변수를 재정의하여 커스터마이징 할 수 있습니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -38,13 +38,13 @@ export default DefaultTheme
} }
``` ```
오버라이딩할 수 있는 [기본 테마 CSS 변수](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css)를 확인하세요. 재정의할 수 있는 기본 테마 CSS 변수는 [여기](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css)를 참고하세요.
## 다른 폰트 사용하기 {#using-different-fonts} ## 다른 폰트 사용하기 {#using-different-fonts}
VitePress는 기본 폰트로 [Inter](https://rsms.me/inter/)를 사용하며, 빌드 출력물에 폰트를 포함합니다. 또한, 이 폰트는 프로덕션 환경에서 자동으로 프리로드됩니다. 하지만, 다른 메인 폰트를 사용하고 싶은 경우에는 바람직하지 않을 수 있습니다. VitePress는 기본 폰트로 [Inter](https://rsms.me/inter/)를 사용하며, 빌드 결과물에 폰트를 포함시킵니다. 폰트는 프로덕션 환경에서 자동으로 미리 로드되지만, 다른 메인 폰트를 사용하고자 할 경우 이는 바람직하지 않을 수 있습니다.
빌드 출력물에서 Inter를 포함하지 않으려면, 대신 `vitepress/theme-without-fonts`에서 테마를 임포트하세요: 빌드 결과물에 Inter를 포함시키지 않으려면, `vitepress/theme-without-fonts`에서 테마를 "import" 합니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* 일반 텍스트 폰트 */ --vp-font-family-base: /* 일반 텍스트 폰트 */
--vp-font-family-mono: /* 코드 폰트 */ --vp-font-family-mono: /* 코드 폰트 */
@ -63,10 +63,10 @@ export default DefaultTheme
``` ```
::: warning ::: warning
[팀 페이지](../reference/default-theme-team-page)와 같은 선택적 컴포넌트를 사용하는 경우, 이들도 `vitepress/theme-without-fonts`에서 가져와야 합니다! 선택적 컴포넌트인 [팀 페이지](../reference/default-theme-team-page) 등을 사용하는 경우, 반드시 이들도 `vitepress/theme-without-fonts`에서 "import" 해야 합니다!
::: :::
폰트가 `@font-face`를 통해 참조된 로컬 파일이라면, 자산으로 처리되어 해시된 파일명과 함께 `.vitepress/dist/assets` 아래에 포함될 것입니다. 이 파일을 프리로드하려면, [transformHead](../reference/site-config#transformhead) 빌드 훅을 사용하세요: 폰트가 `@font-face`를 통해 참조된 로컬 파일인 경우, 에셋으로 처리되어 해시된 파일 이름으로 `.vitepress/dist/assets`에 포함됩니다. 이 파일을 미리 로드하려면 [transformHead](../reference/site-config#transformhead) 빌드 훅을 사용해야 합니다:
```js ```js
// .vitepress/config.js // .vitepress/config.js
@ -102,7 +102,7 @@ import DefaultTheme from 'vitepress/theme'
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
enhanceApp({ app }) { enhanceApp({ app }) {
// 사용자 지정 전역 컴포넌트를 등록하세요 // 커스텀 전역 컴포넌트 등록
app.component('MyGlobalComponent' /* ... */) app.component('MyGlobalComponent' /* ... */)
} }
} }
@ -117,17 +117,17 @@ import DefaultTheme from 'vitepress/theme'
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
enhanceApp({ app }) { enhanceApp({ app }) {
// 사용자 지정 전역 컴포넌트를 등록하세요 // 커스텀 전역 컴포넌트 등록
app.component('MyGlobalComponent' /* ... */) app.component('MyGlobalComponent' /* ... */)
} }
} satisfies Theme } satisfies Theme
``` ```
Vite를 사용하기 때문에, Vite의 [글로브 임포트 기능](https://vitejs.dev/ko/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수 있습니다. Vite를 사용하므로, Vite의 [glob import 기능](https://vitejs.dev/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수 있습니다.
## 레이아웃 슬롯 {#layout-slots} ## 레이아웃 슬롯 {#layout-slots}
기본 테마의 `<Layout/>` 컴포넌트는 페이지의 특정 위치에 컨텐츠를 삽입할 수 있도록 몇 개의 슬롯을 제공합니다. 아웃라인 앞에 컴포넌트를 삽입하는 예시입니다: 기본 테마의 `<Layout/>` 컴포넌트는 페이지의 특정 위치에 컨텐츠를 삽입할 수 있는 몇 가지 슬롯을 가지고 있습니다. 다음은 아웃라인 앞에 컴포넌트를 삽입하는 예제입니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -137,7 +137,7 @@ import MyLayout from './MyLayout.vue'
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
// 슬롯을 삽입하는 래퍼 컴포넌트로 // 슬롯을 삽입하는 래퍼 컴포넌트로
// Layout을 오버라이드합니다 // Layout을 재정의합니다
Layout: MyLayout Layout: MyLayout
} }
``` ```
@ -153,13 +153,13 @@ const { Layout } = DefaultTheme
<template> <template>
<Layout> <Layout>
<template #aside-outline-before> <template #aside-outline-before>
나만의 사용자 사이드바 상단 컨텐츠 My custom sidebar top content
</template> </template>
</Layout> </Layout>
</template> </template>
``` ```
렌더 함수를 사용하는 것도 가능합니다. 또는 렌더 함수를 사용할 수도 있습니다.
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -177,9 +177,9 @@ export default {
} }
``` ```
기본 테마 레이아웃에서 사용할 수 있는 전체 슬롯 목록: 기본 테마 레이아웃에서 사용할 수 있는 슬롯의 전체 목록:
- 프론트매터를 통해 `layout: 'doc'` (기본값)이 활성화될 때: - 전문(front-matter)으로 `layout: 'doc'` (기본값)이 활성화된 경우:
- `doc-top` - `doc-top`
- `doc-bottom` - `doc-bottom`
- `doc-footer-before` - `doc-footer-before`
@ -193,7 +193,7 @@ export default {
- `aside-outline-after` - `aside-outline-after`
- `aside-ads-before` - `aside-ads-before`
- `aside-ads-after` - `aside-ads-after`
- 프론트매터를 통해 `layout: 'home'`이 활성화될 때: - 전문으로 `layout: 'home'`이 활성화된 경우:
- `home-hero-before` - `home-hero-before`
- `home-hero-info-before` - `home-hero-info-before`
- `home-hero-info` - `home-hero-info`
@ -203,10 +203,10 @@ export default {
- `home-hero-after` - `home-hero-after`
- `home-features-before` - `home-features-before`
- `home-features-after` - `home-features-after`
- 프론트매터를 통해 `layout: 'page'`가 활성화될 때: - 전문으로 `layout: 'page'`이 활성화된 경우:
- `page-top` - `page-top`
- `page-bottom` - `page-bottom`
- 찾을 수 없는 (404) 페이지에서: - 페이지를 찾을 수 없음(404)일 때:
- `not-found` - `not-found`
- 항상: - 항상:
- `layout-top` - `layout-top`
@ -218,11 +218,11 @@ export default {
- `nav-screen-content-before` - `nav-screen-content-before`
- `nav-screen-content-after` - `nav-screen-content-after`
## 뷰 전환 API 사용하기 {#using-view-transitions-api} ## 뷰 트랜지션 API 사용하기 {#using-view-transitions-api}
### 외형 토글 {#on-appearance-toggle} ### 외형 토글 {#on-appearance-toggle}
기본 테마를 확장하여 색상 모드가 토글될 때 사용자 정의 전환을 제공할 수 있습니다. 예시: 기본 테마를 확장하여 컬러 모드가 전환될 때 커스텀 트랜지션 효과를 제공할 수 있습니다. 예제:
```vue ```vue
<!-- .vitepress/theme/Layout.vue --> <!-- .vitepress/theme/Layout.vue -->
@ -299,24 +299,24 @@ provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
</style> </style>
``` ```
결과 (**경고!**: 눈부심, 갑작스러운 움직임, 밝은 빛): 결과 (**광과민성 주의!**: 색상 깜빡임, 갑작스러운 움직임, 밝은 빛):
<details> <details>
<summary>데모</summary> <summary>데모</summary>
![외형 토글 전환 데모](/appearance-toggle-transition.webp) ![외형 토글 트랜지션 데모](/appearance-toggle-transition.webp)
</details> </details>
전환에 대한 자세한 정보는 [Chrome 문서](https://developer.chrome.com/docs/web-platform/view-transitions/)를 참고하세요. 트랜지션에 대한 자세한 정보는 [크롬 문서](https://developer.chrome.com/docs/web-platform/view-transitions/)를 참고하세요.
### 라우트 변경 시 {#on-route-change} ### 라우트 변경 시 {#on-route-change}
곧 제공될 예정입니다. 곧 제공될 예정입니다.
## 내부 컴포넌트 오버라이딩하기 {#overriding-internal-components} ## 내부 컴포넌트 재정의하기 {#overriding-internal-components}
Vite의 [별칭](https://vitejs.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 사용자 지정 컴포넌트로 대체할 수 있습니다: Vite의 [별칭](https://vitejs.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 커스텀 컴포넌트로 대체할 수 있습니다:
```ts ```ts
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
@ -338,4 +338,4 @@ export default defineConfig({
}) })
``` ```
컴포넌트의 정확한 이름을 알고 싶다면 [저희 소스 코드](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components)를 참조하세요. 컴포넌트가 내부적으로 사용되기 때문에, 소규모 릴리스 사이에 이름이 업데이트될 수 있습니다. 컴포넌트의 정확한 이름을 알고 싶다면 [Vitepress 소스 코드](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components)를 참고하세요. 컴포넌트는 내부적으로 사용되기 때문에, 마이너 릴리즈 사이에 이름이 변경될 가능성이 있습니다.

@ -2,7 +2,7 @@
## 사용법 {#usage} ## 사용법 {#usage}
VitePress는 모든 Markdown 파일에서 YAML 전문(frontmatter)을 지원하며, 이를 [gray-matter](https://github.com/jonschlinkert/gray-matter)로 분석합니다. 전문은 Markdown 파일의 맨 위에 위치해야 합니다(`<script>` 태그를 포함한 모든 요소 이전에)하며, 세 개의 대시 라인 사이에 유효한 YAML 형식으로 설정되어야 합니다. 예시: VitePress는 모든 마크다운 파일에서 YAML 전문(frontmatter)을 지원하며, [gray-matter](https://github.com/jonschlinkert/gray-matter)로 이를 파싱합니다. 전문은 마크다운 파일의 맨 위에 있어야 하며(모든 엘리먼트 포함 `<script>` 태그 이전), 세 개의 대시 라인 사이에 유효한 YAML 형태로 작성되어야 합니다. 예:
```md ```md
--- ---
@ -11,15 +11,15 @@ editLink: true
--- ---
``` ```
많은 사이트 또는 기본 테마 구성 옵션이 전문에서 대응하는 옵션을 가지고 있습니다. 전문을 사용하여 현재 페이지에 대한 특정 동작을 재정의 할 수 있습니다. 자세한 내용은 [전문 구성 참조](../reference/frontmatter-config)를 참조하십시오. 많은 사이트 또는 기본 테마 구성 옵션은 전문에 해당 옵션이 있습니다. 전문을 사용하여 현재 페이지에 대한 특정 동작을 재정의할 수 있습니다. 자세한 내용은 [전문 구성 레퍼런스](../reference/frontmatter-config)를 참고하세요.
또한 페이지상의 동적 Vue 표현식에서 사용될 수 있는 자체적인 전문 데이터를 정의할 수 있습니다. 또한 페이지에서 동적 Vue 표현식에 사용할 커스텀 전문 데이터를 정의할 수도 있습니다.
## 전문 데이터 접근 {#accessing-frontmatter-data} ## 전문 데이터 접근하기 {#accessing-frontmatter-data}
전문 데이터는 특별한 `$frontmatter` 전역 변수를 통해 접근할 수 있습니다: 전문 데이터는 특별한 `$frontmatter` 전역 변수를 통해 접근할 수 있습니다:
여기 Markdown 파일에서 사용하는 방법의 예시입니다: 다음은 마크다운 파일에서 이를 사용하는 예입니다:
```md ```md
--- ---
@ -32,11 +32,11 @@ editLink: true
가이드 내용 가이드 내용
``` ```
`<script setup>`에서 현재 페이지의 전문 데이터에 접근하려면 [`useData()`](../reference/runtime-api#usedata) 헬퍼를 사용할 수 있습니다. 현재 페이지의 전문 데이터는 [`useData()`](../reference/runtime-api#usedata) 헬퍼를 사용하여 `<script setup>`에서도 접근할 수 있습니다.
## 대체 전문 형식 {#alternative-frontmatter-formats} ## 기타 전문 형식 {#alternative-frontmatter-formats}
VitePress는 중괄호로 시작하고 끝나는 JSON 전문 문도 지원합니다: VitePress는 중괄호로 시작하고 끝나는 JSON 전문 문도 지원합니다:
```json ```json
--- ---

@ -1,9 +1,9 @@
# 시작하기 {#getting-started} # 시작하기 {#getting-started}
## 온라인에서 시도해보기 {#try-it-online} ## 온라인에서 사용해보기 {#try-it-online}
브라우저에서 바로 VitePress를 시도해 볼 수 있습니다 [StackBlitz](https://vitepress.new). [StackBlitz](https://vitepress.new)에서 브라우저로 즉시 VitePress를 사용해 볼 수 있습니다.
## 설치 {#installation} ## 설치 {#installation}
@ -11,10 +11,10 @@
- [Node.js](https://nodejs.org/) 버전 18 이상. - [Node.js](https://nodejs.org/) 버전 18 이상.
- VitePress를 명령줄 인터페이스(CLI)를 통해 접근하기 위한 터미널. - VitePress를 명령줄 인터페이스(CLI)를 통해 접근하기 위한 터미널.
- [Markdown](https://en.wikipedia.org/wiki/Markdown) 문법 지원이 있는 텍스트 에디터. - [마크다운](https://en.wikipedia.org/wiki/Markdown) 문법 지원이 있는 텍스트 에디터.
- [VSCode](https://code.visualstudio.com/)와 [공식 Vue 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=Vue.volar) 사용을 권장합니다. - [VSCode](https://code.visualstudio.com/)와 [공식 Vue 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=Vue.volar) 사용을 권장합니다.
VitePress는 독립 실행형으로 사용하거나 기존 프로젝트에 설치할 수 있습니다. 어떤 경우든 다음과 같이 설치할 수 있습니다: VitePress는 독으로 사용하거나 기존 프로젝트에 설치할 수 있습니다. 두 경우 모두 다음과 같이 설치할 수 있습니다:
::: code-group ::: code-group
@ -40,8 +40,8 @@ $ bun add -D vitepress
::: :::
::: details 필요한 피어 종속성 경고가 나타나나요? ::: details "missing peer deps" 경고가 표시되나요?
PNPM을 사용할 경우 `@docsearch/js`에 대한 누락된 피어 경고를 볼 수 있습니다. 이것은 VitePress 작동을 방해하지 않습니다. 이 경고를 억제하려면, `package.json`에 다음을 추가하세요: PNPM을 사용하는 경우 `@docsearch/js`에 대한 "missing peer deps" 경고가 표시됩니다. 이는 VitePress가 작동하는 것을 방해하지 않습니다. 이 경고를 억제하려면 `package.json`에 다음을 추가합니다:
```json ```json
"pnpm": { "pnpm": {
@ -58,13 +58,13 @@ PNPM을 사용할 경우 `@docsearch/js`에 대한 누락된 피어 경고를
::: tip 참고 ::: tip 참고
VitePress는 ESM-only 패키지입니다. `require()`를 사용하여 가져오지 마십시오, 그리고 가장 가까운 `package.json``"type": "module"`이 포함되어 있는지 확인하거나, 관련 파일(예: `.vitepress/config.js`)의 확장자를 `.mjs`/`.mts`로 변경하십시오. 자세한 내용은 [Vite의 문제 해결 가이드](http://vitejs.dev/ko/guide/troubleshooting.html#this-package-is-esm-only)를 참조하십시오. 또한, 비동기 CJS 컨텍스트 내에서는 대신 `await import('vitepress')`를 사용할 수 있습니다. VitePress는 ESM 전용 패키지입니다. `require()`를 사용하여 가져오지 마시고, `package.json``"type": "module"`이 포함되어 있는지 확인하거나, 관련 파일(예: `.vitepress/config.js`)의 확장자를 `.mjs`/`.mts`로 변경하세요. 자세한 내용은 [Vite 문제 해결 가이드](http://vitejs.dev/ko/guide/troubleshooting.html#this-package-is-esm-only)를 참고하세요. 또한, 비동기 CJS 컨텍스트에서는 `await import('vitepress')`를 사용할 수 있습니다.
::: :::
### 설정 마법사 {#setup-wizard} ### 설정 마법사 {#setup-wizard}
VitePress는 기본 프로젝트를 스캐폴딩하는 데 도움이 되는 명령줄 설정 마법사를 제공합니다. 설치 후, 마법사를 시작하려면 다음을 실행하세요: VitePress는 기본 프로젝트를 구축하는 데 도움이 되는 명령줄 설정 마법사를 제공합니다. 설치 후, 마법사를 시작하려면 다음을 실행하세요:
::: code-group ::: code-group
@ -90,15 +90,15 @@ $ bun vitepress init
<<< @/snippets/init.ansi <<< @/snippets/init.ansi
::: tip Vue를 피어 의존성으로 ::: tip 피어 의존성으로서의 Vue
Vue 컴포넌트나 API를 사용하여 커스터마이즈를 수행하려면, `vue` 명시적으로 의존성으로 설치해야 합니다. 커스텀을 위해 Vue 컴포넌트나 API를 사용하려는 경우, `vue` 명시적으로 의존성으로 설치해야 합니다.
::: :::
## 파일 구조 {#file-structure} ## 파일 구조 {#file-structure}
독립 실행형 VitePress 사이트를 빌딩하는 경우, 현재 디렉토리(`./`)에 사이트를 스캐폴딩할 수 있습니다. 그러나 다른 소스 코드와 함께 기존 프로젝트에 VitePress를 설치하는 경우, 프로젝트의 나머지 부분과 별도로 (`예: `./docs`) 중첩된 디렉토리에 사이트를 스캐폴딩하는 것이 좋습니다. 독립형 VitePress 사이트를 구축하려는 경우, 현재 디렉터리(`./`)에 사이트를 구축할 수 있습니다. 그러나 기존 프로젝트에서 다른 소스 코드와 함께 VitePress를 설치하는 경우, 프로젝트의 나머지 부분과 분리되도록 중첩된 디렉터리(e.g. `./docs`)에 사이트를 구축하는 것이 좋습니다.
VitePress 프로젝트를 `./docs`스캐폴딩하기로 선택한 경우 생성된 파일 구조는 다음과 같아야 합니다: VitePress 프로젝트를 `./docs`구축하기로 한 경우, 생성된 파일 구조는 다음과 같아야 합니다:
``` ```
. .
@ -111,42 +111,42 @@ VitePress 프로젝트를 `./docs`에 스캐폴딩하기로 선택한 경우 생
└─ package.json └─ package.json
``` ```
`docs` 디렉리는 VitePress 사이트의 **프로젝트 루트**로 간주됩니다. `.vitepress` 디렉토리는 VitePress의 설정 파일, 개발 서버 캐시, 빌드 출력 및 선택적 테마 사용자 정의 코드를 위한 예약된 위치입니다. `docs` 디렉리는 VitePress 사이트의 **프로젝트 루트**로 간주됩니다. `.vitepress` 디렉터리는 VitePress의 구성 파일, 개발 서버 캐시, 빌드 출력, 선택적 커스텀 테마 코드가 있는 위치입니다.
::: tip ::: tip
기본적으로, VitePress는 개발 서버 캐시를 `.vitepress/cache`에, 프로덕션 빌드 출력을 `.vitepress/dist`에 저장합니다. Git을 사용하는 경우, 이들을 `.gitignore` 파일에 추가해야 합니다. 이 위치는 또한 [구성할 수 있습니다](../reference/site-config#outdir). 기본적으로 VitePress는 개발 서버 캐시를 `.vitepress/cache` 저장하고, 프로덕션 빌드 출력을 `.vitepress/dist`에 저장합니다. Git을 사용하는 경우, 이러한 디렉토리를 `.gitignore` 파일에 추가해야 합니다. 또는 이러한 위치를 수동으로 [구성](../reference/site-config#outdir)할 수도 있습니다.
::: :::
### 설정 파일 {#the-config-file} ### 구성 파일 {#the-config-file}
설정 파일(`.vitepress/config.js`)을 사용하면 사이트의 제목과 설명과 같은 VitePress 사이트의 다양한 측면을 커스터마이즈할 수 있습니다: 구성 파일(`.vitepress/config.js`)을 사용하면 사이트의 제목과 설명과 같은 VitePress 사이트의 다양한 측면을 커스터마이즈할 수 있습니다:
```js ```js
// .vitepress/config.js // .vitepress/config.js
export default { export default {
// 사이트 수준 옵션 // 사이트 옵션
title: 'VitePress', title: 'VitePress',
description: '그냥 해보는 중.', description: '그냥 해보는 중.',
themeConfig: { themeConfig: {
// 테마 수준 옵션 // 테마 옵션
} }
} }
``` ```
`themeConfig` 옵션을 통해 테마의 동작을 구성할 수도 있습니다. 모든 구성 옵션에 대한 전체 세부 정보는 [구성 참조](../reference/site-config)를 참조하십시오. 테마의 동작은 `themeConfig` 옵션을 통해 구성할 수도 있습니다. 모든 구성 옵션에 대한 자세한 내용은 [구성 레퍼런스](../reference/site-config)를 참고하세요.
### 소스 파일 {#source-files} ### 소스 파일 {#source-files}
`.vitepress` 디렉토리 밖의 마크다운 파일들**소스 파일**로 간주됩니다. `.vitepress` 디렉토리 외부의 마크다운 파일**소스 파일**로 간주됩니다.
VitePress는 **파일 기반 라우팅**을 사용합니다: 각 `.md` 파일은 동일한 경로에 해당하는 `.html` 파일로 컴파일됩니다. 예를 들어, `index.md``index.html`로 컴파일되며, 결과적 VitePress 사이트의 루트 경로 `/`에서 방문할 수 있습니다. VitePress는 **파일 기반 라우팅**을 사용합니다: 각 `.md` 파일은 동일한 경로에 해당하는 `.html` 파일로 컴파일됩니다. 예를 들어, `index.md``index.html`로 컴파일되며, 결과적으로 VitePress 사이트의 루트 경로 `/`에서 방문할 수 있습니다.
VitePress는 또한 깨끗한 URL 생성, 경로 리라이팅 및 동적 페이지 생성 기능을 제공합니다. 이러한 내용은 [라우팅 가이드](./routing)에서 다뤄질 것입니다. 또한 VitePress는 간결한 URL 생성, 경로 재작성, 동적 페이지 생성 기능을 제공합니다. 이러한 내용은 [라우팅 가이드](./routing)에서 다니다.
## 실행 및 작동 {#up-and-running} ## 실행 및 작동 {#up-and-running}
정 프로세스 중에 허용한 경우, 도구는 `package.json`에 다음 npm 스크립트를 주입해야 합니다: 치 과정에서 허용한 경우, 도구는 다음 npm 스크립트를 `package.json`에 추가했을 것입니다:
```json ```json
{ {
@ -160,7 +160,7 @@ VitePress는 또한 깨끗한 URL 생성, 경로 리라이팅 및 동적 페이
} }
``` ```
`docs:dev` 스크립트는 즉각적인 핫 업데이트를 제공하는 로컬 개발 서버를 시작합니다. 다음 명령으로 실행하세요: `docs:dev` 스크립트는 즉각적인 핫 업데이트가 가능한 로컬 개발 서버를 시작합니다. 다음 명령어로 실행할 수 있습니다:
::: code-group ::: code-group
@ -182,7 +182,7 @@ $ bun run docs:dev
::: :::
npm 스크립트 대신, 다음과 같이 VitePress를 직접 호출할 수도 있습니다: npm 스크립트 대신 VitePress를 직접 호출할 수도 있습니다:
::: code-group ::: code-group
@ -204,18 +204,18 @@ $ bun vitepress dev docs
::: :::
명령줄 사용법은 [CLI 참조](../reference/cli)에 문서화되어 있습니다. 더 많은 명령줄 사용법은 [CLI 레퍼런스](../reference/cli)에 문서화되어 있습니다.
개발 서버는 `http://localhost:5173`에서 실행되어야 합니다. 브라우저에서 URL을 방문하여 새 사이트를 확인하세요! 개발 서버는 `http://localhost:5173`에서 실행되어야 합니다. 브라우저에서 URL을 방문하여 새 사이트를 확인하세요!
## 다음 단계는? {#what-s-next} ## 다음 단계는? {#what-s-next}
- 생성된 HTML로 마크다운 파일이 어떻게 매핑되는지 더 잘 이해하려면, [라우팅 가이드](./routing)로 진행하세요. - 마크다운과 이 파일로 생성된 HTML이 어떻게 매핑되는지 더 잘 이해하려면 [라우팅 가이드](./routing)를 참고하세요.
- 페이지에서 할 수 있는 일에 대해 더 알아보려면, 마크다운 콘텐츠 작성이나 Vue 컴포넌트 사용과 같은 "작성" 섹션의 가이드를 참조하십시오. 시작하기 좋은 곳은 [마크다운 확장](./markdown)에 대해 배우는 것입니다. - 페이지에서 할 수 있는 작업, 예를 들어 마크다운 콘텐츠 작성이나 Vue 컴포넌트 사용에 대해 더 알아보려면 가이드의 "글쓰기" 섹션을 참조하세요. 시작하기 좋은 곳은 [마크다운 확장](./markdown)에 대해 배우는 것입니다.
- 기본 문서 테마가 제공하는 기능을 탐색하려면, [기본 테마 구성 참조](../reference/default-theme-config)를 확인하세요. - 기본 문서 테마에서 제공하는 기능을 탐색하려면 [기본 테마 구성 레퍼런스](../reference/default-theme-config)를 확인하세요.
- 사이트의 모양을 더욱 커스터마이즈하고 싶다면, [기본 테마 확장](./extending-default-theme)이나 [커스텀 테마 빌드](./custom-theme)하는 방법을 탐색해보세요. - 사이트의 외관을 더 맞춤화하려면 [기본 테마 확장](./extending-default-theme) 또는 [커스텀 테마 빌드](./custom-theme)를 탐색하세요.
- 문서 사이트가 구성되기 시작하면, [배포 가이드](./deploy)를 반드시 읽어보세요. - 문서 사이트가 형태를 갖추면 [배포 가이드](./deploy)를 꼭 읽어보세요.

@ -1,7 +1,6 @@
# i18n {#internationalization}
# 국제화 {#internationalization} 내장된 i18n 기능을 사용하려면 다음과 같은 디렉토리 구조를 만들어야 합니다:
내장 i18n 기능을 사용하기 위해서는 다음과 같은 디렉토리 구조를 생성해야 합니다:
``` ```
docs/ docs/
@ -18,7 +17,7 @@ docs/
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
export default defineConfig({ export default defineConfig({
// 공유 속성 및 기타 최상위 항목... // 공통 프로퍼티 및 기타 최상위 항목...
locales: { locales: {
root: { root: {
@ -27,16 +26,16 @@ export default defineConfig({
}, },
fr: { fr: {
label: '프랑스어', label: '프랑스어',
lang: 'fr', // 선택 사항, `html` 태그에 `lang` 속성으로 추가됩니다 lang: 'fr', // 선택 사항, `html` 태그에 `lang` 어트리뷰트로 추가됩니다
link: '/fr/guide' // 기본적으로 /fr/ -- navbar 변역 메뉴에 표시됩니다, 외부일 수 있습니다 link: '/fr/guide' // 기본적으로 /fr/ -- navbar 번역 메뉴에 표시됩니다 (외부 링크 가능)
// 다른 로케일 특정 속성... // 다른 로케일 특유의 프로퍼티...
} }
} }
}) })
``` ```
다음 속성들은 각 로케일(루트 포함)에 대해 덮어쓸 수 있습니다: 각 로케일(루트 포함)에 대해 다음 프로퍼티를 재정의할 수 있습니다:
```ts ```ts
interface LocaleSpecificConfig<ThemeConfig = any> { interface LocaleSpecificConfig<ThemeConfig = any> {
@ -50,13 +49,13 @@ interface LocaleSpecificConfig<ThemeConfig = any> {
} }
``` ```
기본 테마의 플레이스홀더 텍스트를 사용자 정의하는 방법은 [`DefaultTheme.Config`](https://github.com/vuejs/vitepress/blob/main/types/default-theme.d.ts) 인터페이스를 참조하세요. 로케일 레벨에서 `themeConfig.algolia` 또는 `themeConfig.carbonAds`를 덮어쓰지 마세요. 다국어 검색을 사용하는 방법에 대해서는 [Algolia 문서](../reference/default-theme-search#i18n)를 참조하세요. 기본 테마의 플레이스홀더 텍스트를 커스텀하는 방법에 대한 자세한 내용은 [`DefaultTheme.Config`](https://github.com/vuejs/vitepress/blob/main/types/default-theme.d.ts) 인터페이스를 참고하십시오. 로케일 수준에서 `themeConfig.algolia` 또는 `themeConfig.carbonAds`를 재정의하지 마십시오. 다국어 검색을 사용하려면 [Algolia docs](../reference/default-theme-search#i18n)를 참조하십시오.
**전문가 팁:** 구성 파일은 `docs/.vitepress/config/index.ts`에도 저장될 수 있습니다. 로케일별로 구성 파일을 생성한 다음 이를 `index.ts`에서 병합하여 내보내는 것으로, 내용을 구성하는데 도움이 될 수 있습니다. **전문가 팁:** 구성 파일은 `docs/.vitepress/config/index.ts`로 저장할 수도 있습니다. 로케일마다 구성 파일을 생성한 후 `index.ts`에서 병합하고 내보내어 내용을 구성하는 데 도움이 될 수 있습니다.
## 각 로케일별 별도의 디렉토리 {#separate-directory-for-each-locale} ## 각 로케일별 디렉토리 {#separate-directory-for-each-locale}
다음은 완전히 괜찮은 구조입니다: 다음은 완벽한 구조입니다:
``` ```
docs/ docs/
@ -68,7 +67,7 @@ docs/
├─ foo.md ├─ foo.md
``` ```
그러나, VitePress는 기본적으로 `/``/en/`로 리다이렉트하지 않습니다. 이를 위해 서버를 구성해야 합니다. 예를 들어, Netlify에서는 다음과 같이 `docs/public/_redirects` 파일을 추가할 수 있습니다: 그러나 기본적으로 VitePress는 `/``/en/`로 리다이렉션하지 않습니다. 이를 위해 서버를 구성해야 합니다. 예를 들어, Netlify에서는 다음과 같이 `docs/public/_redirects` 파일을 추가할 수 있습니다:
``` ```
/* /es/:splat 302 Language=es /* /es/:splat 302 Language=es
@ -76,7 +75,7 @@ docs/
/* /en/:splat 302 /* /en/:splat 302
``` ```
**전문가 팁:** 위의 접근 방식을 사용한다면, `nf_lang` 쿠키를 사용하여 사용자의 언어 선택을 유지할 수 있습니다: **전문가 팁:** 위의 접근 방식을 사용하는 경우 `nf_lang` 쿠키를 사용하여 유저의 언어 선택을 유지할 수 있습니다:
```ts ```ts
// docs/.vitepress/theme/index.ts // docs/.vitepress/theme/index.ts
@ -111,4 +110,4 @@ watchEffect(() => {
## RTL 지원 (실험적) {#rtl-support-experimental} ## RTL 지원 (실험적) {#rtl-support-experimental}
RTL 지원을 위해, 설정에서 `dir: 'rtl'`을 지정하고 <https://github.com/MohammadYounes/rtlcss>, <https://github.com/vkalinichev/postcss-rtl>, 또는 <https://github.com/elchininet/postcss-rtlcss>과 같은 RTLCSS PostCSS 플러그인을 사용하세요. CSS 전문성 문제를 방지하기 위해 `:where([dir="ltr"])``:where([dir="rtl"])`을 접두사로 사용하여 PostCSS 플러그인을 구성해야 합니다. RTL 지원을 위해, 구성 파일에 `dir: 'rtl'`을 지정하고 <https://github.com/MohammadYounes/rtlcss>, <https://github.com/vkalinichev/postcss-rtl> 또는 <https://github.com/elchininet/postcss-rtlcss>와 같은 RTLCSS PostCSS 플러그인을 사용하세요. PostCSS 플러그인을 구성하여 CSS 명시성 문제를 방지하기 위해 `:where([dir="ltr"])``:where([dir="rtl"])`을 접두사로 사용해야 합니다.

@ -1,30 +1,30 @@
# 마크다운 확장 {#markdown-extensions} # 마크다운 확장 기능 {#markdown-extensions}
VitePress는 내장된 마크다운 확장을 제공합니다. VitePress는 내장된 마크다운 확장 기능을 제공합니다.
## 헤더 앵커 {#header-anchors} ## 헤더 앵커 {#header-anchors}
헤더에는 자동으로 앵커 링크가 적용됩니다. 앵커 렌더링은 `markdown.anchor` 옵션을 사용하여 구성할 수 있습니다. 헤더에는 자동으로 앵커 링크가 적용됩니다. 앵커 렌더링은 `markdown.anchor` 옵션을 사용하여 구성할 수 있습니다.
### 사용자 정의 앵커 {#custom-anchors} ### 커스텀 앵커 {#custom-anchors}
자동 생성된 것 대신 헤더에 대한 사용자 정의 앵커 태그를 지정하려면, 헤딩에 접미사를 추가하세요: 자동 생성된 앵커 대신 커스텀 앵커 태그를 지정하려면 헤딩에 접미사를 추가하세요:
``` ```
# 사용자 정의 앵커 사용 {#my-anchor} # Using custom anchors {#my-anchor}
``` ```
이를 통해 기본값인 `#using-custom-anchors` 대신 `#my-anchor`로 헤딩에 링크할 수 있습니다. 이를 통해 기본값인 `#using-custom-anchors` 대신 `#my-anchor`로 헤딩에 링크할 수 있습니다.
## 링크 {#links} ## 링크 {#links}
내부 및 외부 링크는 특별한 처리를 받습니다. 내부 링크와 외부 링크 모두 특별하게 취급됩니다.
### 내부 링크 {#internal-links} ### 내부 링크 {#internal-links}
내부 링크는 SPA 탐색을 위한 라우터 링크로 변환됩니다. 또한, 각 하위 디렉토리에 포함된 모든 `index.md`는 자동으로 `index.html`로 변환되며, 해당 URL은 `/`니다. 내부 링크는 SPA 탐색을 위한 라우터 링크로 변환됩니다. 또한 각 하위 디렉터리에 포함된 모든 `index.md`는 자동으로 `index.html`로 변환되며, 해당 URL은 `/`로 설정됩니다.
예를 들어, 다음과 같은 디렉토리 구조가 주어져 있습니다: 예를 들어, 다음과 같은 디렉터리 구조가 주어진 경우:
``` ```
. .
@ -39,12 +39,12 @@ VitePress는 내장된 마크다운 확장을 제공합니다.
└─ four.md └─ four.md
``` ```
그리고 `foo/one.md`에 있다고 하면: 그리고 현재 `foo/one.md`에 있다고 가정하면:
```md ```md
[](/) <!-- 사용자를 루트 index.md로 보냅니다 --> [Home](/) <!-- 사용자를 루트 index.md로 보냅니다 -->
[foo](/foo/) <!-- foo 디렉토리의 index.html로 보냅니다 --> [foo](/foo/) <!-- foo 디렉토리의 index.html로 보냅니다 -->
[foo 헤딩](./#heading) <!-- foo index 파일의 헤딩으로 앵커링합니다 --> [foo heading](./#heading) <!-- foo index 파일의 헤딩으로 앵커링합니다 -->
[bar - three](../bar/three) <!-- 확장자를 생략할 수 있습니다 --> [bar - three](../bar/three) <!-- 확장자를 생략할 수 있습니다 -->
[bar - three](../bar/three.md) <!-- .md를 추가할 수 있습니다 --> [bar - three](../bar/three.md) <!-- .md를 추가할 수 있습니다 -->
[bar - four](../bar/four.html) <!-- 또는 .html을 추가할 수 있습니다 --> [bar - four](../bar/four.html) <!-- 또는 .html을 추가할 수 있습니다 -->
@ -52,51 +52,51 @@ VitePress는 내장된 마크다운 확장을 제공합니다.
### 페이지 접미사 {#page-suffix} ### 페이지 접미사 {#page-suffix}
기본적으로 페이지와 내부 링크는 `.html` 접미사를 가지고 생성됩니다. 페이지와 내부 링크는 기본적으로 `.html` 접미사와 함께 생성됩니다.
### 외부 링크 {#external-links} ### 외부 링크 {#external-links}
외부 링크는 자동으로 `target="_blank" rel="noreferrer"`받습니다: 외부 링크는 자동으로 `target="_blank" rel="noreferrer"`갖습니다.
- [vuejs.org](https://vuejs.org) - [vuejs.org](https://vuejs.org)
- [GitHub에서 VitePress](https://github.com/vuejs/vitepress) - [VitePress on GitHub](https://github.com/vuejs/vitepress)
## 프론트매터 {#frontmatter} ## 전문 {#frontmatter}
[YAML 프론트매터](https://jekyllrb.com/docs/front-matter/)가 기본적으로 지원됩니다: [YAML 전문](https://jekyllrb.com/docs/front-matter/)이 기본적으로 지원됩니다:
```yaml ```yaml
--- ---
title: 해커처럼 블로깅하기 title: Blogging Like a Hacker
lang: en-US lang: en-US
--- ---
``` ```
이 데이터는 페이지의 나머지 부분, 모든 사용자 정의 및 테마 구성 요소와 함께 사용할 수 있습니다. 이 데이터는 페이지의 나머지 부분과 모든 커스텀 및 테마 컴포넌트에서 사용할 수 있습니다.
자세한 내용은 [프론트매터](../reference/frontmatter-config)를 참조하세요. 자세한 내용은 [전문](../reference/frontmatter-config)을 참고하세요.
## GitHub 스타일 테이블 {#github-style-tables} ## GitHub 스타일 테이블 {#github-style-tables}
**입력** **입력**
```md ```md
| 테이블 | 은 | 멋져 | | Tables | Are | Cool |
| ------------- | :-----------: | ----: | | ------------- | :-----------: | ----: |
| 3열은 | 오른쪽 정렬입니다 | $1600 | | col 3 is | right-aligned | $1600 |
| 2열은 | 가운데 정렬입니다 | $12 | | col 2 is | centered | $12 |
| 얼룩말 줄무늬 | 멋져요 | $1 | | zebra stripes | are neat | $1 |
``` ```
**출력** **출력**
| 테이블 | 은 | 멋져 | | Tables | Are | Cool |
| ------------- | :-----------: | -----: | | ------------- | :-----------: | ----: |
| 3열은 | 오른쪽 정렬입니다 | \$1600 | | col 3 is | right-aligned | $1600 |
| 2열은 | 가운데 정렬입니다 | \$12 | | col 2 is | centered | $12 |
| 얼룩말 줄무늬 | 멋져요 | \$1 | | zebra stripes | are neat | $1 |
## Emoji :tada: ## 이모지 :tada: {#emoji}
**입력** **입력**
@ -122,11 +122,11 @@ lang: en-US
[[toc]] [[toc]]
TOC의 렌더링은 `markdown.toc` 옵션을 사용하여 구성할 수 있습니다. 목차의 렌더링은 `markdown.toc` 옵션을 사용하여 구성할 수 있습니다.
## 사용자 정의 컨테이너 {#custom-containers} ## 커스텀 컨테이너 {#custom-containers}
사용자 정의 컨테이너는 그들의 유형, 제목, 그리고 내용에 의해 정의될 수 있습니다. 커스텀 컨테이너는 타입, 제목, 콘텐츠를 정의할 수 있습니다.
### 기본 제목 {#default-title} ### 기본 제목 {#default-title}
@ -178,7 +178,7 @@ TOC의 렌더링은 `markdown.toc` 옵션을 사용하여 구성할 수 있습
### 사용자 정의 제목 {#custom-title} ### 사용자 정의 제목 {#custom-title}
컨테이너의 "유형" 바로 뒤에 텍스트를 추가하여 사용자 정의 제목을 설정할 수 있습니다. 컨테이너의 "타입" 바로 뒤에 텍스트를 추가하여 커스텀 제목을 설정할 수 있습니다.
**입력** **입력**
@ -206,7 +206,7 @@ console.log('Hello, VitePress!')
``` ```
::: :::
한, 사이트 구성에서 다음과 같은 내용을 추가하여 전역적으로 사용자 정의 제목을 설정할 수 있습니다. 영어로 작성하지 않는 경우 유용합니다: 는 사이트 구성에 다음을 추가하여 커스텀 제목을 전역적으로 설정할 수 있습니다. 이는 제목을 영어로 작성하지 않을 경우 유용합니다:
```ts ```ts
// config.ts // config.ts
@ -227,7 +227,7 @@ export default defineConfig({
### `raw` ### `raw`
VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용될 수 있는 특수 컨테이너입니다. 이는 특히 컴포넌트 라이브러리를 문서화할 때 유용합니다. 더 나은 격리를 위해 [whyframe](https://whyframe.dev/docs/integrations/vitepress)을 확인해보세요. 이것은 VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용할 수 있는 특별한 컨테이너입니다. 컴포넌트 라이브러리를 문서화할 때 특히 유용합니다. 더 나은 분리를 위해 [whyframe](https://whyframe.dev/docs/integrations/vitepress)을 참고해 볼 수 있습니다.
**문법** **문법**
@ -237,15 +237,15 @@ VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용될 수
::: :::
``` ```
`vp-raw` 클래스는 직접 요소에 사용될 수도 있습니다. 현재 스타일 격리는 선택 사항입니다: `vp-raw` 클래스는 엘리먼트에 직접 사용할 수도 있습니다. 스타일 분리는 현재 선택 사항입니다:
- 원하는 패키지 관리자로 `postcss`를 설치하세요: - 선호하는 패키지 매니저를 사용하여 `postcss`를 설치하세요:
```sh ```sh
$ npm add -D postcss $ npm add -D postcss
``` ```
- `docs/postcss.config.mjs`라는 파일을 만들고 이것을 추가하세요: - `docs/postcss.config.mjs`라는 파일을 만들고 다음 내용을 추가하세요:
```js ```js
import { postcssIsolateStyles } from 'vitepress' import { postcssIsolateStyles } from 'vitepress'
@ -255,7 +255,7 @@ VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용될 수
} }
``` ```
이것은 내부적으로 [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config)를 사용합니다. 이렇게 옵션을 전달할 수 있습니다: 이것은 기본적으로 [`postcss-prefix-selector`](https://github.com/RadValentin/postcss-prefix-selector)를 사용합니다. 다음과 같이 옵션을 전달할 수 있습니다:
```js ```js
postcssIsolateStyles({ postcssIsolateStyles({
@ -263,45 +263,45 @@ VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용될 수
}) })
``` ```
## GitHub 스타일 경고 {#github-flavored-alerts} ## GitHub 스타일 알림 {#github-flavored-alerts}
VitePress는 [GitHub 스타일 경고](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)를 콜아웃으로 렌더링하는 것을 지원합니다. 이것은 [사용자 정의 컨테이너](#custom-containers)와 같은 방식으로 렌더링됩니다. VitePress는 [GitHub 스타일 알림](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)을 콜아웃으로 렌더링하는 것을 지원합니다. 이것은 [커스텀 컨테이너](#custom-containers)와 같은 방식으로 렌더링됩니다.
```md ```md
> [!NOTE] > [!NOTE]
> 사용자가 훑어보더라도 알아야 할 정보를 강조합니다. > 문서를 빠르게 탐색할 때에도 사용자가 놓치지 말아야 할 중요한 정보.
> [!TIP] > [!TIP]
> 사용자가 더 성공할 수 있도록 도움이 되는 선택적 정보입니다. > 사용자가 보다 원활하게 목표를 달성하는 데 도움이 되는 정보
> [!IMPORTANT] > [!IMPORTANT]
> 사용자가 성공하기 위해 필수적인 중요 정보입니다. > 사용자가 목표를 달성하는 데 중요한 정보.
> [!WARNING] > [!WARNING]
> 잠재적인 위험으로 인해 즉각적인 사용자의 주의를 요하는 중요한 내용입니다. > 위험 가능성 때문에 사용자의 즉각적인 주의가 필요한 중요한 정보.
> [!CAUTION] > [!CAUTION]
> 행동의 부정적인 잠재적 결과입니다. > 실행할 경우 잠재적으로 부정적인 결과를 생성한다는 것을 알리는 정보.
``` ```
> [!NOTE] > [!NOTE]
> 사용자가 훑어보더라도 알아야 할 정보를 강조합니다. > 문서를 빠르게 탐색할 때에도 사용자가 놓치지 말아야 할 중요한 정보.
> [!TIP] > [!TIP]
> 사용자가 더 성공할 수 있도록 도움이 되는 선택적 정보입니다. > 사용자가 보다 원활하게 목표를 달성하는 데 도움이 되는 정보
> [!IMPORTANT] > [!IMPORTANT]
> 사용자가 성공하기 위해 필수적인 중요 정보입니다. > 사용자가 목표를 달성하는 데 중요한 정보.
> [!WARNING] > [!WARNING]
> 잠재적인 위험으로 인해 즉각적인 사용자의 주의를 요하는 중요한 내용입니다. > 위험 가능성 때문에 사용자의 즉각적인 주의가 필요한 중요한 정보.
> [!CAUTION] > [!CAUTION]
> 행동의 부정적인 잠재적 결과입니다. > 실행할 경우 잠재적으로 부정적인 결과를 생성한다는 것을 알리는 정보.
## 코드 블록 내 구문 강조 {#syntax-highlighting-in-code-blocks} ## 코드 블록 내 구문 강조 {#syntax-highlighting-in-code-blocks}
VitePress는 마크다운 코드 블록 내 언어 문법을 색상이 있는 텍스트로 강조하는 데 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. Shiki는 다양한 프로그래밍 언어를 지원합니다. 코드 블록의 시작 백틱에 유효한 언어 별칭을 추가하기만 하면 됩니다: VitePress는 마크다운 코드 블록 내 언어 문법을 색상이 있는 텍스트로 강조하기 위해 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. Shiki는 다양한 프로그래밍 언어를 지원합니다. 코드 블록의 시작 백틱에 유효한 언어 별칭을 추가하기만 하면 됩니다:
**입력** **입력**
@ -341,9 +341,9 @@ export default {
</ul> </ul>
``` ```
Shiki의 저장소에서 사용 가능한 [유효한 언어 목록](https://shiki.style/languages)이 제공됩니다. Shiki의 리포지터리에서 사용 가능한 [유효한 언어 목록](https://shiki.style/languages)이 제공됩니다.
또한 응용 프로그램 구성에서 구문 강조 테마를 사용자 지정할 수 있습니다. 자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참하세요. 또한 애플리케이션 구성에서 구문 강조 테마를 커스텀 할 수 있습니다. 자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참하세요.
## 코드 블록에서 라인 강조 {#line-highlighting-in-code-blocks} ## 코드 블록에서 라인 강조 {#line-highlighting-in-code-blocks}
@ -373,11 +373,11 @@ export default {
} }
``` ```
단일 라인 뿐만 아니라 여러 개의 단일 라인, 범위 또는 둘 다 지정할 수도 있습니다: 단일 라인 뿐만 아니라 여러 개의 단일 라인, 범위 또는 둘 다 지정할 수도 있습니다:
- 라인 범위: 예를 들어 `{5-8}`, `{3-10}`, `{10-17}` - 라인 범위: `{5-8}`, `{3-10}`, `{10-17}`
- 다수의 단일 라인: 예를 들어 `{4,7,9}` - 여러 단일 라인: `{4,7,9}`
- 라인 범위 및 단일 라인: 예를 들어 `{4,7-13,16,23-27,40}` - 라인 범위와 단일 라인: `{4,7-13,16,23-27,40}`
**입력** **입력**
@ -413,7 +413,7 @@ export default { // 강조됨
} }
``` ```
한, `// [!code highlight]` 주석을 사용하여 직접 라인에 강조를 추가할 수 있습니다. `// [!code highlight]` 주석을 사용하여 직접 라인에 강조를 추가할 수 있습니다.
**입력** **입력**
@ -445,7 +445,7 @@ export default {
`// [!code focus]` 주석을 라인에 추가하면 해당 라인이 포커싱되고 코드의 다른 부분은 흐릿하게 처리됩니다. `// [!code focus]` 주석을 라인에 추가하면 해당 라인이 포커싱되고 코드의 다른 부분은 흐릿하게 처리됩니다.
추가로, `// [!code focus:<lines>]`를 사용하여 포커싱할 라인 수를 정의할 수 있습니다. 추가로 `// [!code focus:<lines>]`를 사용하여 포커싱할 라인 수를 정의할 수 있습니다.
**입력** **입력**
@ -473,7 +473,7 @@ export default {
} }
``` ```
## 코드 블록 내 컬러 차이점 {#colored-diffs-in-code-blocks} ## 코드 블록 내 차이점 색 강조 {#colored-diffs-in-code-blocks}
`// [!code --]` 또는 `// [!code ++]` 주석을 라인에 추가하면 해당 라인의 차이점을 나타내며, 코드 블록의 색상을 유지합니다. `// [!code --]` 또는 `// [!code ++]` 주석을 라인에 추가하면 해당 라인의 차이점을 나타내며, 코드 블록의 색상을 유지합니다.
@ -507,7 +507,7 @@ export default {
## 코드 블록 내 오류 및 경고 {#errors-and-warnings-in-code-blocks} ## 코드 블록 내 오류 및 경고 {#errors-and-warnings-in-code-blocks}
`// [!code warning]` 또는 `// [!code error]` 주석을 라인에 추가하면 해당 색깔에 따라 라인이 색칠됩니다. `// [!code warning]` 또는 `// [!code error]` 주석을 라인에 추가하면 해당 라인이 색칠됩니다.
**입력** **입력**
@ -549,11 +549,11 @@ export default {
} }
``` ```
자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참하세요. 자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참하세요.
또한 울타리 코드 블록에 `:line-numbers` / `:no-line-numbers` 마크를 추가하여 구성에서 설정한 값을 재정의할 수 있습니다. 구성에서 지정한 값을 무시하려면 펜싱 코드 블록에 `:line-numbers` / `:no-line-numbers` 마크를 추가하면 됩니다.
또한 `:line-numbers` 뒤에 `=`를 추가하여 시작 라인 번호를 사용자 정의할 수 있습니다. 예를 들어, `: 또한 `=`를 `:line-numbers` 뒤에 추가하여 시작 라인 번호를 커스텀 할 수도 있습니다. 예를 들어 `:line-numbers=2`는 코드 블록의 라인 번호가 `2`부터 시작함을 의미합니다.
**입력** **입력**
@ -605,10 +605,10 @@ const line4 = 'This is line 4'
<<< @/파일경로 <<< @/파일경로
``` ```
다음과 같이 [라인 하이라이팅](#line-highlighting-in-code-blocks)도 지원합니다: 다음과 같이 [라인 강조](#line-highlighting-in-code-blocks)도 지원합니다:
```md ```md
<<< @/파일경로{하이라이트할 라인} <<< @/파일경로{강조 할 라인}
``` ```
**입력** **입력**
@ -626,7 +626,7 @@ const line4 = 'This is line 4'
<<< @/snippets/snippet.js{2} <<< @/snippets/snippet.js{2}
::: tip ::: tip
'@'의 값은 소스 루트에 해당합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우가 아니면 다릅니다. 상대 경로에서도 가져올 수 있습니다: `@`의 값은 소스 루트에 해당합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우에는 다릅니다. 상대 경로에서도 가져올 수 있습니다:
```md ```md
<<< ../snippets/snippet.js <<< ../snippets/snippet.js
@ -655,7 +655,7 @@ const line4 = 'This is line 4'
```md ```md
<<< @/snippets/snippet.cs{c#} <<< @/snippets/snippet.cs{c#}
<!-- 라인 하이라이팅과 함께: --> <!-- 라인 강조와 함께: -->
<<< @/snippets/snippet.cs{1,2,4-6 c#} <<< @/snippets/snippet.cs{1,2,4-6 c#}
@ -756,46 +756,46 @@ export default config
## 마크다운 파일 포함 {#markdown-file-inclusion} ## 마크다운 파일 포함 {#markdown-file-inclusion}
다른 마크다운 파일에 마크다운 파일을 포함시킬 수 있으며, 중첩도 가능합니다. 마크다운 파일을 다른 마크다운 파일에 포함시킬 수 있으며, 중첩도 가능합니다.
::: tip ::: tip
마크다운 경로 앞에 '@'을 붙이면 소스 루트로 작용합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우가 아닙니다. 마크다운 경로 앞에 `@`를 붙일 수도 있으며, 이는 소스 루트로 작동합니다. 기본적으로 이는 VitePress 프로젝트 루트이며, `srcDir`이 구성되지 않은 경우입니다.
::: :::
예를 들어, 다음과 같이 상대적인 마크다운 파일을 포함 수 있습니다: 다음과 같이 상대적인 마크다운 파일을 포함시킬 수 있습니다:
**입력** **입력**
```md ```md
# 문서 # Docs
## 기초 ## Basics
<!--@include: ./parts/basics.md--> <!--@include: ./parts/basics.md-->
``` ```
**부분 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)
```md ```md
일부 시작하는 방법입니다. Some getting started stuff.
### 구성 ### Configuration
`.foorc.json`을 사용하여 생성할 수 있습니다. Can be created using `.foorc.json`.
``` ```
**동일한 코드** **동일한 코드**
```md ```md
# 문서 # Docs
## 기초 ## Basics
일부 시작하는 방법입니다. Some getting started stuff.
### 구성 ### Configuration
`.foorc.json`을 사용하여 생성할 수 있습니다. Can be created using `.foorc.json`.
``` ```
라인 범위 선택도 지원합니다: 라인 범위 선택도 지원합니다:
@ -803,38 +803,38 @@ export default config
**입력** **입력**
```md ```md
# 문서 # Docs
## 기초 ## Basics
<!--@include: ./parts/basics.md{3,}--> <!--@include: ./parts/basics.md{3,}-->
``` ```
**부분 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)
```md ```md
일부 시작하는 방법입니다. Some getting started stuff.
### 구성 ### Configuration
`.foorc.json`을 사용하여 생성할 수 있습니다. Can be created using `.foorc.json`.
``` ```
**동일한 코드** **동일한 코드**
```md ```md
# 문서 # Docs
## 기초 ## Basics
### 구성 ### Configuration
`.foorc.json`을 사용하여 생성할 수 있습니다. Can be created using `.foorc.json`.
``` ```
선택된 라인 범위의 형식은: `{3,}`, `{,10}`, `{1,10}`이 될 수 있습니다. 선택된 라인 범위의 형식은 `{3,}`, `{,10}`, `{1,10}`이 될 수 있습니다.
VS Code 영역을 사용하여 코드 파일의 해당 부분만 포함할 수도 있습니다. 파일 경로 뒤에 `#`를 붙여 사용자 정의 영역 이름을 제공할 수 있습니다: [VS Code 리전](https://code.visualstudio.com/docs/editor/codebasics#_folding)을 사용하여 코드 파일의 해당 부분만 포함할 수도 있습니다. 파일 경로 뒤에 `#`를 붙이고 커스텀 영역 이름을 제공할 수 있습니다:
**입력** **입력**
@ -847,7 +847,7 @@ VS Code 영역을 사용하여 코드 파일의 해당 부분만 포함할 수
<!--@include: ./parts/basics.md#basic-usage{5,}--> <!--@include: ./parts/basics.md#basic-usage{5,}-->
``` ```
**부분 파일** (`parts/basics.md`) **해당 파일** (`parts/basics.md`)
```md ```md
<!-- #region basic-usage --> <!-- #region basic-usage -->
@ -859,7 +859,7 @@ VS Code 영역을 사용하여 코드 파일의 해당 부분만 포함할 수
<!-- #endregion basic-usage --> <!-- #endregion basic-usage -->
``` ```
**동한 코드** **동한 코드**
```md ```md
# Docs # Docs
@ -872,12 +872,12 @@ VS Code 영역을 사용하여 코드 파일의 해당 부분만 포함할 수
``` ```
::: warning ::: warning
파일이 없는 경우 오류를 발생시키지 않으니, 이 기능을 사용할 때는 내용이 예상대로 렌더링되고 있는지 확인해야 합니다. 파일이 존재하지 않더라도 오류가 발생하지 않는다는 점에 유의하십시오. 따라서 이 기능을 사용할 때 내용이 예상대로 렌더링되고 있는지 확인해야 합니다.
::: :::
## 수식 {#math-equations} ## 수식 {#math-equations}
현재 선택 사항입니다. 활성화하려면 `markdown-it-mathjax3`를 설치하고 설정 파일에서 `markdown.math``true`로 설정해야 합니다: 선택 사항입니다. 활성화하려면 `markdown-it-mathjax3`를 설치하고 설정 파일에서 `markdown.math``true`로 설정해야 합니다:
```sh ```sh
npm add -D markdown-it-mathjax3 npm add -D markdown-it-mathjax3
@ -895,8 +895,8 @@ export default {
**입력** **입력**
```md ```md
$a \ne 0$일 때, $(ax^2 + bx + c = 0)$의 두 해는 $a \ne 0$ 일 때, $(ax^2 + bx + c = 0)$의 두 해는 다음과 같습니다:
$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$입니다 $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$
**맥스웰 방정식:** **맥스웰 방정식:**
@ -922,7 +922,7 @@ $$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$
## 이미지 지연 로딩 {#image-lazy-loading} ## 이미지 지연 로딩 {#image-lazy-loading}
마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 설정 파일에서 `lazyLoading``true`로 설정하세요: 마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 구성 파일에서 `lazyLoading``true`로 설정하세요:
```js ```js
export default { export default {
@ -937,7 +937,7 @@ export default {
## 고급 설정 {#advanced-configuration} ## 고급 설정 {#advanced-configuration}
VitePress는 마크다운 렌더링을 위해 [markdown-it](https://github.com/markdown-it/markdown-it)을 사용합니다. 위의 확장 프로그램 대부분은 커스텀 플러그인을 통해 구현됩니다. `.vitepress/config.js``markdown` 옵션을 사용하여 `markdown-it` 인스턴스를 더욱 커스터마이징할 수 있습니다: VitePress는 마크다운 렌더러로 [markdown-it](https://github.com/markdown-it/markdown-it)을 사용합니다. 위의 많은 확장 기능은 커스텀 플러그인을 통해 구현됩니다. `.vitepress/config.js``markdown` 옵션을 사용하여 `markdown-it` 인스턴스를 추가로 커스터마이즈할 수 있습니다:
```js ```js
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -964,4 +964,4 @@ export default defineConfig({
}) })
``` ```
[설정 참조: 앱 설정](../reference/site-config#markdown)에서 구성 가능한 속성의 전체 목록을 확인할 수 있습니다. 구성 가능한 프로퍼티의 전체 목록은 [레퍼런스: 앱 구성](../reference/site-config#markdown)에서 확인하세요.

@ -1,23 +1,23 @@
# MPA 모드 <Badge type="warning" text="실험적" /> {#mpa-mode} # MPA 모드 <Badge type="warning" text="실험적" /> {#mpa-mode}
MPA(멀티 페이지 애플리케이션) 모드는 `vitepress build --mpa` 명령어를 통해 또는 `mpa: true` 옵션을 통해 설정 파일에서 활성화할 수 있습니다. MPA (다중 페이지 애플리케이션) 모드는 명령줄에서 `vitepress build --mpa`를 통해 활성화할 수 있으며, 구성 파일에서 `mpa: true` 옵션을 통해서도 활성화할 수 있습니다.
MPA 모드에서는 모든 페이지가 기본적으로 JavaScript 없이 렌더링됩니다. 결과적으로, 생산 사이트는 감사 도구로부터 초기 방문 성능 점수를 더 좋게 받을 가능성이 높습니다. MPA 모드에서는 모든 페이지가 기본적으로 JavaScript 없이 렌더링됩니다. 그 결과, 프로덕션 사이트는 감사 도구로부터 초기 방문 성능 점수가 더 좋을 가능성이 있습니다.
그러나, SPA 네비게이션이 없기 때문에, 페이지 간 링크는 전체 페이지를 다시 로드하게 합니다. MPA 모드에서의 포스트-로드 탐색은 SPA 모드처럼 즉각적으로 느껴지지 않을 것입니다. 그러나 SPA 탐색이 없기 때문에 페이지 간 링크는 전체 페이지를 새로 고침합니다. MPA 모드에서의 포스트-로드 탐색은 SPA 모드만큼 즉각적으로 느껴지지 않을 것입니다.
또한, 기본적으로 JS 없음을 의미하는 것은 여러분이 본질적으로 Vue를 서버 측 템플리팅 언어로만 사용하고 있다는 것을 의미합니다. 브라우저에서는 이벤트 핸들러가 연결되지 않으므로, 상호 작용성이 없을 것입니다. 클라이언트 측 JavaScript를 로드하려면 특별한 `<script client>` 태그를 사용해야 합니다: 또한 기본적으로 JS가 없다는 것은 Vue를 순전히 서버 사이드 템플릿 언어로 사용하고 있다는 것을 의미합니다. 브라우저에서는 이벤트 핸들러가 첨부되지 않으므로 상호작용이 없습니다. 클라이언트 사이드 JavaScript를 로드하려면 특별한 `<script client>` 태그를 사용해야 합니다:
```html ```html
<script client> <script client>
document.querySelector('h1').addEventListener('click', () => { document.querySelector('h1').addEventListener('click', () => {
console.log('클라이언트 측 JavaScript!') console.log('client side JavaScript!')
}) })
</script> </script>
# 안녕하세요 # Hello
``` ```
`<script client>`는 VitePress 전용 기능으로, Vue 기능이 아닙니다. `.md``.vue` 파일 모두에서 작동하지만 MPA 모드에서만 작동합니다. 모든 테마 컴포넌트의 클라이언트 스크립트는 함께 번들링되며, 특정 페이지의 클라이언트 스크립트는 해당 페이지만을 위해 분할됩니다. `<script client>`는 VitePress 전용 기능이며, Vue 기능이 아닙니다. 이 기능은 `.md` 파일과 `.vue` 파일에서 모두 작동하지만, MPA 모드에서만 사용됩니다. 모든 테마 컴포넌트의 클라이언트 스크립트는 함께 번들링되지만, 특정 페이지에 대한 클라이언트 스크립트는 개별적으로 처리됩니다.
`<script client>`**Vue 컴포넌트 코드로 평가되지 않는다**는 점을 주의하세요: 이것은 일반 JavaScript 모듈로 처리됩니다. 이러한 이유로, MPA 모드는 여러분의 사이트가 절대적으로 최소한의 클라이언트 측 상호작용만을 필요로 할 때만 사용되어야 합니다. `<script client>`**Vue 컴포넌트 코드로 평가되지 않음**을 유의하십시오. 이는 단순한 JavaScript 모듈로 처리됩니다. 이러한 이유로, 사이트가 최소한의 클라이언트 사이드 상호작용을 요구하는 경우에만 MPA 모드를 사용하는 것이 좋습니다.

@ -1,48 +1,48 @@
--- ---
개요: 심층 outline: deep
--- ---
# 라우팅 {#routing} # 라우팅 {#routing}
## 파일 기반 라우팅 {#file-based-routing} ## 파일 기반 라우팅 {#file-based-routing}
VitePress는 파일 기반 라우팅을 사용하므로, 생성된 HTML 페이지는 소스 마크다운 파일의 디렉토리 구조에서 매핑됩니다. 예를 들어, 다음과 같은 디렉토리 구조가 주어진 경우: VitePress는 파일 기반 라우팅을 사용하므로, 생성된 HTML 페이지는 소스 마크다운 파일의 디렉토리 구조에서 매핑됩니다. 예를 들어, 다음과 같은 디렉토리 구조가 있다고 가정하면:
``` ```
. .
├─ 가이드 ├─ guide
│ ├─ 시작하기.md │ ├─ getting-started.md
│ └─ index.md │ └─ index.md
├─ index.md ├─ index.md
└─ 프롤로그.md └─ prologue.md
``` ```
생성된 HTML 페이지는 다음과 같습니다: 생성된 HTML 페이지는 다음과 같습니다:
``` ```
index.md --> /index.html (접근 가능 경로 /) index.md --> /index.html (/ 로 접근 가능)
프롤로그.md --> /프롤로그.html prologue.md --> /prologue.html
가이드/index.md --> /가이드/index.html (접근 가능 경로 /가이드/) guide/index.md --> /guide/index.html (/guide/ 로 접근 가능)
가이드/시작하기.md --> /가이드/시작하기.html guide/getting-started.md --> /guide/getting-started.html
``` ```
결과적으로 생성된 HTML은 정적 파일을 제공할 수 있는 모든 웹 서버에서 호스팅할 수 있습니다. 생성된 HTML은 정적 파일을 제공할 수 있는 모든 웹 서버에서 호스팅할 수 있습니다.
## 루트와 소스 디렉토리 {#root-and-source-directory} ## 루트와 소스 디렉토리 {#root-and-source-directory}
VitePress 프로젝트의 파일 구조에 두 가지 중요한 개념이 있습니다: **프로젝트 루트**와 **소스 디렉토리**. VitePress 프로젝트의 파일 구조에 두 가지 중요한 개념이 있습니다: **프로젝트 루트**와 **소스 디렉토리**입니다.
### 프로젝트 루트 {#project-root} ### 프로젝트 루트 {#project-root}
프로젝트 루트는 VitePress가 `.vitepress` 특수 디렉토리를 찾으려고 시도하는 위치입니다. `.vitepress` 디렉토리는 VitePress의 설정 파일, 개발 서버 캐시, 빌드 출력, 그리고 선택적 테마 커스터마이징 코드를 위한 예약된 위치입니다. 프로젝트 루트는 VitePress가 `.vitepress` 특수 디렉토리를 찾으려고 하는 위치입니다. `.vitepress` 디렉토리는 VitePress의 구성 파일, 개발 서버 캐시, 빌드 출력물, 그리고 선택적인 커스텀 테마 코드를 위한 예약된 위치입니다.
명령 줄에서 `vitepress dev``vitepress build`를 실행할 때, VitePress는 현재 작업 디렉토리를 프로젝트 루트로 사용합니다. 서브 디렉토리를 루트로 지정하려면 상대 경로를 명령에 전달해야 합니다. 예를 들어, VitePress 프로젝트가 `./docs`에 위치한 경우, `vitepress dev docs`를 실행해야 합니다: 명령줄에서 `vitepress dev``vitepress build`를 실행하면 VitePress는 현재 작업 디렉토리를 프로젝트 루트로 사용합니다. 서브 디렉토리를 루트로 지정하려면 명령어에 상대 경로를 전달해야 합니다. 예를 들어, VitePress 프로젝트가 `./docs`에 위치한 경우, `vitepress dev docs`를 실행해야 합니다:
``` ```
. .
├─ docs # 프로젝트 루트 ├─ docs # 프로젝트 루트
│ ├─ .vitepress # 설정 디렉토리 │ ├─ .vitepress # 구성 폴더
│ ├─ 시작하기.md │ ├─ getting-started.md
│ └─ index.md │ └─ index.md
└─ ... └─ ...
``` ```
@ -51,53 +51,53 @@ VitePress 프로젝트의 파일 구조에서 두 가지 중요한 개념이 있
vitepress dev docs vitepress dev docs
``` ```
것은 다음과 같은 소스-HTML 매핑을 결과로 합니다: 렇게 하면 다음과 같은 소스에서 HTML로의 매핑이 이루어집니다:
``` ```
docs/index.md --> /index.html (접근 가능 경로 /) docs/index.md --> /index.html (/ 로 접근 가능)
docs/시작하기.md --> /시작하기.html docs/getting-started.md --> /getting-started.html
``` ```
### 소스 디렉토리 {#source-directory} ### 소스 디렉토리 {#source-directory}
소스 디렉토리는 마크다운 소스 파일이 위치하는 곳입니다. 기본적으로, 이는 프로젝트 루트와 동일합니다. 하지만, [`srcDir`](../reference/site-config#srcdir) 설정 옵션을 통해 이를 구성할 수 있습니다. 소스 디렉터리는 마크다운 소스 파일이 저장되는 위치입니다. 기본적으로 프로젝트 루트와 동일합니다. 그러나 [`srcDir`](../reference/site-config#srcdir) 구성 옵션으로 설정할 수 있습니다.
`srcDir` 옵션은 프로젝트 루트에 상대적으로 해결됩니다. 예를 들어, `srcDir: 'src'`로 설정하면, 파일 구조는 다음과 같아질 것입니다: `srcDir` 옵션은 프로젝트 루트를 기준으로 해석됩니다. 예를 들어, `srcDir: 'src'`로 설정하면 파일 구조는 다음과 같이 됩니다:
``` ```
. # 프로젝트 루트 . # 프로젝트 루트
├─ .vitepress # 설정 디렉토 ├─ .vitepress # 구성 디렉터
└─ src # 소스 디렉 └─ src # 소스 디렉
├─ 시작하기.md ├─ getting-started.md
└─ index.md └─ index.md
``` ```
결과적으로 생성된 소스-HTML 매핑: 소스에서 HTML로 매핑된 결과:
``` ```
src/index.md --> /index.html (접근 가능 경로 /) src/index.md --> /index.html (/ 로 접근 가능)
src/시작하기.md --> /시작하기.html src/getting-started.md --> /getting-started.html
``` ```
## 페이지 간 연결 {#linking-between-pages} ## 페이지 간 연결 {#linking-between-pages}
페이지 간 연결 시 절대 경로와 상대 경로를 모두 사용할 수 있습니다. `.md``.html` 확장자 모두 작동하더라도, 파일 확장자를 생략하여 VitePress가 설정에 기반한 최종 URL을 생성하도록 하는 것이 좋은 방법입니다. 페이지 간 링크를 만들 때 절대 경로와 상대 경로 모두 사용할 수 있습니다. `.md``.html` 확장자 모두 작동하지만, VitePress가 구성에 따라 최종 URL을 생성할 수 있도록 파일 확장자를 생략하는 것이 좋은 방법입니다.
```md ```md
<!-- 수행 --> <!-- Do -->
[시작하기](./getting-started) [시작하기](./getting-started)
[시작하기](../guide/getting-started) [시작하기](../guide/getting-started)
<!-- 수행하지 말 것 --> <!-- Don't -->
[시작하기](./getting-started.md) [시작하기](./getting-started.md)
[시작하기](./getting-started.html) [시작하기](./getting-started.html)
``` ```
[Asset Handling](./asset-handling)에서 이미지와 같은 에셋에 연결하는 방법에 대해 자세히 알아보세요. 이미지와 같은 에셋에 링크하는 방법에 대해 더 알아보려면 [에셋 처리](./asset-handling)를 참고하세요.
### VitePress 페이지가 아닌 페이지로 연결 {#linking-to-non-vitepress-pages} ### VitePress 페이지가 아닌 페이지로 연결 {#linking-to-non-vitepress-pages}
VitePress에서 생성하지 않은 사이트의 페이지에 연결하려면, 전체 URL을 사용해야 합니다(새 탭에서 열림) 또는 명시적으로 대상을 지정해야 합니다: VitePress로 생성되지 않은 페이지에 연결하려면 전체 URL(새 탭에서 열림)을 사용하거나 명시적으로 target을 지정해야 합니다:
**입력** **입력**
@ -111,9 +111,9 @@ VitePress에서 생성하지 않은 사이트의 페이지에 연결하려면,
::: tip 참고 ::: tip 참고
마크다운 링크에서 `base`자동으로 URL에 추가됩니다. 즉, base 외부의 페이지에 연결하려면 링크에 `../../pure.html`와 같은 것이 필요합니다(브라우저에 의해 현재 페이지에 상대적으로 해결됨). 마크다운 링크에서 `base`URL 앞에 자동으로 추가됩니다. 이는 기본 경로 외부의 페이지에 링크하려면 링크에 `../../pure.html`과 같은 내용이 필요하다는 것을 의미합니다(브라우저에서 현재 페이지를 기준으로 해석됨).
또는, 앵커 태그 문을 직접 사용할 수 있습니다: 또는 앵커 태그 문을 직접 사용할 수 있습니다:
```md ```md
<a href="/pure.html" target="_self">Link to pure.html</a> <a href="/pure.html" target="_self">Link to pure.html</a>
@ -121,42 +121,42 @@ VitePress에서 생성하지 않은 사이트의 페이지에 연결하려면,
::: :::
## 깨끗한 URL 생성 {#generating-clean-url} ## 간결한 URL 생성 {#generating-clean-url}
::: warning 서버 지원 필요 ::: warning 서버 지원 필요
VitePress로 깨끗한 URL을 제공하려면 서버 측 지원이 필요합니다. VitePress가 간결한 URL을 제공하려면 서버 측 지원이 필요합니다.
::: :::
기본적으로, VitePress는 `.html`로 끝나는 URL로 들어오는 링크를 해결합니다. 그러나, 일부 사용자는 `.html` 확장자 없이 "깨끗한 URL"을 선호할 수 있습니다 - 예를 들어, `example.com/path` 대신 `example.com/path.html`. 기본적으로 VitePress는 `.html`로 끝나는 URL로 들어오는 링크를 처리합니다. 하지만 일부 사용자는 `.html` 확장자가 없는 "간결한 URL"을 선호할 수 있습니다. 예를 들어, `example.com/path.html` 대신 `example.com/path`.
일부 서버나 호스팅 플랫폼(예: Netlify, Vercel, GitHub 페이지)은 `/foo`와 같은 URL을 `/foo.html`로 매핑할 수 있는 기능을 제공합니다(리다이렉트 없이): 일부 서버 또는 호스팅 플랫폼(예: Netlify, Vercel, GitHub Pages)은 리다이렉션 없이 `/foo`와 같은 URL을 `/foo.html`로 매핑할 수 있는 기능을 제공합니다:
- Netlify와 GitHub 페이지는 기본적으로 이 기능을 지원합니다. - Netlify와 GitHub Pages는 기본적으로 이 기능을 지원합니다.
- Vercel은 [`vercel.json`에서 `cleanUrls` 옵션을 활성화](https://vercel.com/docs/concepts/projects/project-configuration#cleanurls)해야 합니다. - Vercel은 [`vercel.json`에서 `cleanUrls` 옵션을 활성화](https://vercel.com/docs/concepts/projects/project-configuration#cleanurls)해야 합니다.
이 기능을 사용할 수 있다면, VitePress의 자체 [`cleanUrls`](../reference/site-config#cleanurls) 설정 옵션을 활성화해서: 이 기능을 사용할 수 있는 경우, VitePress의 자체 [`cleanUrls`](../reference/site-config#cleanurls) 구성 옵션을 활성화해서:
- 페이지 간의 들어오는 링크가 `.html` 확장자 없이 생성됩니다. - 페이지 간의 들어오는 링크가 `.html` 확장자 없이 생성됩니다.
- 현재 경로가 `.html`로 끝나면, 라우터가 클라이언트 측에서 확장자가 없는 경로로 리다이렉트를 수행합니다. - 현재 경로가 `.html`로 끝나는 경우, 라우터가 확장자 없는 경로로 클라이언트 리다이렉션을 수행합니다.
그러나, 서버를 이러한 지원으로 구성할 수 없다면, 다음과 같은 디렉토리 구조를 수동으로 활용해야 합니다: 하지만 서버가 이러한 구성을 지원하지 않는 경우, 다음과 같은 디렉토리 구조를 수동으로 사용해야 합니다:
``` ```
. .
├─ 시작하기 ├─ getting-started
│ └─ index.md │ └─ index.md
├─ 설치 ├─ installation
│ └─ index.md │ └─ index.md
└─ index.md └─ index.md
``` ```
## 라우트 재작성 {#route-rewrites} ## 라우트 재작성 {#route-rewrites}
소스 디렉토리 구조와 생성된 페이지 간의 매핑을 커스터마이즈할 수 있습니다. 복잡한 프로젝트 구조를 가지고 있을 때 유용합니다. 예를 들어, 여러 패키지가 있는 모노레포를 가지고 있고, 소스 파일과 함께 문서를 배치하고 싶다고 가정해 봅시다: 프로젝트의 소스 디렉토리 구조와 생성된 페이지 간의 매핑을 사용자 정의할 수 있습니다. 이는 복잡한 프로젝트 구조를 가질 때 유용합니다. 예를 들어, 여러 패키지가 있는 모노레포를 가지고 있고, 소스 파일과 함께 문서를 다음과 같이 배치하고 싶다고 가정해 봅시다:
``` ```
. .
├─ 패키지 ├─ packages
│ ├─ pkg-a │ ├─ pkg-a
│ │ └─ src │ │ └─ src
│ │ ├─ pkg-a-code.ts │ │ ├─ pkg-a-code.ts
@ -167,67 +167,67 @@ VitePress로 깨끗한 URL을 제공하려면 서버 측 지원이 필요합니
│ └─ pkg-b-docs.md │ └─ pkg-b-docs.md
``` ```
그리고 VitePress 페이지가 다음과 같이 생성되기를 원합니다: 그리고 VitePress 페이지를 다음과 같이 생성하고 싶다고 가정해 봅시다:
``` ```
packages/pkg-a/src/pkg-a-docs.md --> /pkg-a/index.html packages/pkg-a/src/pkg-a-docs.md --> /pkg-a/index.html
packages/pkg-b/src/pkg-b-docs.md --> /pkg-b/index.html packages/pkg-b/src/pkg-b-docs.md --> /pkg-b/index.html
``` ```
이것은 다음과 같이 [`rewrites`](../reference/site-config#rewrites) 옵션을 구성하여 달성할 수 있습니다: 이것은 [`rewrites`](../reference/site-config#rewrites) 옵션을 구성하여 구현할 수 있습니다:
```ts ```ts
// .vitepress/config.js // .vitepress/config.js
export default { export default {
rewrites: { rewrites: {
'패키지/pkg-a/src/pkg-a-docs.md': 'pkg-a/index.md', 'packages/pkg-a/src/pkg-a-docs.md': 'pkg-a/index.md',
'패키지/pkg-b/src/pkg-b-docs.md': 'pkg-b/index.md' 'packages/pkg-b/src/pkg-b-docs.md': 'pkg-b/index.md'
} }
} }
``` ```
`rewrites` 옵션은 동적 라우트 매개변수도 지원합니다. 위의 예제에서, 많은 패키지를 가지고 있다면 모든 경로를 나열하는 것은 장황할 것입니다. 모두 같은 파일 구조를 가지고 있다면, 설정을 다음과 같이 간단하게 할 수 있습니다: `rewrites` 옵션은 동적 라우트 파라미터도 지원합니다. 위 예에서 많은 패키지를 가지고 있다면 모든 경로를 나열하는 것이 번거로울 것입니다. 동일한 파일 구조를 가지고 있는 경우, 구성은 다음과 같이 간단하게 만들 수 있습니다:
```ts ```ts
export default { export default {
rewrites: { rewrites: {
'패키지/:pkg/src/(.*)': ':pkg/index.md' 'packages/:pkg/src/(.*)': ':pkg/index.md'
} }
} }
``` ```
재작성 경로는 `path-to-regexp` 패키지를 사용하여 컴파일됩니다 - 보다 고급 구문에 대해서는 [해당 문서](https://github.com/pillarjs/path-to-regexp#parameters)를 참조하십시오. 라우트 재작성은 `path-to-regexp` 패키지를 사용하여 컴파일됩니다. 보다 고급 문법에 대해서는 [여기](https://github.com/pillarjs/path-to-regexp#parameters)를 참고하십시오.
::: warning 재작성과 상대 링크 ::: warning 재작성과 상대 링크
재작성이 활성화된 경우, **상대 링크는 재작성된 경로를 기반으로 해야 합니다**. 예를 들어, `패키지/pkg-a/src/pkg-a-code.md`에서 `패키지/pkg-b/src/pkg-b-code.md`로 상대 링크를 생성하려면 다음을 사용해야 합니다: 재작성 기능이 활성화되면, **상대 링크는 재작성된 경로를 기준으로 해야 합니다**. 예를 들어, `packages/pkg-a/src/pkg-a-code.md`에서 `packages/pkg-b/src/pkg-b-code.md`로 상대 링크를 생성하려면, 다음과 같이 사용해야 합니다:
```md ```md
[PKG B로의 링크](../pkg-b/pkg-b-code) [Link to PKG B](../pkg-b/pkg-b-code)
``` ```
::: :::
## 동적 라우트 {#dynamic-routes} ## 동적 라우트 {#dynamic-routes}
단일 마크다운 파일과 동적 데이터를 사용하여 많은 페이지를 생성할 수 있습니다. 예를 들어, 프로젝트의 모든 패키지에 해당하는 페이지를 생성하는 `패키지/[pkg].md` 파일을 만들 수 있습니다. 여기서 `[pkg]` 세그먼트는 각 페이지를 다른 페이지와 구별하는 라우트 **매개변수**입니다. 단일 마크다운 파일과 동적 데이터를 사용하여 여러 페이지를 생성할 수 있습니다. 예를 들어, 프로젝트의 모든 패키지에 해당하는 페이지를 생성하는 `packages/[pkg].md` 파일을 만들 수 있습니다. 여기서 `[pkg]` 세그먼트는 각 페이지를 구분하는 라우트 **파라미터**입니다.
### 경로 로더 파일 {#paths-loader-file} ### 경로 로더 파일 {#paths-loader-file}
VitePress는 정적 사이트 생성기이므로, 가능한 페이지 경로는 빌드 시에 결정되어야 합니다. 따라서 동적 라우트 페이지는 **경로 로더 파일**을 동반해야 합니다. `패키지/[pkg].md`의 경우, `패키지/[pkg].paths.js`(`.ts`도 지원)가 필요합니다: VitePress는 정적 사이트 생성기이므로, 가능한 페이지 경로는 빌드 시에 결정되어야 합니다. 따라서 동적 라우트 페이지는 반드시 **경로 로더 파일**과 함께 제공되어야 합니다. `packages/[pkg].md`의 경우, `packages/[pkg].paths.js` (`.ts`도 지원됩니다) 파일이 필요합니다:
``` ```
. .
└─ 패키지 └─ packages
├─ [pkg].md # 라우트 템플릿 ├─ [pkg].md # route template
└─ [pkg].paths.js # 라우트 경로 로더 └─ [pkg].paths.js # route paths loader
``` ```
경로 로더는 `params` 속성을 가진 객체의 배열을 반환하는 `paths` 메서드를 기본 export로 제공하는 객체여야 합니다. 이러한 객체 각각은 해당하는 페이지를 생성할 것입니다. 경로 로더는 `paths` 메서드를 기본 내보내기로 제공하는 객체를 포함해야 합니다. `paths` 메서드는 `params` 객체 프로퍼티를 가진 배열을 반환해야 합니다. 이 객체들 각각이 해당하는 페이지를 생성하게 됩니다.
다음 `paths` 배열이 주어진 경우: 다음과 같이 `paths` 배열이 주어진 경우:
```js ```js
// 패키지/[pkg].paths.js // packages/[pkg].paths.js
export default { export default {
paths() { paths() {
return [ return [
@ -242,20 +242,20 @@ export default {
``` ```
. .
└─ 패키지 └─ packages
├─ foo.html ├─ foo.html
└─ bar.html └─ bar.html
``` ```
### 여러 매개변수 {#multiple-params} ### 여러 파라미터 {#multiple-params}
동적 라우트는 여러 매개변수를 포함할 수 있습니다: 동적 라우트는 여러 파라미터를 포함할 수 있습니다:
**파일 구조** **파일 구조**
``` ```
. .
└─ 패키지 └─ packages
├─ [pkg]-[version].md ├─ [pkg]-[version].md
└─ [pkg]-[version].paths.js └─ [pkg]-[version].paths.js
``` ```
@ -273,11 +273,11 @@ export default {
} }
``` ```
**출력** **결과물**
``` ```
. .
└─ 패키지 └─ packages
├─ foo-1.0.0.html ├─ foo-1.0.0.html
├─ foo-2.0.0.html ├─ foo-2.0.0.html
├─ bar-1.0.0.html ├─ bar-1.0.0.html
@ -286,7 +286,7 @@ export default {
### 동적으로 경로 생성 {#dynamically-generating-paths} ### 동적으로 경로 생성 {#dynamically-generating-paths}
경로 로더 모듈은 Node.js에서 실행되며 빌드 시에만 실행됩니다. 로컬 또는 원격 데이터를 사용하여 경로 배열을 동적으로 생성할 수 있습니다. 경로 로더 모듈은 Node.js에서 실행되며 빌드 시에만 실행됩니다. 로컬 또는 원격 데이터를 사용하여 동적으로 경로 배열을 생성할 수 있습니다.
로컬 파일에서 경로 생성: 로컬 파일에서 경로 생성:
@ -296,7 +296,7 @@ import fs from 'fs'
export default { export default {
paths() { paths() {
return fs return fs
.readdirSync('패키지') .readdirSync('packages')
.map((pkg) => { .map((pkg) => {
return { params: { pkg }} return { params: { pkg }}
}) })
@ -323,16 +323,16 @@ export default {
} }
``` ```
### 페이지에서 매개변수 접근 {#accessing-params-in-page} ### 페이지에서 파라미터에 접근 {#accessing-params-in-page}
각 페이지에 추가 데이터를 전달하기 위해 매개변수를 사용할 수 있습니다. 마크다운 라우트 파일은 `$params` 전역 속성을 통해 현재 페이지 매개변수에 Vue 표현식에서 접근할 수 있습니다: 파라미터를 사용하여 각 페이지에 추가 데이터를 전달할 수 있습니다. 마크다운 라우트 파일은 `$params` 전역 프로퍼티를 통해 Vue 표현식에서 현재 페이지 파라미터에 접근할 수 있습니다:
```md ```md
- 패키지 이름: {{ $params.pkg }} - 패키지 이름: {{ $params.pkg }}
- 버전: {{ $params.version }} - 버전: {{ $params.version }}
``` ```
[`useData`](../reference/runtime-api#usedata) 런타임 API를 통해 마크다운 파일과 Vue 컴포넌트에서 현재 페이지의 매개변수에도 접근할 수 있습니다: 또는 [`useData`](../reference/runtime-api#usedata) 런타임 API를 통해 현재 페이지의 파라미터에 접근할 수 있습니다. 이는 마크다운 파일과 Vue 컴포넌트 모두에서 사용할 수 있습니다:
```vue ```vue
<script setup> <script setup>
@ -347,9 +347,9 @@ console.log(params.value)
### 원시 콘텐츠 렌더링 {#rendering-raw-content} ### 원시 콘텐츠 렌더링 {#rendering-raw-content}
페이지로 전달된 매개변수는 클라이언트 JavaScript 페이로드에 직렬화되므로, 예를 들어 원격 CMS에서 가져온 원시 마크다운이나 HTML 콘텐츠와 같이 무거운 데이터를 매개변수로 전달하지 마십시오. 페이지에 전달되는 파라미터는 클라이언트 JavaScript 페이로드에서 직렬화되므로, 원격 CMS에서 가져온 원시 Markdown이나 HTML 콘텐츠와 같은 무거운 데이터를 파라미터로 전달하지 마십시오.
대신, 각 경로 객체의 `content` 속성을 사용하여 각 페이지에 이러한 콘텐츠를 전달할 수 있습니다: 대신, 각 경로 객체의 `content` 프로퍼티를 사용하여 이러한 콘텐츠를 각 페이지에 전달할 수 있습니다:
```js ```js
export default { export default {
@ -366,7 +366,7 @@ export default {
} }
``` ```
그런 다음 다음 특수 문을 사용하여 마크다운 파일 자체의 일부로 콘텐츠를 렌더링하세요: 그런 다음 특수 문을 사용하여 마크다운 파일 자체의 일부로 콘텐츠를 렌더링할 수 있습니다:
```md ```md
<!-- @content --> <!-- @content -->

@ -1,6 +1,6 @@
# 사이트맵 생성 {#sitemap-generation} # 사이트맵 생성 {#sitemap-generation}
VitePress는 사이트를 위한 `sitemap.xml` 파일 생성을 기본적으로 지원합니다. 이를 활성화하려면 다음을 `.vitepress/config.js`에 추가하세요: VitePress는 사이트`sitemap.xml` 파일 생성을 지원합니다. 이를 활성화하려면 `.vitepress/config.js`에 다음을 추가하십시오:
```ts ```ts
export default { export default {
@ -14,7 +14,7 @@ export default {
## 옵션 {#options} ## 옵션 {#options}
사이트맵 지원은 [`sitemap`](https://www.npmjs.com/package/sitemap) 모듈에 의해 제공됩니다. 설정 파일의 `sitemap` 옵션에 이 모듈이 지원하는 모든 옵션을 전달할 수 있습니다. 이 옵션`SitemapStream` 생성자에 직접 전달됩니다. 자세한 내용은 [`sitemap` 문서](https://www.npmjs.com/package/sitemap#options-you-can-pass)를 참조하세요. 예제: 사이트맵 지원은 [`sitemap`](https://www.npmjs.com/package/sitemap) 모듈에 의해 제공됩니다. 구성 파일의 `sitemap` 옵션에 지원되는 모든 옵션을 전달할 수 있습니다. 이러한 옵션은 `SitemapStream` 생성자에 직접 전달됩니다. 자세한 내용은 [`sitemap` 문서](https://www.npmjs.com/package/sitemap#options-you-can-pass)를 참고하세요. 예:
```ts ```ts
export default { export default {
@ -25,7 +25,7 @@ export default {
} }
``` ```
설정 파일에서 `base`를 사용하는 경우, `hostname` 옵션에 이를 추가해야 합니다: 구성 파일에서 `base`를 사용하는 경우, `hostname` 옵션에 이것을 추가해야 합니다:
```ts ```ts
export default { export default {
@ -36,16 +36,16 @@ export default {
} }
``` ```
## `transformItems` Hook ## `transformItems` Hook {#transformitems-hook}
`sitemap.transformItems` 훅을 사용하여 `sitemap.xml` 파일에 작성되기 전에 사이트맵 항목을 수정할 수 있습니다. 이 훅은 사이트맵 항목 배열을 인자로 받아 배열을 반환해야 합니다. 예제: `sitemap.transformItems` 훅을 사용하여 `sitemap.xml` 파일에 작성되기 전에 사이트맵 아이템을 수정할 수 있습니다. 이 훅은 사이트맵 아이템 배열을 인자로 받고 사이트맵 아이템 배열을 반환해야 합니다. 예제:
```ts ```ts
export default { export default {
sitemap: { sitemap: {
hostname: 'https://example.com', hostname: 'https://example.com',
transformItems: (items) => { transformItems: (items) => {
// 새로운 항목 추가 또는 기존 항목 수정/필터링 // 새로운 아이템 추가 또는 기존 아이템 수정/필터링
items.push({ items.push({
url: '/extra-page', url: '/extra-page',
changefreq: 'monthly', changefreq: 'monthly',

@ -4,13 +4,13 @@ outline: deep
# SSR 호환성 {#ssr-compatibility} # SSR 호환성 {#ssr-compatibility}
VitePress는 Vue의 서버 사이드 렌더링(SSR) 기능을 사용하여 프로덕션 빌드 중에 Node.js에서 앱을 사전 렌더링합니다. 이는 테마 컴포넌트의 모든 사용자 정의 코드가 SSR 호환성을 준수해야 함을 의미합니다. VitePress는 Vue의 서버 사이드 렌더링(SSR) 기능을 사용하여 프로덕션 빌드 중에 Node.js에서 애플리케이션을 사전 렌더링합니다. 이는 테마 컴포넌트의 모든 커스텀 코드가 SSR 호환성을 준수해야 함을 의미합니다.
[공식 Vue 문서의 SSR 섹션](https://vuejs.org/guide/scaling-up/ssr.html)은 SSR이 무엇인지, SSR/SSG 간의 관계 및 SSR 친화적인 코드 작성에 대한 일반적인 참고 사항에 대한 더 많은 컨텍스트를 제공합니다. 핵심 원칙은 브라우저/DOM API에는 Vue 컴포넌트의 `beforeMount` 또는 `mounted` 후크에서만 접근해야 합니다. 공식 Vue 문서의 [SSR 섹션](https://vuejs.org/guide/scaling-up/ssr.html)은 SSR이 무엇인지, SSR / SSG 간의 관계, 그리고 SSR 친화적인 코드를 작성할 때의 일반적인 주의 사항에 대해 더 많은 정보를 제공합니다. 핵심 원칙은 Vue 컴포넌트의 `beforeMount` 또는 `mounted` 훅에서만 브라우저 / DOM API에 접근하는 것입니다.
## `<ClientOnly>` ## `<ClientOnly>`
SSR 친화적이지 않은 컴포넌트(예: 사용자 정의 지시문이 포함된 경우)를 사용하거나 시연하는 경우, 내장된 `<ClientOnly>` 컴포넌트 내부에 이를 래핑할 수 있습니다: SSR 친화적이지 않은 컴포넌트(예: 커스텀 디렉티브를 포함한 컴포넌트)를 사용하거나 시연하는 경우, 내장된 `<ClientOnly>` 컴포넌트로 해당 컴포넌트를 래핑할 수 있습니다:
```md ```md
<ClientOnly> <ClientOnly>
@ -18,11 +18,11 @@ SSR 친화적이지 않은 컴포넌트(예: 사용자 정의 지시문이 포
</ClientOnly> </ClientOnly>
``` ```
## 가져오기 시 브라우저 API에 접근하는 라이브러리 {#libraries-that-access-browser-api-on-import} ## "import" 시 브라우저 API에 접근하는 라이브러리 {#libraries-that-access-browser-api-on-import}
일부 컴포넌트나 라이브러리는 **가져오기 시**에 브라우저 API에 접근합니다. 가져오기를 통해 브라우저 환경을 가정하는 코드를 사용하려면 동적으로 이를 가져와야 합니다. 일부 컴포넌트나 라이브러리는 **"import" 시** 브라우저 API에 접근합니다. "import" 시 브라우저 환경을 가정하는 코드를 사용하려면, 동적 "import"를 사용해야 합니다.
### Mounted 후크에서 가져오기 {#importing-in-mounted-hook} ### Mounted 에서 가져오기 {#importing-in-mounted-hook}
```vue ```vue
<script setup> <script setup>
@ -38,7 +38,7 @@ onMounted(() => {
### 조건부 가져오기 {#conditional-import} ### 조건부 가져오기 {#conditional-import}
`import.meta.env.SSR` 플래그([Vite env 변수](https://vitejs.dev/ko/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 가져올 수도 있습니다: `import.meta.env.SSR` 플래그([Vite 환경 변수](https://vitejs.dev/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 "import" 할 수도 있습니다:
```js ```js
if (!import.meta.env.SSR) { if (!import.meta.env.SSR) {
@ -48,7 +48,7 @@ if (!import.meta.env.SSR) {
} }
``` ```
[`Theme.enhanceApp`](./custom-theme#theme-interface)가 비동기적일 수 있기 때문에, 가져오기 시에 브라우저 API에 접근하는 Vue 플러그인을 조건부로 가져오고 등록할 수 있습니다: [`Theme.enhanceApp`](./custom-theme#theme-interface)은 비동기로 사용할 수 있기 때문에, "import" 시 브라우저 API에 접근하는 Vue 플러그인을 조건부로 "import"하고 등록할 수 있습니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -82,7 +82,7 @@ export default {
### `defineClientComponent` ### `defineClientComponent`
VitePress는 가져오기 시에 브라우저 API에 접근하는 Vue 컴포넌트를 가져오기 위한 편리한 도우미를 제공합니다. VitePress는 "import" 시 브라우저 API에 접근하는 Vue 컴포넌트를 "import" 할 수 있는 편리한 헬퍼를 제공합니다.
```vue ```vue
<script setup> <script setup>
@ -109,7 +109,7 @@ const clientCompRef = ref(null)
const ClientComp = defineClientComponent( const ClientComp = defineClientComponent(
() => import('component-that-access-window-on-import'), () => import('component-that-access-window-on-import'),
// args are passed to h() - https://vuejs.org/api/render-function.html#h // h() 에 전달된 인자 - https://vuejs.org/api/render-function.html#h
[ [
{ {
ref: clientCompRef ref: clientCompRef
@ -133,4 +133,4 @@ const ClientComp = defineClientComponent(
</template> </template>
``` ```
대상 컴포넌트는 래퍼 컴포넌트의 mounted 후크에서만 가져올 것입니다. 대상 컴포넌트는 래퍼 컴포넌트의 mounted 훅에서만 "import" 됩니다.

@ -1,18 +1,18 @@
# Markdown에서 Vue 사용하기 {#using-vue-in-markdown} # 마크다운에서 Vue 사용하기 {#using-vue-in-markdown}
VitePress에서 각 Markdown 파일은 HTML로 컴파일된 다음 [Vue 단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 처리됩니다. 이는 Markdown 내에서 동적 템플릿, Vue 컴포넌트 사용 또는 `<script>` 태그를 추가하여 임의의 페이지 내 Vue 컴포넌트 로직을 사용할 수 있을 의미합니다. VitePress에서는 각 마크다운 파일이 HTML로 컴파일된 후 [Vue 단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 처리됩니다. 이는 마크다운 내에서 Vue 컴포넌트를 사용하거나 동적 템플릿을 사용하거나 `<script>` 태그를 추가하여 임의의 페이지 내 Vue 컴포넌트 로직을 사용할 수 있다는 것을 의미합니다.
VitePress가 Vue의 컴파일러를 활용하여 Markdown 콘텐츠의 순수 정적 부분을 자동으로 감지하고 최적화한다는 점에 주목할 가치가 있습니다. 정적 콘텐츠는 단일 자리표시자 노드로 최적화되어 초기 방문시 페이지의 JavaScript 페이로드에서 제거됩니다. 또한 클라이언트 측 하이드레이션 중에도 건너뜁니다. 간단히 말해서, 주어진 페이지에서 동적 부분에 대해서만 비용을 지불합니다. VitePress는 Vue의 컴파일러를 활용하여 마크다운 콘텐츠의 순수 정적 부분을 자동으로 감지하고 최적화합니다. 정적 콘텐츠는 단일 플레이스홀더 노드로 최적화되어 초기 방문 시 페이지의 JavaScript 페이로드에서 제거됩니다. 또한 클라이언트 측 하이드레이션 중에도 건너뜁니다. 요약하자면 특정 페이지에서는 동적 부분에 대해서만 비용을 지불하면 됩니다.
::: tip SSR 호환성 ::: tip SSR 호환성
모든 Vue 사용은 SSR과 호환되어야 합니다. 자세한 내용과 일반적인 해결 방법은 [SSR 호환성](./ssr-compat)을 참조하십시오. 모든 Vue 사용은 SSR과 호환되어야 합니다. 자세한 내용 및 일반적인 해결 방법은 [SSR 호환성](./ssr-compat)을 참고하세요.
::: :::
## 템플릿 {#templating} ## 템플릿 {#templating}
### 보간(interpolation) {#interpolation} ### 보간 문법 {#interpolation}
Markdown 파일은 먼저 HTML로 컴파일되고 나서 Vite 프로세스 파이프라인으로 Vue 컴포넌트로 전달됩니다. 이는 텍스트에서 Vue 스타일 보간을 사용할 수 있음을 의미합니다: 마크다운 파일은 먼저 HTML로 컴파일된 다음 Vue 컴포넌트로 Vite 프로세스 파이프라인에 전달됩니다. 이는 텍스트에서 Vue 스타일 보간 문법을 사용할 수 있음을 의미합니다:
**입력** **입력**
@ -24,9 +24,9 @@ VitePress가 Vue의 컴파일러를 활용하여 Markdown 콘텐츠의 순수
<div class="language-text"><pre><code>{{ 1 + 1 }}</code></pre></div> <div class="language-text"><pre><code>{{ 1 + 1 }}</code></pre></div>
### 지시문 {#directives} ### 디렉티브 {#directives}
자인상 원시 HTML도 마크다운에서 유효하기 때문에 지시문도 동작합니다: 렉티브도 사용할 수 있습니다(원시 HTML도 마크다운에서 작동함):
**입력** **입력**
@ -38,9 +38,9 @@ VitePress가 Vue의 컴파일러를 활용하여 Markdown 콘텐츠의 순수
<div class="language-text"><pre><code><span v-for="i in 3">{{ i }} </span></code></pre></div> <div class="language-text"><pre><code><span v-for="i in 3">{{ i }} </span></code></pre></div>
## `<script>` `<style>` {#script-and-style} ## `<script>` & `<style>` {#script-and-style}
Markdown 파일의 최상위 `<script>``<style>` 태그는 Vue SFC에서와 마찬가지로 작동합니다. `<script setup>`, `<style module>` 등을 포함합니다. 여기서 주된 차이점은 `<template>` 태그가 없다는 것입니다: 다른 모든 최상위 콘텐츠는 Markdown입니다. 또한 모든 태그는 frontmatter **이후에** 위치해야 함을 유의하십시오: 루트 레벨의 `<script>``<style>` 태그는 마크다운 파일에서 Vue SFCs에서와 마찬가지로 작동하며, `<script setup>`, `<style module>` 등도 포함됩니다. 여기서 주요 차이점은 `<template>` 태그가 없다는 것입니다: 다른 모든 루트 레벨의 컨텐츠는 마크다운입니다. 또한 **모든 태그는 전문 이후에 배치**되어야 합니다:
```html ```html
--- ---
@ -53,7 +53,7 @@ import { ref } from 'vue'
const count = ref(0) const count = ref(0)
</script> </script>
## Markdown 콘텐츠 ## 마크다운 컨텐츠
현재 카운트: {{ count }} 현재 카운트: {{ count }}
@ -67,11 +67,11 @@ const count = ref(0)
</style> </style>
``` ```
::: warning Markdown에서 `<style scoped>` 사용을 피하세요 ::: warning 마크다운에서 `<style scoped>` 사용을 피하세요
Markdown에서 `<style scoped>`를 사용할 경우, 현재 페이지의 모든 요소에 특별한 속성을 추가해야 하므로 페이지 크기가 현저하게 증가할 수 있습니다. 페이지 내에서 지역적으로 범위가 지정된 스타일링이 필요할 때는 `<style module>`이 선호됩니다. 마크다운에서 `<style scoped>`를 사용할 때는 현재 페이지의 모든 엘리먼트에 특수한 어트리뷰트를 추가해야 하므로 페이지 크기를 크게 부풀릴 수 있습니다. 페이지에서 로컬 범위의 스타일링이 필요한 경우 `<style module>`을 사용하는 것이 좋습니다.
::: :::
현재 페이지의 메타데이터에 접근할 수 있는 [`useData` 도우미](../reference/runtime-api#usedata)와 같은 VitePress의 런타임 API에도 접근할 수 있습니다: 또한 현재 페이지의 메타데이터에 접근할 수 있는 [`useData` 헬퍼](../reference/runtime-api#usedata)와 같은 VitePress의 런타임 API에도 접근할 수 있습니다:
**입력** **입력**
@ -90,7 +90,7 @@ const { page } = useData()
```json ```json
{ {
"path": "/using-vue.html", "path": "/using-vue.html",
"title": "Markdown에서 Vue 사용하기", "title": "마크다운에서 Vue 사용하기",
"frontmatter": {}, "frontmatter": {},
... ...
} }
@ -98,11 +98,11 @@ const { page } = useData()
## 컴포넌트 사용하기 {#using-components} ## 컴포넌트 사용하기 {#using-components}
Markdown 파일 내에서 Vue 컴포넌트를 직접 가져오고 사용할 수 있습니다. 마크다운 파일 내에서 Vue 컴포넌트를 직접 가져와서 사용할 수 있습니다.
### Markdown에서 가져오기 {#importing-in-markdown} ### 마크다운에서 컴포넌트 가져오기 {#importing-in-markdown}
컴포넌트가 몇 페이지에서만 사용되는 경우, 해당되는 곳에서 명시적으로 가져오는 것이 좋습니다. 이를 통해 적절하게 코드를 분할하고 관련 페이지가 표시될 때만 로드할 수 있습니다: 컴포넌트가 몇 페이지에서만 사용되는 경우, 사용되는 곳에서 명시적으로 가져오는 것이 좋습니다. 이렇게 하면 적절하게 코드를 분할하고 관련 페이지가 표시될 때만 로드할 수 있습니다:
```md ```md
<script setup> <script setup>
@ -122,31 +122,31 @@ import CustomComponent from '../components/CustomComponent.vue'
### 전역적으로 컴포넌트 등록하기 {#registering-components-globally} ### 전역적으로 컴포넌트 등록하기 {#registering-components-globally}
컴포넌트가 대부분의 페이지에서 사용될 것인 경우, Vue 앱 인스턴스를 사용자 지정하여 전역적으로 등록할 수 있습니다. 예제는 [기본 테마 확장](./extending-default-theme#registering-global-components) 관련 섹션을 참조하십시오. 컴포넌트가 대부분의 페이지에서 사용될 경우, Vue 앱 인스턴스를 커스텀하여 전역적으로 등록할 수 있습니다. [기본 테마 확장](./extending-default-theme#registering-global-components)의 관련 섹션을 예제를 참고하세요.
::: warning 중요 ::: warning 중요
커스텀 컴포넌트의 이름이 하이픈을 포함하거나 파스칼케이스(PascalCase)인지 확인하십시오. 그렇지 않으면 인라인 요소로 처리되어 `<p>` 태그 내에 포함되어 하이드레이션 불일치가 발생할 수 있습니다. `<p>`는 내부에 블록 요소를 포함할 수 없기 때문입니다. 커스텀 컴포넌트의 이름에 하이픈이 포함되어 있거나 파스칼케이스(PascalCase)e인지 확인하세요. 그렇지 않으면 인라인 요소로 처리되어 `<p>` 태그 안에 래핑됩니다. `<p>`는 블록 엘리먼트를 내부에 배치할 수 없기 때문에 하이드레이션 불일치가 발생합니다.
::: :::
### 헤더에 컴포넌트 사용하기 <ComponentInHeader /> {#using-components-in-headers} ### 헤더에 <ComponentInHeader /> 컴포넌트 사용하기 {#using-components-in-headers}
헤더에서 Vue 컴포넌트를 사용할 수 있지만, 다음 구문 사이의 차이를 유의하십시오: 헤더에서 Vue 컴포넌트를 사용할 수 있지만, 다음 문법간 차이점에 주의해야 합니다:
| Markdown | 출력 HTML | 파싱된 헤더 | | 마크다운 | 출력 HTML | 파싱된 헤더 |
| ------------------------------------------------------- | ----------------------------------------- | ------------- | |--------------------------------------------------------| ----------------------------------------- | ------------- |
| <pre v-pre><code> # 텍스트 &lt;Tag/&gt; </code></pre> | `<h1>텍스트 <Tag/></h1>` | `텍스트` | | <pre v-pre><code> # text &lt;Tag/&gt; </code></pre> | `<h1>text <Tag/></h1>` | `text` |
| <pre v-pre><code> # 텍스트 \`&lt;Tag/&gt;\` </code></pre> | `<h1>텍스트 <code>&lt;Tag/&gt;</code></h1>` | `텍스트 <Tag/>` | | <pre v-pre><code> # text \`&lt;Tag/&gt;\` </code></pre> | `<h1>text <code>&lt;Tag/&gt;</code></h1>` | `text <Tag/>` |
`<code>`둘러싸인 HTML은 그대로 표시됩니다; **아니면** `<code>`로 둘러싸이지 않은 HTML만 Vue에 의해 파싱됩니다. `<code>`감싼 HTML은 있는 그대로 표시되며, **감싸지 않은** HTML만 Vue에 의해 파싱됩니다.
::: tip ::: tip
출력 HTML은 [Markdown-it](https://github.com/Markdown-it/Markdown-it)에 의해 이루어지며, 파싱된 헤더는 VitePress(사이드바와 문서 제목 모두에 사용됨)에 의해 처리됩니다. 출력 HTML은 [Markdown-it](https://github.com/Markdown-it/Markdown-it)에 의해 생성되며, 파싱된 헤더는 VitePress에 의해 처리됩니다(사이드바와 문서 제목 모두에 사용됩니다).
::: :::
## 이스케이프 {#escaping} ## 이스케이프 {#escaping}
`v-pre` 지시문을 사용하여 `<span>`이나 다른 요소에 Vue 보간을 이스케이프할 수 있습니다: Vue 보간 문법을 회피하려면, `<span>` 또는 다른 엘리먼트에 `v-pre` 디렉티브를 사용하여 감쌀 수 있습니다:
**입력** **입력**
@ -160,7 +160,7 @@ import CustomComponent from '../components/CustomComponent.vue'
<p>이것은 <span v-pre>{{ 그대로 표시됩니다 }}</span></p> <p>이것은 <span v-pre>{{ 그대로 표시됩니다 }}</span></p>
</div> </div>
한, 전체 단락을 `v-pre` 커스텀 컨테이너로 둘러싸도록 선택할 수 있습니다: 는 전체 문단을 `v-pre` 커스텀 컨테이너로 감쌀 수도 있습니다:
```md ```md
::: v-pre ::: v-pre
@ -180,7 +180,7 @@ import CustomComponent from '../components/CustomComponent.vue'
## 코드 블록에서 이스케이프 해제하기 {#unescape-in-code-blocks} ## 코드 블록에서 이스케이프 해제하기 {#unescape-in-code-blocks}
기본적으로 모든 fenced 코드 블록은 자동으로 `v-pre`로 둘러싸입니다. 따라서 내부에서 Vue 구문을 처리하지 않습니다. 펜스 내에서 Vue 스타일 보간을 활성화하려면, 예를 들어 `js-vue`처럼 언어에 `-vue` 접미사를 추가할 수 있습니다: 기본적으로 모든 펜스 코드 블록은 자동으로 `v-pre`로 감싸져 있어, 내부에서는 Vue 문법이 처리되지 않습니다. 펜스 내부에서 Vue 스타일 보간 문법을 사용하려면, `js-vue`처럼 언어에 `-vue` 접미사를 추가할 수 있습니다:
**입력** **입력**
@ -196,11 +196,11 @@ import CustomComponent from '../components/CustomComponent.vue'
안녕하세요 {{ 1 + 1 }} 안녕하세요 {{ 1 + 1 }}
``` ```
는 일부 토큰이 제대로 구문 강조되지 않을 수 있음을 의미합니다. 로 인해 특정 토큰이 올바르게 강조 표시되지 않을 수 있습니다.
## CSS 전처리기 사용하기 {#using-css-pre-processors} ## CSS 전처리기 사용하기 {#using-css-pre-processors}
VitePress는 CSS 전처리기에 대한 [내장 지원](https://vitejs.dev/ko/guide/features.html#css-pre-processors)을 가지고 있습니다: `.scss`, `.sass`, `.less`, `.styl``.stylus` 파일. 이것들을 위한 Vite 특정 플러그인을 설치할 필요는 없지만, 해당 전처리기 자체는 설치해야 합니다: VitePress는 CSS 전처리기`.scss`, `.sass`, `.less`, `.styl`, `.stylus` 파일에 대해 [기본 지원](https://vitejs.dev/guide/features.html#css-pre-processors)을 제공합니다. 이를 위해 Vite 전용 플러그인을 설치할 필요는 없지만, 해당 전처리기 자체는 설치해야 합니다:
``` ```
# .scss 및 .sass # .scss 및 .sass
@ -213,7 +213,7 @@ npm install -D less
npm install -D stylus npm install -D stylus
``` ```
그런 다음 다음을 Markdown 및 테마 컴포넌트에서 사용할 수 있습니다: 그런 다음 마크다운 및 테마 컴포넌트에서 다음과 같이 사용할 수 있습니다:
```vue ```vue
<style lang="sass"> <style lang="sass">
@ -222,9 +222,9 @@ npm install -D stylus
</style> </style>
``` ```
## Teleports 사용하기 {#using-teleports} ## 텔레포트 사용하기 {#using-teleports}
현재 VitePress는 본문으로만 teleport에 대한 SSG 지원을 가지고 있습니다. 다른 대상을 위해서는, 내장된 `<ClientOnly>` 컴포넌트 내에 감싸거나 텔레포트 마크업을 최종 페이지 HTML의 올바른 위치에 주입할 수 있습니다 [`postRender` 훅](../reference/site-config#postrender)을 통해. VitePress는 현재 body로 텔레포트를 사용하는 SSG만 지원합니다. 다른 대상에 대해 텔레포트를 사용하려면 내장된 `<ClientOnly>` 컴포넌트로 감싸거나 [`postRender` 훅](../reference/site-config#postrender)을 통해 최종 페이지 HTML의 올바른 위치에 텔레포트 마크업을 삽입할 수 있습니다.
<ModalDemo /> <ModalDemo />

@ -1,10 +1,10 @@
# VitePress란 무엇인가? {#what-is-vitepress} # VitePress란 무엇인가? {#what-is-vitepress}
VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 설계된 [정적 사이트 생성기](https://en.wikipedia.org/wiki/Static_site_generator) (SSG)입니다. 간단히 말해, VitePress는 [Markdown](https://en.wikipedia.org/wiki/Markdown)으로 작성된 소스 컨텐츠를 가져와서 테마를 적용하고, 어디에나 쉽게 배포할 수 있는 정적 HTML 페이지를 생성합니다. VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 설계된 [정적 사이트 생성기](https://en.wikipedia.org/wiki/Static_site_generator) (SSG)입니다. 다시말해 VitePress는 [마크다운](https://en.wikipedia.org/wiki/Markdown)으로 작성된 소스 컨텐츠를 가져와서 테마를 적용하고, 어디에나 쉽게 배포할 수 있는 정적 HTML 페이지를 생성합니다.
<div class="tip custom-block" style="padding-top: 8px"> <div class="tip custom-block" style="padding-top: 8px">
그냥 시도해보고 싶으세요? [빠른 시작](./getting-started)으로 건너뛰세요. 그냥 한번 사용해보고 싶으신가요? [빠른 시작](./getting-started)으로 건너뛰세요.
</div> </div>
@ -12,46 +12,46 @@ VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해
- **문서화** - **문서화**
VitePress는 기술 문서를 위해 설계된 기본 테마와 함께 제공됩니다. 이 테마는 바로 지금 읽고 있는 이 페이지뿐만 아니라 [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) 그리고 [기타 많은](https://www.vuetelescope.com/explore?framework.slug=vitepress) 문서화에 힘을 실어줍니다. VitePress는 기술 문서를 위해 설계된 기본 테마가 함께 제공됩니다. 지금 읽고 있는 이 페이지와 [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) 및 [다양한 프로젝트](https://www.vuetelescope.com/explore?framework.slug=vitepress) 문서는 모두 이 테마를 기반으로 합니다.
[공식 Vue.js 문서](https://vuejs.org/)도 VitePress 기반으로 되어 있지만, 여러 번역 간에 공유되는 커스텀 테마를 사용합니다. [Vue.js 공식 문서](https://vuejs.org/)도 VitePress 기반으로 되어 있으며, 여러 번역본에 걸쳐 공유되는 커스텀 테마를 사용합니다.
- **블로그, 포트폴리오 및 마케팅 사이트** - **블로그, 포트폴리오 및 마케팅 사이트**
VitePress는 표준 Vite + Vue 애플리케이션의 개발자 경험과 함께 [완전히 맞춤화된 테마](./custom-theme)를 지원합니다. Vite 기반이기 때문에 풍부한 생태계에서 Vite 플러그인을 직접 활용할 수 있습니다. 또한, VitePress는 [데이터 불러오기](./data-loading) (로컬 또는 원격) 및 [동적으로 경로 생성하기](./routing#dynamic-routes)를 위한 유연한 API를 제공합니다. 빌드 시점에 데이터를 결정할 수 있다면 거의 모든 것을 구축할 수 있습니다. VitePress는 표준 Vite + Vue 애플리케이션의 개발자 경험을 가진 [커스텀 테마](./custom-theme)를 지원합니다. Vite 기반이기 때문에 Vite 생태계의 풍부한 플러그인을 직접 활용할 수 있습니다. 또한, VitePress는 [데이터 로딩](./data-loading) (로컬 또는 원격) 및 [동적 라우트 생성](./routing#dynamic-routes)을 위한 유연한 API를 제공합니다. 빌드 시점에 데이터를 결정할 수 있다면 거의 모든 것을 구축할 수 있습니다.
공식 [Vue.js 블로그](https://blog.vuejs.org/)는 로컬 콘텐츠를 기반으로 색인 페이지를 생성하는 간단한 블로그입니다. 공식 [Vue.js 블로그](https://blog.vuejs.org/)는 로컬 콘텐츠 기반의 인덱스 페이지를 생성하는 간단한 블로그입니다.
## 개발자 경험 {#developer-experience} ## 개발자 경험 {#developer-experience}
VitePress는 Markdown 컨텐츠를 다룰 때 훌륭한 개발자 경험(DX)을 제공하고자 합니다. VitePress는 마크다운 컨텐츠를 다룰 때 훌륭한 개발자 경험(DX)을 제공하고자 합니다.
- **[Vite 구동:](https://vitejs.dev/)** 즉각적인 서버 시작이 가능하며, 페이지 새로고침 없이 항상 (<100ms) 즉시 수정 사항이 반영됩니다. - **[Vite로 작동](https://vitejs.dev/)**: 즉각적인 서버 시작 가능, 페이지 새로고침 없이 즉시(<100ms) 수정 사항 반영.
- **[내장 Markdown 확장 기능:](./markdown)** Frontmatter, 테이블, 구문 하이라이팅… 필요한 것이라면 무엇이든 있습니다. 특히, VitePress는 코드 블록과 작업할 때 많은 고급 기능을 제공하여 기술적 문서에 이상적입니다. - **[내장된 마크다운 확장 기능](./markdown)**: 서문, 표, 구문 강조 등 무엇이든 가능. 특히 VitePress는 코드 블록 작업을 위한 고급 기능을 많이 제공하여 기술적 문서에 이상적.
- **[Vue를 향상된 Markdown:](./using-vue)** 각 Markdown 페이지는 HTML과 100% 문법 호환성을 가진 Vue 템플릿 덕분에 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)입니다. Vue 템플릿 기능이나 가져온 Vue 컴포넌트를 사용하여 정적 콘텐츠에 상호작용성을 삽입할 수 있습니다. - **[Vue로 향상된 마크다운](./using-vue)**: 각 마크다운 페이지는 HTML과 100% 문법 호환성을 가진 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)입니다. Vue 템플릿 기능이나 컴포넌트를 사용하여 정적 콘텐츠에 상호작용 기능을 포함할 수 있습니다.
## 성능 {#performance} ## 성능 {#performance}
전통적인 SSG들과 달리 각 탐색이 전체 페이지 새로고침을 초래하는 것이 아니라, VitePress로 생성된 웹사이트는 초기 방문 시 정적 HTML을 제공하지만, 사이트 내 이후 탐색에 대해서는 [싱글 페이지 애플리케이션](https://en.wikipedia.org/wiki/Single-page_application) (SPA)이 됩니다. 우리의 견해에 따르면, 이 모델은 성능에 있어 최적의 균형을 제공합니다: 전통적인 SSG들과 달리, VitePress로 생성된 웹사이트는 초기 방문 시 정적 HTML을 제공하지만, 이후 사이트 내 탐색에 대해서는 [단일 페이지 애플리케이션](https://en.wikipedia.org/wiki/Single-page_application) (SPA)이 됩니다. 이 모델은 성능에 대한 최적의 균형을 제공합니다:
- **빠른 초기 로딩** - **빠른 초기 로딩**
어떤 페이지에 대한 초기 방문은 빠른 로딩 속도와 최적의 SEO를 위해 정적으로 사전 렌더링된 HTML이 제공됩니다. 그런 다음 페이지는 Vue SPA로 페이지를 변환하는 JavaScript 번들을 로드합니다("hydration"). SPA hydration이 느리다는 일반적인 가정과 달리, 이 과정은 실제로 Vue 3의 순수 성능과 컴파일러 최적화 덕분에 매우 빠릅니다. [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F)에서 일반적인 VitePress 사이트는 저사양 모바일 장치에서도 느린 네트워크에서 거의 완벽한 성능 점수를 달성합니다. 초기 페이지 방문은 사전 렌더링된 HTML을 제공하여 빠른 로딩 속도와 최적의 SEO를 제공합니다. 그 후 페이지를 Vue SPA로 전환하는 JavaScript 번들이 로드됩니다(이것을 "하이드레이션"이라고 함). 일반적으로 SPA 하이드레이션이 느리다고 생각할 수 있지만, Vue 3의 성능과 컴파일러 최적화 덕분에 이 과정은 매우 빠릅니다. [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F)에서 일반적인 VitePress 사이트는 네트워크 속도가 느린 저가형 모바일 기기에서도 거의 완벽한 성능 점수를 얻습니다.
- **빠른 후속 로드 탐색** - **빠른 포스트 로드 탐색**
더 중요한 것은 초기 로드 **이후** 사용자 경험이 개선된다는 것입니다. 사이트 내의 이후 탐색에서는 전체 페이지 새로고침이 더 이상 발생하지 않습니다. 대신, 들어오는 페이지의 콘텐츠가 가져와져 동적으로 업데이트됩니다. VitePress는 또한 뷰포트 내 링크에 대한 페이지 청크를 자동으로 사전 로드합니다. 대부분의 경우, 이후 로드 탐색은 즉각적으로 느껴질 것입니다. 더 중요한 것은 SPA 모델이 처음 로드된 후 더 나은 UX를 제공한다는 것입니다. 이후 사이트 내에서 탐색을 해도 전체 페이지가 다시 로드되는 현상이 더 이상 발생하지 않습니다. 대신 페이지의 콘텐츠를 불러와 동적으로 업데이트 합니다. 또한 VitePress는 뷰포트 내에 있는 링크의 페이지 청크를 자동으로 미리 가져옵니다. 이렇게 하면 대부분의 경우 유저는 이미 로드된 페이지에서 탐색할 때 새 페이지가 즉시 로드됩니다.
- **패널티 없는 상호작용성** - **페널티 없는 상호작용**
정적 Markdown 내에 내장된 동적 Vue 파트를 hydrate할 수 있도록 각 Markdown 페이지는 Vue 컴포넌트로 처리되고 JavaScript로 컴파일됩니다. 이것은 비효율적으로 들릴 수 있지만, Vue 컴파일러는 정적 부분과 동적 부분을 분리하여 hydration 비용과 페이로드 크기를 최소화하는 데 충분히 똑똑합니다. 초기 페이지 로드에 대해서, 정적 부분은 JavaScript 페이로드에서 자동으로 제거되고 hydration 동안 건너뛰어집니다. 정적 마크다운 내에 내장된 동적 Vue 부분을 하이드레이션 할 수 있도록 각 마크다운 페이지는 Vue 컴포넌트로 처리되고 JavaScript로 컴파일됩니다. 이는 비효율적으로 보일 수 있지만, Vue 컴파일러는 정적 부분과 동적 부분을 분리하여 하이드레이션 비용과 페이로드 크기를 최소화합니다. 초기 페이지 로드 시, 정적 부분은 자동으로 JavaScript 페이로드에서 제거되고 하이드레이션 중 건너뜁니다.
## VuePress는 어떤가요? {#what-about-vuepress} ## VuePress는 어떤가요? {#what-about-vuepress}
VitePress는 VuePress의 영적 후계자입니다. 원래 VuePress는 Vue 2와 webpack에 기반을 두고 있었습니다. Vue 3와 Vite를 기반으로 한 VitePress는 훨씬 더 나은 DX, 더 나은 프로덕션 성능, 더 완성된 기본 테마, 그리고 더욱 유연한 커스터마이징 API를 제공합니다. VitePress는 VuePress의 후속 버전 입니다. 원래 VuePress는 Vue 2와 webpack을 기반으로 했습니다. Vue 3와 Vite를 기반으로 한 VitePress는 훨씬 더 나은 DX, 더 나은 프로덕션 성능, 더 다듬어진 기본 테마, 더 유연한 커스터마이징 API를 제공합니다.
VitePress와 VuePress 사이의 API 차이는 주로 테마와 커스터마이징에 있습니다. 기본 테마를 사용하는 VuePress 1을 사용하는 경우, VitePress로 마이그레이션하는 것이 비교적 간단할 수 있습니다. VitePress와 VuePress의 API 차이는 주로 테마와 커스터마이징에 있습니다. 기본 테마를 사용하는 VuePress 1을 사용 중이라면 VitePress로의 마이그레이션은 비교적 간단할 것입니다.
VuePress 2에도 투자된 노력이 있으며, 이것도 Vue 3와 Vite를 지원하고 VuePress 1과 더 호환됩니다. 그러나 동시에 두 개의 SSG를 병행하여 유지하는 것은 지속 가능하지 않으므로, Vue 팀은 장기적으로 주요 권장 SSG로 VitePress에 집중하기로 결정했습니다. VuePress 2도 Vue 3와 Vite를 지원하며 VuePress 1과의 호환성을 높이기 위해 많은 노력이 투자되었습니다. 그러나 두 SSG를 병렬로 유지하는 것은 지속 가능하지 않으므로 Vue 팀은 장기적인 관점에서 주요 권장 SSG인 VitePress에 집중하기로 결정했습니다.

@ -2,12 +2,12 @@
layout: home layout: home
title: VitePress title: VitePress
titleTemplate: Vite & Vue로 구동되는 정적 사이트 생성기 titleTemplate: Vite & Vue 기반 정적 사이트 생성기
hero: hero:
name: VitePress name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기 text: Vite & Vue 기반 정적 사이트 생성기
tagline: 마크다운으로 멋진 문서를 몇 분 안에 tagline: 단 몇 분 만에 마크다운을 우아한 문서로 변환
actions: actions:
- theme: brand - theme: brand
text: VitePress란 무엇인가? text: VitePress란 무엇인가?
@ -24,17 +24,17 @@ hero:
features: features:
- icon: 📝 - icon: 📝
title: 콘텐츠에 집중하세요 title: 콘텐츠에 집중
details: 단지 마크다운으로 아름다운 문서 사이트를 쉽게 만들 수 있습니다. details: 마크다운으로만 아름다운 문서 사이트를 쉽게 만들기.
- icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 256.32"><defs><linearGradient id="a" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"/><stop offset="100%" stop-color="#BD34FE"/></linearGradient><linearGradient id="b" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"/><stop offset="8.333%" stop-color="#FFDD35"/><stop offset="100%" stop-color="#FFA800"/></linearGradient></defs><path fill="url(#a)" d="M255.153 37.938 134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"/><path fill="url(#b)" d="M185.432.063 96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028 72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"/></svg> - icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 256.32"><defs><linearGradient id="a" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"/><stop offset="100%" stop-color="#BD34FE"/></linearGradient><linearGradient id="b" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"/><stop offset="8.333%" stop-color="#FFDD35"/><stop offset="100%" stop-color="#FFA800"/></linearGradient></defs><path fill="url(#a)" d="M255.153 37.938 134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"/><path fill="url(#b)" d="M185.432.063 96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028 72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"/></svg>
title: Vite DX를 즐기세요 title: Vite DX(개발자 경험) 즐겨보기
details: 즉각적인 서버 시작, 번개 같은 핫 업데이트, 및 Vite 생태계 플러그인을 활용하세요. details: 즉각적인 서버 시작, 매우 빠른 업데이트, Vite 생태계 플러그인을 활용.
- icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 220.8"><path fill="#41B883" d="M204.8 0H256L128 220.8 0 0h97.92L128 51.2 157.44 0h47.36Z"/><path fill="#41B883" d="m0 0 128 220.8L256 0h-51.2L128 132.48 50.56 0H0Z"/><path fill="#35495E" d="M50.56 0 128 133.12 204.8 0h-47.36L128 51.2 97.92 0H50.56Z"/></svg> - icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 220.8"><path fill="#41B883" d="M204.8 0H256L128 220.8 0 0h97.92L128 51.2 157.44 0h47.36Z"/><path fill="#41B883" d="m0 0 128 220.8L256 0h-51.2L128 132.48 50.56 0H0Z"/><path fill="#35495E" d="M50.56 0 128 133.12 204.8 0h-47.36L128 51.2 97.92 0H50.56Z"/></svg>
title: Vue로 커스터마이징하세요 title: Vue로 커스터마이징
details: 마크다운에서 직접 Vue 구문과 컴포넌트를 사용하거나 Vue로 커스텀 테마를 만들어보세요. details: Vue 문법과 컴포넌트를 마크다운에서 직접 사용하거나 Vue로 커스텀 테마를 구축.
- icon: 🚀 - icon: 🚀
title: 빠른 사이트 출시 title: 웹사이트를 빠르게 제공
details: 정적 HTML로 빠른 초기 로드와 클라이언트 측 라우팅으로 빠른 포스트 로드 내비게이션을 제공합니다. details: 정적 HTML로 빠른 초기 로딩, 클라이언트 측 라우팅을 통한 빠른 탐색.
--- ---
<style> <style>

@ -2,72 +2,72 @@
## `vitepress dev` ## `vitepress dev`
지정된 디렉토리를 루트로 사용하여 VitePress 개발 서버 시작. 기본값은 현재 디렉토리입니다. 현재 디렉토리에서 실행할 때는 `dev` 명령을 생략할 수도 있습니다. 지정된 디렉터리를 루트로 하여 VitePress 개발 서버를 시작합니다. 기본값은 현재 디렉터리입니다. 현재 디렉터리에서 실행할 때 `dev` 명령은 생략할 수 있습니다.
### 사용법 ### 사용법 {#usage}
```sh ```sh
# 현재 디렉토리에서 시작, `dev` 생략 # 현재 디렉토리에서 시작, `dev` 생략
vitepress vitepress
# 서브 디렉토리에서 시작 # 하위 디렉터리에서 시작
vitepress dev [root] vitepress dev [root]
``` ```
### 옵션 ### 옵션 {#options}
| 옵션 | 설명 | | 옵션 | 설명 |
|-----------------|-----------------------------------------| | ---------------- | ----------------------------------------------------------------- |
| `--open [path]` | 시작 시 브라우저 열기 (`boolean \| string`) | | `--open [path]` | 시작 시 브라우저 열기 (`boolean \| string`) |
| `--port <port>` | 포트 지정 (`number`) | | `--port <port>` | 포트 지정 (`number`) |
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) | | `--base <path>` | Public 기본 경로 (기본값: `/`) (`string`) |
| `--cors` | CORS 활성화 | | `--cors` | CORS 활성화 |
| `--strictPort` | 지정된 포트가 이미 사용 중인 경우 종료 (`boolean`) | | `--strictPort` | 지정된 포트가 이미 사용 중인 경우 종료 (`boolean`) |
| `--force` | 최적화기가 캐시를 무시하고 다시 번들링하도록 강제 (`boolean`) | | `--force` | 옵티마이저가 캐시를 무시하고 다시 번들링하도록 강제 (`boolean`) |
## `vitepress build` ## `vitepress build`
VitePress 사이트를 프로덕션 용으로 빌드합니다. VitePress 사이트를 프로덕션 빌드합니다.
### 사용법 ### 사용법 {#usage-1}
```sh ```sh
vitepress build [root] vitepress build [root]
``` ```
### 옵션 ### 옵션 {#options-1}
| 옵션 | 설명 | | 옵션 | 설명 |
|--------------------------------|--------------------------------------------------------------------------------------| | ----------------------------- |---------------------------------------------------------------------------------------------|
| `--mpa` (실험적) | 클라이언트 측 수화 없이 [MPA 모드](../guide/mpa-mode)에서 빌드 (`boolean`) | | `--mpa` (실험적) | 클라이언트 측 하이드레이션 없이 [MPA 모드](../guide/mpa-mode)로 빌드 (`boolean`) |
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) | | `--base <path>` | Public 기본 경로 (기본값: `/`) (`string`) |
| `--target <target>` | 트랜스파일 대상 (기본값: `"modules"`) (`string`) | | `--target <target>` | 트랜스파일 대상 (기본값: `"modules"`) (`string`) |
| `--outDir <dir>` | **cwd**에 상대적인 출력 디렉토리 (기본값: `<root>/.vitepress/dist`) (`string`) | | `--outDir <dir>` | **cwd** 기준 출력 디렉터리 (기본값: `<root>/.vitepress/dist`) (`string`) |
| `--minify [minifier]` | 미니화 활성화/비활성화하거나 사용할 미니화기를 지정 (기본값: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) | | `--minify [minifier]` | minify 활성화/비활성화 또는 사용할 minify 도구 지정 (기본값: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) |
| `--assetsInlineLimit <number>` | 바이트 단위로 정적 자산 base64 인라인 임계값 (기본값: `4096`) (`number`) | | `--assetsInlineLimit <number>`| 바이트 단위의 정적 에셋 base64 인라인 임계값 (기본값: `4096`) (`number`) |
## `vitepress preview` ## `vitepress preview`
프로덕션 빌드를 로컬에서 미리 볼 수 있습니다. 프로덕션 빌드를 로컬에서 미리 보기 합니다.
### 사용법 ### 사용법 {#usage-2}
```sh ```sh
vitepress preview [root] vitepress preview [root]
``` ```
### 옵션 ### 옵션 {#options-2}
| 옵션 | 설명 | | 옵션 | 설명 |
|-----------------|--------------------------------| | ---------------- | ----------------------------------------- |
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) | | `--base <path>` | Public 기본 경로 (기본값: `/`) (`string`) |
| `--port <port>` | 포트 지정 (`number`) | | `--port <port>` | 포트 지정 (`number`) |
## `vitepress init` ## `vitepress init`
현재 디렉리에서 [설정 마법사](../guide/getting-started#setup-wizard) 시작. 현재 디렉리에서 [설정 마법사](../guide/getting-started#setup-wizard) 시작합니다.
### 사용법 ### 사용법 {#usage-3}
```sh ```sh
vitepress init vitepress init

@ -1,15 +1,15 @@
# 배지 {#badge} # 배지 {#badge}
배지는 헤더에 상태를 추가할 수 있게 해줍니다. 예를 들어, 섹션의 유형이나 지원되는 버전을 명시하는 것이 유용할 수 있습니다. 배지는 헤더에 상태를 추가할 수 있게 해줍니다. 예를 들어, 섹션의 타입을 지정하거나 지원되는 버전을 표시하는 데 유용할 수 있습니다.
## 사용법 {#usage} ## 사용법 {#usage}
글로벌하게 사용 가능한 `Badge` 컴포넌트를 사용할 수 있습니다. `Badge` 컴포넌트는 전역으로 사용 가능합니다.
```html ```html
### 제목 <Badge type="info" text="default" /> ### 제목 <Badge type="info" text="default" />
### 제목 <Badge type="tip" text="^1.9.0" /> ### 제목 <Badge type="tip" text="^1.9.0" />
### 제목 <Badge type="warning" text="beta" /> ### 제목 <Badge type="warning" text="배타" />
### 제목 <Badge type="danger" text="주의" /> ### 제목 <Badge type="danger" text="주의" />
``` ```
@ -17,22 +17,22 @@
### 제목 <Badge type="info" text="default" /> ### 제목 <Badge type="info" text="default" />
### 제목 <Badge type="tip" text="^1.9.0" /> ### 제목 <Badge type="tip" text="^1.9.0" />
### 제목 <Badge type="warning" text="beta" /> ### 제목 <Badge type="warning" text="배타" />
### 제목 <Badge type="danger" text="주의" /> ### 제목 <Badge type="danger" text="주의" />
## 사용자 정의 자식 요소 {#custom-children} ## 커스텀 하위 노드 {#custom-children}
`<Badge>``children`을 받아들이며, 이는 배지 안에 표시됩니다. `<Badge>``children`을 받아서 배지 내부에 표시합니다.
```html ```html
### 제목 <Badge type="info">사용자 정의 요소</Badge> ### 제목 <Badge type="info">커스텀 노드</Badge>
``` ```
### 제목 <Badge type="info">사용자 정의 요소</Badge> ### 제목 <Badge type="info">커스텀 노드</Badge>
## 타입 색상 사용자 정의 {#customize-type-color} ## 타입 색상 커스터마이징 {#customize-type-color}
css 변수를 오버라이딩함으로써 배지의 스타일을 사용자 정의할 수 있습니다. 다음은 기본값입니다: 배지의 스타일은 CSS 변수를 재정의하여 커스터마이징 할 수 있습니다. 다음은 기본값입니다:
```css ```css
:root { :root {
@ -56,14 +56,14 @@ css 변수를 오버라이딩함으로써 배지의 스타일을 사용자 정
## `<Badge>` ## `<Badge>`
`<Badge>` 컴포넌트는 다음의 prop들을 받습니다: `<Badge>` 컴포넌트는 다음과 같은 프로퍼티를 사용합니다:
```ts ```ts
interface Props { interface Props {
// `<slot>`이 전달되면, 이 값은 무시됩니다. // `<slot>`이 전달되면, 이 값은 무시.
text?: string text?: string
// 기본값`tip`입니다. // 기본값: `tip`.
type?: 'info' | 'tip' | 'warning' | 'danger' type?: 'info' | 'tip' | 'warning' | 'danger'
} }
``` ```

@ -1,13 +1,13 @@
# 카본 광고 {#carbon-ads} # 카본 광고 {#carbon-ads}
VitePress는 [카본 광고](https://www.carbonads.net/)에 대한 내장된 네이티브 지원을 제공합니다. config에서 카본 광고 자격증명을 정의함으로써, VitePress는 페이지에 광고를 표시합니다. VitePress는 [카본 광고](https://www.carbonads.net/)에 대한 기본적인 지원을 제공합니다. 구성에서 카본 광고 자격 증명을 정의하면 VitePress는 페이지에 광고를 표시합니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
carbonAds: { carbonAds: {
code: '당신의-카본-코드', code: 'your-carbon-code',
placement: '당신의-카본-위치' placement: 'your-carbon-placement'
} }
} }
} }
@ -19,4 +19,4 @@ export default {
`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` `//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}`
``` ```
카본 광고 설정에 대해 자세히 알아보려면, [카본 광고 웹사이트](https://www.carbonads.net/)를 방문해 주십시오. 카본 광고 구성에 대해 더 알고 싶다면 [카본 광고 웹사이트](https://www.carbonads.net/)를 방문하세요.

@ -1,14 +1,14 @@
# 기본 테마 설정 {#default-theme-config} # 기본 테마 구성 {#default-theme-config}
테마 설정을 통해 테마를 사용자 정의할 수 있습니다. 설정 파일의 `themeConfig` 옵션을 통해 테마 설정을 정의할 수 있습니다: 테마 구성은 테마를 커스텀 할 수 있게 해줍니다. 구성 파일에서 `themeConfig` 옵션을 통해 테마 구성을 정의할 수 있습니다:
```ts ```ts
export default { export default {
lang: 'en-US', lang: 'ko-KR',
title: 'VitePress', title: 'VitePress',
description: 'Vite & Vue로 구동되는 정적 사이트 생성기.', description: 'Vite 및 Vue로 기반 정적 사이트 생성기.',
// 테마 관련 설정. // 테마 관련 구성.
themeConfig: { themeConfig: {
logo: '/logo.svg', logo: '/logo.svg',
nav: [...], nav: [...],
@ -17,19 +17,19 @@ export default {
} }
``` ```
**이 페이지에 문서화된 옵션은 기본 테마에만 적용됩니다.** 다른 테마는 다른 테마 설정을 기대합니다. 커스텀 테마를 사용할 때, 테마 설정 객체는 테마로 전달되어 테마가 그것에 따라 조건적인 동작을 정의할 수 있습니다. **이 페이지에 문서화된 옵션은 기본 테마에만 적용됩니다.** 다른 테마는 다른 테마 구성이 필요합니다. 커스텀 테마를 사용하는 경우, 테마 구성 객체는 테마에 전달되어 테마가 이를 기반으로 다르게 동작할 수 있습니다.
## i18nRouting ## i18nRouting
- 타입: `boolean` - 타입: `boolean`
예를 들어 `zh`로 로케일을 변경하면 URL이 `/foo` (또는 `/en/foo/`)에서 `/zh/foo`로 변경됩니다. 이 동작을 비활성화하려면 `themeConfig.i18nRouting``false`로 설정하세요. 로케일을 `ko`로 변경하면 URL이 `/foo` (또는 `/en/foo/`)에서 `/ko/foo`로 변경됩니다. 이 동작을 비활성화하려면 `themeConfig.i18nRouting``false`로 설정하세요.
## logo ## logo
- 타입: `ThemeableImage` - 타입: `ThemeableImage`
내비게이션 바에 사이트 제목 바로 앞에 표시되는 로고 파일입니다. 경로 문자열을 받거나, 밝은/어두운 모드에 따라 다른 로고를 설정하기 위해 객체를 사용할 수 있습니다. 네비게이션 바에 사이트 제목 바로 앞에 표시할 로고 파일입니다. 경로 문자열 또는 라이트/다크 모드에 대해 다른 로고를 설정할 수 있는 객체를 사용합니다.
```ts ```ts
export default { export default {
@ -50,7 +50,7 @@ type ThemeableImage =
- 타입: `string | false` - 타입: `string | false`
내비게이션에서 기본 사이트 제목(`app config`의 `title`)을 대체하기 위해 이 항목을 사용자 정의할 수 있습니다. `false`로 설정하면 내비게이션의 제목이 비활성화됩니다. `logo`가 이미 사이트 제목 텍스트를 포함하고 있을 때 유용합니다. 이 항목을 커스텀하여 네비게이션 바의 기본 사이트 제목(애플리케이션 구성의 `title`)을 대체할 수 있습니다. `false`로 설정하면 네비게이션 바에서 제목이 비활성화됩니다. 이미 사이트 제목 텍스트가 포함된 `logo` 있을 때 유용합니다.
```ts ```ts
export default { export default {
@ -64,7 +64,7 @@ export default {
- 타입: `NavItem` - 타입: `NavItem`
내비게이션 메뉴 항목의 설정입니다. 자세한 내용은 [기본 테마: Nav](./default-theme-nav#navigation-links)에서 확인할 수 있습니다. 네비게이션 바 메뉴 아이템의 구성입니다. 자세한 내용은 [기본 테마: 네비게이션 바](./default-theme-nav#navigation-links)를 참고하세요.
```ts ```ts
export default { export default {
@ -112,7 +112,7 @@ interface NavItemWithChildren {
- 타입: `Sidebar` - 타입: `Sidebar`
사이드바 메뉴 항목의 설정입니다. 자세한 내용은 [기본 테마: Sidebar](./default-theme-sidebar)에서 확인할 수 있습니다. 사이드바 메뉴 항목에 대한 구성입니다. 자세한 내용은 [기본 테마: 사이드바](./default-theme-sidebar)에서 확인하세요.
```ts ```ts
export default { export default {
@ -140,28 +140,41 @@ export interface SidebarMulti {
export type SidebarItem = { export type SidebarItem = {
/** /**
* 항목의 텍스트 레이블. * 아이템의 텍스트 레이블
*/ */
text?: string text?: string
/** /**
* 항목의 링크. * 아이템의 링크
*/ */
link?: string link?: string
/** /**
* 항목의 자식들. * 아이템의 하위 항목
*/ */
items?: SidebarItem[] items?: SidebarItem[]
/** /**
* 명시되지 않은 경우, 그룹은 접을 수 없습니다. * 명시하지 않은 경우, 그룹을 접을 수 없습니다.
* *
* `true`이면, 그룹은 접을 수 있고 기본적으로 접혀 있습니다 * `true`: 그룹은 접을 수 있고 기본적으로 접혀 있습니다.
* *
* `false`이면, 그룹은 접을 수 있지만 기본적으로 펼쳐져 있습니다 * `false`: 그룹은 접을 수 있고 기본적으로 펼쳐져 있습니다.
*/ */
collapsed?: boolean collapsed?: boolean
/**
* 하위 아이템에 대한 기본 경로입니다.
*/
base?: string
/**
* 이전/다음 페이지의 푸터에 나타나는 텍스트를 커스텀 합니다.
*/
docFooterText?: string
rel?: string
target?: string
} }
``` ```
@ -169,37 +182,37 @@ export type SidebarItem = {
- 타입: `boolean | 'left'` - 타입: `boolean | 'left'`
- 기본값: `true` - 기본값: `true`
- [frontmatter](./frontmatter-config#aside)를 통해 페이지별로 재정의 가능 - [전문](./frontmatter-config#aside)을 통해 페이지별로 재정의할 수 있습니다.
이 값을 `false`로 설정하면 aside 컨테이너의 렌더링을 방지합니다.\ `false`: 어사이드 컨테이너가 렌더링되지 않습니다.\
이 값을 `true`로 설정하면 aside를 오른쪽에 렌더링합니다.\ `true`: 어사이드가 오른쪽에 렌더링됩니다.\
이 값을 `left`로 설정하면 aside를 왼쪽에 렌더링합니다. `left`: 어사이드가 왼쪽에 렌더링됩니다.
모든 뷰포트에 대해 비활성화하려면 `outline: false`를 사용해야 합니다. 모든 뷰포트에 비활성화하려면 `outline: false`를 사용해야 합니다.
## outline ## outline
- 타입: `Outline | Outline['level'] | false` - 타입: `Outline | Outline['level'] | false`
- [frontmatter](./frontmatter-config#outline)를 통해 페이지별로 레벨 재정의 가능 - [전문](./frontmatter-config#outline)을 사용해 각 페이지별로 계층 구조를 재정의할 수 있습니다.
이 값을 `false`로 설정하면 윤곽선 컨테이너의 렌더링을 방지합니다. 자세한 내용은 이 인터페이스를 참조하세요: 이 값을 `false`로 설정하면 아웃라인(개요) 컨테이너가 렌더링되지 않습니다. 자세한 내용은 아래 인터페이스를 참고하세요:
```ts ```ts
interface Outline { interface Outline {
/** /**
* 개요에 표시될 제목 수준. * 아웃라인에 표시할 제목 레벨.
* 단일 수치는 해당 수준의 제목만 표시됨을 의미합니다. * 단일 숫자는 해당 레벨의 제목만 표시됨을 의미합니다.
* 튜플이 전달되면 첫 번째 수치는 최소 수준이고 두 번째 수치는 최대 수준입니다. * 튜플이 전달되면, 첫 번째 숫자는 최소 수준을, 두 번째 숫자는 최대 수준을 나타냅니다.
* `'deep'``[2, 6]`과 동일하며, `<h2>`부터 `<h6>`까지의 모든 제목이 표시됨을 의미합니다. * `'deep'``[2, 6]`과 동일하며, 이는 `<h2>`에서 `<h6>`까지의 모든 제목이 표시됨을 의미합니다.
* *
* @default 2 * @default 2
*/ */
level?: number | [number, number] | 'deep' level?: number | [number, number] | 'deep'
/** /**
* 개요에 표시될 제목. * 아웃라인에 표시될 제목.
* *
* @default '이 페이지에서' * @default 'On this page'
*/ */
label?: string label?: string
} }
@ -209,7 +222,7 @@ interface Outline {
- 타입: `SocialLink[]` - 타입: `SocialLink[]`
내비게이션에 아이콘과 함께 소셜 계정 링크를 표시하기 위해 이 옵션을 정의할 수 있습니다. 이 옵션을 정의하여 네비게이션 바에 소셜 링크를 아이콘과 함께 표시할 수 있습니다.
```ts ```ts
export default { export default {
@ -217,14 +230,14 @@ export default {
socialLinks: [ socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }, { icon: 'github', link: 'https://github.com/vuejs/vitepress' },
{ icon: 'twitter', link: '...' }, { icon: 'twitter', link: '...' },
// SVG 문자열을 전달하여 사용자 정의 아이콘을 추가할 수도 있습니다: // SVG를 문자열로 전달하여 커스텀 아이콘을 추가할 수도 있습니다:
{ {
icon: { icon: {
svg: '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Dribbble</title><path d="M12...6.38z"/></svg>' svg: '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="m354-287 126-76 126 77-33-144 111-96-146-13-58-136-58 135-146 13 111 97-33 143ZM233-120l65-281L80-590l288-25 112-265 112 265 288 25-218 189 65 281-247-149-247 149Zm247-350Z"/></svg>'
}, },
link: '...', link: '...',
// 접근성을 위해 사용자 정의 레이블을 포함할 수도 있습니다 (선택 사항이지만 권장됨): // 접근성을 위해 커스텀 레이블을 포함할 수도 있습니다 (선택 사항이지만 권장됨):
ariaLabel: '멋진 링크' ariaLabel: '스타 링크'
} }
] ]
} }
@ -256,16 +269,16 @@ type SocialLinkIcon =
## footer ## footer
- 타입: `Footer` - 타입: `Footer`
- [frontmatter](./frontmatter-config#footer)를 통해 페이지별로 재정의 가능 - [전문](./frontmatter-config#footer)을 사용해 페이지별로 재정의할 수 있습니다.
풋터 설정입니다. 풋터에 메시지나 저작권 텍스트를 추가할 수 있지만, 사이드바를 포함하지 않는 페이지에서만 표시됩니다. 이는 디자인 우려사항 때문입니다. 푸터 구성입니다. 메시지 또는 저작권 텍스트를 푸터에 추가할 수 있지만, 이는 페이지에 사이드바가 포함되지 않은 경우에만 표시됩니다. 이는 디자인상의 이유 때문입니다.
```ts ```ts
export default { export default {
themeConfig: { themeConfig: {
footer: { footer: {
message: 'MIT 라이선스에 따라 릴리즈되었습니다.', message: 'MIT 라이선스에 따라 릴리즈되었습니다.',
copyright: '저작권 © 2019-현재 Evan You' copyright: '저작권 © 2019-현재 홍길동'
} }
} }
} }
@ -274,16 +287,16 @@ export default {
```ts ```ts
export interface Footer { export interface Footer {
message?: string message?: string
COPYRIGHT?: string copyright?: string
} }
``` ```
## editLink ## editLink
- 타입: `EditLink` - 타입: `EditLink`
- [frontmatter](./frontmatter-config#editlink)를 통해 페이지별로 재정의 가능 - [전문](./frontmatter-config#footer)을 사용해 페이지별로 재정의할 수 있습니다.
편집 링크를 통해 GitHub이나 GitLab과 같은 Git 관리 서비스에서 페이지를 편집하는 링크를 표시할 수 있습니다. [기본 테마: 편집 링크](./default-theme-edit-link)에서 자세한 내용을 확인하세요. 편집 링크 기능을 사용하면 GitHub 또는 GitLab과 같은 Git 관리 서비스에서 페이지를 편집할 수 있는 링크를 표시할 수 있습니다. 자세한 내용은 [기본 테마: 편집 링크](./default-theme-edit-link)를 참고하세요.
```ts ```ts
export default { export default {
@ -307,13 +320,13 @@ export interface EditLink {
- 타입: `LastUpdatedOptions` - 타입: `LastUpdatedOptions`
마지막 업데이트 텍스트와 날짜 형식을 사용자 정의할 수 있습니다. 마지막 업데이트된 날짜의 텍스트와 날짜 형식을 커스텀 할 수 있습니다.
```ts ```ts
export default { export default {
themeConfig: { themeConfig: {
lastUpdated: { lastUpdated: {
text: '업데이트 되었습니다', text: '마지막 업데이트 날짜',
formatOptions: { formatOptions: {
dateStyle: 'full', dateStyle: 'full',
timeStyle: 'medium' timeStyle: 'medium'
@ -326,7 +339,7 @@ export default {
```ts ```ts
export interface LastUpdatedOptions { export interface LastUpdatedOptions {
/** /**
* @default '마지막 업데이트' * @default 'Last updated'
*/ */
text?: string text?: string
@ -342,7 +355,7 @@ export interface LastUpdatedOptions {
- 타입: `AlgoliaSearch` - 타입: `AlgoliaSearch`
[Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트를 검색할 수 있는 옵션입니다. [기본 테마: 검색](./default-theme-search)에서 자세히 알아보세요. [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트를 검색할 수 있는 옵션입니다. 자세한 내용은 [기본 테마: 검색](./default-theme-search)을 참고하세요.
```ts ```ts
export interface AlgoliaSearchOptions extends DocSearchProps { export interface AlgoliaSearchOptions extends DocSearchProps {
@ -376,13 +389,13 @@ export interface CarbonAdsOptions {
} }
``` ```
[기본 테마: Carbon Ads](./default-theme-carbon-ads)에서 자세히 알아보세요. 자세한 내용은 [기본 테마: 카본 광고](./default-theme-carbon-ads)를 참고하세요.
## docFooter ## docFooter
- 타입: `DocFooter` - 타입: `DocFooter`
영어로 문서를 작성하지 않을 때 이전 및 다음 링크 위에 나타나는 텍스트를 사용자 정의하는 데 사용할 수 있습니다. 또한 이전/다음 링크를 전역적으로 비활성화할 수 있습니다. 이전/다음 링크를 선택적으로 활성화/비활성화하려면 [frontmatter](./default-theme-prev-next-links)를 사용할 수 있습니다. 이 옵션은 이전 및 다음 링크에 표시되는 텍스트를 커스텀하는 데 사용합니다. 영어로 문서를 작성하지 않는 경우 유용합니다. 또한 이전/다음 링크를 전역적으로 비활성화할 수도 있습니다. 선택적으로 이전/다음 링크를 활성화/비활성화하려면 [전문](./default-theme-prev-next-links)을 사용합니다.
```ts ```ts
export default { export default {
@ -405,48 +418,48 @@ export interface DocFooter {
## darkModeSwitchLabel ## darkModeSwitchLabel
- 타입: `string` - 타입: `string`
- 기본값: `외관` - 기본값: `Appearance`
어두운 모드 전환 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다. 이 옵션은 다크 모드 스위치 레이블을 커스텀할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## lightModeSwitchTitle ## lightModeSwitchTitle
- 타입: `string` - 타입: `string`
- 기본값: `라이트 테마로 전환` - 기본값: `Switch to light theme`
호버 시 나타나는 라이트 모드 전환 제목을 사용자 정의하는 데 사용할 수 있습니다. 이 옵션은 라이트 모드 스위치 타이틀을 커스텀할 때 사용합니다. 이것은 호버(hover)할 때 나타납니다.
## darkModeSwitchTitle ## darkModeSwitchTitle
- 타입: `string` - 타입: `string`
- 기본값: `어두운 테마로 전환` - 기본값: `Switch to dark theme`
호버 시 나타나는 어두운 모드 전환 제목을 사용자 정의하는 데 사용할 수 있습니다. 호버 시 나타나는 다크 모드 스위치 타이틀을 커스텀할 때 사용합니다.
## sidebarMenuLabel ## sidebarMenuLabel
- 타입: `string` - 타입: `string`
- 기본값: `메뉴` - 기본값: `Menu`
사이드바 메뉴 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다. 사이드바 메뉴 레이블을 커스텀 할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## returnToTopLabel ## returnToTopLabel
- 타입: `string` - 타입: `string`
- 기본값: `맨 위로 돌아가기` - 기본값: `Return to top`
맨 위로 돌아가기 버튼의 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다. 맨 위로 이동 버튼의 레이블을 커스텀 할 때 사용합니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## langMenuLabel ## langMenuLabel
- 타입: `string` - 타입: `string`
- 기본값: `언어 변경` - 기본값: `Change language`
내비게이션 바의 언어 토글 버튼의 aria-label을 사용자 정의하는 데 사용됩니다. [i18n](../guide/i18n)을 사용하는 경우에만 사용됩니다. 네비게이션 바에서 언어 토글 버튼의 aria-label을 커스텀 할 때 사용합니다. 이는 [i18n](../guide/i18n)을 사용하는 경우에만 사용됩니다.
## externalLinkIcon ## externalLinkIcon
- 타입: `boolean` - 타입: `boolean`
- 기본값: `false` - 기본값: `false`
마크다운의 외부 링크 옆에 외부 링크 아이콘을 표시할지 여부니다. 마크다운의 외부 링크 옆에 외부 링크 아이콘을 표시할지 여부를 설정합니다.

@ -1,8 +1,8 @@
# 편집 링크 {#edit-link} # 편집 링크 {#edit-link}
## 사이트 레벨 설정 {#site-level-config} ## 사이트 단계에서 설정하기 {#site-level-config}
편집 링크를 사용하면 GitHub이나 GitLab과 같은 Git 관리 서비스에서 페이지를 편집하는 링크를 표시할 수 있습니다. 활성화하려면, `themeConfig.editLink` 옵션을 설정에 추가하세요. 편집 링크는 GitHub, GitLab과 같은 Git 관리 서비스에서 페이지를 편집할 수 있는 링크를 표시할 수 있게 해줍니다. 이를 활성화하려면 `themeConfig.editLink` 옵션을 구성에 추가하세요.
```js ```js
export default { export default {
@ -16,7 +16,7 @@ export default {
`pattern` 옵션은 링크의 URL 구조를 정의하며, `:path`는 페이지 경로로 대체됩니다. `pattern` 옵션은 링크의 URL 구조를 정의하며, `:path`는 페이지 경로로 대체됩니다.
또한 [`PageData`](./runtime-api#usedata)를 인수로 받아 URL 문자열을 반환하는 순수 함수를 넣을 수도 있습니다. 또한, [`PageData`](./runtime-api#usedata)를 인자로 받아 URL 문자열을 반환하는 순수 함수를 사용할 수도 있습니다.
```js ```js
export default { export default {
@ -34,24 +34,24 @@ export default {
} }
``` ```
이 함수는 부작용이 없어야 하며, 범위 외의 것에 접근할 수 없으며, 브라우저에서 직렬화되어 실행됩니다. 이 함수는 브라우저에서 직렬화되어 실행되므로, 부작용을 가지지 않고 해당 스코프 외부의 어떤 것도 참조하지 않도록 해야 합니다.
기본적으로, 이 옵션은 문서 페이지 하단에 "Edit this page"라는 링크 텍스트를 추가합니다. `text` 옵션을 정의하여 이 텍스트를 사용자 정의할 수 있습니다. 기본적으로 이 설정은 문서 페이지 하단에 "Edit this page"이라는 텍스트 링크를 추가합니다. 이 텍스트는 `text` 옵션을 정의하여 커스터마이징 할 수 있습니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
editLink: { editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path', pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'GitHub에서 이 페이지를 편집하세요' text: '이 페이지 편집 제안하기'
} }
} }
} }
``` ```
## 프론트매터 설정 {#frontmatter-config} ## 전문에서 설정하기 {#frontmatter-config}
프론트매터의 `editLink` 옵션을 사용하여 페이지별로 이 기능을 비활성화할 수 있습니다: 페이지별로 이 기능을 비활성화하려면, 전문에서 `editLink` 옵션을 사용하세요:
```yaml ```yaml
--- ---

@ -1,13 +1,13 @@
# 푸터 {#footer} # 푸터 {#footer}
VitePress는 `themeConfig.footer`가 존재할 때 페이지 하단에 전역 푸터를 표시합니다. `themeConfig.footer`가 존재하면 VitePress는 페이지 하단에 전역 푸터를 표시합니다.
```ts ```ts
export default { export default {
themeConfig: { themeConfig: {
footer: { footer: {
message: 'Released under the MIT License.', message: 'MIT 라이선스에 따라 릴리즈되었습니다.',
copyright: 'Copyright © 2019-present Niceplugin' copyright: '저작권 © 2019-현재 홍길동'
} }
} }
} }
@ -23,28 +23,28 @@ export interface Footer {
} }
``` ```
위의 구성은 HTML 문자열도 지원합니다. 예를 들어, 푸터 텍스트에 몇 가지 링크를 구성하고 싶다면, 다음과 같이 구성을 조정할 수 있습니다: 위의 구성은 HTML 문자열도 지원합니다. 예를 들어, 푸터 텍스트에 링크를 포함하고 싶다면, 다음과 같이 구성을 수정하면 됩니다:
```ts ```ts
export default { export default {
themeConfig: { themeConfig: {
footer: { footer: {
message: '<a href="https://github.com/vuejs/vitepress/blob/main/LICENSE">MIT 라이선스</a>에 따라 릴리즈되었습니다.', message: '<a href="https://github.com/vuejs/vitepress/blob/main/LICENSE">MIT 라이선스</a>에 따라 릴리즈되었습니다.',
copyright: '저작권 © 2019-현재 <a href="https://github.com/yyx990803">Evan You</a>' copyright: '저작권 © 2019-현재 <a href="https://github.com/niceplugin">홍길동</a>'
} }
} }
} }
``` ```
::: warning ::: warning
`message``저작권`에는 `<p>` 요소 안에 렌더링되기 때문에 인라인 요소만 사용할 수 있습니다. 블록 요소를 추가하고 싶다면, 대신 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 슬롯을 사용하는 것을 고려하세요. `message``copyright`는 `<p>` 엘리먼트 내부에 렌더링되므로 인라인 엘리먼트만 사용할 수 있습니다. 블록 엘리먼트를 추가하려면 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 슬롯을 사용하는 것이 좋습니다.
::: :::
푸터는 [사이드바](./default-theme-sidebar)가 보이는 경우에는 표시되지 않습니다. [사이드바](./default-theme-sidebar)가 표시되는 경우 푸터는 표시되지 않습니다.
## 프론트매터 구성 {#frontmatter-config} ## 전문에서 설정하기 {#frontmatter-config}
이 기능은 프론트매터의 `footer` 옵션을 사용하여 페이지별로 비활성화될 수 있습니다: 이 기능은 전문의 `footer` 옵션을 사용하여 페이지별로 비활성화 할 수 있습니다.
```yaml ```yaml
--- ---

@ -1,6 +1,6 @@
# 홈페이지 {#home-page} # 홈 페이지 {#home-page}
VitePress 기본 테마는 홈페이지 레이아웃을 제공하며, 이 사이트의 [홈페이지](../)에서도 사용된 것을 볼 수 있습니다. [frontmatter](./frontmatter-config)에 `layout: home`을 지정함으로써 여러분의 페이지에도 이를 사용할 수 있습니다. VitePress 기본 테마는 홈 페이지 레이아웃을 제공합니다. 이것은 이 사이트의 [홈 페이지](../)에도 사용되었습니다. `layout: home`을 [전문](./frontmatter-config)에 지정하여 어느 페이지에서도 이를 사용할 수 있습니다.
```yaml ```yaml
--- ---
@ -8,11 +8,11 @@ layout: home
--- ---
``` ```
하지만, 이 옵션만으로는 큰 효과를 보지 못합니다. `hero``features`와 같은 추가적인 옵션을 설정함으로써 홈페이지에 여러 가지 다른 사전 템플릿 "섹션"을 추가할 수 있습니다. 하지만 이 옵션만으로는 많은 것을 할 수 없습니다. 다행히도 `hero``features`와 같은 추가 옵션을 설정하여 홈 페이지에 다양한 사전 템플릿 "섹션"들을 추가할 수 있습니다.
## Hero 섹션 {#hero-section} ## Hero 섹션 {#hero-section}
Hero 섹션은 홈페이지 맨 위에 옵니다. 여기에서 Hero 섹션을 구성하는 방법입니다. Hero 섹션은 홈 페이지의 상단에 위치합니다. Hero 섹션을 구성하는 방법은 다음과 같습니다.
```yaml ```yaml
--- ---
@ -20,38 +20,38 @@ layout: home
hero: hero:
name: VitePress name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기. text: Vite & Vue 기반 정적 사이트 생성기
tagline: Lorem ipsum... tagline: 단 몇 분 만에 마크다운을 우아한 문서로 변환
image: image:
src: /logo.png src: /logo.png
alt: VitePress alt: VitePress
actions: actions:
- theme: brand - theme: brand
text: 시작하기 text: VitePress란 무엇인가?
link: /guide/what-is-vitepress link: /guide/what-is-vitepress
- theme: alt - theme: alt
text: GitHub에서 보기 text: GitHub
link: https://github.com/vuejs/vitepress link: https://github.com/vuejs/vitepress
--- ---
``` ```
```ts ```ts
interface Hero { interface Hero {
// `text` 위에 표시되는 문자열입니다. 브랜드 색상이 // `text` 위에 브랜드 색상으로 표시되는 문자열.
// 함께 제공되며 제품 이름과 같이 짧을 것으로 예상됩니다. // 제품명 등 간략한 내용을 추천.
name?: string name?: string
// hero 섹션의 주요 텍스트입니다. // hero 섹션의 본문.
// 이는 `h1` 태그로 정의됩니다. // `h1` 태그로 정의됨.
text: string text: string
// `text` 아래에 표시되는 태그라인입니다. // `text` 아래에 표시되는 슬로건 문자열.
tagline?: string tagline?: string
// 이미지는 텍스트 및 태그라인 영역 옆에 표시됩니다. // `text``tagline` 옆에 표시되는 이미지.
image?: ThemeableImage image?: ThemeableImage
// 홈 hero 섹션에 표시할 작업 버튼들입니다. // hero 섹션에 표시할 버튼 리스트.
actions?: HeroAction[] actions?: HeroAction[]
} }
@ -61,26 +61,26 @@ type ThemeableImage =
| { light: string; dark: string; alt?: string } | { light: string; dark: string; alt?: string }
interface HeroAction { interface HeroAction {
// 버튼의 색상 테마입니다. 기본값은 `brand`입니다. // 버튼의 색상 테마. 기본값: `brand`
theme?: 'brand' | 'alt' theme?: 'brand' | 'alt'
// 버튼의 레이블입니다. // 버튼의 레이블.
text: string text: string
// 버튼의 목적지 링크입니다. // 버튼의 목적지 링크.
link: string link: string
// 링크 타겟 속성입니다. // 링크의 target 어트리뷰트.
target?: string target?: string
// 링크 rel 속성입니다. // 링크의 rel 어트리뷰트.
rel?: string rel?: string
} }
``` ```
### 이름 색상 사용자 정의 {#customizing-the-name-color} ### `name` 색상 커스터마이징 {#customizing-the-name-color}
VitePress는 `name`대해 브랜드 색상 (`--vp-c-brand-1`)을 사용합니다. 하지만, `--vp-home-hero-name-color` 변수를 오버라이딩함으로써 이 색상을 사용자 정의할 수 있습니다. VitePress는 `name`브랜드 색상(`--vp-c-brand-1`)을 사용합니다. 하지만 `--vp-home-hero-name-color` 변수를 재정의하여 이 색상을 커스텀 할 수 있습니다.
```css ```css
:root { :root {
@ -88,7 +88,7 @@ VitePress는 `name`에 대해 브랜드 색상 (`--vp-c-brand-1`)을 사용합
} }
``` ```
또한 `--vp-home-hero-name-background`와 결합하여 `name`에 그라데이션 색상을 부여할 수도 있습니다. 또한 `--vp-home-hero-name-background` 변수를 정의해 추가적으로 `name`을 그라데이션 색상으로 커스터마이징도 가능합니다.
```css ```css
:root { :root {
@ -97,11 +97,11 @@ VitePress는 `name`에 대해 브랜드 색상 (`--vp-c-brand-1`)을 사용합
} }
``` ```
## 기능 섹션 {#features-section} ## Features 섹션 {#features-section}
기능 섹션에서는 Hero 섹션 바로 다음에 보여주고 싶은 기능의 수를 제한 없이 나열할 수 있습니다. 구성하려면 frontmatter에 `features` 옵션을 전달합니다. Features 섹션에서는 Hero 섹션 바로 아래에 표시할 각 feature를 원하는 만큼 나열할 수 있습니다. 이를 구성하려면 `features` 옵션을 전문에 전달하면 됩니다.
기능에 대해 이모지나 이미지 형태의 아이콘을 제공할 수 있습니다. 구성된 아이콘가 이미지(svg, png, jpeg...)인 경우, 적절한 너비와 높이를 가진 아이콘을 제공해야 합니다; 필요한 경우 어두운 테마 및 밝은 테마의 변형뿐만 아니라 설명, 본질적인 크기도 제공할 수 있습니다. feature에 아이콘을 제공할 수 있으며, 이는 이모지 또는 이미지의 형태일 수 있습니다. 아이콘으로 이미지(svg, png, jpeg 등)를 사용하려면 적절한 너비와 높이를 제공해야 하며, 필요에 따라 설명, 이미지의 고유 크기, 다크 테마와 라이트 테마에 대한 변형 아이콘도 제공할 수 있습니다.
```yaml ```yaml
--- ---
@ -109,49 +109,49 @@ layout: home
features: features:
- icon: 🛠️ - icon: 🛠️
title: 항상 간단하고 최소한의 title: Simple and minimal, always
details: Lorem ipsum... details: Lorem ipsum...
- icon: - icon:
src: /cool-feature-icon.svg src: /cool-feature-icon.svg
title: 또 다른 멋진 기능 title: Another cool feature
details: Lorem ipsum... details: Lorem ipsum...
- icon: - icon:
dark: /dark-feature-icon.svg dark: /dark-feature-icon.svg
light: /light-feature-icon.svg light: /light-feature-icon.svg
title: 또 다른 멋진 기능 title: Another cool feature
details: Lorem ipsum... details: Lorem ipsum...
--- ---
``` ```
```ts ```ts
interface Feature { interface Feature {
// 각 기능 상자에 아이콘을 표시합니다. // 각 feature 박스에 표시할 아이콘.
icon?: FeatureIcon icon?: FeatureIcon
// 기능의 제목입니다. // feature의 제목.
title: string title: string
// 기능의 세부 정보입니다. // feature의 세부 정보.
details: string details: string
// 기능 구성 요소에서 클릭 시 링크합니다. // feature 컴포넌트 클릭 시 링크.
// 링크는 내부 또는 외부 모두 가능합니다. // 링크는 내부 또는 외부 모두 가능.
// //
// 예: `guide/reference/default-theme-home-page` 또는 `https://example.com` // 예: `guide/reference/default-theme-home-page` 또는 `https://example.com`
link?: string link?: string
// 기능 구성 요소 내에서 표시될 링크 텍스트입니다. // feature 컴포넌트 내 표시될 링크 텍스트.
// `link` 옵션과 함께 사용하는 것이 좋습니다. // `link` 옵션과 함께 사용하는 것을 추천.
// //
// 예: `더 알아보기`, `페이지 방문`, // 예: `더 알아보기`, `페이지 방문`
linkText?: string linkText?: string
// `link` 옵션을 위한 링크 rel 속성입니다. // `link` 옵션을 위한 링크 rel 어트리뷰트.
// //
// 예: `external` // 예: `external`
rel?: string rel?: string
// `link` 옵션을 위한 링크 target 속성입니다. // `link` 옵션을 위한 링크 target 어트리뷰트.
target?: string target?: string
} }
@ -169,7 +169,7 @@ type FeatureIcon =
## 마크다운 컨텐츠 {#markdown-content} ## 마크다운 컨텐츠 {#markdown-content}
`---` frontmatter 구분자 아래에 마크다운을 더함으로써 사이트의 홈페이지에 추가 컨텐츠를 추가할 수 있습니다. 홈 페이지 레이아웃에 추가 컨텐츠를 작성하려면 전문 구분선 `---` 아래에 마크다운을 추가하면 됩니다.
````md ````md
--- ---
@ -177,12 +177,12 @@ layout: home
hero: hero:
name: VitePress name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기. text: Vite & Vue 기반 정적 사이트 생성기
--- ---
## 시작하기 ## 시작하기
`npx`를 사용하여 바로 VitePress를 사용할 수 있습니다! `npx`를 사용하여 VitePress를 바로 시작할 수 있습니다!
```sh ```sh
npm init npm init
@ -191,5 +191,5 @@ npx vitepress init
```` ````
::: info ::: info
VitePress는 항상 `layout: home` 페이지의 추가 컨텐츠에 자동 스타일을 적용하지는 않았습니다. 이전 동작으로 되돌리려면, frontmatter에 `markdownStyles: false`를 추가할 수 있습니다. `layout: home` 페이지의 추가 컨텐츠에 자동으로 기본 마크다운 스타일이 적용됩니다(영문 원서에서는 반대로 설명함). 스타일을 적용하지 않으려면 전문에 `markdownStyles: false`를 추가하면 됩니다.
::: :::

@ -1,12 +1,12 @@
# 마지막 업데이트 시간 {#last-updated} # 마지막 업데이트 날짜 {#last-updated}
마지막 내용의 업데이트 시간은 페이지의 오른쪽 하단에 표시됩니다. 활성화하려면 config`lastUpdated` 옵션을 추가하세요. 마지막 업데이트 날짜는 페이지 오른쪽 하단에 표시됩니다. 이를 활성화하려면 구성 파일`lastUpdated` 옵션을 추가하세요.
::: tip ::: tip
업데이트 시간을 보려면 markdown 파일을 커밋해야 합니다. 마크다운 파일을 커밋해야 업데이트된 시간을 확인할 수 있습니다.
::: :::
## 사이트 수준 설정 {#site-level-config} ## 사이트 단계에서 설정하기 {#site-level-config}
```js ```js
export default { export default {
@ -14,9 +14,9 @@ export default {
} }
``` ```
## 프런트매터 설정 {#frontmatter-config} ## 전문에서 설정하기 {#frontmatter-config}
이 기능은 frontmatter의 `lastUpdated` 옵션을 사용하여 페이지별로 비활성화할 수 있습니다: 페이지별로 이 기능을 비활성화하려면, 전문에서 `lastUpdated` 옵션을 사용하세요:
```yaml ```yaml
--- ---
@ -24,4 +24,4 @@ lastUpdated: false
--- ---
``` ```
자세한 내용은 [기본 테마: 마지막 업데이트 시간](./default-theme-config#lastupdated)를 참조하세요. 테마 수준에서 참 값을 설정하면 사이트 또는 페이지 수준에서 명시적으로 비활성화하지 않는 한 기능이 활성화됩니다. 자세한 내용은 [기본 테마: lastUpdated](./default-theme-config#lastupdated)를 참고하세요. 테마 레벨에서 참(truthy) 값을 설정하면, 사이트나 페이지 레벨에서 명시적으로 비활성화하지 않는 한 기능이 활성화됩니다.

@ -1,6 +1,6 @@
# 레이아웃 {#layout} # 레이아웃 {#layout}
페이지 [프런트매터](./frontmatter-config)에 `layout` 옵션을 설정함으로써 페이지 레이아웃을 선택할 수 있습니다. `doc`, `page`, `home` 세 가지 레이아웃 옵션이 있습니다. 아무것도 지정하지 않으면, 해당 페이지는 `doc` 페이지로 처리됩니다. 페이지의 [전문](./frontmatter-config)에 `layout` 옵션을 설정하여 페이지 레이아웃을 선택할 수 있습니다. `doc`, `page`, `home` 세 가지 레이아웃 옵션이 있습니다. 아무것도 지정하지 않으면 `doc` 페이지로 처리됩니다.
```yaml ```yaml
--- ---
@ -8,38 +8,38 @@ layout: doc
--- ---
``` ```
## Doc 레이아웃 {#doc-layout} ## `doc` 레이아웃 {#doc-layout}
`doc` 옵션은 기본 레이아웃이며, 전체 마크다운 내용을 "문서화"된 모양으로 스타일링합니다. 이것은 전체 내용을 `vp-doc` css 클래스로 감싸고, 그 아래 요소들에 스타일을 적용함으로써 작동합니다. `doc` 옵션은 기본 레이아웃으로, 전체 마크다운 콘텐츠를 "문서" 스타일로 변환합니다. 이 레이아웃은 전체 콘텐츠를 `vp-doc` CSS 클래스로 감싸고, 하위 엘리먼트에 스타일을 적용하는 방식으로 작동합니다.
`p``h2`와 같은 거의 모든 일반 요소들은 특별한 스타일링을 받습니다. 따라서 마크다운 내용 내에 사용자 정의 HTML을 추가할 경우, 이러한 스타일들에 영향을 받게 될 것임을 명심하세요. `p``h2` 같은 거의 모든 일반적인 엘리먼트들이 특별한 스타일을 갖게 됩니다. 따라서 마크다운 콘텐츠에 커스텀 HTML을 추가할 경우, 해당 HTML도 이러한 스타일의 영향을 받게 된다는 점을 유념해야 합니다.
또한 아래 나열된 문서화 특정 기능들을 제공합니다. 이 기능들은 이 레이아웃에서만 활성화됩니다. 이 레이아웃에서는 아래에 나열된 문서 전용 기능들도 제공됩니다. 이 기능들은 오직 이 레이아웃에서만 활성화됩니다.
- 편집 링크 - 편집 링크
- 이전/다음 링크 - 이전/다음 링크
- 개요 - 개요(outline)
- [카본 광고](./default-theme-carbon-ads) - [카본 광고](./default-theme-carbon-ads)
## 페이지 레이아웃 {#page-layout} ## `page` 레이아웃 {#page-layout}
`page` 옵션은 "빈 페이지"로 처리됩니다. 마크다운은 여전히 파싱되며, 모든 [마크다운 확장](../guide/markdown) 기능은 `doc` 레이아웃과 동일하게 작동하지만, 기본 스타일은 적용받지 않습니다. `page` 옵션은 "빈 페이지"로 처리됩니다. 마크다운은 여전히 파싱되며, 모든 [마크다운 확장 기능](../guide/markdown)이 `doc` 레이아웃과 동일하게 작동하지만, 기본 스타일링은 적용되지 않습니다.
페이지 레이아웃을 통해 VitePress 테마의 마크업 영향을 받지 않고 모든 것을 직접 스타일링할 수 있습니다. 이는 사용자 정의 페이지를 생성하고 싶을 때 유용합니다. 이 페이지 레이아웃은 VitePress 테마가 마크업에 영향을 미치지 않도록 하여, 모든 스타일을 직접 지정할 수 있게 해줍니다. 이는 커스텀 페이지를 만들고자 할 때 유용합니다.
이 레이아웃에서도 페이지가 일치하는 사이드바 구성이 있는 경우 여전히 사이드바가 표시됨을 유의하세요. 이 레이아웃에서도 페이지에 매칭되는 사이드바 구성이 있는 경우 사이드바는 여전히 표시됩니다.
## 레이아웃 {#home-layout} ## `home` 레이아웃 {#home-layout}
`home` 옵션은 템플릿화된 "홈페이지"를 생성합니다. 이 레이아웃에서는 `hero``features`와 같은 추가 옵션을 설정해 컨텐츠를 더 자세히 커스터마이즈할 수 있습니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)를 방문해주세요. `home` 옵션은 템플릿화된 "홈 페이지"를 생성합니다. 이 레이아웃에서는 `hero``features` 같은 추가 옵션을 설정하여 콘텐츠를 더 커스터마이징 할 수 있습니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)를 참고하세요.
## 레이아웃 없음 {#no-layout} ## 레이아웃 없음 {#no-layout}
레이아웃을 원하지 않는 경우, 프런트매터를 통해 `layout: false`를 전달할 수 있습니다. 이 옵션은 완전히 맞춤화된 랜딩 페이지(기본적으로 사이드바, 내비게이션 바, 또는 푸터 없음)를 원할 때 유용합니다. 어떤 레이아웃도 원하지 않는 경우, 전문에 `layout: false`를 전달할 수 있습니다. 이 옵션은 (기본적으로 사이드바, 네비게이션 바, 또는 푸터가 없는) 완전히 커스터마이징 가능한 랜딩 페이지를 만들고자 할 때 유용합니다.
## 사용자 정의 레이아웃 {#custom-layout} ## 커스텀 레이아웃 {#custom-layout}
또한 사용자 정의 레이아웃을 사용할 수 있습니다: 커스텀 레이아웃을 사용할 수도 있습니다:
```md ```md
--- ---
@ -47,7 +47,7 @@ layout: foo
--- ---
``` ```
이것은 컨텍스트에 등록된 `foo`라는 이름의 컴포넌트를 찾습니다. 예를 들어, `.vitepress/theme/index.ts`에서 컴포넌트를 전역으로 등록할 수 있습니다: 이것은 컨텍스트에 등록된 `foo`라는 이름의 컴포넌트를 찾습니다. 예를 들어 `.vitepress/theme/index.ts`에서 컴포넌트를 전역으로 등록할 수 있습니다:
```ts ```ts
import DefaultTheme from 'vitepress/theme' import DefaultTheme from 'vitepress/theme'

@ -1,10 +1,10 @@
# Nav {#nav} # 네비게이션 바 {#nav}
Nav 페이지 상단에 표시되는 내비게이션 바입니다. 사이트 제목, 전역 메뉴 링크 등을 포함하고 있습니다. 네비게이션 바는 페이지 상단에 표시되며, 사이트 제목, 전역 메뉴 링크 등이 포함됩니다.
## 사이트 제목 및 로고 {#site-title-and-logo} ## 사이트 제목 및 로고 {#site-title-and-logo}
기본적으로 nav는 [`config.title`](./site-config#title) 값이 참조하는 사이트 제목을 표시합니다. nav에 표시되는 내용을 변경하고 싶다면 `themeConfig.siteTitle` 옵션에 사용자 정의 텍스트를 정의할 수 있습니다. 기본적으로 네비게이션 바는 [`config.title`](./site-config#title) 값을 참조하여 사이트 제목을 표시합니다. 여기에 표시되는 내용을 변경하려면 `themeConfig.siteTitle` 옵션에 커스텀 텍스트를 정의합니다.
```js ```js
export default { export default {
@ -14,7 +14,7 @@ export default {
} }
``` ```
사이트에 로고가 있다면 이미지 경로를 전달하여 표시할 수 있습니다. 로고를 `public` 디렉터리에 위치시키고, 그 절대 경로를 정의해야 합니다. 사이트에 로고가 있는 경우, 이미지의 경로를 전달하여 로고를 표시할 수 있습니다. 로고는 `public` 폴더에 배치하고, 이것의 절대 경로를 정의해야 합니다.
```js ```js
export default { export default {
@ -24,7 +24,7 @@ export default {
} }
``` ```
로고를 추가하면 사이트 제목과 함께 표시됩니다. 로고만 필요하고 사이트 제목 텍스트를 숨기고 싶다면 `siteTitle` 옵션에 `false`를 설정하세요. 로고를 추가하면 사이트 제목과 함께 표시됩니다. 로고만 필요하고 사이트 제목 텍스트를 숨기고 싶다면, `siteTitle` 옵션을 `false`로 설정하면 됩니다.
```js ```js
export default { export default {
@ -35,27 +35,27 @@ export default {
} }
``` ```
`alt` 속성을 추가하거나 어두운/밝은 모드에 따라 로고를 커스터마이즈하고 싶다면 객체로써 로고를 전달할 수 있습니다. 자세한 내용은 [`themeConfig.logo`](./default-theme-config#logo)를 참하세요. 로고에 `alt` 어트리뷰트를 추가하거나 다크/라이트 모드에 따라 커스터마이징 하려면, 로고를 객체 형태로 전달해야 합니다. 자세한 내용은 [`themeConfig.logo`](./default-theme-config#logo)를 참하세요.
## 내비게이션 링크 {#navigation-links} ## 네비게이션 바 링크 {#navigation-links}
`themeConfig.nav` 옵션을 정의하여 nav에 링크를 추가할 수 있습니다. `themeConfig.nav` 옵션을 정의하여 네비게이션 바에 링크를 추가할 수 있습니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
nav: [ nav: [
{ text: '가이드', link: '/guide' }, { text: '가이드', link: '/guide' },
{ text: '설정', link: '/config' }, { text: '구성', link: '/config' },
{ text: '변경사항', link: 'https://github.com/...' } { text: '변경사항', link: 'https://github.com/...' }
] ]
} }
} }
``` ```
`text`nav에 표시되는 실제 텍스트이고, `link`는 텍스트를 클릭할 때 이동할 링크입니다. 링크는 실제 파일의 경로를 `.md` 접두어 없이 설정하고 항상 `/`로 시작해야 합니다. `text`네비게이션 바에 표시되는 실제 텍스트이며, `link`는 텍스트를 클릭했을 때 이동할 링크입니다. 링크의 경로는 `.md` 접미사 없이 실제 파일 경로로 설정하며, 항상 `/`로 시작해야 합니다.
Nav 링크는 드롭다운 메뉴일 수도 있습니다. 이를 위해 링크 옵션에 `items` 키를 설정하세요. 네비게이션 바 링크는 드롭다운 메뉴가 될 수 있습니다. 이를 위해 `link` 옵션에 `items` 키를 설정합니다.
```js ```js
export default { export default {
@ -75,9 +75,9 @@ export default {
} }
``` ```
드롭다운 메뉴 제목(`위 예제에서의 드롭다운 메뉴`)은 드롭다운 대화상자를 열 버튼이 되므로 `link` 속성을 가질 수 없습니다. 드롭다운 메뉴의 제목(위 예제에서 `드롭다운 메뉴`)은 드롭다운 대화 상자를 여는 버튼이 되므로 `link` 프로퍼티를 가질 수 없습니다.
더 많은 중첩된 항목을 전달하여 드롭다운 메뉴 항목에 "섹션"을 추가할 수도 있습니다. 드롭다운 메뉴 아이템에 더 많은 중첩된 아이템을 전달하여 "섹션"을 추가할 수도 있습니다.
```js ```js
export default { export default {
@ -116,14 +116,14 @@ export default {
### 링크의 "active" 상태 커스터마이징 {#customize-link-s-active-state} ### 링크의 "active" 상태 커스터마이징 {#customize-link-s-active-state}
현재 페이지가 일치하는 경로에 있을 때 Nav 메뉴 항목이 강조 표시됩니다. 매치되길 원하는 경로를 커스터마이징하고 싶다면 문자열 값으로 `activeMatch` 속성과 정규식을 정의하세요. 네비게이션 바 메뉴 아이템은 현재 페이지가 매칭되는 경로에 있을 때 강조 표시됩니다. 매칭할 경로를 커스터마이징 하려면 `activeMatch` 프로퍼티에 정규식을 문자열 값으로 정의합니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
nav: [ nav: [
// 사용자가 `/config/` 경로에 있을 때 // `/config/` 경로에 있을 때
// 이 링크는 활성 상태가 됩니다. // 이 링크는 활성화된 상태가 됩니다.
{ {
text: '가이드', text: '가이드',
link: '/guide', link: '/guide',
@ -135,22 +135,22 @@ export default {
``` ```
::: warning ::: warning
`activeMatch`는 정규식 문자열로 예상되지만, 문자열로 정의해야 합니다. 실제 RegExp 객체를 여기서 사용할 수 없는 이유는 빌드 시간 동안 직렬화가 가능하지 않기 때문입니다. `activeMatch`는 정규식이어야 하지만, 문자열로 정의해야 합니다. 실제 RegExp 객체를 사용할 수 없는 이유는 빌드하는 동안 직렬화할 수 없기 때문입니다.
::: :::
### 링크의 "target" 및 "rel" 속성 커스터마이즈 {#customize-link-s-target-and-rel-attributes} ### 링크의 "target" 및 "rel" 어트리뷰트 커스터마이징 {#customize-link-s-target-and-rel-attributes}
기본적으로 VitePress는 링크가 외부 링크인지에 따라 `target``rel` 속성을 자동으로 결정합니다. 하지만 원한다면 이들도 커스터마이징할 수 있습니다. 기본적으로 VitePress는 링크가 외부 링크인지 여부에 따라 `target``rel` 어트리뷰트를 자동으로 결정합니다. 하지만 원한다면 이를 커스터마이징 할 수도 있습니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
nav: [ nav: [
{ {
text: '상품', text: 'GitHub 쇼핑몰',
link: 'https://www.thegithubshop.com/', link: 'https://www.thegithubshop.com/',
target: '_self', target: '_self',
rel: 'sponsored' rel: 'sponsored' // https://developers.google.com/search/docs/crawling-indexing/qualify-outbound-links
} }
] ]
} }
@ -159,11 +159,11 @@ export default {
## 소셜 링크 {#social-links} ## 소셜 링크 {#social-links}
[`socialLinks`](./default-theme-config#sociallinks)를 참하세요. [`socialLinks`](./default-theme-config#sociallinks)를 참하세요.
## 사용자 정의 구성 요소 {#custom-components} ## 커스텀 컴포넌트 {#custom-components}
`component` 옵션을 사용하여 탐색 모음에 사용자 정의 구성 요소를 포함할 수 있습니다. `component` 키는 Vue 구성 요소 이름이어야 하며, [Theme.enhanceApp](../guide/custom-theme#theme-interface)을 사용하여 전역으로 등록해야 합니다. 네비게이션 바에 커스텀 컴포넌트를 포함하려면 `component` 옵션을 사용하세요. `component` 키는 Vue 컴포넌트 이름이어야 하며, [Theme.enhanceApp](../guide/custom-theme#theme-interface)을 사용하여 전역으로 등록해야 합니다.
```js ```js
// .vitepress/config.js // .vitepress/config.js
@ -175,7 +175,7 @@ export default {
items: [ items: [
{ {
component: 'MyCustomComponent', component: 'MyCustomComponent',
// 구성 요소에 전달할 선택적 props // 컴포넌트에 전달할 선택적 프로퍼티
props: { props: {
title: 'My Custom Component' title: 'My Custom Component'
} }
@ -190,7 +190,7 @@ export default {
} }
``` ```
그런 다음, 구성 요소를 전역으로 등록해야 합니다: 그런 다음, 컴포넌트를 전역적으로 등록해야 합니다:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js
@ -209,8 +209,8 @@ export default {
} }
``` ```
구성 요소가 탐색 모음에 렌더링됩니다. VitePress는 구성 요소에 다음과 같은 추가 props를 제공합니다: 컴포넌트는 네비게이션 바에 렌더링될 것입니다. VitePress는 컴포넌트에 다음과 같은 추가 프로퍼티를 제공합니다:
- `screenMenu`: 구성 요소가 모바일 탐색 메뉴 내부에 있는지 여부를 나타내는 선택적 boolean 값 - `screenMenu`: 컴포넌트가 모바일 네비게이션 바 메뉴 내부에 있는지를 나타내는 선택적 boolean 값
예제는 [여기](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)에서 확인할 수 있습니다. e2e 테스트 예제를 [여기](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)에서 확인할 수 있습니다.

@ -1,6 +1,6 @@
# 이전 다음 링크 {#prev-next-links} # 이전/다음 링크 {#prev-next-links}
이전 페이지와 다음 페이지에 대한 텍스트와 링크를 사용자 정의할 수 있습니다(문서 하단에 표시됨). 사이드바에 있는 텍스트와 다른 텍스트를 원하는 경우에 유용합니다. 또한, 하단부를 비활성화하거나 사이드바에 포함되지 않은 페이지로 링크하는 것이 유용할 수 있습니다. 문서 하단에 표시되는 이전 페이지와 다음 페이지의 텍스트와 링크를 커스터마이징 할 수 있습니다. 사이드바에 있는 텍스트와 다른 텍스트를 원할 경우 유용합니다. 또한 푸터를 비활성화하거나 사이드바에 포함되지 않은 페이지로 링크할 때도 유용할 수 있습니다.
## prev ## prev
@ -8,11 +8,11 @@
- 세부 사항: - 세부 사항:
이전 페이지로의 링크에 표시할 텍스트/링크를 지정합니다. frontmatter에서 이를 설정하지 않으면, 사이드바 구성에서 텍스트/링크를 추론합니다. 이전 페이지로 가는 링크에 표시할 텍스트/링크를 지정합니다. 전문에서 이 항목을 설정하지 않으면, 사이드바 구성에서 텍스트/링크가 유추됩니다.
- 예제: - 예제:
- 텍스트만 사용자 정의할 경우: - 텍스트만 커스터마이징하려면:
```yaml ```yaml
--- ---
@ -20,17 +20,17 @@
--- ---
``` ```
- 텍스트와 링크 모두 사용자 정의할 경우: - 텍스트와 링크를 모두 커스터마이즈하려면:
```yaml ```yaml
--- ---
prev: prev:
text: '마크다운' text: '마크다운 확장 기능'
link: '/guide/markdown' link: '/guide/markdown'
--- ---
``` ```
- 이전 페이지 숨기기: - 이전 페이지를 숨기려면:
```yaml ```yaml
--- ---
@ -40,4 +40,4 @@
## next ## next
`prev`와 동일하지만 다음 페이지에 대한 설정입니다. `prev`와 동일하지만, 다음 페이지에 대한 설정입니다.

@ -6,7 +6,7 @@ outline: deep
## 로컬 검색 {#local-search} ## 로컬 검색 {#local-search}
VitePress는 [minisearch](https://github.com/lucaong/minisearch/)를 통해 브라우저 내 인덱스를 사용한 퍼지 전문 검색을 지원합니다. 이 기능을 활성화하려면, `.vitepress/config.ts` 파일에서 `themeConfig.search.provider` 옵션을 `'local'`로 설정하면 됩니다: VitePress는 [minisearch](https://github.com/lucaong/minisearch/)로 브라우저 내 인덱스를 사용하는 퍼지(full-text) 검색을 지원합니다. 이 기능을 활성화하려면 `.vitepress/config.ts` 파일에서 `themeConfig.search.provider` 옵션을 `'local'`로 설정하면 됩니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -20,15 +20,15 @@ export default defineConfig({
}) })
``` ```
결과: 결과:
![검색 모달의 스크린샷](/search.png) ![검색 모달의 스크린샷](/search.png)
또는, [Algolia DocSearch](#algolia-search)나 <https://www.npmjs.com/package/vitepress-plugin-search>, <https://www.npmjs.com/package/vitepress-plugin-pagefind> 같은 커뮤니티 플러그인을 사용할 수 있습니다. 대안으로 [Algolia DocSearch](#algolia-search), <https://www.npmjs.com/package/vitepress-plugin-search>, <https://www.npmjs.com/package/vitepress-plugin-pagefind> 같은 커뮤니티 플러그인을 사용할 수 있습니다.
### i18n {#local-search-i18n} ### i18n {#local-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다: 다국어 검색을 사용하려면 다음과 같은 구성을 사용해야 합니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -39,24 +39,24 @@ export default defineConfig({
provider: 'local', provider: 'local',
options: { options: {
locales: { locales: {
zh: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오. ko: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오.
translations: { translations: {
button: { button: {
buttonText: '搜索', buttonText: '검색',
buttonAriaLabel: '搜索' buttonAriaLabel: '검색'
}, },
modal: { modal: {
displayDetails: '显示详细列表', displayDetails: '상세 목록 표시',
resetButtonTitle: '重置搜索', resetButtonTitle: '검색 지우기',
backButtonTitle: '关闭搜索', backButtonTitle: '검색 닫기',
noResultsText: '没有结果', noResultsText: '결과를 찾을 수 없습니다',
footer: { footer: {
selectText: '选择', selectText: '선택',
selectKeyAriaLabel: '输入', selectKeyAriaLabel: '선택하기',
navigateText: '导航', navigateText: '탐색',
navigateUpKeyAriaLabel: '上箭头', navigateUpKeyAriaLabel: '위로',
navigateDownKeyAriaLabel: '下箭头', navigateDownKeyAriaLabel: '아래로',
closeText: '关闭', closeText: '닫기',
closeKeyAriaLabel: 'esc' closeKeyAriaLabel: 'esc'
} }
} }
@ -69,9 +69,9 @@ export default defineConfig({
}) })
``` ```
### miniSearch 옵션 {#mini-search-options} ### MiniSearch 옵션 {#mini-search-options}
다음과 같이 MiniSearch를 구성할 수 있습니다: MiniSearch를 다음과 같이 구성할 수 있습니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -103,11 +103,11 @@ export default defineConfig({
}) })
``` ```
[MiniSearch 문서](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)에서 더 많은 정보를 얻을 수 있습니다. 더 자세한 내용은 [MiniSearch 문서](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)를 참고하세요.
### 사용자 정의 콘텐츠 렌더러 {#custom-content-renderer} ### 커스텀 컨텐츠 렌더러 {#custom-content-renderer}
색인 생성 전에 마크다운 콘텐츠를 렌더링하는 데 사용되는 함수를 커스터마이즈할 수 있습니다: 마크다운 컨텐츠를 인덱싱하기 전에 렌더링하는 데 사용되는 함수를 커스터마이징할 수 있습니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -131,11 +131,11 @@ export default defineConfig({
}) })
``` ```
이 함수는 클라이언트 사이드 사이트 데이터에서 제거될 것이므로, 여기서 Node.js API를 사용할 수 있습니다. 이 함수는 클라이언트 사이드 사이트 데이터에서 제거되므로, Node.js API를 사용할 수 있습니다.
#### 예: 검색에서 페이지 제외 {#example-excluding-pages-from-search} #### 예: 검색에서 페이지 제외 {#example-excluding-pages-from-search}
페이지에 `search: false`프론트매터에 추가하여 검색에서 페이지를 제외할 수 있습니다. 또는 다음과 같이 합니다: 페이지의 전문`search: false`를 추가하여 검색에서 해당 페이지를 제외할 수 있습니다. 또는:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -158,10 +158,10 @@ export default defineConfig({
``` ```
::: warning 참고 ::: warning 참고
사용자 정의 `_render` 함수를 제공하는 경우, `search: false` 프론트매터를 직접 처리해야 합니다. 또한, `md.render`가 호출되기 전에 `env` 객체가 완전히 채워지지 않으므로, `frontmatter`와 같은 선택적 `env` 속성에 대한 검사는 그 이후에 수행해야 합니다. 커스텀 `_render` 함수가 제공된 경우, `search: false` 전문을 직접 처리해야 합니다. 또한, `md.render`가 호출되기 전에 `env` 객체가 완전히 채워지지 않으므로, `frontmatter`와 같은 선택적 `env` 프로퍼티에 대한 검사는 그 이후에 수행해야 합니다.
::: :::
#### 예: 콘텐츠 변환 - 앵커 추가 {#example-transforming-content-adding-anchors} #### 예: 콘텐츠 변환 - 앵커 추가 {#example-transforming-content-adding-anchors}
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -185,7 +185,7 @@ export default defineConfig({
## Algolia 검색 {#algolia-search} ## Algolia 검색 {#algolia-search}
VitePress는 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트 검색을 지원합니다. 시작 가이드를 참조하세요. 작동하게 하려면 `.vitepress/config.ts`에서 최소한 다음 정보를 제공해야 합니다: VitePress는 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용한 문서 사이트 검색 기능을 지원합니다. 시작 가이드를 참고하세요. `.vitepress/config.ts`에서 이 기능을 사용하려면 최소한 다음 구성을 제공해야 합니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -206,7 +206,7 @@ export default defineConfig({
### i18n {#algolia-search-i18n} ### i18n {#algolia-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다: 다국어 검색을 사용하려면 다음과 같이 구성해야 합니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -220,43 +220,43 @@ export default defineConfig({
apiKey: '...', apiKey: '...',
indexName: '...', indexName: '...',
locales: { locales: {
zh: { ko: {
placeholder: '搜索文档', placeholder: '문서 검색',
translations: { translations: {
button: { button: {
buttonText: '搜索文档', buttonText: '검색',
buttonAriaLabel: '搜索文档' buttonAriaLabel: '검색'
}, },
modal: { modal: {
searchBox: { searchBox: {
resetButtonTitle: '清除查询条件', resetButtonTitle: '검색 지우기',
resetButtonAriaLabel: '清除查询条件', resetButtonAriaLabel: '검색 지우기',
cancelButtonText: '取消', cancelButtonText: '취소',
cancelButtonAriaLabel: '取消' cancelButtonAriaLabel: '취소'
}, },
startScreen: { startScreen: {
recentSearchesTitle: '搜索历史', recentSearchesTitle: '검색 기록',
noRecentSearchesText: '没有搜索历史', noRecentSearchesText: '최근 검색 없음',
saveRecentSearchButtonTitle: '保存至搜索历史', saveRecentSearchButtonTitle: '검색 기록에 저장',
removeRecentSearchButtonTitle: '从搜索历史中移除', removeRecentSearchButtonTitle: '검색 기록에서 삭제',
favoriteSearchesTitle: '收藏', favoriteSearchesTitle: '즐겨찾기',
removeFavoriteSearchButtonTitle: '从收藏中移除' removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제'
}, },
errorScreen: { errorScreen: {
titleText: '无法获取结果', titleText: '결과를 가져올 수 없습니다',
helpText: '你可能需要检查你的网络连接' helpText: '네트워크 연결을 확인하세요'
}, },
footer: { footer: {
selectText: '选择', selectText: '선택',
navigateText: '切换', navigateText: '탐색',
closeText: '关闭', closeText: '닫기',
searchByText: '搜索提供者' searchByText: '검색 기준'
}, },
noResultsScreen: { noResultsScreen: {
noResultsText: '无法找到相关结果', noResultsText: '결과를 찾을 수 없습니다',
suggestedQueryText: '你可以尝试查询', suggestedQueryText: '새로운 검색을 시도할 수 있습니다',
reportMissingResultsText: '你认为该查询应该有结果?', reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?',
reportMissingResultsLinkText: '点击反馈' reportMissingResultsLinkText: '피드백 보내기 클릭'
} }
} }
} }
@ -268,11 +268,11 @@ export default defineConfig({
}) })
``` ```
[이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 덮어쓸 수 있습니다. 공식 Algolia 문서에서 더 많은 정보를 알아보세요. [이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 재작성 할 수 있습니다. 이에 대해 자세히 알고 싶다면 Algolia 공식 문서를 참고하세요.
### 크롤러 구성 {#crawler-config} ### 크롤러 구성 {#crawler-config}
이 사이트가 사용하는 것을 기반으로 한 예제 구성입니다: 이 사이트에서 사용하는 예제 구성을 소개합니다:
```ts ```ts
new Crawler({ new Crawler({
@ -285,7 +285,7 @@ new Crawler({
exclusionPatterns: [], exclusionPatterns: [],
ignoreCanonicalTo: false, ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'], discoveryPatterns: ['https://vitepress.dev/**'],
schedule: '매주 토요일 05:10에', schedule: 'at 05:10 on Saturday',
actions: [ actions: [
{ {
indexName: 'vitepress', indexName: 'vitepress',
@ -296,8 +296,8 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: '문서' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',
lvl3: '.content h3', lvl3: '.content h3',

@ -1,6 +1,6 @@
# 사이드바 {#sidebar} # 사이드바 {#sidebar}
사이드바는 문서의 주요 탐색 블록입니다. 사이드바 메뉴를 [`themeConfig.sidebar`](./default-theme-config#sidebar)에서 설정할 수 있습니다. 사이드바는 문서의 기본 탐색 블록입니다. [`themeConfig.sidebar`](./default-theme-config#sidebar)에서 사이드바 메뉴를 구성할 수 있습니다.
```js ```js
export default { export default {
@ -19,9 +19,9 @@ export default {
} }
``` ```
## 기 {#the-basics} ## 기본 사용법 {#the-basics}
사이드바 메뉴의 가장 간단한 형태는 링크의 단일 배열을 전달하는 것입니다. 첫 번째 레벨 아이템은 사이드바의 "섹션"을 정의합니다. 해당 섹션의 제목인 `text`와 실제 탐색 링크인 `items`를 포함해야 합니다. 사이드바 메뉴의 가장 간단한 형태는 링크 배열을 전달하는 것입니다. 첫 번째 계층 아이템은 사이드바의 "섹션"을 정의합니다. 이 섹션에는 제목인 `text`와 실제 탐색 링크인 `items`가 포함되어야 합니다.
```js ```js
export default { export default {
@ -48,7 +48,7 @@ export default {
} }
``` ```
`link``/`로 시작하는 실제 파일 경로를 지정해야 합니다. 링크 끝에 슬래시를 추가하면 해당 디렉리의 `index.md`를 보여줍니다. `link``/`로 시작하는 실제 파일 경로를 지정해야 합니다. 링크 끝에 슬래시를 추가하면 해당 디렉리의 `index.md`를 보여줍니다.
```js ```js
export default { export default {
@ -66,20 +66,20 @@ export default {
} }
``` ```
루트 레벨부터 시작해서 최대 6레벨 깊이까지 사이드바 아이템을 중첩할 수 있습니다. 6레벨 이상 중첩된 아이템은 무시되며 사이드바에 표시되지 않습니다. 사이드바 아이템을 루트 단계에서 최대 6단계까지 중첩할 수 있습니다. 6단계를 초과하는 중첩 아이템은 무시되며 사이드바에 표시되지 않습니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
sidebar: [ sidebar: [
{ {
text: '레벨 1', text: '1단계',
items: [ items: [
{ {
text: '레벨 2', text: '2단계',
items: [ items: [
{ {
text: '레벨 3', text: '3단계',
items: [ items: [
... ...
] ]
@ -93,11 +93,11 @@ export default {
} }
``` ```
## 다중 사이드바 {#multiple-sidebars} ## 여러 사이드바 {#multiple-sidebars}
페이지 경로에 따라 다른 사이드바를 표시할 수 있습니다. 예를 들어, 이 사이트에 표시된 것과 같이 "가이드" 페이지와 "설정" 페이지와 같이 문서의 콘텐츠 섹션을 별도로 생성할 수 있습니다. 페이지 경로에 따라 다른 사이드바를 표시할 수 있습니다. 예를 들어 이 사이트처럼 문서의 각 섹션을 "가이드"와 "레퍼런스" 페이지에 따라 별도로 만들고 싶을 수 있습니다.
이를 위해 먼저 각 원하는 섹션에 대한 디렉토리로 페이지를 구성합니다: 이를 위해 먼저 각 섹션 디렉터리로 페이지를 구성합니다:
``` ```
. .
@ -111,32 +111,32 @@ export default {
└─ four.md └─ four.md
``` ```
다음, 구성을 업데이트하여 각 섹션에 대한 사이드바를 정의합니다. 이때, 배열 대신 객체를 전달해야 합니다. 런 다음 각 섹션에 대한 사이드바를 정의하도록 구성 파일을 업데이트합니다. 이런 경우에는 배열 대신 객체를 전달해야 합니다.
```js ```js
export default { export default {
themeConfig: { themeConfig: {
sidebar: { sidebar: {
// 이 사이드바는 사용자 // 이 사이드바는 유저
// `guide` 디렉토리에 있을 때 표시됩니다. // `guide` 디렉토리에 있을 때 표시됩니다.
'/guide/': [ '/guide/': [
{ {
text: '가이드', text: '가이드',
items: [ items: [
{ text: '인덱스', link: '/guide/' }, { text: '개요', link: '/guide/' },
{ text: '하나', link: '/guide/one' }, { text: '하나', link: '/guide/one' },
{ text: '둘', link: '/guide/two' } { text: '둘', link: '/guide/two' }
] ]
} }
], ],
// 이 사이드바는 사용자 // 이 사이드바는 유저
// `config` 디렉토리에 있을 때 표시됩니다. // `config` 디렉토리에 있을 때 표시됩니다.
'/config/': [ '/config/': [
{ {
text: '설정', text: '설정',
items: [ items: [
{ text: '인덱스', link: '/config/' }, { text: '개요', link: '/config/' },
{ text: '셋', link: '/config/three' }, { text: '셋', link: '/config/three' },
{ text: '넷', link: '/config/four' } { text: '넷', link: '/config/four' }
] ]
@ -149,7 +149,7 @@ export default {
## 접을 수 있는 사이드바 그룹 {#collapsible-sidebar-groups} ## 접을 수 있는 사이드바 그룹 {#collapsible-sidebar-groups}
사이드바 그룹에 `collapsed` 옵션을 추가하면 각 섹션을 숨기기/보이기 위한 토글 버튼이 나타납니다. 사이드바 그룹에 `collapsed` 옵션을 추가하면 각 섹션을 접거나 펼칠 수 있는 토글 버튼이 표시됩니다.
```js ```js
export default { export default {
@ -165,7 +165,7 @@ export default {
} }
``` ```
모든 섹션은 기본적으로 "열림" 상태입니다. 초기 페이지 로드 시 "닫힘" 상태로 하고 싶다면 `collapsed` 옵션을 `true`로 설정하세요. 모든 섹션은 기본적으로 "열림" 상태입니다. 초기 페이지 로드 시 "닫힘" 상태로 두려면 `collapsed` 옵션을 `true`로 설정합니다.
```js ```js
export default { export default {
@ -183,7 +183,7 @@ export default {
## `useSidebar` <Badge type="info" text="composable" /> ## `useSidebar` <Badge type="info" text="composable" />
사이드바 관련 데이터를 반환합니다. 반환된 객체는 다음과 같은 유형을 가집니다: 사이드바 관련 데이터를 반환합니다. 반환된 객체는 다음과 같은 타입을 가집니다:
```ts ```ts
export interface DocSidebar { export interface DocSidebar {

@ -5,7 +5,7 @@ const members = [
{ {
avatar: 'https://github.com/yyx990803.png', avatar: 'https://github.com/yyx990803.png',
name: 'Evan You', name: 'Evan You',
title: '창작자', title: 'Creator',
links: [ links: [
{ icon: 'github', link: 'https://github.com/yyx990803' }, { icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' } { icon: 'twitter', link: 'https://twitter.com/youyuxi' }
@ -14,7 +14,7 @@ const members = [
{ {
avatar: 'https://github.com/kiaking.png', avatar: 'https://github.com/kiaking.png',
name: 'Kia King Ishii', name: 'Kia King Ishii',
title: '개발자', title: 'Developer',
links: [ links: [
{ icon: 'github', link: 'https://github.com/kiaking' }, { icon: 'github', link: 'https://github.com/kiaking' },
{ icon: 'twitter', link: 'https://twitter.com/KiaKing85' } { icon: 'twitter', link: 'https://twitter.com/KiaKing85' }
@ -25,11 +25,11 @@ const members = [
# 팀 페이지 {#team-page} # 팀 페이지 {#team-page}
팀을 소개하고 싶다면, 팀 페이지를 구성하기 위해 Team 컴포넌트를 사용할 수 있습니다. 이러한 컴포넌트를 사용하는 방법에는 두 가지가 있습니다. 하나는 문서 페이지에 포함시키는 것이고, 다른 하나는 전체 팀 페이지를 만드는 것입니다. 팀을 소개하고자 할 때, 팀 컴포넌트를 사용하여 팀 페이지를 구성할 수 있습니다. 이 컴포넌트를 사용하는 방법은 두 가지가 있습니다. 하나는 문서 페이지에 포함시키는 방법이고, 다른 하나는 전체 팀 페이지를 만드는 방법입니다.
## 페이지에서 팀 멤버 보여주기 {#show-team-members-in-a-page} ## 페이지에서 팀 구성원 보여주기 {#show-team-members-in-a-page}
`vitepress/theme`에서 제공되는 `<VPTeamMembers>` 컴포넌트를 사용하여 어떤 페이지에서든 팀 멤버 목록을 표시할 수 있습니다. `vitepress/theme`에서 제공되는 `<VPTeamMembers>` 컴포넌트를 사용하여, 어떤 페이지에서도 팀 구성원 목록을 표시할 수 있습니다.
```html ```html
<script setup> <script setup>
@ -39,7 +39,7 @@ const members = [
{ {
avatar: 'https://www.github.com/yyx990803.png', avatar: 'https://www.github.com/yyx990803.png',
name: 'Evan You', name: 'Evan You',
title: '창작자', title: 'Creator',
links: [ links: [
{ icon: 'github', link: 'https://github.com/yyx990803' }, { icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' } { icon: 'twitter', link: 'https://twitter.com/youyuxi' }
@ -49,28 +49,28 @@ const members = [
] ]
</script> </script>
# 우리 팀 # Our Team
우리 훌륭한 팀을 만나보세요. Say hello to our awesome team.
<VPTeamMembers size="small" :members="members" /> <VPTeamMembers size="small" :members="members" />
``` ```
위 코드는 카드 형태의 요소로 팀 멤버를 표시합니다. 아래와 비슷하게 표시될 것입니다. 위 코드는 카드 형태의 엘리먼트로 팀 구성원을 표시합니다. 아래와 비슷한 형태로 표시됩니다.
<VPTeamMembers size="small" :members="members" /> <VPTeamMembers size="small" :members="members" />
`<VPTeamMembers>` 컴포넌트는 `small``medium`의 두 가지 다른 크기로 제공됩니다. 선호도에 달렸지만, 보통 문서 페이지에서 사용할 때는 `small` 크기가 더 잘 맞을 것입니다. 또한 "description"이나 "sponsor" 버튼을 추가하는 등 각 멤버에 대해 더 많은 속성을 추가할 수 있습니다. [`<VPTeamMembers>`](#vpteammembers)에서 더 자세히 알아보세요. `<VPTeamMembers>` 컴포넌트는 `small``medium` 두 가지 크기로 제공됩니다. 개인의 선호도에 따라 선택할 수 있지만, 일반적으로 `small` 사이즈가 문서 페이지에 더 적합합니다. 또한, 각 구성원에 "설명"이나 "후원" 버튼과 같은 프로퍼티를 추가할 수도 있습니다. 자세한 내용은 [`<VPTeamMembers>`](#vpteammembers)에서 확인할 수 있습니다.
문서 페이지에 팀 멤버를 포함시키는 것은 전용 전체 팀 페이지를 만드는 것이 너무 과한 경우나, 문서 맥락을 참조로 일부 멤버를 소개할 때 좋습니다. 문서 페이지에 팀 구성원을 포함시키는 것은 전용 팀 페이지를 만드는 것이 과할 수 있는 소규모 팀이나, 문서의 맥락에 따라 일부 구성원을 소개할 때 좋습니다.
멤버 수가 많거나, 멤버를 보여주기 위해 더 많은 공간을 원한다면 [전체 팀 페이지 만들기](#create-a-full-team-page)를 고려해보세요. 만약 많은 수의 구성원이 있거나, 팀 구성원을 보여줄 더 많은 공간이 필요하다면, [전체 팀 페이지 만들기](#create-a-full-team-page)를 고려해 보세요.
## 전체 팀 페이지 만들기 {#create-a-full-team-page} ## 전체 팀 페이지 만들기 {#create-a-full-team-page}
문서 페이지에 팀 멤버를 추가하는 대신, 전체 팀 페이지를 만들 수도 있습니다. 사용자 지정 [홈 페이지](./default-theme-home-page)를 생성하는 방법과 유사합니다. 팀 구성원을 문서 페이지에 추가하는 대신, 전체 팀 페이지를 만들어 [홈 페이지](./default-theme-home-page)를 커스텀하는 것처럼 팀 페이지를 만들 수도 있습니다.
팀 페이지를 생성하려면 먼저, 새 md 파일을 만듭니다. 파일 이름은 중요하지 않지만, 여기서는 `team.md`라고 하겠습니다. 이 파일에서 frontmatter 옵션 `layout: page`를 설정한 다음, `TeamPage` 컴포넌트를 사용하여 페이지 구조를 구성합니다. 팀 페이지를 만들려면, 먼저 새로운 마크다운 파일을 생성하세요. 파일 이름은 중요하지 않지만, 여기서는 `team.md`라고 부르겠습니다. 이 파일에서 전문 옵션에 `layout: page`를 설정한 후, `TeamPage` 컴포넌트를 사용하여 페이지 구조를 구성합니다.
```html ```html
--- ---
@ -87,7 +87,7 @@ const members = [
{ {
avatar: 'https://www.github.com/yyx990803.png', avatar: 'https://www.github.com/yyx990803.png',
name: 'Evan You', name: 'Evan You',
title: '창작자', title: 'Creator',
links: [ links: [
{ icon: 'github', link: 'https://github.com/yyx990803' }, { icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' } { icon: 'twitter', link: 'https://twitter.com/youyuxi' }
@ -100,11 +100,11 @@ const members = [
<VPTeamPage> <VPTeamPage>
<VPTeamPageTitle> <VPTeamPageTitle>
<template #title> <template #title>
우리 팀 Our Team
</template> </template>
<template #lead> <template #lead>
VitePress의 개발은 국제적인 The development of VitePress is guided by an international
팀에 의해 지도되며, 그 중 일부는 아래에 소개되어 있습니다. team, some of whom have chosen to be featured below.
</template> </template>
</VPTeamPageTitle> </VPTeamPageTitle>
<VPTeamMembers <VPTeamMembers
@ -113,17 +113,17 @@ const members = [
</VPTeamPage> </VPTeamPage>
``` ```
전체 팀 페이지를 생성할 때는 모든 컴포넌트를 `<VPTeamPage>` 컴포넌트로 감싸야 합니다. 이 컴포넌트는 공간 구조와 같은 적절한 레이아웃 구조를 팀 관련 컴포넌트에 적용할 것입니다. 전체 팀 페이지를 만들 때는 모든 컴포넌트를 `<VPTeamPage>` 컴포넌트로 감싸야 합니다. 이 컴포넌트는 중첩된 팀 관련 컴포넌트들이 적절한 레이아웃 구조와 간격을 갖도록 합니다.
`<VPPageTitle>` 컴포넌트는 페이지 제목 섹션을 추가합니다. 제목은 `<h1>` 헤딩입니다. 팀에 대해 문서화하려면 `#title``#lead` 슬롯을 사용하십시오. `<VPPageTitle>` 컴포넌트는 페이지 제목 섹션을 추가합니다. 제목은 `<h1>` 헤딩으로 표시됩니다. `#title``#lead` 슬롯을 사용하여 팀에 대한 설명을 작성할 수 있습니다.
`<VPMembers>`는 문서 페이지에서 사용할 때와 동일하게 작동합니다. 회원 목록을 표시합니다. `<VPMembers>` 컴포넌트는 문서 페이지에서 사용할 때와 동일하게 작동하며, 팀 구성원 목록을 표시합니다.
### 팀 멤버를 구분하기 위한 섹션 추가 {#add-sections-to-divide-team-members} ### 팀 구성원을 구분하기 위한 섹션 추가 {#add-sections-to-divide-team-members}
팀 페이지에 "섹션"을 추가할 수 있습니다. 예를 들어, 코어 팀 멤버와 커뮤니티 파트너와 같은 다양한 유형의 팀 멤버가 있을 수 있습니다. 이러한 멤버를 섹션으로 나누어 각 그룹의 역할을 더 잘 설명할 수 있습니다. 팀 페이지에 "섹션"을 추가할 수도 있습니다. 예를 들어, 핵심 팀 구성원과 커뮤니티 파트너와 같은 다양한 유형의 팀 구성원이 있을 수 있습니다. 이 구성원들을 섹션으로 나누어 각 그룹의 역할을 더 잘 설명할 수 있습니다.
이를 위해 이전에 만든 `team.md` 파일에 `<VPTeamPageSection>` 컴포넌트를 추가하십시오. 이를 위해 이전에 만든 `team.md` 파일에 `<VPTeamPageSection>` 컴포넌트를 추가하세요.
```html ```html
--- ---
@ -143,12 +143,12 @@ const partners = [...]
<VPTeamPage> <VPTeamPage>
<VPTeamPageTitle> <VPTeamPageTitle>
<template #title>우리 팀</template> <template #title>Our Team</template>
<template #lead>...</template> <template #lead>...</template>
</VPTeamPageTitle> </VPTeamPageTitle>
<VPTeamMembers size="medium" :members="coreMembers" /> <VPTeamMembers size="medium" :members="coreMembers" />
<VPTeamPageSection> <VPTeamPageSection>
<template #title>파트너</template> <template #title>Partners</template>
<template #lead>...</template> <template #lead>...</template>
<template #members> <template #members>
<VPTeamMembers size="small" :members="partners" /> <VPTeamMembers size="small" :members="partners" />
@ -157,13 +157,13 @@ const partners = [...]
</VPTeamPage> </VPTeamPage>
``` ```
`<VPTeamPageSection>` 컴포넌트는 `VPTeamPageTitle` 컴포넌트와 유사하게 `#title``#lead` 슬롯을 가질 수 있으며, 팀 멤버를 표시하기 위한 `#members` 슬롯도 가질 수 있습니다. `<VPTeamPageSection>` 컴포넌트는 `VPTeamPageTitle` 컴포넌트처럼 `#title``#lead` 슬롯을 가질 수 있으며, 팀 구성원을 표시하기 위한 `#members` 슬롯도 있습니다.
`#members` 슬롯 안에 `<VPTeamMembers>` 컴포넌트를 넣는 것을 잊지 마십시오. `#members` 슬롯 내부에는 `<VPTeamMembers>` 컴포넌트를 추가해야 합니다.
## `<VPTeamMembers>` ## `<VPTeamMembers>`
`<VPTeamMembers>` 컴포넌트는 주어진 멤버 목록을 표시합니다. `<VPTeamMembers>` 컴포넌트는 주어진 팀 구성원 목록을 표시합니다.
```html ```html
<VPTeamMembers <VPTeamMembers
@ -178,63 +178,63 @@ const partners = [...]
```ts ```ts
interface Props { interface Props {
// 각 회원의 크기입니다. 기본값은 `medium`입니다. // 각 구성원 사이즈. 기본값: `medium`
size?: 'small' | 'medium' size?: 'small' | 'medium'
// 표시할 회원 목록입니다. // 표시할 구성원 목록.
members: TeamMember[] members: TeamMember[]
} }
interface TeamMember { interface TeamMember {
// 회원의 아바타 이미지입니다. // 구성원 아바타 이미지.
avatar: string avatar: string
// 회원의 이름입니다. // 구성원 이름.
name: string name: string
// 회원 이름 아래에 표시될 직함입니다. // 구성원 이름 아래에 표시될 직함.
// 예: 개발자, 소프트웨어 엔지니어 등 // 예: 개발자, 소프트웨어 엔지니어 등
title?: string title?: string
// 회원이 속한 조직입니다. // 구성원이 속한 조직.
org?: string org?: string
// 조직의 URL입니다. // 조직의 URL.
orgLink?: string orgLink?: string
// 회원에 대한 설명입니다. // 구성원에 대한 설명.
desc?: string desc?: string
// 소셜 링크입니다. 예: GitHub, Twitter 등. // 소셜 링크. 예: GitHub, Twitter 등.
// 여기에 소셜 링크 객체를 전달할 수 있습니다. // 소셜 링크 객체를 전달해야 함.
// 참: https://vitepress.dev/ko/reference/default-theme-config.html#sociallinks // 참: https://vitepress.dev/ko/reference/default-theme-config.html#sociallinks
links?: SocialLink[] links?: SocialLink[]
// 회원의 후원 페이지 URL입니다. // 구성원의 후원 페이지 URL.
sponsor?: string sponsor?: string
// 후원 링크의 텍스트입니다. 기본값은 'Sponsor'입니다. // 후원 링크 텍스트. 기본값: 'Sponsor'
actionText?: string actionText?: string
} }
``` ```
## `<VPTeamPage>` ## `<VPTeamPage>`
전체 팀 페이지를 생성할 때 기본 컴포넌트입니다. 단일 슬롯만 허용합니다. 전달된 모든 팀 관련 컴포넌트에 적절한 스타일을 적용합니다. 전체 팀 페이지를 만들 때 사용하는 루트 컴포넌트입니다. 단일 슬롯만 허용하며, 전달된 모든 팀 관련 컴포넌트에 스타일을 적용합니다.
## `<VPTeamPageTitle>` ## `<VPTeamPageTitle>`
페이지의 "제목" 섹션을 추가합니다. `<VPTeamPage>` 아래에서 맨 처음 사용하는 것이 가장 좋습니다. `#title``#lead` 슬롯을 받습니다. 페이지의 "제목" 섹션을 추가합니다. `<VPTeamPage>` 아래 맨 처음 사용하는 것이 가장 좋습니다. `#title``#lead` 슬롯이 있습니다.
```html ```html
<VPTeamPage> <VPTeamPage>
<VPTeamPageTitle> <VPTeamPageTitle>
<template #title> <template #title>
우리 팀 Our Team
</template> </template>
<template #lead> <template #lead>
VitePress의 개발은 국제적인 The development of VitePress is guided by an international
팀에 의해 지도되며, 그 중 일부는 아래에 소개되어 있습니다. team, some of whom have chosen to be featured below.
</template> </template>
</VPTeamPageTitle> </VPTeamPageTitle>
</VPTeamPage> </VPTeamPage>
@ -242,13 +242,13 @@ interface TeamMember {
## `<VPTeamPageSection>` ## `<VPTeamPageSection>`
팀 페이지 내에 "섹션"을 생성합니다. `#title`, `#lead`, 그리고 `#members` 슬롯을 받습니다. `<VPTeamPage>` 안에 원하는 만큼 많은 섹션을 추가할 수 있습니다. 팀 페이지 내에 "섹션"을 생성합니다. `#title`, `#lead`, `#members` 슬롯이 있습니다. `<VPTeamPage>` 안에 원하는 만큼 섹션을 추가할 수 있습니다.
```html ```html
<VPTeamPage> <VPTeamPage>
... ...
<VPTeamPageSection> <VPTeamPageSection>
<template #title>파트너</template> <template #title>Partners</template>
<template #lead>Lorem ipsum...</template> <template #lead>Lorem ipsum...</template>
<template #members> <template #members>
<VPTeamMembers :members="data" /> <VPTeamMembers :members="data" />

@ -2,20 +2,20 @@
outline: deep outline: deep
--- ---
# 프론트매터 구성 {#frontmatter-config} # 전문 구성 {#frontmatter-config}
프론트매터(머리말)는 페이지 기반 구성을 가능하게 합니다. 모든 마크다운 파일에서, 사이트 수준 또는 테마 수준의 구성 옵션을 재정의하기 위해 프론트매터 구성을 사용할 수 있습니다. 또한, 프론트매터에서만 정의할 수 있는 구성 옵션이 있습니다. 전문은 페이지 기반 구성을 가능하게 합니다. 각 마크다운 파일에서 전문 구성을 사용하여 사이트 수준 또는 테마 수준의 구성 옵션을 재정의할 수 있습니다. 또한, 전문에서만 정의할 수 있는 구성 옵션도 있습니다.
사용 예: 사용 예:
```md ```md
--- ---
title: VitePress로 문서화 title: Docs with VitePress
editLink: true editLink: true
--- ---
``` ```
Vue 표현식에서 `$frontmatter` 전역을 통해 프론트매터 데이터에 접근할 수 있습니다: Vue 표현식에서 `$frontmatter` 전역 변수를 통해 전문 데이터에 접근할 수 있습니다:
```md ```md
{{ $frontmatter.title }} {{ $frontmatter.title }}
@ -23,9 +23,9 @@ Vue 표현식에서 `$frontmatter` 전역을 통해 프론트매터 데이터에
## title ## title
- 유형: `string` - 타입: `string`
페이지의 제목입니다. [config.title](./site-config#title)과 동일하며, 사이트 수준의 구성을 재정의합니다. 페이지의 제목입니다. [config.title](./site-config#title)과 동일하며, 사이트 레벨의 구성을 재정의합니다.
```yaml ```yaml
--- ---
@ -35,22 +35,22 @@ title: VitePress
## titleTemplate ## titleTemplate
- 유형: `string | boolean` - 타입: `string | boolean`
제목의 접미사입니다. [config.titleTemplate](./site-config#titletemplate)와 동일하며, 사이트 수준의 구성을 재정의합니다. 제목의 접미사입니다. [config.titleTemplate](./site-config#titletemplate)와 동일하며, 사이트 레벨의 구성을 재정의합니다.
```yaml ```yaml
--- ---
title: VitePress title: VitePress
titleTemplate: Vite & Vue로 구동되는 정적 사이트 생성기 titleTemplate: Vite & Vue powered static site generator
--- ---
``` ```
## description ## description
- 유형: `string` - 타입: `string`
페이지의 설명입니다. [config.description](./site-config#description)과 동일하며, 사이트 수준의 구성을 재정의합니다. 페이지의 설명입니다. [config.description](./site-config#description)과 동일하며, 사이트 레벨의 구성을 재정의합니다.
```yaml ```yaml
--- ---
@ -60,19 +60,19 @@ description: VitePress
## head ## head
- 유형: `HeadConfig[]` - 타입: `HeadConfig[]`
현재 페이지에 삽입할 추가 head 태그를 지정합니다. 사이트 수준 구성에 의해 삽입된 head 태그들 이후에 추가됩니다. 현재 페이지에 삽입할 추가 head 태그를 지정합니다. 사이트 수준 구성에 의해 삽입된 head 태그에 추가됩니다.
```yaml ```yaml
--- ---
head: head:
- - meta - - meta
- name: description - name: description
content: 안녕하세요 content: hello
- - meta - - meta
- name: keywords - name: keywords
content: 슈퍼 두퍼 SEO content: super duper SEO
--- ---
``` ```
@ -84,18 +84,18 @@ type HeadConfig =
## 기본 테마 전용 {#default-theme-only} ## 기본 테마 전용 {#default-theme-only}
다음 프론트매터 옵션은 기본 테마를 사용할 때만 적용됩니다. 다음 전문 옵션은 기본 테마를 사용할 때만 적용됩니다.
### layout ### layout
- 유형: `doc | home | page` - 타입: `doc | home | page`
- 기본값: `doc` - 기본값: `doc`
페이지의 레이아웃을 결정합니다. 페이지의 레이아웃을 결정합니다.
- `doc` - 마크다운 텐츠에 기본 문서 스타일을 적용합니다. - `doc` - 마크다운 텐츠에 기본 문서 스타일을 적용합니다.
- `home` - "홈 페이지"를 위한 특별한 레이아웃입니다. `hero``features`와 같은 추가 옵션을 추가하여 아름다운 랜딩 페이지를 빠르게 만들 수 있습니다. - `home` - "홈 페이지"를 위한 특별 레이아웃입니다. 아름다운 랜딩 페이지를 빠르게 만들기 위해 `hero``features`와 같은 옵션을 추가할 수 있습니다.
- `page` - `doc`비슷하게 동작하지만 콘텐츠에 스타일을 적용하지 않습니다. 완전히 사용자 정의된 페이지를 만들고 싶을 때 유용합니다. - `page` - `doc`유사하게 작동하지만 콘텐츠에 스타일을 적용하지 않습니다. 완전히 커스텀 페이지를 만들 때 유용합니다.
```yaml ```yaml
--- ---
@ -105,18 +105,18 @@ layout: doc
### hero <Badge type="info" text="홈 페이지 전용" /> ### hero <Badge type="info" text="홈 페이지 전용" />
`layout``home`으로 설정될 때 홈 히어로 섹션의 내용을 정의합니다. [기본 테마: 홈 페이지](./default-theme-home-page)에서 자세한 내용을 확인할 수 있습니다. `layout``home`으로 설정된 경우, 홈 히어로 섹션의 내용을 정의합니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)에서 확인할 수 있습니다.
### features <Badge type="info" text="홈 페이지 전용" /> ### features <Badge type="info" text="홈 페이지 전용" />
`layout``home`으로 설정될 때 기능 섹션에 표시할 항목을 정의합니다. [기본 테마: 홈 페이지](./default-theme-home-page)에서 자세한 내용을 확인할 수 있습니다. `layout``home`으로 설정된 경우, 기능 섹션에 표시할 항목을 정의합니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)에서 확인할 수 있습니다.
### navbar ### navbar
- 유형: `boolean` - 타입: `boolean`
- 기본값: `true` - 기본값: `true`
[navbar](./default-theme-nav)를 표시할지 여부입니다. [네비게이션 바](./default-theme-nav)를 표시할지 여부를 설정합니다.
```yaml ```yaml
--- ---
@ -126,10 +126,10 @@ navbar: false
### sidebar ### sidebar
- 유형: `boolean` - 타입: `boolean`
- 기본값: `true` - 기본값: `true`
[sidebar](./default-theme-sidebar)를 표시할지 여부입니다. [사이드바](./default-theme-sidebar)를 표시할지 여부를 설정합니다.
```yaml ```yaml
--- ---
@ -139,14 +139,14 @@ sidebar: false
### aside ### aside
- 유형: `boolean | 'left'` - 타입: `boolean | 'left'`
- 기본값: `true` - 기본값: `true`
`doc` 레이아웃에서 aside 컴포넌트의 위치를 정의합니다. `doc` 레이아웃에서 어사이드(aside) 컴포넌트의 위치를 정의합니다.
이 값을 `false`로 설정하면 aside 컨테이너가 렌더링되지 않습니다.\ 이 값을 `false`로 설정하면 어사이드 컨테이너가 렌더링되지 않습니다.\
이 값을 `true`로 설정하면 aside가 오른쪽에 렌더링됩니다.\ 이 값을 `true`로 설정하면 어사이드를 오른쪽에 렌더링합니다.\
이 값을 `'left'`로 설정하면 aside가 왼쪽에 렌더링됩니다. 이 값을 `'left'`로 설정하면 어사이드를 왼쪽에 렌더링합니다.
```yaml ```yaml
--- ---
@ -156,17 +156,17 @@ aside: false
### outline ### outline
- 유형: `number | [number, number] | 'deep' | false` - 타입: `number | [number, number] | 'deep' | false`
- 기본값: `2` - 기본값: `2`
페이지에 표시할 개요의 헤더 레벨입니다. [config.themeConfig.outline.level](./default-theme-config#outline)과 동일하며, 사이트 수준 구성에서 설정 값을 재정의합니다. 페이지에 표시할 아웃라인(개요) 헤더의 레벨을 설정합니다. [config.themeConfig.outline.level](./default-theme-config#outline)과 동일하며, 사이트 수준 구성에서 설정 값을 재정의합니다.
### lastUpdated ### lastUpdated
- 유형: `boolean | Date` - 타입: `boolean | Date`
- 기본값: `true` - 기본값: `true`
현재 페이지의 바닥글에 [마지막 업데이트](./default-theme-last-updated) 텍스트를 표시할지 여부입니다. 날짜와 시간이 지정되면 마지막 git 수정 타임스탬프 대신 표시됩니다. 현재 페이지의 푸터에 [마지막 업데이트 날짜](./default-theme-last-updated) 텍스트를 표시할지 여부를 설정합니다. 날짜/시간이 지정되면 마지막 git 수정 타임스탬프 대신 해당 날짜/시간이 표시됩니다.
```yaml ```yaml
--- ---
@ -176,10 +176,10 @@ lastUpdated: false
### editLink ### editLink
- 유형: `boolean` - 타입: `boolean`
- 기본값: `true` - 기본값: `true`
현재 페이지의 바닥글에 [편집 링크](./default-theme-edit-link)를 표시할지 여부입니다. 현재 페이지의 푸터에 [편집 링크](./default-theme-edit-link)를 표시할지 여부를 설정합니다.
```yaml ```yaml
--- ---
@ -189,10 +189,10 @@ editLink: false
### footer ### footer
- 유형: `boolean` - 타입: `boolean`
- 기본값: `true` - 기본값: `true`
[footer](./default-theme-footer)를 표시할지 여부입니다. [푸터](./default-theme-footer)를 표시할지 여부를 설정합니다.
```yaml ```yaml
--- ---
@ -202,9 +202,9 @@ footer: false
### pageClass ### pageClass
- 유형: `string` - 타입: `string`
특정 페이지에 추가 클래스 이름을 추가합니다. 페이지에 추가할 클래스 입니다.
```yaml ```yaml
--- ---
@ -212,7 +212,7 @@ pageClass: custom-page-class
--- ---
``` ```
그런 다음 `.vitepress/theme/custom.css` 파일에서 이 특정 페이지의 스타일을 사용자 정의할 수 있습니다: 그런 다음 `.vitepress/theme/custom.css` 파일에서 이 페이지의 스타일을 커스텀 할 수 있습니다:
```css ```css
.custom-page-class { .custom-page-class {

@ -1,35 +1,35 @@
# 런타임 API {#runtime-api} # 런타임 API {#runtime-api}
VitePress는 앱 데이터에 액세스할 수 있도록 몇 가지 내장 API를 제공합니다. 또한 전역적으로 사용할 수 있는 몇 가지 내장 컴포넌트도 제공합니다. VitePress는 애플리케이션 데이터를 액세스할 수 있는 여러 내장 API를 제공합니다. 그리고 전역적으로 사용할 수 있는 몇 가지 내장 컴포넌트도 제공합니다.
도우미 메서드는 `vitepress`에서 전역적으로 가져올 수 있으며 일반적으로 사용자 지정 테마 Vue 컴포넌트에서 사용됩니다. 그러나 마크다운 파일이 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 컴파일되기 때문에 `.md` 페이지 내에서도 사용할 수 있습니다. 헬퍼 메서드는 `vitepress`에서 전역적으로 사용할 수 있으며, 주로 커스텀 테마의 Vue 컴포넌트에서 사용됩니다. 또한 마크다운 파일이 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 컴파일되기 때문에 `.md` 페이지 내에서도 사용할 수 있습니다.
`use*`로 시작하는 메서드는 `setup()` 또는 `<script setup>` 내에서만 사용할 수 있는 [Vue 3 구성 API](https://vuejs.org/guide/introduction.html#composition-api) 함수("컴퍼저블")임을 나타냅니다. `use*`로 시작하는 메서드는 [Vue 3 Composition API](https://vuejs.org/guide/introduction.html#composition-api) 함수("컴포저블")를 나타내며, 이는 `setup()` 또는 `<script setup>` 내부에서만 사용할 수 있습니다.
## `useData` <Badge type="info" text="컴저블" /> ## `useData` <Badge type="info" text="컴저블" />
페이지별 데이터를 반환합니다. 반환된 객체는 다음 유형을 가집니다: 페이지별 데이터를 반환합니다. 반환된 객체는 다음과 같은 타입을 가집니다:
```ts ```ts
interface VitePressData<T = any> { interface VitePressData<T = any> {
/** /**
* 사이트 수준 메타데이터 * 사이트 레벨 메타데이터
*/ */
site: Ref<SiteData<T>> site: Ref<SiteData<T>>
/** /**
* .vitepress/config.js에서의 themeConfig * .vitepress/config.js 의 themeConfig
*/ */
theme: Ref<T> theme: Ref<T>
/** /**
* 페이지 수준 메타데이터 * 페이지 레벨 메타데이터
*/ */
page: Ref<PageData> page: Ref<PageData>
/** /**
* 페이지 앞부분 메타데이터 * 페이지 전문 메타데이터
*/ */
frontmatter: Ref<PageData['frontmatter']> frontmatter: Ref<PageData['frontmatter']>
/** /**
* 동적 라우트 매개변수 * 동적 라우트 파라미터
*/ */
params: Ref<PageData['params']> params: Ref<PageData['params']>
title: Ref<string> title: Ref<string>
@ -58,7 +58,7 @@ interface PageData {
} }
``` ```
**예:** **예:**
```vue ```vue
<script setup> <script setup>
@ -72,9 +72,9 @@ const { theme } = useData()
</template> </template>
``` ```
## `useRoute` <Badge type="info" text="컴저블" /> ## `useRoute` <Badge type="info" text="컴저블" />
현재 라우트 객체를 다음 유형으로 반환합니다: 다음과 같은 타입으로 현재 라우트 객체를 반환합니다:
```ts ```ts
interface Route { interface Route {
@ -84,9 +84,9 @@ interface Route {
} }
``` ```
## `useRouter` <Badge type="info" text="컴저블" /> ## `useRouter` <Badge type="info" text="컴저블" />
다른 페이지로 프로그래밍 방식으로 이동할 수 있도록 VitePress 라우터 인스턴스를 반환합니다. 프로그래밍 방식으로 다른 페이지로 이동할 수 있도록 VitePress 라우터 인스턴스를 반환합니다.
```ts ```ts
interface Router { interface Router {
@ -95,38 +95,38 @@ interface Router {
*/ */
route: Route route: Route
/** /**
* 새 URL로 이동합니다. * 새 URL로 이동.
*/ */
go: (to?: string) => Promise<void> go: (to?: string) => Promise<void>
/** /**
* 라우트가 변경되기 전에 호출됩니다. 이동을 취소하려면 `false`를 반환하십시오. * 라우트가 변경되기 전에 호출. 탐색을 취소하려면 `false`를 반환.
*/ */
onBeforeRouteChange?: (to: string) => Awaitable<void | boolean> onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>
/** /**
* 페이지 컴포넌트가 로드되기 전(히스토리 상태가 업데이트된 후)에 호출됩니다. * 페이지 컴포넌트가 로드되기 전(히스토리 상태가 업데이트된 후)에 호출.
* 이동을 취소하려면 `false`를 반환하십시오. * 탐색을 취소하려면 `false`를 반환.
*/ */
onBeforePageLoad?: (to: string) => Awaitable<void | boolean> onBeforePageLoad?: (to: string) => Awaitable<void | boolean>
/** /**
* 라우트가 변경된 후 호출됩니다. * 라우트가 변경된 후 호출.
*/ */
onAfterRouteChanged?: (to: string) => Awaitable<void> onAfterRouteChanged?: (to: string) => Awaitable<void>
} }
``` ```
## `withBase` <Badge type="info" text="도움" /> ## `withBase` <Badge type="info" text="헬퍼" />
- **타입**: `(path: string) => string` - **타입**: `(path: string) => string`
설정된 [`base`](./site-config#base)를 주어진 URL 경로에 추가합니다. [Base URL](../guide/asset-handling#base-url)도 참조하십시오. 구성된 [`base`](./site-config#base)를 지정된 URL 경로에 추가합니다. [Base URL](../guide/asset-handling#base-url)을 참고하세요.
## `<Content />` <Badge type="info" text="컴포넌트" /> ## `<Content />` <Badge type="info" text="컴포넌트" />
`<Content />` 컴포넌트는 렌더링된 마크다운 내용을 표시합니다. [자신만의 테마를 만들 때](../guide/custom-theme) 유용합니다. `<Content />` 컴포넌트는 렌더링된 마크다운 내용을 표시합니다. [커스텀 테마를 만들 때](../guide/custom-theme) 유용합니다.
```vue ```vue
<template> <template>
<h1>커스텀 레이아웃!</h1> <h1>Custom Layout!</h1>
<Content /> <Content />
</template> </template>
``` ```
@ -135,9 +135,9 @@ interface Router {
`<ClientOnly />` 컴포넌트는 클라이언트 측에서만 슬롯을 렌더링합니다. `<ClientOnly />` 컴포넌트는 클라이언트 측에서만 슬롯을 렌더링합니다.
VitePress 애플리케이션은 정적 빌드를 생성할 때 Node.js에서 서버 렌더링되므로, 모든 Vue 사용은 범용 코드 요구 사항에 부합해야 합니다. 간단히 말해서, beforeMount 또는 mounted 훅에서만 브라우저 / DOM API에 액세스하십시오. VitePress 애플리케이션은 정적 빌드를 생성할 때 Node.js에서 서버 렌더링되므로 모든 Vue 사용은 범용 코드 요구 사항을 준수해야 합니다. 간단히 말해서, 브라우저 / DOM API는 반드시 beforeMount 또는 mounted 훅에서만 접근해야 합니다.
SSR 친화적이지 않은 컴포넌트(예: 커스텀 지시문이 포함된 경우)를 사용하거나 시연하는 경우 해당 컴포넌트를 `ClientOnly` 컴포넌트 안에 포함시킬 수 있습니다. SSR 친화적이지 않은(예: 커스텀 디렉티브를 포함하는) 컴포넌트를 사용하는 경우, 이를 `ClientOnly` 컴포넌트 내부에 래핑할 수 있습니다.
```vue-html ```vue-html
<ClientOnly> <ClientOnly>
@ -145,15 +145,15 @@ SSR 친화적이지 않은 컴포넌트(예: 커스텀 지시문이 포함된
</ClientOnly> </ClientOnly>
``` ```
- 관련: [SSR 호환성](../guide/ssr-compat) - 참고: [SSR 호환성](../guide/ssr-compat)
## `$frontmatter` <Badge type="info" text="템플릿 전역" /> ## `$frontmatter` <Badge type="info" text="템플릿 전역" />
Vue 표현식에서 현재 페이지의 [앞부분 메타데이터](../guide/frontmatter)를 직접 액세스합니다. Vue 표현식에서 현재 페이지의 [전문](../guide/frontmatter) 데이터에 직접 접근합니다.
```md ```md
--- ---
title: 안녕하세요 title: Hello
--- ---
# {{ $frontmatter.title }} # {{ $frontmatter.title }}
@ -161,7 +161,7 @@ title: 안녕하세요
## `$params` <Badge type="info" text="템플릿 전역" /> ## `$params` <Badge type="info" text="템플릿 전역" />
Vue 표현식에서 현재 페이지의 [동적 라우트 매개변수](../guide/routing#dynamic-routes)를 직접 액세스합니다. Vue 표현식에서 현재 페이지의 [동적 라우트 파라미터](../guide/routing#dynamic-routes)에 직접 접근합니다.
```md ```md
- package name: {{ $params.pkg }} - package name: {{ $params.pkg }}

@ -2,31 +2,31 @@
outline: deep outline: deep
--- ---
# 사이트 설정 {#site-config} # 사이트 구성 {#site-config}
사이트 설정은 사이트의 전역 설정을 정의할 수 있는 곳입니다. 앱 설정 옵션은 사용되는 테마에 상관없이 모든 VitePress 사이트에 적용되는 설정을 정의합니다. 예를 들어, 기본 디렉토리 또는 사이트의 제목 등이 있습니다. 사이트 구성(config)은 사이트의 전역 설정을 정의할 수 있는 곳입니다. 애플리케이션 구성 옵션은 사용 중인 테마와 상관없이 모든 VitePress 사이트에 적용되는 설정을 정의합니다. 예를 들어 기본 디렉터리나 사이트의 제목 등이 있습니다.
## 개요 {#overview} ## 개요 {#overview}
### 설정 해석 {#config-resolution} ### 구성 분석 {#config-resolution}
설정 파일은 항상 `<root>/.vitepress/config.[ext]`에서 해석되며, 여기서 `<root>`는 여러분의 VitePress [프로젝트 루트](../guide/routing#root-and-source-directory), 그리고 `[ext]`는 지원되는 파일 확장명 중 하나입니다. TypeScript는 기본적으로 지원됩니다. 지원되는 확장명에는 `.js`, `.ts`, `.mjs`, 그리고 `.mts`가 포함됩니다. 구성 파일은 항상 `<root>/.vitepress/config.[ext]`에서 처리됩니다. 여기서 `<root>`는 VitePress [프로젝트 루트](../guide/routing#root-and-source-directory)를 의미하며, `[ext]`는 지원되는 파일 확장자 중 하나입니다. TypeScript는 기본적으로 지원됩니다. 지원되는 확장자에는 `.js`, `.ts`, `.mjs`, `.mts`가 포함됩니다.
설정 파일에서는 ES 모듈 문법의 사용을 권장합니다. 설정 파일은 객체를 기본 내보내기해야 합니다: 구성 파일에서는 ES 모듈 구문을 사용하는 것이 권장됩니다. 구성 파일은 객체를 "default export"해야 합니다:
```ts ```ts
export default { export default {
// 앱 레벨 설정 옵션 // 애플리케이션 레벨의 구성 옵션
lang: 'en-US', lang: 'en-US',
title: 'VitePress', title: 'VitePress',
description: 'Vite & Vue를 활용한 정적 사이트 생성기.', description: 'Vite & Vue powered static site generator.',
... ...
} }
``` ```
::: details 동적(비동기) 설정 ::: details 동적(비동기) 구성
동적으로 설정을 생성해야 하는 경우, 함수를 기본 내보내기로 사용할 수도 있습니다. 예를 들면: 구성을 동적으로 생성해야 하는 경우, 함수를 "default export" 할 수 있습니다. 예:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -35,12 +35,12 @@ export default async () => {
const posts = await (await fetch('https://my-cms.com/blog-posts')).json() const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
return defineConfig({ return defineConfig({
// 앱 레벨 설정 옵션 // 애플리케이션 레벨의 구성 옵션
lang: 'en-US', lang: 'en-US',
title: 'VitePress', title: 'VitePress',
description: 'Vite & Vue를 활용한 정적 사이트 생성기.', description: 'Vite & Vue powered static site generator.',
// 테마 레벨 설정 옵션 // 테마 레벨의 구성 옵션
themeConfig: { themeConfig: {
sidebar: [ sidebar: [
...posts.map((post) => ({ ...posts.map((post) => ({
@ -53,7 +53,7 @@ export default async () => {
} }
``` ```
예를 들어 상위 수준의 `await`도 사용할 수 있습니다: 상위 수준의 `await`도 사용할 수 있습니다. 예:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -80,9 +80,9 @@ export default defineConfig({
::: :::
### 설정 옵션에 대한 인텔리센스 {#config-intellisense} ### 구성 인텔리센스 {#config-intellisense}
`defineConfig` 헬퍼를 사용하면 설정 옵션에 대해 TypeScript로 제공되는 인텔리센스를 활용할 수 있습니다. 여러분의 IDE가 지원한다면, JavaScript와 TypeScript 모두에서 작동할 것입니다. `defineConfig` 헬퍼를 사용하면 구성 옵션에 대해 TypeScript 기반의 인텔리센스(자동완성)를 제공받을 수 있습니다. IDE가 이를 지원하는 경우, JavaScript와 TypeScript 모두에서 작동합니다.
```js ```js
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
@ -92,21 +92,21 @@ export default defineConfig({
}) })
``` ```
### 타입이 지정된 테마 설정 {#typed-theme-config} ### 타입이 지정된 테마 구성 {#typed-theme-config}
기본적으로, `defineConfig` 헬퍼는 기본 테마에서 테마 설정 유형을 예상합니다: 기본적으로 `defineConfig` 헬퍼는 기본 테마에서 테마 구성 타입을 예측합니다:
```ts ```ts
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
export default defineConfig({ export default defineConfig({
themeConfig: { themeConfig: {
// 유형`DefaultTheme.Config` // 타입`DefaultTheme.Config`
} }
}) })
``` ```
커스텀 테마를 사용하고 테마 설정에 대한 타입 검사를 원한다면, 대신 `defineConfigWithTheme`을 사용해야 하며, 일반 인수를 통해 귀하의 커스텀 테마에 대한 설정 유형을 전달해야 합니다: 커스텀 테마를 사용하고 테마 구성에 대한 타입 검사를 원한다면, `defineConfigWithTheme`를 사용하고 제네릭 인수를 통해 커스텀 테마의 구성 타입을 전달해야 합니다:
```ts ```ts
import { defineConfigWithTheme } from 'vitepress' import { defineConfigWithTheme } from 'vitepress'
@ -114,102 +114,102 @@ import type { ThemeConfig } from 'your-theme'
export default defineConfigWithTheme<ThemeConfig>({ export default defineConfigWithTheme<ThemeConfig>({
themeConfig: { themeConfig: {
// 유형`ThemeConfig` // 타입`ThemeConfig`
} }
}) })
``` ```
### Vite, Vue & Markdown 설정 {#vite-vue-markdown-config} ### Vite, Vue, Markdown 설정 {#vite-vue-markdown-config}
- **Vite** - **Vite**
여러분은 VitePress 설정에서 [vite](#vite) 옵션을 사용하여 기본 Vite 인스턴스를 구성할 수 있습니다. 별도의 Vite 설정 파일을 만들 필요는 없습니다. VitePress 구성에서 [vite](#vite) 옵션을 사용하여 기본 Vite 인스턴스를 구성할 수 있습니다. 별도의 Vite 구성 파일을 만들 필요는 없습니다.
- **Vue** - **Vue**
VitePress는 이미 Vite 공식 Vue 플러그인([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))을 포함하고 있습니다. VitePress 설정에서 [vue](#vue) 옵션을 사용하여 그 옵션을 구성할 수 있습니다. VitePress는 이미 Vite 공식 Vue 플러그인([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))을 포함하고 있습니다. VitePress 구성에서 [vue](#vue) 옵션을 사용하여 해당 옵션을 구성할 수 있습니다.
- **Markdown** - **Markdown**
[Markdown-It](https://github.com/markdown-it/markdown-it) 인스턴스를 VitePress 설정에서 [markdown](#markdown) 옵션을 사용하여 구성할 수 있습니다. [Markdown-It](https://github.com/markdown-it/markdown-it) 인스턴스를 VitePress 구성에서 [markdown](#markdown) 옵션을 사용하여 구성할 수 있습니다.
## 사이트 메타데이터 {#site-metadata} ## 사이트 메타데이터 {#site-metadata}
### title ### title
- 유형: `string` - 타입: `string`
- 기본값: `VitePress` - 기본값: `VitePress`
- 페이지별로 [frontmatter](./frontmatter-config#title)를 통해 재정의 가능 - [전문](./frontmatter-config#title)을 통해 페이지별로 재정의 가능
사이트의 제목입니다. 기본 테마를 사용할 경우, 이것은 내비게이션 바에 표시됩니다. 사이트의 제목입니다. 기본 테마를 사용할 경우, 이 내비게이션 바에 표시됩니다.
전체 페이지 제목에 기본 접미사로도 사용됩니다. 그렇지 않으면 [`titleTemplate`](#titletemplate)이 정의되어 있습니다. 개별 페이지의 최종 제목은 첫 번째 `<h1>` 헤더의 텍스트 내용과 전역 `title`을 접미사로 결합한 것입니다. 예를 들어 다음과 같은 설정과 페이지 내용을 가진 경우: [`titleTemplate`](#titletemplate)이 정의되지 않은 경우, 모든 개별 페이지 제목의 기본 접미사로 사용됩니다. 개별 페이지의 최종 제목은 첫 번째 `<h1>` 헤더의 텍스트 콘텐츠와 전역 `title`을 접미사로 결합한 것입니다. 예를 들어 다음 구성과 페이지 콘텐츠가 있을 경우:
```ts ```ts
export default { export default {
title: '나의 멋진 사이트' title: 'My Awesome Site'
} }
``` ```
```md ```md
# 안녕하세요 # Hello
``` ```
페이지의 제목은 `안녕하세요 | 나의 멋진 사이트`가 될 것입니다. 페이지의 제목은 `Hello | My Awesome Site`가 됩니다.
### titleTemplate ### titleTemplate
- 유형: `string | boolean` - 타입: `string | boolean`
- 페이지별로 [frontmatter](./frontmatter-config#titletemplate)를 통해 재정의 가능 - [전문](./frontmatter-config#titletemplate)을 통해 페이지별로 재정의 가능
각 페이지의 제목 접미사 또는 전체 제목을 사용자 정의할 수 있습니다. 예를 들면: 각 페이지의 제목 접미사 또는 전체 제목을 커스터마이징할 수 있습니다. 예를 들어:
```ts ```ts
export default { export default {
title: '나의 멋진 사이트', title: 'My Awesome Site',
titleTemplate: '커스텀 접미사' titleTemplate: 'Custom Suffix'
} }
``` ```
```md ```md
# 안녕하세요 # Hello
``` ```
페이지의 제목은 `안녕하세요 | 커스텀 접미사`가 될 것입니다. 페이지의 제목은 `Hello | Custom Suffix`가 됩니다.
`:title` 기호를 `titleTemplate`에 사용하여 제목이 어떻게 렌더링될지 완전히 사용자 정의할 수 있습니다: 제목이 렌더링되는 방식을 완전히 커스터마이징하려면 `titleTemplate`에서 `:title` 심볼을 사용할 수 있습니다:
```ts ```ts
export default { export default {
titleTemplate: ':title - 커스텀 접미사' titleTemplate: ':title - Custom Suffix'
} }
``` ```
이 경우 `:title`은 페이지의 첫 번째 `<h1>` 헤더에서 추론된 텍스트로 대체됩니다. 이전 예제 페이지의 제목은 `안녕하세요 - 커스텀 접미사`가 될 것입니다. 여기서 `:title`은 페이지의 첫 번째 `<h1>` 헤더에서 추론된 텍스트로 대체됩니다. 이전 예제 페이지의 제목은 `Hello - Custom Suffix`가 됩니다.
이 옵션 `false`로 설정하여 제목 접미사를 비활성화할 수 있습니다. 이 옵션 `false`로 설정하여 제목 접미사를 비활성화할 수 있습니다.
### description ### description
- 유형: `string` - 타입: `string`
- 기본값: `VitePress 사이트` - 기본값: `A VitePress site`
- 페이지별로 [frontmatter](./frontmatter-config#description)를 통해 재정의 가능 - [전문](./frontmatter-config#description)을 통해 페이지별로 재정의 가능
사이트에 대한 설명입니다. 이것은 페이지 HTML의 `<meta>` 태그로 렌더링됩니다. 사이트의 설명입니다. 이는 페이지 HTML의 `<meta>` 태그로 렌더링됩니다.
```ts ```ts
export default { export default {
description: 'VitePress 사이트' description: 'A VitePress site'
} }
``` ```
### head ### head
- 유형: `HeadConfig[]` - 타입: `HeadConfig[]`
- 기본값: `[]` - 기본값: `[]`
- 페이지별로 [frontmatter](./frontmatter-config#head)를 통해 추가 가능 - [전문](./frontmatter-config#head)을 통해 페이지별로 추가 가능
페이지 HTML의 `<head>` 태그에 렌더링할 추가 요소들입니다. 사용자가 추가한 태그는 VitePress 태그 뒤, `head` 태그가 닫히기 전에 렌더링됩니다. 페이지 HTML의 `<head>` 태그에 렌더링할 추가 엘리먼트입니다. 추가한 태그는 VitePress 태그 뒤 ~ 닫는 `head` 태그 앞에 렌더링됩니다.
```ts ```ts
type HeadConfig = type HeadConfig =
@ -222,14 +222,14 @@ type HeadConfig =
```ts ```ts
export default { export default {
head: [['link', { rel: 'icon', href: '/favicon.ico' }]] head: [['link', { rel: 'icon', href: '/favicon.ico' }]]
} // base가 설정된 경우, /base/favicon.ico를 사용하세요 } // favicon.ico를 public 디렉토리에 배치하거나 base가 설정된 경우,
// /base/favicon.ico를 사용하세요.
/* 다음을 렌더링할 것입니다: /* 다음과 같이 랜더링:
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
*/ */
``` ```
#### 예제: Google Fonts 추가 {#example-adding-google-fonts} #### 예제: Google 폰트 추가 {#example-adding-google-fonts}
```ts ```ts
export default { export default {
@ -249,7 +249,7 @@ export default {
] ]
} }
/* 다음을 렌더링할 것입니다: /* 다음과 같이 랜더링:
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
@ -273,7 +273,7 @@ export default {
] ]
} }
/* 다음을 렌더링할 것입니다: /* 다음과 같이 랜더링:
<script id="register-sw"> <script id="register-sw">
;(() => { ;(() => {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
@ -304,7 +304,7 @@ export default {
] ]
} }
/* 다음을 렌더링할 것입니다: /* 다음과 같이 랜더링:
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script> <script>
window.dataLayer = window.dataLayer || []; window.dataLayer = window.dataLayer || [];
@ -317,10 +317,10 @@ export default {
### lang ### lang
- 유형: `string` - 타입: `string`
- 기본값: `en-US` - 기본값: `en-US`
사이트의 lang 속성입니다. 이것은 페이지 HTML의 `<html lang="en-US">` 태그로 렌더링됩니다. 사이트의 언어 어트리뷰트입니다. 이는 페이지 HTML의 `<html lang="en-US">` 태그로 렌더링됩니다.
```ts ```ts
export default { export default {
@ -330,12 +330,12 @@ export default {
### base ### base
- 유형: `string` - 타입: `string`
- 기본값: `/` - 기본값: `/`
사이트가 배포될 기본 URL입니다. 여러분이 사이트를 GitHub 페이지와 같은 하위 경로에 배포할 계획이라면 이것을 설정해야 합니다. 예를 들어, 여러분의 사이트를 `https://foo.github.io/bar/`에 배포할 계획이라면 base를 `'/bar/'`로 설정해야 합니다. 항상 슬래시로 시작하고 끝나야 합니다. 사이트가 배포될 기본 URL입니다. 예를 들어 GitHub Pages와 같이 서브 경로에 사이트를 배포하려는 경우 이것을 설정해야 합니다. `https://foo.github.io/bar/` 에 사이트를 배포하려면 `'/bar/'`로 설정해야 합니다. 항상 슬래시로 시작하고 끝나야 합니다.
base는 자동으로 다른 옵션에서 /로 시작하는 모든 URL에 자동으로 추가되므로 한 번만 지정하면 됩니다. 이것은 다른 옵션에서 `/`로 시작하는 모든 URL에 자동으로 추가되므로, 한 번만 지정하면 됩니다.
```ts ```ts
export default { export default {
@ -347,20 +347,20 @@ export default {
### cleanUrls ### cleanUrls
- 유형: `boolean` - 타입: `boolean`
- 기본값: `false` - 기본값: `false`
`true`로 설정하면, VitePress는 URL에서 끝부분 `.html`을 제거합니다. 또한 [클린 URL 생성](../guide/routing#generating-clean-url)을 참조하세요. `true`로 설정하면 VitePress는 URL에서 `.html`을 제거합니다. [간결한 URL 생성](../guide/routing#generating-clean-url)을 참고하세요.
::: warning 서버 지원 필요 ::: warning 서버 지원 필요
이를 활성화하려면 호스팅 플랫폼에서 추가 구성이 필요할 수 있습니다. 작동하려면 서버가 `/foo.html`을 방문할 때 `/foo`**리디렉션 없이** 제공할 수 있어야 합니다. 이를 활성화하려면 호스팅 플랫폼에서 추가 구성이 필요할 수 있습니다. 서버가 `/foo`를 방문할 때 **리디렉션 없이** `/foo.html` 제공할 수 있어야 합니다.
::: :::
### rewrites ### rewrites
- 유형: `Record<string, string>` - 타입: `Record<string, string>`
사용자 지정 디렉토리 &lt;-&gt; URL 매핑을 정의합니다. 자세한 내용은 [라우팅: 라우트 재작성](../guide/routing#route-rewrites)을 참조하십시오. 커스텀 디렉터리와 URL 매핑을 정의합니다. 자세한 내용은 [라우팅: 라우트 재작성](../guide/routing#route-rewrites)을 참고하세요.
```ts ```ts
export default { export default {
@ -374,10 +374,10 @@ export default {
### srcDir ### srcDir
- 유형: `string` - 타입: `string`
- 기본값: `.` - 기본값: `.`
프로젝트 루트에 대해 상대적인 마크다운 페이지가 저장되는 디렉토리입니다. 또한 [루트 및 소스 디렉토리](../guide/routing#root-and-source-directory)를 참조하십시오. 마크다운 페이지가 저장되는 디렉터리입니다. 프로젝트 루트에 상대적입니다. 또한 [루트와 소스 디렉터리](../guide/routing#root-and-source-directory)를 참고하세요.
```ts ```ts
export default { export default {
@ -387,10 +387,10 @@ export default {
### srcExclude ### srcExclude
- 유형: `string` - 타입: `string`
- 기본값: `undefined` - 기본값: `undefined`
소스 콘텐츠로 제외해야 하는 마크다운 파일을 일치시키는 [글로브 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)입니다. 소스 컨텐츠에서 제외해야 하는 마크다운 파일을 매칭하기 위한 [glob 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)입니다.
```ts ```ts
export default { export default {
@ -400,10 +400,10 @@ export default {
### outDir ### outDir
- 유형: `string` - 타입: `string`
- 기본값: `./.vitepress/dist` - 기본값: `./.vitepress/dist`
사이트의 빌드 출력 위치로, [프로젝트 루트](../guide/routing#root-and-source-directory)에 대해 상대적입니다. 사이트의 빌드 결과물 위치입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다.
```ts ```ts
export default { export default {
@ -413,10 +413,10 @@ export default {
### assetsDir ### assetsDir
- 유형: `string` - 타입: `string`
- 기본값: `assets` - 기본값: `assets`
생성된 자산을 중첩할 디렉토리를 지정합니다. 경로는 [`outDir`](#outdir) 내부에 있어야 하며 이에 대해 상대적으로 해결됩니다. 생성된 에셋을 포함할 디렉터리를 지정합니다. 경로는 [`outDir`](#outdir) 내에 있어야 하며, 그것을 기준으로 처리됩니다.
```ts ```ts
export default { export default {
@ -426,10 +426,10 @@ export default {
### cacheDir ### cacheDir
- 유형: `string` - 타입: `string`
- 기본값: `./.vitepress/cache` - 기본값: `./.vitepress/cache`
캐시 파일을 위한 디렉토리로, [프로젝트 루트](../guide/routing#root-and-source-directory)에 대해 상대적입니다. 또한: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)을 참하세요. 캐시 파일을 위한 디렉터리입니다. [프로젝트 루트](../guide/routing#root-and-source-directory)에 상대적입니다. [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)을 참하세요.
```ts ```ts
export default { export default {
@ -439,12 +439,12 @@ export default {
### ignoreDeadLinks ### ignoreDeadLinks
- 유형: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]` - 타입: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
- 기본값: `false` - 기본값: `false`
`true`로 설정하면, VitePress는 죽은 링크로 인해 빌드가 실패하지 않습니다. `true`로 설정하면, 빌드 시 죽은 링크로 인해 실패하지 않습니다.
`'localhostLinks'`로 설정하면, 빌드가 죽은 링크로 실패하지만, `localhost` 링크는 확인하지 않습니다. `'localhostLinks'`로 설정하면, 죽은 링크가 있으면 빌드에 실패하지만 `localhost` 링크는 확인하지 않습니다.
```ts ```ts
export default { export default {
@ -452,18 +452,18 @@ export default {
} }
``` ```
정확한 url 문자열, 정규식 패턴, 또는 사용자 정의 필터 함수의 배열일 수도 있습니다. 정확히 일치하는 URL 문자열, 정규 표현식 패턴, 커스텀 필터 함수로 구성된 배열도 가능합니다.
```ts ```ts
export default { export default {
ignoreDeadLinks: [ ignoreDeadLinks: [
// 정확한 url "/playground"를 무시 // "/playground"과 정확히 일치하는 url 무시
'/playground', '/playground',
// 모든 localhost 링크 무시 // 모든 localhost 링크 무시
/^https?:\/\/localhost/, /^https?:\/\/localhost/,
// 모든 "/repl/" 포함 링크 무시 // 모든 "/repl/" 포함 링크 무시
/\/repl\//, /\/repl\//,
// 사용자 정의 함수, "ignore"를 포함한 모든 링크 무시 // 커스텀 함수, "ignore"를 포함한 모든 링크 무시
(url) => { (url) => {
return url.toLowerCase().includes('ignore') return url.toLowerCase().includes('ignore')
} }
@ -476,14 +476,14 @@ export default {
- 타입: `boolean` - 타입: `boolean`
- 기본값: `false` - 기본값: `false`
`true`로 설정하면, 초기 HTML에 인라인으로 포함되는 대신 별도의 JavaScript 청크로 페이지 메타데이터를 추출합니다. 이렇게 하면 각 페이지의 HTML 페이로드가 줄어들고 페이지 메타데이터 캐싱이 가능해져 사이트에 많은 페이지가 있을 때 서버 대역폭이 줄어듭니다. `true`로 설정하면 페이지 메타데이터를 초기 HTML에 인라인으로 삽입하는 대신 별도의 JavaScript 청크로 추출합니다. 이렇게 하면 각 페이지의 HTML 페이로드가 작아지고 페이지 메타데이터를 캐시할 수 있어, 사이트에 많은 페이지가 있을 때 서버 대역폭을 줄일 수 있습니다.
### mpa <Badge type="warning" text="실험적" /> ### mpa <Badge type="warning" text="실험적" />
- 타입: `boolean` - 타입: `boolean`
- 기본값: `false` - 기본값: `false`
`true`로 설정하면, 프로덕션 앱이 [MPA 모드](../guide/mpa-mode)로 빌드됩니다. MPA 모드는 기본적으로 0kb의 JavaScript를 제공하지만, 클라이언트 측 탐색을 비활성화하고 상호작용에 대해 명시적인 동의가 필요합니다. `true`로 설정하면 프로덕션 애플리케이션이 [MPA 모드](../guide/mpa-mode)로 빌드됩니다. MPA 모드는 기본적으로 0kb JavaScript를 제공하지만, 클라이언트 사이드 탐색을 비활성화하고 상호작용을 위한 명시적인 옵트인을 필요로 합니다.
## 테마 {#theming} ## 테마 {#theming}
@ -492,34 +492,34 @@ export default {
- 타입: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions` - 타입: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions`
- 기본값: `true` - 기본값: `true`
다크 모드(HTML 요소에 `.dark` 클래스 추가) 활성화 여부입니다. 다크 모드를 활성화 여부를 설정합니다 (`.dark` 클래스를 `<html>` 엘리먼트에 추가).
- 옵션이 `true`로 설정되면, 기본 테마는 사용자의 선호 색상 체계에 따라 결정됩니다. - `true`: 기본 테마는 유저의 선호 색상 설정에 따라 결정됩니다.
- 옵션이 `dark`로 설정되면, 테마는 기본적으로 다크 모드가 되며, 사용자가 수동으로 전환할 수 있습니다. - `dark`: 유저가 수동으로 변경하지 않는 한 기본 테마는 다크 모드가 됩니다.
- 옵션이 `false`로 설정되면, 사용자는 테마를 전환할 수 없습니다. - `false`: 유저는 테마를 전환할 수 없습니다.
- 옵션이 `'force-dark'`로 설정된 경우, 테마는 항상 어둡게 유지되며 사용자는 이를 변경할 수 없습니다. - `'force-dark'`: 테마는 항상 다크 모드가 되며 유저는 이를 전환할 수 없습니다.
- 옵션이 `'force-auto'`로 설정된 경우, 테마는 항상 사용자의 선호 색상에 의해 결정되며 사용자는 이를 변경할 수 없습니다. - `'force-auto'`: 테마는 항상 유저의 선호 색상 설정에 따라 결정되며 유저는 이를 전환할 수 없습니다.
이 옵션은 `vitepress-theme-appearance` 키를 사용하여 로컬 스토리지에서 사용자 설정을 복원하는 인라인 스크립트를 삽입합니다. 이는 페이지가 렌더링되기 전에 `.dark` 클래스가 적용되어 깜임을 방지합니다. 이 옵션은 `vitepress-theme-appearance` 키를 사용하여 로컬 스토리지에서 유저 설정을 복원하는 인라인 스크립트를 삽입합니다. 이는 페이지가 렌더링되기 전에 `.dark` 클래스가 적용되어 깜임을 방지합니다.
`appearance.initialValue``'dark' | undefined`만 가능합니다. Refs나 게터는 지원되지 않습니다. `appearance.initialValue``'dark'` 또는 `undefined`만 가능합니다. Refs 또는 getter는 지원되지 않습니다.
### lastUpdated ### lastUpdated
- 타입: `boolean` - 타입: `boolean`
- 기본값: `false` - 기본값: `false`
Git을 사용하여 각 페이지의 마지막 업데이트 타임스탬프를 가져옵니다. 타임스탬프는 각 페이지의 페이지 데이터에 포함되며, [`useData`](./runtime-api#usedata)를 통해 접근할 수 있습니다. 각 페이지의 마지막 업데이트 타임스탬프를 Git을 사용하여 가져올지 여부를 설정합니다. 타임스탬프는 각 페이지의 페이지 데이터에 포함되며, [`useData`](./runtime-api#usedata)를 통해 접근할 수 있습니다.
기본 테마를 사용하는 경우, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 옵션을 통해 텍스트를 사용자 정의할 수 있습니다. 기본 테마를 사용할 때, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 옵션을 통해 텍스트를 커스터마이징할 수 있습니다.
## 사용자 정의 {#customization} ## 커스터마이징 {#customization}
### markdown ### markdown
- 타입: `MarkdownOption` - 타입: `MarkdownOption`
Markdown 파서 옵션을 구성합니다. VitePress는 파서로 [Markdown-it](https://github.com/markdown-it/markdown-it)를, 언어 구문을 강조하는 데 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. 이 옵션 안에서 필요에 맞는 다양한 Markdown 관련 옵션을 전달할 수 있습니다. 마크다운 파서 옵션을 구성합니다. VitePress는 파서로 [Markdown-it](https://github.com/markdown-it/markdown-it)을 사용하고, 언어 구문 강조를 위해 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. 이 옵션 내에서 다양한 마크다운 관련 옵션을 전달하여 필요에 맞게 조정할 수 있습니다.
```js ```js
export default { export default {
@ -527,18 +527,18 @@ export default {
} }
``` ```
모든 사용 가능한 옵션에 대해서는 [타입 선언과 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts)를 확인하세요. 사용 가능한 모든 옵션에 대해서는 [타입 선언 및 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts)를 참고하세요.
### vite ### vite
- 타입: `import('vite').UserConfig` - 타입: `import('vite').UserConfig`
내부 Vite 개발 서버/번들러에 직접 [Vite 설정](https://vitejs.dev/config/)을 전달합니다. 내부 Vite 개발 서버/번들러에 직접 [Vite 구성](https://vitejs.dev/config/)을 전달합니다.
```js ```js
export default { export default {
vite: { vite: {
// Vite 설정 옵션 // Vite 구성 옵션
} }
} }
``` ```
@ -547,7 +547,7 @@ export default {
- 타입: `import('@vitejs/plugin-vue').Options` - 타입: `import('@vitejs/plugin-vue').Options`
내부 플러그인 인스턴스에 [`@vitejs/plugin-vue` 옵션](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)을 직접 전달합니다. 내부 플러그인 인스턴스에 직접 [`@vitejs/plugin-vue` 옵션](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)을 전달합니다.
```js ```js
export default { export default {
@ -557,20 +557,20 @@ export default {
} }
``` ```
## 빌드 후크 {#build-hooks} ## 빌드 {#build-hooks}
VitePress 빌드 후크는 웹사이트에 새로운 기능과 동작을 추가할 수 있습니다: VitePress 빌드 훅은 웹사이트에 새로운 기능과 동작을 추가할 수 있게 합니다:
- 사이트맵 - 사이트맵
- 검색 색인 작성 - 검색 인덱싱
- PWA - PWA
- Teleports - 텔레포트
### buildEnd ### buildEnd
- 타입: `(siteConfig: SiteConfig) => Awaitable<void>` - 타입: `(siteConfig: SiteConfig) => Awaitable<void>`
`buildEnd`는 빌드 CLI 후크로, 빌드(정적 사이트 생성, SSG) 완료 후 VitePress CLI 프로세스가 종료되기 전에 실행됩니다. `buildEnd`는 빌드 CLI 훅으로, 빌드(SSG)가 완료된 후 VitePress CLI 프로세스가 종료되기 전에 실행됩니다.
```ts ```ts
export default { export default {
@ -584,7 +584,7 @@ export default {
- 타입: `(context: SSGContext) => Awaitable<SSGContext | void>` - 타입: `(context: SSGContext) => Awaitable<SSGContext | void>`
`postRender`SSG 렌더링이 완료되었을 때 호출되는 빌드 후크입니다. SSG 중 Teleports 콘텐츠를 다루는 것을 허용합니다. `postRender`빌드 훅으로, SSG 렌더링이 완료되었을 때 호출됩니다. 이를 통해 SSG 동안 텔레포트 콘텐츠를 핸들링 할 수 있습니다.
```ts ```ts
export default { export default {
@ -606,10 +606,10 @@ interface SSGContext {
- 타입: `(context: TransformContext) => Awaitable<HeadConfig[]>` - 타입: `(context: TransformContext) => Awaitable<HeadConfig[]>`
`transformHead`는 각 페이지를 생성하기 전에 head를 변환하는 빌드 후크입니다. 정적으로 VitePress 설정에 추가할 수 없는 head 항목을 추가할 수 있습니다. 기존 항목과 자동으로 병합되므로 추가 항목만 반환하면 됩니다. `transformHead`는 각 페이지를 생성하기 전에 헤드를 변환하는 빌드 훅입니다. VitePress 구성에 정적으로 추가할 수 없는 헤드 항목을 추가할 수 있습니다. 기존 항목과 자동으로 병합되므로 추가 항목만 반환하면 됩니다.
::: warning ::: warning
`context` 내부에서 어떤 것도 변형하지 마세요. `context` 내부의 어떤 것도 변경하지 마세요.
::: :::
```ts ```ts
@ -622,8 +622,8 @@ export default {
```ts ```ts
interface TransformContext { interface TransformContext {
page: string // 예: index.md (srcDir에 대해 상대적) page: string // 예: index.md (srcDir에 상대적)
assets: string[] // 모든 비-js/css 자산을 전적으로 해결된 공개 URL로 assets: string[] // js/css가 아닌 모든 에셋을 완전히 처리된 public URL로 표시.
siteConfig: SiteConfig siteConfig: SiteConfig
siteData: SiteData siteData: SiteData
pageData: PageData pageData: PageData
@ -634,7 +634,7 @@ interface TransformContext {
} }
``` ```
후크는 웹사이트를 정적으로 생성할 때만 호출됩니다. 개발 중에는 호출되지 않습니다. 개발 중에 동적 head 항목을 추가해야 하는 경우, [`transformPageData`](#transformpagedata) 후크를 사용할 수 있습니다: 훅은 사이트를 정적으로 생성할 때만 호출됩니다. 개발 중에는 호출되지 않습니다. 개발 중에 동적 헤드 항목을 추가해야 하는 경우, [`transformPageData`](#transformpagedata) 훅을 대신 사용할 수 있습니다:
```ts ```ts
export default { export default {
@ -654,7 +654,7 @@ export default {
} }
``` ```
#### 예시: 정규 URL `<link>` 추가 {#example-adding-a-canonical-url-link} #### 예제: 표준 URL `<link>` 추가 {#example-adding-a-canonical-url-link}
```ts ```ts
export default { export default {
@ -676,10 +676,10 @@ export default {
- 타입: `(code: string, id: string, context: TransformContext) => Awaitable<string | void>` - 타입: `(code: string, id: string, context: TransformContext) => Awaitable<string | void>`
`transformHtml`는 디스크에 저장하기 전 각 페이지의 콘텐츠를 변환하는 빌드 훅입니다. `transformHtml`은 각 페이지의 내용을 디스크에 저장하기 전에 변환하는 빌드 훅입니다.
::: warning ::: warning
`context`에서는 어떠한 것도 변경하지 마세요. 또한, html 콘텐츠를 수정하는 것은 런타임에 수화 문제를 일으킬 수 있습니다. `context`부의 어떤 것도 변경하지 마세요. HTML 내용을 수정하면 런타임에 하이드레이션 문제가 발생할 수 있습니다.
::: :::
```ts ```ts
@ -694,10 +694,10 @@ export default {
- 타입: `(pageData: PageData, context: TransformPageContext) => Awaitable<Partial<PageData> | { [key: string]: any } | void>` - 타입: `(pageData: PageData, context: TransformPageContext) => Awaitable<Partial<PageData> | { [key: string]: any } | void>`
`transformPageData`는 각 페이지의 `pageData`를 변환하는 훅입니다. `pageData`를 직접 변경하거나 변경된 값을 반환하여 페이지 데이터에 병합할 수 있습니다. `transformPageData`는 각 페이지의 `pageData`를 변환하는 훅입니다. `pageData`를 직접 변경하거나, 변경된 값을 반환하여 페이지 데이터에 병합할 수 있습니다.
::: warning ::: warning
`context`에서는 어떠한 것도 변경하지 마세요. 또한, 이 작업은 개발 서버의 성능에 영향을 줄 수 있으므로 주의하세요. 특히, 훅에서 네트워크 요청이나 이미지 생성과 같은 무거운 연산을 수행하는 경우에는 조건부 로직을 위해 `process.env.NODE_ENV === 'production'` 확인할 수 있습니다. `context`부의 어떤 것도 변경하지 마세요. 이 훅에서 네트워크 요청이나 이미지 생성과 같은 무거운 연산이 있을 경우 개발 서버의 성능에 영향을 줄 수 있으니 주의하세요. 조건부 로직을 위해 `process.env.NODE_ENV === 'production'` 확인할 수 있습니다.
::: :::
```ts ```ts

@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* fonte de texto normal */ --vp-font-family-base: /* fonte de texto normal */
--vp-font-family-mono: /* fonte de código */ --vp-font-family-mono: /* fonte de código */

@ -289,7 +289,7 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: 'Documentation' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',

@ -10,7 +10,7 @@
Вы можете ссылаться на статические ресурсы в ваших файлах разметки, компоненты `*.vue` в теме, стили и обычные файлы `.css`, используя абсолютные пути (основанные на корне проекта) или относительные пути (основанные на вашей файловой системе). Последнее похоже на поведение, к которому вы привыкли, если использовали Vite, Vue CLI или `file-loader` в webpack. Вы можете ссылаться на статические ресурсы в ваших файлах разметки, компоненты `*.vue` в теме, стили и обычные файлы `.css`, используя абсолютные пути (основанные на корне проекта) или относительные пути (основанные на вашей файловой системе). Последнее похоже на поведение, к которому вы привыкли, если использовали Vite, Vue CLI или `file-loader` в webpack.
Распространенные типы файлов изображений, мультимедиа и шрифтов определяются и включаются в качестве ресурсов автоматически. Распространённые типы файлов изображений, мультимедиа и шрифтов определяются и включаются в качестве ресурсов автоматически.
::: tip Связанные файлы не рассматриваются как ресурсы ::: tip Связанные файлы не рассматриваются как ресурсы
PDF-файлы или другие документы, на которые есть ссылки в файлах с разметкой, не рассматриваются автоматически как ресурсы. Чтобы сделать связанные файлы доступными, вы должны вручную поместить их в каталог [`public`](#the-public-directory) вашего проекта. PDF-файлы или другие документы, на которые есть ссылки в файлах с разметкой, не рассматриваются автоматически как ресурсы. Чтобы сделать связанные файлы доступными, вы должны вручную поместить их в каталог [`public`](#the-public-directory) вашего проекта.

@ -175,7 +175,7 @@ export default {
} }
``` ```
**Types** **Типы**
```ts ```ts
interface ContentOptions<T = ContentData[]> { interface ContentOptions<T = ContentData[]> {
@ -226,7 +226,7 @@ interface ContentOptions<T = ContentData[]> {
## Загрузчики типизированных данных {#typed-data-loaders} ## Загрузчики типизированных данных {#typed-data-loaders}
При использовании TypeScript вы можете ввести свой загрузчик и экспортировать `data` следующим образом: При использовании TypeScript можно ввести свой загрузчик и экспортировать `data` следующим образом:
```ts ```ts
import { defineLoader } from 'vitepress' import { defineLoader } from 'vitepress'

@ -4,7 +4,7 @@ outline: deep
# Развёртывание вашего сайта VitePress {#deploy-your-vitepress-site} # Развёртывание вашего сайта VitePress {#deploy-your-vitepress-site}
Следующие руководства основаны на некоторых общих предположениях: Следующие инструкции основаны на некоторых общих предположениях:
- Сайт VitePress находится в директории `docs` вашего проекта. - Сайт VitePress находится в директории `docs` вашего проекта.
- Вы используете выходной каталог сборки по умолчанию (`.vitepress/dist`). - Вы используете выходной каталог сборки по умолчанию (`.vitepress/dist`).
@ -19,7 +19,7 @@ outline: deep
} }
``` ```
## Создание и локальное тестирование {#build-and-test-locally} ## Сборка и локальное тестирование {#build-and-test-locally}
1. Выполните эту команду, чтобы собрать документацию: 1. Выполните эту команду, чтобы собрать документацию:
@ -33,9 +33,9 @@ outline: deep
$ npm run docs:preview $ npm run docs:preview
``` ```
Команда `preview` загрузит локальный статический веб-сервер, который будет обслуживать выходной каталог `.vitepress/dist` по адресу `http://localhost:4173`. Вы можете использовать это, чтобы убедиться, что всё выглядит хорошо, прежде чем отправлять в производство. Команда `preview` загрузит локальный статический веб-сервер, который будет обслуживать выходной каталог `.vitepress/dist` по адресу `http://localhost:4173`. Вы можете использовать его для теста, чтобы убедиться, что всё выглядит хорошо, прежде чем отправлять в производство.
3. Вы можете настроить порт сервера, передав `--port` в качестве аргумента. 3. Можно указать порт сервера, передав `--port` в качестве аргумента.
```json ```json
{ {
@ -55,11 +55,11 @@ outline: deep
## Заголовки кэша HTTP {#http-cache-headers} ## Заголовки кэша HTTP {#http-cache-headers}
Если вы контролируете HTTP-заголовки на своем рабочем сервере, вы можете настроить заголовки `cache-control` для достижения лучшей производительности при повторных посещениях. Если вы контролируете HTTP-заголовки на своем рабочем сервере, можно настроить заголовки `cache-control` для достижения лучшей производительности при повторных посещениях.
В производственной сборке используются хэшированные имена файлов для статических ресурсов (JavaScript, CSS и другие импортированные ресурсы, не находящиеся в `public`). Если вы просмотрите предварительную версию с помощью сетевой вкладки devtools вашего браузера, вы увидите файлы типа `app.4f283b18.js`. В производственной сборке используются хэшированные имена файлов для статических ресурсов (JavaScript, CSS и другие импортированные ресурсы, не находящиеся в `public`). Если вы просмотрите предварительную версию с помощью вкладки «Network» («Сеть») инструментов разработчика вашего браузера, вы увидите файлы типа `app.4f283b18.js`.
Этот хэш `4f283b18` генерируется из содержимого этого файла. Один и тот же хэшированный URL гарантированно обслуживает одно и то же содержимое файла — если содержимое меняется, то и URL тоже. Это означает, что вы можете смело использовать самые сильные заголовки кэша для этих файлов. Все такие файлы будут помещены в каталог `assets/` в выходном каталоге, поэтому вы можете настроить для них следующий заголовок: Этот хэш `4f283b18` генерируется из содержимого этого файла. Один и тот же хэшированный URL гарантированно обслуживает одно и то же содержимое файла — если содержимое меняется, то и URL тоже. Это означает, что можно смело использовать самые сильные настройки кэширования для этих файлов. Все такие файлы будут помещены в каталог `assets/` в выходном каталоге, поэтому вы можете настроить для них следующий заголовок:
``` ```
Cache-Control: max-age=31536000,immutable Cache-Control: max-age=31536000,immutable
@ -198,7 +198,7 @@ Cache-Control: max-age=31536000,immutable
### GitLab Pages {#gitlab-pages} ### GitLab Pages {#gitlab-pages}
1. Установите `outDir` в конфигурации VitePress на `../public`. Настройте опцию `base` на `'/<репозиторий>/'`, если вы хотите развернуть ваш проект по адресу на `https://<имя пользователя>.gitlab.io/<репозиторий>/`. 1. Установите значение `../public` для параметра `outDir` в конфигурации VitePress. Настройте опцию `base` на `'/<репозиторий>/'`, если вы хотите развернуть ваш проект по адресу `https://<имя пользователя>.gitlab.io/<репозиторий>/`. Вам не нужна опция `base`, если вы выполняете развёртывание на личном домене, страницах пользователя или группы, или если в GitLab включен параметр «Использовать уникальный домен».
2. Создайте файл с именем `.gitlab-ci.yml` в корне вашего проекта с приведённым ниже содержимым. Это позволит создавать и развёртывать ваш сайт каждый раз, когда вы вносите изменения в его содержимое: 2. Создайте файл с именем `.gitlab-ci.yml` в корне вашего проекта с приведённым ниже содержимым. Это позволит создавать и развёртывать ваш сайт каждый раз, когда вы вносите изменения в его содержимое:

@ -4,7 +4,7 @@ outline: deep
# Расширение темы по умолчанию {#extending-the-default-theme} # Расширение темы по умолчанию {#extending-the-default-theme}
Тема VitePress по умолчанию оптимизирована для документации и может быть настроена по своему усмотрению. Полный список опций можно найти в главе [Настройки темы по умолчанию](../reference/default-theme-config). Тема VitePress по умолчанию оптимизирована для документации и может быть настроена по вашему усмотрению. Полный список опций можно найти в главе [Настройки темы по умолчанию](../reference/default-theme-config).
Однако есть ряд случаев, когда одной лишь конфигурации будет недостаточно. Например: Однако есть ряд случаев, когда одной лишь конфигурации будет недостаточно. Например:
@ -12,7 +12,7 @@ outline: deep
2. Вам нужно изменить экземпляр приложения Vue, например, чтобы зарегистрировать глобальные компоненты; 2. Вам нужно изменить экземпляр приложения Vue, например, чтобы зарегистрировать глобальные компоненты;
3. Вам нужно внедрить пользовательский контент в тему через слоты макета. 3. Вам нужно внедрить пользовательский контент в тему через слоты макета.
Эти расширенные настройки потребуют использования пользовательской темы, которая «расширяет» тема по умолчанию. Эти расширенные настройки потребуют использования пользовательской темы, которая «расширяет» тему по умолчанию.
::: tip СОВЕТ ::: tip СОВЕТ
Прежде чем приступить к работе, обязательно прочитайте главу [Пользовательская тема](./custom-theme), чтобы понять, как работают пользовательские темы. Прежде чем приступить к работе, обязательно прочитайте главу [Пользовательская тема](./custom-theme), чтобы понять, как работают пользовательские темы.
@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* normal text font */ --vp-font-family-mono: --vp-font-family-base: /* normal text font */ --vp-font-family-mono:
/* code font */; /* code font */;
@ -124,7 +124,7 @@ export default {
} satisfies Theme } satisfies Theme
``` ```
Поскольку мы используем Vite, вы также можете использовать [глобальную функцию импорта](https://vitejs.dev/guide/features.html#glob-import) Vite для автоматической регистрации каталога компонентов. Поскольку мы используем Vite, можно применять [глобальную функцию импорта](https://vitejs.dev/guide/features.html#glob-import) Vite для автоматической регистрации каталога компонентов.
## Слоты макета {#layout-slots} ## Слоты макета {#layout-slots}

@ -11,7 +11,7 @@ editLink: true
--- ---
``` ```
Многие параметры конфигурации сайта или темы по умолчанию имеют соответствующие опции в блоке метаданных. Вы можете использовать метаданные, чтобы переопределить определённое поведение только для текущей страницы. Подробности см. в [Справочнике по настройке метаданных](../reference/frontmatter-config). Многие параметры конфигурации сайта или темы по умолчанию имеют соответствующие опции в блоке метаданных. Вы можете использовать метаданные, чтобы переопределить заданное поведение только для текущей страницы. Подробности см. в [Справочнике по настройке метаданных](../reference/frontmatter-config).
Вы также можете определить собственные метаданные, которые будут использоваться в динамических выражениях Vue на странице. Вы также можете определить собственные метаданные, которые будут использоваться в динамических выражениях Vue на странице.

@ -63,7 +63,7 @@ VitePress — это пакет, предназначенный только д
### Мастер настройки {#setup-wizard} ### Мастер настройки {#setup-wizard}
VitePress поставляется с мастером настройки командной строки, который поможет вам создать базовый проект. После установки запустите мастер, запустив его: VitePress поставляется с мастером настройки командной строки, который поможет вам создать базовый проект. После установки запустите мастер, выполнив команду:
::: code-group ::: code-group
@ -133,13 +133,13 @@ export default {
} }
``` ```
Вы также можете настроить поведение темы с помощью опции `themeConfig`. Загляните в главу [Настройка сайта](../reference/site-config) для получения подробной информации обо всех параметрах конфигурации. Вы также можете настроить поведение темы с помощью опции `themeConfig`. Загляните в главу [Конфигурация сайта](../reference/site-config) для получения подробной информации обо всех настраиваемых параметрах.
### Исходные файлы {#source-files} ### Исходные файлы {#source-files}
Файлы Markdown за пределами директории `.vitepress` считаются **исходными файлами**. Файлы Markdown за пределами директории `.vitepress` считаются **исходными файлами**.
VitePress использует **маршрутизацию на основе файлов**: Каждый файл `.md` компилируется в соответствующий файл `.html` с тем же путем. Например, `index.md` будет скомпилирован в `index.html`, и его можно будет посетить по корневому пути `/` результирующего сайта VitePress. VitePress использует **маршрутизацию на основе файлов**: Каждый файл `.md` компилируется в соответствующий файл `.html` с тем же путём. Например, `index.md` будет скомпилирован в `index.html`, и его можно будет посетить по корневому пути `/` результирующего сайта VitePress.
VitePress также предоставляет возможность генерировать чистые URL-адреса, переписывать пути и динамически генерировать страницы. Всё это будет рассмотрено в [Руководстве по маршрутизации](./routing). VitePress также предоставляет возможность генерировать чистые URL-адреса, переписывать пути и динамически генерировать страницы. Всё это будет рассмотрено в [Руководстве по маршрутизации](./routing).
@ -159,7 +159,7 @@ VitePress также предоставляет возможность гене
} }
``` ```
Скрипт `docs:dev` запустит локальный dev-сервер с мгновенными горячими обновлениями. Запустите его с помощью следующей команды: Скрипт `docs:dev` запустит локальный dev-сервер с мгновенными горячими обновлениями. Выполните следующую команду:
::: code-group ::: code-group

@ -210,7 +210,7 @@ console.log('Привет, VitePress!')
::: :::
Кроме того, вы можете установить пользовательские заголовки глобально, добавив следующее содержимое в конфигурацию сайта, полезное, если вы пишете не на английском языке: Кроме того, можно установить пользовательские заголовки глобально, добавив следующее содержимое в конфигурацию сайта, полезное, если вы пишете не на английском языке:
```ts ```ts
// config.ts // config.ts
@ -269,7 +269,7 @@ export default defineConfig({
## Оповещения в стиле GitHub {#github-flavored-alerts} ## Оповещения в стиле GitHub {#github-flavored-alerts}
VitePress также поддерживает [Оповещения в стиле GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) для отображения в виде призывов. Они будут отображаться так же, как и [пользовательские контейнеры](#custom-containers). VitePress также поддерживает [Оповещения в стиле GitHub](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) для отображения в виде вставок. Они будут отображаться так же, как и [пользовательские контейнеры](#custom-containers).
```md ```md
> [!NOTE] > [!NOTE]
@ -305,7 +305,7 @@ VitePress также поддерживает [Оповещения в стил
## Подсветка синтаксиса в блоках кода {#syntax-highlighting-in-code-blocks} ## Подсветка синтаксиса в блоках кода {#syntax-highlighting-in-code-blocks}
VitePress использует [Shiki](https://github.com/shikijs/shiki) для выделения синтаксиса языка в блоках кода Markdown с помощью цветного текста. Shiki поддерживает широкий спектр языков программирования. Всё, что вам нужно сделать, это добавить правильный псевдоним языка к начальным значкам блока кода: VitePress использует [Shiki](https://github.com/shikijs/shiki) для выделения синтаксиса языка в блоках кода Markdown с помощью цветного текста. Shiki поддерживает широкий спектр языков программирования. Всё, что вам нужно сделать, это добавить правильный псевдоним языка к начальным обратным кавычкам блока кода:
**Разметка** **Разметка**
@ -375,7 +375,7 @@ export default {
} }
``` ```
Помимо одной строки, вы можете указать несколько отдельных строк, диапазонов или и то, и другое: Помимо одной строки, можно указать несколько отдельных строк, диапазонов или и то, и другое:
- Диапазоны строк, например: `{5-8}`, `{3-10}`, `{10-17}` - Диапазоны строк, например: `{5-8}`, `{3-10}`, `{10-17}`
- Несколько одиночных строк, например: `{4,7,9}` - Несколько одиночных строк, например: `{4,7,9}`
@ -477,7 +477,7 @@ export default {
## Подсветка различий в блоках кода {#colored-diffs-in-code-blocks} ## Подсветка различий в блоках кода {#colored-diffs-in-code-blocks}
Добавление в строку комментариев `// [!code --]` или `// [!code ++]` создаст diff этой строки, сохраняя цвета блока кода. Добавление в строку комментариев `// [!code --]` или `// [!code ++]` подсветит различие этой строки от другой, сохраняя цвета блока кода.
**Разметка** **Разметка**
@ -553,9 +553,9 @@ export default {
Более подробную информацию см. в секции [`markdown`](../reference/site-config#markdown). Более подробную информацию см. в секции [`markdown`](../reference/site-config#markdown).
Вы можете добавить метки `:line-numbers` / `:no-line-numbers` в ваши ограждённые блоки кода, чтобы переопределить значение, установленное в конфиге. Вы можете добавить метки `:line-numbers` / `:no-line-numbers` в ваши изолированные блоки кода, чтобы переопределить значение, установленное в конфиге.
Вы также можете настроить номер начальной строки, добавив `=` после `:line-numbers`. Например, `:line-numbers=2` означает, что номера строк в блоках кода будут начинаться с `2`. Вы также можете настроить номер начальной строки, добавив `=` после `:line-numbers`. Например, `:line-numbers=2` означает, что нумерация строк в блоках кода будет начинаться с `2`.
**Разметка** **Разметка**
@ -628,7 +628,7 @@ const line4 = 'Строка 4'
<<< @/snippets/snippet.js{2} <<< @/snippets/snippet.js{2}
::: tip СОВЕТ ::: tip СОВЕТ
Значение `@` соответствует корню источника. По умолчанию это корень проекта VitePress, если не настроен `srcDir`. Альтернативно вы также можете импортировать из относительных путей: Значение `@` соответствует корню источника. По умолчанию это корень проекта VitePress, если не настроен параметр `srcDir`. Альтернативно вы также можете импортировать из относительных путей:
```md ```md
<<< ../snippets/snippet.js <<< ../snippets/snippet.js
@ -652,7 +652,7 @@ const line4 = 'Строка 4'
<<< @/snippets/snippet-with-region.js#snippet{1} <<< @/snippets/snippet-with-region.js#snippet{1}
Вы также можете указать язык внутри фигурных скобок (`{}`) следующим образом: Кроме того, можно указать язык внутри фигурных скобок (`{}`) следующим образом:
```md ```md
<<< @/snippets/snippet.cs{c#} <<< @/snippets/snippet.cs{c#}
@ -670,7 +670,7 @@ const line4 = 'Строка 4'
## Группы кодов {#code-groups} ## Группы кодов {#code-groups}
Вы можете сгруппировать несколько блоков кода следующим образом: Можно сгруппировать несколько блоков кода следующим образом:
**Разметка** **Разметка**

@ -6,7 +6,7 @@
Однако из-за отсутствия навигации SPA межстраничные ссылки будут приводить к полной перезагрузке страницы. После загрузки навигация в режиме MPA будет не такой мгновенной, как в режиме SPA. Однако из-за отсутствия навигации SPA межстраничные ссылки будут приводить к полной перезагрузке страницы. После загрузки навигация в режиме MPA будет не такой мгновенной, как в режиме SPA.
Также обратите внимание, что «no-JS-by-default» («без JS по умолчанию») означает, что вы используете Vue исключительно как серверный язык шаблонов. Никаких обработчиков событий в браузере не будет, поэтому интерактивности не будет. Чтобы загрузить JavaScript со стороны клиента, вам нужно использовать специальный тег `<script client>`: Также обратите внимание, что «no-JS-by-default» («без JS по умолчанию») означает, что вы используете Vue исключительно как серверный язык шаблонов. Никаких обработчиков событий в браузере не будет, как и интерактивности. Чтобы загрузить JavaScript со стороны клиента, вам нужно использовать специальный тег `<script client>`:
```html ```html
<script client> <script client>

@ -188,7 +188,7 @@ export default {
} }
``` ```
Опция `rewrites` также поддерживает динамические параметры маршрута. В приведенном выше примере, если у вас много пакетов, перечислять все пути было бы скучно. Учитывая, что все они имеют одинаковую структуру файлов, вы можете упростить конфигурацию следующим образом: Опция `rewrites` также поддерживает динамические параметры маршрута. В приведённом выше примере, если у вас много пакетов, перечислять все пути было бы скучно. Учитывая, что все они имеют одинаковую структуру файлов, можно упростить конфигурацию следующим образом:
```ts ```ts
export default { export default {
@ -345,7 +345,7 @@ console.log(params.value)
### Рендеринг необработанного содержимого {#rendering-raw-content} ### Рендеринг необработанного содержимого {#rendering-raw-content}
Параметры, передаваемые странице, будут сериализованы в полезной нагрузке клиентского JavaScript, поэтому вам следует избегать передачи в параметрах больших объемов данных, например, необработанного Markdown или HTML-контента, полученного из удаленной CMS. Параметры, передаваемые странице, будут сериализованы в полезной нагрузке клиентского JavaScript, поэтому вам следует избегать передачи в параметрах больших объемов данных, например, необработанного Markdown или HTML-контента, полученного из удалённой CMS.
Вместо этого вы можете передавать такое содержимое на каждую страницу с помощью свойства `content` каждого объекта path: Вместо этого вы можете передавать такое содержимое на каждую страницу с помощью свойства `content` каждого объекта path:

@ -123,7 +123,7 @@ import CustomComponent from '../components/CustomComponent.vue'
Если компонент будет использоваться на большинстве страниц, его можно зарегистрировать глобально, настроив экземпляр приложения Vue. Пример смотрите в соответствующей главе [Расширение темы по умолчанию](./extending-default-theme#registering-global-components). Если компонент будет использоваться на большинстве страниц, его можно зарегистрировать глобально, настроив экземпляр приложения Vue. Пример смотрите в соответствующей главе [Расширение темы по умолчанию](./extending-default-theme#registering-global-components).
::: warning ВАЖНО ::: warning ВАЖНО
Убедитесь, что имя пользовательского компонента содержит дефис или написано в PascalCase. В противном случае он будет рассматриваться как встроенный элемент и заключен в тег `<p>`, что приведет к несоответствию гидратации, поскольку `<p>` не позволяет размещать внутри него блочные элементы. Убедитесь, что имя пользовательского компонента содержит дефис или написано в PascalCase. В противном случае он будет рассматриваться как встроенный элемент и заключен в тег `<p>`, что приведёт к несоответствию гидратации, поскольку `<p>` не позволяет размещать внутри него блочные элементы.
::: :::
### Использование компонентов в заголовках <ComponentInHeader /> {#using-components-in-headers} ### Использование компонентов в заголовках <ComponentInHeader /> {#using-components-in-headers}
@ -177,7 +177,7 @@ HTML, обёрнутый `<code>`, будет отображаться как е
## Unescape в блоках кода {#unescape-in-code-blocks} ## Unescape в блоках кода {#unescape-in-code-blocks}
По умолчанию все изолированные блоки кода автоматически оборачиваются `v-pre`, поэтому внутри них не будет обрабатываться синтаксис Vue. Чтобы включить интерполяцию в стиле Vue внутри фигурных скобок, вы можете добавить к языку суффикс `-vue`, например `js-vue`: По умолчанию все изолированные блоки кода автоматически оборачиваются `v-pre`, поэтому внутри них не будет обрабатываться синтаксис Vue. Чтобы включить интерполяцию в стиле Vue внутри фигурных скобок, можно добавить к языку суффикс `-vue`, например `js-vue`:
**Разметка** **Разметка**

@ -1,6 +1,6 @@
# Carbon Ads {#carbon-ads} # Carbon Ads {#carbon-ads}
В VitePress встроена встроенная поддержка [Carbon Ads](https://www.carbonads.net/). Определив в конфиге учётные данные Carbon Ads, VitePress будет отображать рекламу на странице. VitePress имеет встроенную поддержку [Carbon Ads](https://www.carbonads.net/). Определив в конфиге учётные данные Carbon Ads, VitePress будет отображать рекламу на странице.
```js ```js
export default { export default {
@ -13,10 +13,10 @@ export default {
} }
``` ```
Эти значения используются для вызова сценария carbon CDN, как показано ниже: Эти значения используются для вызова сценария Carbon CDN, как показано ниже:
```js ```js
;`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}` ;`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}`
``` ```
Чтобы узнать больше о конфигурации Carbon Ads, посетите [веб-сайт Carbon Ads](https://www.carbonads.net/). Чтобы узнать больше о настройке Carbon Ads, посетите [веб-сайт Carbon Ads](https://www.carbonads.net/).

@ -299,7 +299,7 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: 'Documentation' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',

@ -161,6 +161,12 @@ aside: false
Уровни заголовков в оглавлении для отображения на странице. Это то же самое, что и [config.themeConfig.outline.level](./default-theme-config#outline), и оно переопределяет значение, установленное в конфигурации сайта. Уровни заголовков в оглавлении для отображения на странице. Это то же самое, что и [config.themeConfig.outline.level](./default-theme-config#outline), и оно переопределяет значение, установленное в конфигурации сайта.
```yaml
---
outline: [2, 4]
---
```
### lastUpdated {#lastupdated} ### lastUpdated {#lastupdated}
- Тип: `boolean | Date` - Тип: `boolean | Date`

@ -55,7 +55,7 @@ export default DefaultTheme
``` ```
```css ```css
/* .vitepress/theme/custom.css */ /* .vitepress/theme/my-fonts.css */
:root { :root {
--vp-font-family-base: /* normal text font */ --vp-font-family-base: /* normal text font */
--vp-font-family-mono: /* code font */ --vp-font-family-mono: /* code font */

@ -80,7 +80,7 @@ interface HeroAction {
### 自定义 name 的颜色 {#customizing-the-name-color} ### 自定义 name 的颜色 {#customizing-the-name-color}
VitePress 通过 (`--vp-c-brand-1`) 设置 `name` 的颜色 .但是,可以通过覆盖 `--vp-home-hero-name-color` 变量来自定义此颜色。 VitePress 通过 (`--vp-c-brand-1`) 设置 `name` 的颜色但是,可以通过覆盖 `--vp-home-hero-name-color` 变量来自定义此颜色。
```css ```css
:root { :root {

@ -159,3 +159,57 @@ export default {
## 社交链接 {#social-links} ## 社交链接 {#social-links}
参考 [`socialLinks`](./default-theme-config#sociallinks)。 参考 [`socialLinks`](./default-theme-config#sociallinks)。
## 自定义组件
你可以通过使用 `component` 选项在导航栏中包含自定义组件。`component` 键对应的值应为 Vue 组件名,并且必须使用 [Theme.enhanceApp](../guide/custom-theme#theme-interface) 全局注册。
```js
// .vitepress/config.js
export default {
themeConfig: {
nav: [
{
text: 'My Menu',
items: [
{
component: 'MyCustomComponent',
// 可选的 props 传递给组件
props: {
title: 'My Custom Component'
}
}
]
},
{
component: 'AnotherCustomComponent'
}
]
}
}
```
然后,你需要全局注册该组件:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyCustomComponent from './components/MyCustomComponent.vue'
import AnotherCustomComponent from './components/AnotherCustomComponent.vue'
/** @type {import('vitepress').Theme} */
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('MyCustomComponent', MyCustomComponent)
app.component('AnotherCustomComponent', AnotherCustomComponent)
}
}
```
你的组件将在导航栏中渲染。 VitePress 会向组件提供以下额外的 props
- `screenMenu`:一个可选的布尔值,指示组件是否在移动导航菜单内
你可以在端到端测试中查看示例 [这里](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)。

@ -289,7 +289,7 @@ new Crawler({
lvl1: '.content h1', lvl1: '.content h1',
content: '.content p, .content li', content: '.content p, .content li',
lvl0: { lvl0: {
selectors: '', selectors: 'section.has-active div h2',
defaultValue: 'Documentation' defaultValue: 'Documentation'
}, },
lvl2: '.content h2', lvl2: '.content h2',

@ -102,6 +102,10 @@ interface Router {
* 在页面组件加载前history 状态更新后)调用。返回 `false` 表示取消导航 * 在页面组件加载前history 状态更新后)调用。返回 `false` 表示取消导航
*/ */
onBeforePageLoad?: (to: string) => Awaitable<void | boolean> onBeforePageLoad?: (to: string) => Awaitable<void | boolean>
/**
* 在页面组件加载后(页面组件实际更新前)调用
*/
onAfterPageLoad?: (to: string) => Awaitable<void>
/** /**
* 在路由更改后调用 * 在路由更改后调用
*/ */

@ -333,7 +333,7 @@ export default {
- 类型:`string` - 类型:`string`
- 默认值: `/` - 默认值: `/`
站点将部署到的 base URL。如果计划在子路径例如 GitHub 页面下部署站点,则需要设置此项。如果计划将站点部署到 `https://foo.github.io/bar/`,那么应该将 `base` 设置为 `'/bar/'`。它应该始终以 `/` 开头和结尾。 站点将部署到的 base URL。如果计划在子路径例如 GitHub 页面下部署站点,则需要设置此项。如果计划将站点部署到 `https://foo.github.io/bar/`,那么应该将 `base` 设置为 `'/bar/'`。它应该始终以 `/` 开头和结尾。
base 会自动添加到其他选项中以 `/` 开头的所有 URL 前面,因此只需指定一次。 base 会自动添加到其他选项中以 `/` 开头的所有 URL 前面,因此只需指定一次。

@ -1,6 +1,6 @@
{ {
"name": "vitepress", "name": "vitepress",
"version": "1.3.1", "version": "1.4.0",
"description": "Vite & Vue powered static site generator", "description": "Vite & Vue powered static site generator",
"keywords": [ "keywords": [
"vite", "vite",
@ -98,22 +98,23 @@
"*": "prettier --write --ignore-unknown" "*": "prettier --write --ignore-unknown"
}, },
"dependencies": { "dependencies": {
"@docsearch/css": "^3.6.0", "@docsearch/css": "^3.6.2",
"@docsearch/js": "^3.6.0", "@docsearch/js": "^3.6.2",
"@shikijs/core": "^1.10.3", "@shikijs/core": "^1.22.0",
"@shikijs/transformers": "^1.10.3", "@shikijs/transformers": "^1.22.0",
"@types/markdown-it": "^14.1.1", "@shikijs/types": "^1.22.0",
"@vitejs/plugin-vue": "^5.0.5", "@types/markdown-it": "^14.1.2",
"@vue/devtools-api": "^7.3.5", "@vitejs/plugin-vue": "^5.1.4",
"@vue/shared": "^3.4.31", "@vue/devtools-api": "^7.4.6",
"@vueuse/core": "^10.11.0", "@vue/shared": "^3.5.11",
"@vueuse/integrations": "^10.11.0", "@vueuse/core": "^11.1.0",
"focus-trap": "^7.5.4", "@vueuse/integrations": "^11.1.0",
"focus-trap": "^7.6.0",
"mark.js": "8.11.1", "mark.js": "8.11.1",
"minisearch": "^7.0.0", "minisearch": "^7.1.0",
"shiki": "^1.10.3", "shiki": "^1.22.0",
"vite": "^5.3.3", "vite": "^5.4.8",
"vue": "^3.4.31" "vue": "^3.5.11"
}, },
"devDependencies": { "devDependencies": {
"@clack/prompts": "^0.7.0", "@clack/prompts": "^0.7.0",
@ -124,12 +125,12 @@
"@mdit-vue/plugin-title": "^2.1.3", "@mdit-vue/plugin-title": "^2.1.3",
"@mdit-vue/plugin-toc": "^2.1.3", "@mdit-vue/plugin-toc": "^2.1.3",
"@mdit-vue/shared": "^2.1.3", "@mdit-vue/shared": "^2.1.3",
"@polka/compression": "^1.0.0-next.25", "@polka/compression": "^1.0.0-next.28",
"@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-commonjs": "^28.0.0",
"@rollup/plugin-json": "^6.1.0", "@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-replace": "^6.0.1",
"@types/cross-spawn": "^6.0.6", "@types/cross-spawn": "^6.0.6",
"@types/debug": "^4.1.12", "@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
@ -140,55 +141,55 @@
"@types/markdown-it-emoji": "^3.0.1", "@types/markdown-it-emoji": "^3.0.1",
"@types/micromatch": "^4.0.9", "@types/micromatch": "^4.0.9",
"@types/minimist": "^1.2.5", "@types/minimist": "^1.2.5",
"@types/node": "^20.14.10", "@types/node": "^22.7.4",
"@types/postcss-prefix-selector": "^1.16.3", "@types/postcss-prefix-selector": "^1.16.3",
"@types/prompts": "^2.4.9", "@types/prompts": "^2.4.9",
"chokidar": "^3.6.0", "chokidar": "^3.6.0",
"conventional-changelog-cli": "^5.0.0", "conventional-changelog-cli": "^5.0.0",
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"debug": "^4.3.5", "debug": "^4.3.7",
"esbuild": "^0.23.0", "esbuild": "^0.24.0",
"execa": "^9.3.0", "execa": "^9.4.0",
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"get-port": "^7.1.0", "get-port": "^7.1.0",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"lint-staged": "^15.2.7", "lint-staged": "^15.2.10",
"lodash.template": "^4.5.0", "lodash.template": "^4.5.0",
"lru-cache": "^11.0.0", "lru-cache": "^11.0.1",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
"markdown-it-anchor": "^9.0.1", "markdown-it-anchor": "^9.2.0",
"markdown-it-attrs": "^4.1.6", "markdown-it-attrs": "^4.2.0",
"markdown-it-container": "^4.0.0", "markdown-it-container": "^4.0.0",
"markdown-it-emoji": "^3.0.0", "markdown-it-emoji": "^3.0.0",
"markdown-it-mathjax3": "^4.3.2", "markdown-it-mathjax3": "^4.3.2",
"micromatch": "^4.0.7", "micromatch": "^4.0.8",
"minimist": "^1.2.8", "minimist": "^1.2.8",
"nanoid": "^5.0.7", "nanoid": "^5.0.7",
"ora": "^8.0.1", "ora": "^8.1.0",
"p-map": "^7.0.2", "p-map": "^7.0.2",
"path-to-regexp": "^6.2.2", "path-to-regexp": "^6.3.0",
"picocolors": "^1.0.1", "picocolors": "^1.1.0",
"pkg-dir": "^8.0.0", "pkg-dir": "^8.0.0",
"playwright-chromium": "^1.45.1", "playwright-chromium": "^1.47.2",
"polka": "^1.0.0-next.25", "polka": "^1.0.0-next.28",
"postcss-prefix-selector": "^1.16.1", "postcss-prefix-selector": "^2.0.0",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"punycode": "^2.3.1", "punycode": "^2.3.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"rollup": "^4.18.1", "rollup": "^4.24.0",
"rollup-plugin-dts": "^6.1.1", "rollup-plugin-dts": "^6.1.1",
"rollup-plugin-esbuild": "^6.1.1", "rollup-plugin-esbuild": "^6.1.1",
"semver": "^7.6.2", "semver": "^7.6.3",
"simple-git-hooks": "^2.11.1", "simple-git-hooks": "^2.11.1",
"sirv": "^2.0.4", "sirv": "^2.0.4",
"sitemap": "^8.0.0", "sitemap": "^8.0.0",
"supports-color": "^9.4.0", "supports-color": "^9.4.0",
"typescript": "^5.5.3", "tinyglobby": "^0.2.9",
"vitest": "^2.0.2", "typescript": "^5.6.2",
"vue-tsc": "^2.0.26", "vitest": "^2.1.2",
"wait-on": "^7.2.0" "vue-tsc": "^2.1.6",
"wait-on": "^8.0.1"
}, },
"peerDependencies": { "peerDependencies": {
"markdown-it-mathjax3": "^4", "markdown-it-mathjax3": "^4",
@ -202,7 +203,7 @@
"optional": true "optional": true
} }
}, },
"packageManager": "pnpm@9.5.0", "packageManager": "pnpm@9.12.0",
"pnpm": { "pnpm": {
"peerDependencyRules": { "peerDependencyRules": {
"ignoreMissing": [ "ignoreMissing": [

File diff suppressed because it is too large Load Diff

@ -1,11 +1,11 @@
import { copy } from 'fs-extra' import { copy } from 'fs-extra'
import fg from 'fast-glob' import { globSync } from 'tinyglobby'
function toDest(file) { function toDest(file) {
return file.replace(/^src\//, 'dist/') return file.replace(/^src\//, 'dist/')
} }
fg.sync('src/client/**').forEach((file) => { globSync(['src/client/**']).forEach((file) => {
if (/(\.ts|tsconfig\.json)$/.test(file)) return if (/(\.ts|tsconfig\.json)$/.test(file)) return
copy(file, toDest(file)) copy(file, toDest(file))
}) })

@ -1,7 +1,7 @@
import { copy } from 'fs-extra' import { copy } from 'fs-extra'
import fg from 'fast-glob' import { globSync } from 'tinyglobby'
fg.sync('src/shared/**/*.ts').forEach(async (file) => { globSync(['src/shared/**/*.ts']).forEach(async (file) => {
await Promise.all([ await Promise.all([
copy(file, file.replace(/^src\/shared\//, 'src/node/')), copy(file, file.replace(/^src\/shared\//, 'src/node/')),
copy(file, file.replace(/^src\/shared\//, 'src/client/')) copy(file, file.replace(/^src\/shared\//, 'src/client/'))

@ -1,4 +1,4 @@
import { defineComponent, h } from 'vue' import { defineComponent, h, watch } from 'vue'
import { useData, useRoute } from 'vitepress' import { useData, useRoute } from 'vitepress'
import { contentUpdatedCallbacks } from '../utils' import { contentUpdatedCallbacks } from '../utils'
@ -11,7 +11,8 @@ export const Content = defineComponent({
}, },
setup(props) { setup(props) {
const route = useRoute() const route = useRoute()
const { site } = useData() const { frontmatter, site } = useData()
watch(frontmatter, runCbs, { deep: true, flush: 'post' })
return () => return () =>
h( h(
props.as, props.as,

@ -87,7 +87,7 @@ function createHeadElement([tag, attrs, innerHTML]: HeadConfig) {
if (innerHTML) { if (innerHTML) {
el.innerHTML = innerHTML el.innerHTML = innerHTML
} }
if (tag === 'script' && !attrs.async) { if (tag === 'script' && attrs.async == null) {
// async is true by default for dynamically created scripts // async is true by default for dynamically created scripts
;(el as HTMLScriptElement).async = false ;(el as HTMLScriptElement).async = false
} }

@ -1,5 +1,5 @@
import siteData from '@siteData' import siteData from '@siteData'
import { useDark } from '@vueuse/core' import { useDark, usePreferredDark } from '@vueuse/core'
import { import {
computed, computed,
inject, inject,
@ -79,13 +79,15 @@ export function initData(route: Route): VitePressData {
const isDark = const isDark =
appearance === 'force-dark' appearance === 'force-dark'
? ref(true) ? ref(true)
: appearance : appearance === 'force-auto'
? useDark({ ? usePreferredDark()
storageKey: APPEARANCE_KEY, : appearance
initialValue: () => (appearance === 'dark' ? 'dark' : 'auto'), ? useDark({
...(typeof appearance === 'object' ? appearance : {}) storageKey: APPEARANCE_KEY,
}) initialValue: () => (appearance === 'dark' ? 'dark' : 'auto'),
: ref(false) ...(typeof appearance === 'object' ? appearance : {})
})
: ref(false)
const hashRef = ref(inBrowser ? location.hash : '') const hashRef = ref(inBrowser ? location.hash : '')

@ -150,8 +150,6 @@ function newRouter(): Router {
url.hash url.hash
return import(/*@vite-ignore*/ path) return import(/*@vite-ignore*/ path)
}) })
} else if (import.meta.env.SSR) {
pageModule = import(/*@vite-ignore*/ `${pageFilePath}?t=${Date.now()}`)
} else { } else {
pageModule = import(/*@vite-ignore*/ pageFilePath) pageModule = import(/*@vite-ignore*/ pageFilePath)
} }

@ -29,6 +29,10 @@ export interface Router {
* updated). Return `false` to cancel the navigation. * updated). Return `false` to cancel the navigation.
*/ */
onBeforePageLoad?: (to: string) => Awaitable<void | boolean> onBeforePageLoad?: (to: string) => Awaitable<void | boolean>
/**
* Called after the page component is loaded (before the page component is updated).
*/
onAfterPageLoad?: (to: string) => Awaitable<void>
/** /**
* Called after the route changes. * Called after the route changes.
*/ */
@ -94,6 +98,8 @@ export function createRouter(
throw new Error(`Invalid route component: ${comp}`) throw new Error(`Invalid route component: ${comp}`)
} }
await router.onAfterPageLoad?.(href)
route.path = inBrowser ? pendingPath : withBase(pendingPath) route.path = inBrowser ? pendingPath : withBase(pendingPath)
route.component = markRaw(comp) route.component = markRaw(comp)
route.data = import.meta.env.PROD route.data = import.meta.env.PROD

@ -22,7 +22,7 @@ const isExternal = computed(
) )
const component = computed(() => { const component = computed(() => {
return props.tag || props.href ? 'a' : 'button' return props.tag || (props.href ? 'a' : 'button')
}) })
</script> </script>

@ -78,6 +78,12 @@ function onBlur() {
color: var(--vp-c-brand-2); color: var(--vp-c-brand-2);
} }
.button[aria-expanded="false"] + .menu {
opacity: 0;
visibility: hidden;
transform: translateY(0);
}
.VPFlyout:hover .menu, .VPFlyout:hover .menu,
.button[aria-expanded="true"] + .menu { .button[aria-expanded="true"] + .menu {
opacity: 1; opacity: 1;
@ -85,12 +91,6 @@ function onBlur() {
transform: translateY(0); transform: translateY(0);
} }
.button[aria-expanded="false"] + .menu {
opacity: 0;
visibility: hidden;
transform: translateY(0);
}
.button { .button {
display: flex; display: flex;
align-items: center; align-items: center;

@ -13,7 +13,7 @@ export type MenuItem = Omit<Header, 'slug' | 'children'> & {
children?: MenuItem[] children?: MenuItem[]
} }
export function resolveTitle(theme: DefaultTheme.Config) { export function resolveTitle(theme: DefaultTheme.Config): string {
return ( return (
(typeof theme.outline === 'object' && (typeof theme.outline === 'object' &&
!Array.isArray(theme.outline) && !Array.isArray(theme.outline) &&
@ -23,7 +23,7 @@ export function resolveTitle(theme: DefaultTheme.Config) {
) )
} }
export function getHeaders(range: DefaultTheme.Config['outline']) { export function getHeaders(range: DefaultTheme.Config['outline']): MenuItem[] {
const headers = [ const headers = [
...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)') ...document.querySelectorAll('.VPDoc :where(h1,h2,h3,h4,h5,h6)')
] ]
@ -80,38 +80,13 @@ export function resolveHeaders(
? [2, 6] ? [2, 6]
: levelsRange : levelsRange
headers = headers.filter((h) => h.level >= high && h.level <= low) return buildTree(headers, high, low)
// clear previous caches
resolvedHeaders.length = 0
// update global header list for active link rendering
for (const { element, link } of headers) {
resolvedHeaders.push({ element, link })
}
const ret: MenuItem[] = []
outer: for (let i = 0; i < headers.length; i++) {
const cur = headers[i]
if (i === 0) {
ret.push(cur)
} else {
for (let j = i - 1; j >= 0; j--) {
const prev = headers[j]
if (prev.level < cur.level) {
;(prev.children || (prev.children = [])).push(cur)
continue outer
}
}
ret.push(cur)
}
}
return ret
} }
export function useActiveAnchor( export function useActiveAnchor(
container: Ref<HTMLElement>, container: Ref<HTMLElement>,
marker: Ref<HTMLElement> marker: Ref<HTMLElement>
) { ): void {
const { isAsideEnabled } = useAside() const { isAsideEnabled } = useAside()
const onScroll = throttleAndDebounce(setActiveLink, 100) const onScroll = throttleAndDebounce(setActiveLink, 100)
@ -221,3 +196,38 @@ function getAbsoluteTop(element: HTMLElement): number {
} }
return offsetTop return offsetTop
} }
function buildTree(data: MenuItem[], min: number, max: number): MenuItem[] {
resolvedHeaders.length = 0
const result: MenuItem[] = []
const stack: (MenuItem | { level: number; shouldIgnore: true })[] = []
data.forEach((item) => {
const node = { ...item, children: [] }
let parent = stack[stack.length - 1]
while (parent && parent.level >= node.level) {
stack.pop()
parent = stack[stack.length - 1]
}
if (
node.element.classList.contains('ignore-header') ||
(parent && 'shouldIgnore' in parent)
) {
stack.push({ level: node.level, shouldIgnore: true })
return
}
if (node.level > max || node.level < min) return
resolvedHeaders.push({ element: node.element, link: node.link })
if (parent) parent.children!.push(node)
else result.push(node)
stack.push(node)
})
return result
}

@ -1,9 +1,5 @@
/* webfont-marker-begin */ /* webfont-marker-begin */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
html body {
font-synthesis: style;
}
/* webfont-marker-end */ /* webfont-marker-end */
@font-face { @font-face {

@ -19,7 +19,10 @@ export { default as VPHomeContent } from './components/VPHomeContent.vue'
export { default as VPHomeHero } from './components/VPHomeHero.vue' export { default as VPHomeHero } from './components/VPHomeHero.vue'
export { default as VPHomeFeatures } from './components/VPHomeFeatures.vue' export { default as VPHomeFeatures } from './components/VPHomeFeatures.vue'
export { default as VPHomeSponsors } from './components/VPHomeSponsors.vue' export { default as VPHomeSponsors } from './components/VPHomeSponsors.vue'
export { default as VPLink } from './components/VPLink.vue'
export { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue' export { default as VPDocAsideSponsors } from './components/VPDocAsideSponsors.vue'
export { default as VPSocialLink } from './components/VPSocialLink.vue'
export { default as VPSocialLinks } from './components/VPSocialLinks.vue'
export { default as VPSponsors } from './components/VPSponsors.vue' export { default as VPSponsors } from './components/VPSponsors.vue'
export { default as VPTeamPage } from './components/VPTeamPage.vue' export { default as VPTeamPage } from './components/VPTeamPage.vue'
export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue' export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue'

@ -5,7 +5,7 @@
"outDir": "../../dist/client", "outDir": "../../dist/client",
"declaration": true, "declaration": true,
"declarationDir": "../../dist/client-types", "declarationDir": "../../dist/client-types",
"types": ["vite/client"], "types": ["vite/client", "@types/node"],
"paths": { "paths": {
"vitepress": ["index.ts"], "vitepress": ["index.ts"],
"vitepress/theme": ["../../theme.d.ts"] "vitepress/theme": ["../../theme.d.ts"]

@ -52,9 +52,7 @@ export async function build(
} }
const entryPath = path.join(siteConfig.tempDir, 'app.js') const entryPath = path.join(siteConfig.tempDir, 'app.js')
const { render } = await import( const { render } = await import(pathToFileURL(entryPath).href)
pathToFileURL(entryPath).toString() + '?t=' + Date.now()
)
await task('rendering pages', async () => { await task('rendering pages', async () => {
const appChunk = const appChunk =

@ -52,11 +52,7 @@ export async function renderPage(
try { try {
// resolve page data so we can render head tags // resolve page data so we can render head tags
const { __pageData } = await import( const { __pageData } = await import(
pathToFileURL( pathToFileURL(path.join(config.tempDir, pageServerJsFileName)).href
path.join(config.tempDir, pageServerJsFileName)
).toString() +
'?t=' +
Date.now()
) )
pageData = __pageData pageData = __pageData
} catch (e) { } catch (e) {

@ -1,6 +1,6 @@
import fs from 'fs-extra' import fs from 'fs-extra'
import path from 'path' import path from 'path'
import glob from 'fast-glob' import { glob, type GlobOptions } from 'tinyglobby'
import type { SiteConfig } from './config' import type { SiteConfig } from './config'
import matter from 'gray-matter' import matter from 'gray-matter'
import { normalizePath } from 'vite' import { normalizePath } from 'vite'
@ -54,11 +54,11 @@ export interface ContentOptions<T = ContentData[]> {
transform?: (data: ContentData[]) => T | Promise<T> transform?: (data: ContentData[]) => T | Promise<T>
/** /**
* Options to pass to `fast-glob`. * Options to pass to `tinyglobby`.
* You'll need to manually specify `node_modules` and `dist` in * You'll need to manually specify `node_modules` and `dist` in
* `globOptions.ignore` if you've overridden it. * `globOptions.ignore` if you've overridden it.
*/ */
globOptions?: glob.Options globOptions?: GlobOptions
} }
export interface ContentData { export interface ContentData {
@ -118,6 +118,7 @@ export function createContentLoader<T = ContentData[]>(
files = ( files = (
await glob(pattern, { await glob(pattern, {
ignore: ['**/node_modules/**', '**/dist/**'], ignore: ['**/node_modules/**', '**/dist/**'],
expandDirectories: false,
...globOptions ...globOptions
}) })
).sort() ).sort()

@ -19,13 +19,12 @@ import MarkdownIt from 'markdown-it'
import anchorPlugin from 'markdown-it-anchor' import anchorPlugin from 'markdown-it-anchor'
import attrsPlugin from 'markdown-it-attrs' import attrsPlugin from 'markdown-it-attrs'
import { full as emojiPlugin } from 'markdown-it-emoji' import { full as emojiPlugin } from 'markdown-it-emoji'
import type { BuiltinTheme, Highlighter } from 'shiki'
import type { import type {
BuiltinTheme,
Highlighter,
LanguageInput, LanguageInput,
ShikiTransformer, ShikiTransformer,
ThemeRegistrationAny ThemeRegistrationAny
} from 'shiki' } from '@shikijs/types'
import type { Logger } from 'vite' import type { Logger } from 'vite'
import { containerPlugin, type ContainerOptions } from './plugins/containers' import { containerPlugin, type ContainerOptions } from './plugins/containers'
import { gitHubAlertsPlugin } from './plugins/githubAlerts' import { gitHubAlertsPlugin } from './plugins/githubAlerts'

@ -48,7 +48,7 @@ export const containerPlugin = (
render: (tokens: Token[], idx: number) => render: (tokens: Token[], idx: number) =>
tokens[idx].nesting === 1 ? `<div class="vp-raw">\n` : `</div>\n` tokens[idx].nesting === 1 ? `<div class="vp-raw">\n` : `</div>\n`
}) })
.use(...createCodeGroup(options)) .use(...createCodeGroup(options, md))
} }
type ContainerArgs = [typeof container, string, { render: RenderRule }] type ContainerArgs = [typeof container, string, { render: RenderRule }]
@ -79,7 +79,7 @@ function createContainer(
] ]
} }
function createCodeGroup(options: Options): ContainerArgs { function createCodeGroup(options: Options, md: MarkdownIt): ContainerArgs {
return [ return [
container, container,
'code-group', 'code-group',
@ -111,7 +111,7 @@ function createCodeGroup(options: Options): ContainerArgs {
if (title) { if (title) {
const id = nanoid(7) const id = nanoid(7)
tabs += `<input type="radio" name="group-${name}" id="tab-${id}" ${checked}><label for="tab-${id}">${title}</label>` tabs += `<input type="radio" name="group-${name}" id="tab-${id}" ${checked}><label data-title="${md.utils.escapeHtml(title)}" for="tab-${id}">${title}</label>`
if (checked && !isHtml) tokens[i].info += ' active' if (checked && !isHtml) tokens[i].info += ' active'
checked = '' checked = ''

@ -90,7 +90,7 @@ export async function highlight(
} }
] ]
const vueRE = /-vue$/ const vueRE = /-vue(?=:|$)/
const lineNoStartRE = /=(\d*)/ const lineNoStartRE = /=(\d*)/
const lineNoRE = /:(no-)?line-numbers(=\d*)?$/ const lineNoRE = /:(no-)?line-numbers(=\d*)?$/
const mustacheRE = /\{\{.*?\}\}/g const mustacheRE = /\{\{.*?\}\}/g

@ -16,7 +16,7 @@ import type { MarkdownEnv } from '../../shared'
* captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]'] * captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]']
*/ */
export const rawPathRegexp = export const rawPathRegexp =
/^(.+?(?:(?:\.([a-z0-9]+))?))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/ /^(.+?(?:(?:\.([a-z0-9]+))?))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)? ?(\S+)?}))? ?(?:\[(.+)\])?$/
export function rawPathToToken(rawPath: string) { export function rawPathToToken(rawPath: string) {
const [ const [
@ -25,12 +25,13 @@ export function rawPathToToken(rawPath: string) {
region = '', region = '',
lines = '', lines = '',
lang = '', lang = '',
attrs = '',
rawTitle = '' rawTitle = ''
] = (rawPathRegexp.exec(rawPath) || []).slice(1) ] = (rawPathRegexp.exec(rawPath) || []).slice(1)
const title = rawTitle || filepath.split('/').pop() || '' const title = rawTitle || filepath.split('/').pop() || ''
return { filepath, extension, region, lines, lang, title } return { filepath, extension, region, lines, lang, attrs, title }
} }
export function dedent(text: string): string { export function dedent(text: string): string {
@ -126,7 +127,7 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
.replace(/^@/, srcDir) .replace(/^@/, srcDir)
.trim() .trim()
const { filepath, extension, region, lines, lang, title } = const { filepath, extension, region, lines, lang, attrs, title } =
rawPathToToken(rawPath) rawPathToToken(rawPath)
state.line = startLine + 1 state.line = startLine + 1
@ -134,7 +135,7 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
const token = state.push('fence', 'code', 0) const token = state.push('fence', 'code', 0)
token.info = `${lang || extension}${lines ? `{${lines}}` : ''}${ token.info = `${lang || extension}${lines ? `{${lines}}` : ''}${
title ? `[${title}]` : '' title ? `[${title}]` : ''
}` } ${attrs ?? ''}`
const { realPath, path: _path } = state.env as MarkdownEnv const { realPath, path: _path } = state.env as MarkdownEnv
const resolvedPath = path.resolve(path.dirname(realPath ?? _path), filepath) const resolvedPath = path.resolve(path.dirname(realPath ?? _path), filepath)

@ -57,21 +57,33 @@ export async function createMarkdownToVueRenderFn(
base, base,
siteConfig?.logger siteConfig?.logger
) )
pages = pages.map((p) => slash(p.replace(/\.md$/, ''))) pages = pages.map((p) => slash(p.replace(/\.md$/, '')))
const dynamicRoutes = new Map(
siteConfig?.dynamicRoutes?.routes.map((r) => [
r.fullPath,
slash(path.join(srcDir, r.route))
]) || []
)
const rewrites = new Map(
Object.entries(siteConfig?.rewrites.map || {}).map(([key, value]) => [
slash(path.join(srcDir, key)),
slash(path.join(srcDir, value!))
]) || []
)
return async ( return async (
src: string, src: string,
file: string, file: string,
publicDir: string publicDir: string
): Promise<MarkdownCompileResult> => { ): Promise<MarkdownCompileResult> => {
const fileOrig = file const fileOrig = dynamicRoutes.get(file) || file
const alias = file = rewrites.get(file) || file
siteConfig?.rewrites.map[file] || // virtual dynamic path file
siteConfig?.rewrites.map[file.slice(srcDir.length + 1)]
file = alias ? path.join(srcDir, alias) : file
const relativePath = slash(path.relative(srcDir, file)) const relativePath = slash(path.relative(srcDir, file))
const cacheKey = JSON.stringify({ src, file: fileOrig })
const cacheKey = JSON.stringify({ src, file: relativePath })
if (isBuild || options.cache !== false) { if (isBuild || options.cache !== false) {
const cached = cache.get(cacheKey) const cached = cache.get(cacheKey)
if (cached) { if (cached) {

@ -402,8 +402,9 @@ export async function createVitePressPlugin(
config.publicDir config.publicDir
) )
const relativePath = slash(path.relative(srcDir, file))
const payload: PageDataPayload = { const payload: PageDataPayload = {
path: `/${slash(path.relative(srcDir, file))}`, path: `/${siteConfig.rewrites.map[relativePath] || relativePath}`,
pageData pageData
} }

@ -8,7 +8,7 @@ import {
import fs from 'fs-extra' import fs from 'fs-extra'
import c from 'picocolors' import c from 'picocolors'
import path from 'path' import path from 'path'
import glob from 'fast-glob' import { glob } from 'tinyglobby'
import { type SiteConfig, type UserConfig } from '../siteConfig' import { type SiteConfig, type UserConfig } from '../siteConfig'
import { resolveRewrites } from './rewritesPlugin' import { resolveRewrites } from './rewritesPlugin'
@ -19,7 +19,7 @@ export async function resolvePages(
userConfig: UserConfig, userConfig: UserConfig,
logger: Logger logger: Logger
) { ) {
// Important: fast-glob doesn't guarantee order of the returned files. // Important: tinyglobby doesn't guarantee order of the returned files.
// We must sort the pages so the input list to rollup is stable across // We must sort the pages so the input list to rollup is stable across
// builds - otherwise different input order could result in different exports // builds - otherwise different input order could result in different exports
// order in shared chunks which in turns invalidates the hash of every chunk! // order in shared chunks which in turns invalidates the hash of every chunk!
@ -32,7 +32,8 @@ export async function resolvePages(
'**/node_modules/**', '**/node_modules/**',
'**/dist/**', '**/dist/**',
...(userConfig.srcExclude || []) ...(userConfig.srcExclude || [])
] ],
expandDirectories: false
}) })
).sort() ).sort()

@ -6,7 +6,7 @@ import {
} from 'vite' } from 'vite'
import path, { dirname, resolve } from 'path' import path, { dirname, resolve } from 'path'
import { isMatch } from 'micromatch' import { isMatch } from 'micromatch'
import glob from 'fast-glob' import { glob } from 'tinyglobby'
const loaderMatch = /\.data\.m?(j|t)s($|\?)/ const loaderMatch = /\.data\.m?(j|t)s($|\?)/
@ -98,9 +98,11 @@ export const staticDataPlugin: Plugin = {
// load the data // load the data
let watchedFiles let watchedFiles
if (watch) { if (watch) {
if (typeof watch === 'string') watch = [watch]
watchedFiles = ( watchedFiles = (
await glob(watch, { await glob(watch, {
ignore: ['**/node_modules/**', '**/dist/**'] ignore: ['**/node_modules/**', '**/dist/**'],
expandDirectories: false
}) })
).sort() ).sort()
} }
@ -121,7 +123,7 @@ export const staticDataPlugin: Plugin = {
}, },
transform(_code, id) { transform(_code, id) {
if (server && loaderMatch.test(id)) { if (server && loaderMatch.test(id) && '_importGlobMap' in server) {
// register this module as a glob importer // register this module as a glob importer
const { watch } = idToLoaderModulesMap[id]! const { watch } = idToLoaderModulesMap[id]!
if (watch) { if (watch) {

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save